|
|
1.1 root 1: /*
2: * /packages/iso9660-files filesystem handler
3: *
4: * (c) 2009 Laurent Vivier <[email protected]>
5: * (c) 2010 Mark Cave-Ayland <[email protected]>
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.