|
|
1.1 root 1: /*
2: * /packages/ext2-files
3: *
4: * (c) 2008-2009 Laurent Vivier <[email protected]>
5: * (c) 2010 Mark Cave-Ayland <[email protected]>
6: *
7: * This file has been copied from EMILE, http://emile.sf.net
8: *
9: */
10:
11: #include "config.h"
12: #include "libopenbios/bindings.h"
13: #include "libext2.h"
14: #include "ext2_utils.h"
15: #include "fs/fs.h"
16: #include "libc/vsprintf.h"
17: #include "libc/diskio.h"
18:
19: extern void ext2_init( void );
20:
21: typedef struct {
22: enum { FILE, DIR } type;
23: union {
24: ext2_FILE *file;
25: ext2_DIR *dir;
26: };
27: } ext2_COMMON;
28:
29: typedef struct {
30: ext2_VOLUME *volume;
31: ext2_COMMON *common;
32: } ext2_info_t;
33:
34: DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" );
35:
36:
37: static const int days_month[12] =
38: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
39: static const int days_month_leap[12] =
40: { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
41:
42: static inline int is_leap(int year)
43: {
44: return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
45: }
46:
47: static void
48: print_date(time_t sec)
49: {
50: unsigned int second, minute, hour, month, day, year;
51: int current;
52: const int *days;
53:
54: second = sec % 60;
55: sec /= 60;
56:
57: minute = sec % 60;
58: sec /= 60;
59:
60: hour = sec % 24;
61: sec /= 24;
62:
63: year = sec * 100 / 36525;
64: sec -= year * 36525 / 100;
65: year += 1970;
66:
67: days = is_leap(year) ? days_month_leap : days_month;
68:
69: current = 0;
70: month = 0;
71: while (month < 12) {
72: if (sec <= current + days[month]) {
73: break;
74: }
75: current += days[month];
76: month++;
77: }
78: month++;
79:
80: day = sec - current + 1;
81:
82: forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
83: year, month, day, hour, minute, second);
84: }
85:
86:
87: /************************************************************************/
88: /* Standard package methods */
89: /************************************************************************/
90:
91: /* ( -- success? ) */
92: static void
93: ext2_files_open( ext2_info_t *mi )
94: {
95: int fd;
96: char *path = my_args_copy();
97:
98: fd = open_ih( my_parent() );
99: if ( fd == -1 ) {
100: free( path );
101: RET( 0 );
102: }
103:
104: mi->volume = ext2_mount(fd);
105: if (!mi->volume) {
106: RET( 0 );
107: }
108:
109: mi->common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
110: if (mi->common == NULL)
111: RET( 0 );
112:
113: mi->common->dir = ext2_opendir(mi->volume, path);
114: if (mi->common->dir == NULL) {
115: mi->common->file = ext2_open(mi->volume, path);
116: if (mi->common->file == NULL) {
117: free(mi->common);
118: RET( 0 );
119: }
120: mi->common->type = FILE;
121: RET( -1 );
122: }
123: mi->common->type = DIR;
124: RET( -1 );
125: }
126:
127: /* ( -- ) */
128: static void
129: ext2_files_close( ext2_info_t *mi )
130: {
131: ext2_COMMON *common = mi->common;
132:
133: if (common->type == FILE)
134: ext2_close(common->file);
135: else if (common->type == DIR)
136: ext2_closedir(common->dir);
137: free(common);
138:
139: ext2_umount(mi->volume);
140: }
141:
142: /* ( buf len -- actlen ) */
143: static void
144: ext2_files_read( ext2_info_t *mi )
145: {
146: int count = POP();
147: char *buf = (char *)cell2pointer(POP());
148:
149: ext2_COMMON *common = mi->common;
150: if (common->type != FILE)
151: RET( -1 );
152:
153: RET ( ext2_read( common->file, buf, count ) );
154: }
155:
156: /* ( pos.d -- status ) */
157: static void
158: ext2_files_seek( ext2_info_t *mi )
159: {
160: long long pos = DPOP();
161: int offs = (int)pos;
162: int whence = SEEK_SET;
163: int ret;
164: ext2_COMMON *common = mi->common;
165:
166: if (common->type != FILE)
167: RET( -1 );
168:
169: ret = ext2_lseek(common->file, offs, whence);
170: if (ret)
171: RET( -1 );
172: else
173: RET( 0 );
174: }
175:
176: /* ( addr -- size ) */
177: static void
178: ext2_files_load( ext2_info_t *mi )
179: {
180: char *buf = (char *)cell2pointer(POP());
181: int count;
182:
183: ext2_COMMON *common = mi->common;
184: if (common->type != FILE)
185: RET( -1 );
186:
187: /* Seek to the end in order to get the file size */
188: ext2_lseek(common->file, 0, SEEK_END);
189: count = common->file->offset;
190: ext2_lseek(common->file, 0, SEEK_SET);
191:
192: RET ( ext2_read( common->file, buf, count ) );
193: }
194:
195: /* ( -- cstr ) */
196: static void
197: ext2_files_get_path( ext2_info_t *mi )
198: {
199: ext2_COMMON *common = mi->common;
200:
201: if (common->type != FILE)
202: RET( 0 );
203:
204: RET( pointer2cell(strdup(common->file->path)) );
205: }
206:
207: /* ( -- cstr ) */
208: static void
209: ext2_files_get_fstype( ext2_info_t *mi )
210: {
211: PUSH( pointer2cell(strdup("ext2")) );
212: }
213:
214: /* static method, ( pathstr len ihandle -- ) */
215: static void
216: ext2_files_dir( ext2_info_t *dummy )
217: {
218: ext2_COMMON *common;
219: ext2_VOLUME *volume;
220: struct ext2_dir_entry_2 *entry;
221: struct ext2_inode inode;
222: int fd;
223:
224: ihandle_t ih = POP();
225: char *path = pop_fstr_copy();
226:
227: fd = open_ih( ih );
228: if ( fd == -1 ) {
229: free( path );
230: return;
231: }
232:
233: volume = ext2_mount(fd);
234: if (!volume) {
235: return;
236: }
237:
238: common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
239: common->dir = ext2_opendir(volume, path);
240:
241: forth_printf("\n");
242: while ( (entry = ext2_readdir(common->dir)) ) {
243: ext2_get_inode(common->dir->volume, entry->inode, &inode);
244: forth_printf("% 10d ", inode.i_size);
245: print_date(inode.i_mtime);
246: if (S_ISDIR(inode.i_mode))
247: forth_printf("%s\\\n", entry->name);
248: else
249: forth_printf("%s\n", entry->name);
250: }
251:
252: ext2_closedir( common->dir );
253: ext2_umount( volume );
254:
255: close_io( fd );
256:
257: free( common );
258: free( path );
259: }
260:
261: /* static method, ( pos.d ih -- flag? ) */
262: static void
263: ext2_files_probe( ext2_info_t *dummy )
264: {
265: ihandle_t ih = POP_ih();
266: long long offs = DPOP();
267: int fd, ret = 0;
268:
269: fd = open_ih(ih);
270: if (fd >= 0) {
271: if (ext2_probe(fd, offs)) {
272: ret = -1;
273: }
274: close_io(fd);
275: } else {
276: ret = -1;
277: }
278:
279: RET (ret);
280: }
281:
282:
283: static void
284: ext2_initializer( ext2_info_t *dummy )
285: {
286: fword("register-fs-package");
287: }
288:
289: NODE_METHODS( ext2 ) = {
290: { "probe", ext2_files_probe },
291: { "open", ext2_files_open },
292: { "close", ext2_files_close },
293: { "read", ext2_files_read },
294: { "seek", ext2_files_seek },
295: { "load", ext2_files_load },
296: { "dir", ext2_files_dir },
297:
298: /* special */
299: { "get-path", ext2_files_get_path },
300: { "get-fstype", ext2_files_get_fstype },
301:
302: { NULL, ext2_initializer },
303: };
304:
305: void
306: ext2_init( void )
307: {
308: REGISTER_NODE( ext2 );
309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.