Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / iso9660 / iso9660_fs.c
1 /*
2  * /packages/iso9660-files filesystem handler
3  *
4  * (c) 2009 Laurent Vivier <Laurent@vivier.eu>
5  * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
6  */
7
8 #include "config.h"
9 #include "libopenbios/bindings.h"
10 #include "libiso9660.h"
11 #include "fs/fs.h"
12 #include "libc/vsprintf.h"
13 #include "libc/diskio.h"
14
15 extern void     iso9660_init( void );
16
17 typedef struct {
18         enum { FILE, DIR } type;
19         union {
20                 iso9660_FILE *file;
21                 iso9660_DIR * dir;
22         };
23 } iso9660_COMMON;
24
25 typedef struct {
26         iso9660_VOLUME *volume;
27         iso9660_COMMON *common;
28 } iso9660_info_t;
29
30 DECLARE_NODE( iso9660, 0, sizeof(iso9660_info_t), "+/packages/iso9660-files" );
31
32 /* ( -- success? ) */
33 static void
34 iso9660_files_open( iso9660_info_t *mi )
35 {
36         int fd;
37         char *path = my_args_copy();
38
39         if ( ! path )
40                 RET( 0 );
41  
42         fd = open_ih( my_parent() );
43         if ( fd == -1 ) {
44                 free( path );
45                 RET( 0 );
46         }
47  
48         mi->volume = iso9660_mount( fd );
49         if ( mi->volume == NULL ) {
50                 free( path );
51                 close_io( fd );
52                 RET( 0 );
53         }
54
55         mi->common->dir = iso9660_opendir( mi->volume, path );
56         if ( mi->common->dir == NULL ) {
57                 mi->common->file = iso9660_open( mi->volume, path );
58                 if (mi->common->file == NULL) {
59                         iso9660_umount( mi->volume );
60                         close_io( fd );
61                         free( path );
62                         RET( 0 );
63                 }
64                 mi->common->type = FILE;
65                 free( path );
66                 RET( -1 );
67         }
68         mi->common->type = DIR;
69         free( path );
70
71         RET( -1 );
72 }
73
74 /* ( -- ) */
75 static void
76 iso9660_files_close( iso9660_info_t *mi )
77 {
78         int fd = mi->volume->fd;
79  
80         if (mi->common->type == FILE )
81                 iso9660_close( mi->common->file );
82         else if ( mi->common->type == DIR )
83                 iso9660_closedir( mi->common->dir );
84         iso9660_umount( mi->volume );
85         close_io( fd );
86 }
87
88 /* ( buf len -- actlen ) */
89 static void
90 iso9660_files_read( iso9660_info_t *mi )
91 {
92         int count = POP();
93         char *buf = (char *)cell2pointer(POP());
94         int ret;
95  
96         if ( mi->common->type != FILE )
97                 PUSH( 0 );
98  
99         ret = iso9660_read( mi->common->file, buf, count );
100  
101         PUSH( ret );
102 }
103
104 /* ( pos.d -- status ) */
105 static void
106 iso9660_files_seek( iso9660_info_t *mi )
107 {
108         long long pos = DPOP();
109         cell ret;
110         int offs = (int)pos;
111         int whence = SEEK_SET;
112
113         if (mi->common->type != FILE)
114                 PUSH( -1 );
115
116         if( offs == -1 ) {
117                 offs = 0;
118                 whence = SEEK_END;
119         }
120  
121         ret = iso9660_lseek(mi->common->file, offs, whence);
122  
123         PUSH( (ret < 0)? -1 : 0 );
124 }
125
126 /* ( -- filepos.d ) */
127 static void
128 iso9660_files_offset( iso9660_info_t *mi )
129 {
130         if ( mi->common->type != FILE )
131                 DPUSH( -1 );
132  
133         DPUSH( mi->common->file->offset );
134 }
135
136 /* ( addr -- size ) */
137 static void
138 iso9660_files_load( iso9660_info_t *mi)
139 {
140         char *buf = (char*)cell2pointer(POP());
141         int ret, size;
142  
143         if ( mi->common->type != FILE )
144                 PUSH( 0 );
145  
146         size = 0;
147         while(1) {
148                 ret = iso9660_read( mi->common->file, buf, 512 );
149                 if (ret <= 0)
150                         break;
151                 buf += ret;
152                 size += ret;
153                 if (ret != 512)
154                         break;
155         }
156         PUSH( size );
157 }
158
159 /* static method, ( pathstr len ihandle -- ) */
160 static void
161 iso9660_files_dir( iso9660_info_t *dummy )
162 {
163         iso9660_VOLUME *volume;
164         iso9660_COMMON *common;
165         struct iso_directory_record *idr;
166         char name_buf[256];
167         int fd;
168  
169         ihandle_t ih = POP();
170         char *path = pop_fstr_copy();
171
172         fd = open_ih( ih );
173         if ( fd == -1 ) {
174                 free( path );
175                 return;
176         }
177  
178         volume = iso9660_mount( fd );
179         if ( volume == NULL ) {
180                 free ( path );
181                 close_io( fd );
182                 return;
183         }
184
185         common = malloc(sizeof(iso9660_COMMON));
186         common->dir = iso9660_opendir( volume, path );
187
188         forth_printf("\n");
189         while ( (idr = iso9660_readdir(common->dir)) ) {
190  
191                 forth_printf("% 10d ", isonum_733(idr->size));
192                 forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
193                              idr->date[0] + 1900, /* year */
194                              idr->date[1], /* month */
195                              idr->date[2], /* day */
196                              idr->date[3], idr->date[4], idr->date[5]);
197                 iso9660_name(common->dir->volume, idr, name_buf);
198                 if (idr->flags[0] & 2)
199                         forth_printf("%s\\\n", name_buf);
200                 else
201                         forth_printf("%s\n", name_buf);
202         }
203
204         iso9660_closedir( common->dir );
205         iso9660_umount( volume );
206
207         close_io( fd );
208
209         free( common );
210         free( path );
211 }
212
213 /* static method, ( pos.d ih -- flag? ) */
214 static void
215 iso9660_files_probe( iso9660_info_t *dummy )
216 {
217         ihandle_t ih = POP_ih();
218         long long offs = DPOP();
219         int fd, ret = 0;
220
221         fd = open_ih(ih);
222         if (fd >= 0) {
223                 if (iso9660_probe(fd, offs)) {
224                         ret = -1;
225                 }
226                 close_io(fd);
227         } else {
228                 ret = -1;
229         }
230
231         RET (ret);
232 }
233
234 static void
235 iso9660_files_block_size( iso9660_info_t *dummy )
236 {
237         PUSH(2048);
238 }
239  
240 static void
241 iso9660_initializer( iso9660_info_t *dummy )
242 {
243         fword("register-fs-package");
244 }
245  
246 NODE_METHODS( iso9660 ) = {
247         { "probe",      iso9660_files_probe             },
248         { "open",       iso9660_files_open              },
249         { "close",      iso9660_files_close             },
250         { "read",       iso9660_files_read              },
251         { "seek",       iso9660_files_seek              },
252         { "offset",     iso9660_files_offset            },
253         { "load",       iso9660_files_load              },
254         { "dir",        iso9660_files_dir               },
255         { "block-size", iso9660_files_block_size        },
256         { NULL,         iso9660_initializer     },
257 };
258
259 void
260 iso9660_init( void )
261 {
262         REGISTER_NODE( iso9660 );
263 }