4 * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
5 * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
7 * This file has been copied from EMILE, http://emile.sf.net
12 #include "libopenbios/bindings.h"
14 #include "ext2_utils.h"
16 #include "libc/vsprintf.h"
17 #include "libc/diskio.h"
19 extern void ext2_init( void );
22 enum { FILE, DIR } type;
34 DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" );
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 };
42 static inline int is_leap(int year)
44 return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
48 print_date(time_t sec)
50 unsigned int second, minute, hour, month, day, year;
63 year = sec * 100 / 36525;
64 sec -= year * 36525 / 100;
67 days = is_leap(year) ? days_month_leap : days_month;
72 if (sec <= current + days[month]) {
75 current += days[month];
80 day = sec - current + 1;
82 forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
83 year, month, day, hour, minute, second);
87 /************************************************************************/
88 /* Standard package methods */
89 /************************************************************************/
93 ext2_files_open( ext2_info_t *mi )
96 char *path = my_args_copy();
98 fd = open_ih( my_parent() );
104 mi->volume = ext2_mount(fd);
109 mi->common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
110 if (mi->common == NULL)
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) {
120 mi->common->type = FILE;
123 mi->common->type = DIR;
129 ext2_files_close( ext2_info_t *mi )
131 ext2_COMMON *common = mi->common;
133 if (common->type == FILE)
134 ext2_close(common->file);
135 else if (common->type == DIR)
136 ext2_closedir(common->dir);
139 ext2_umount(mi->volume);
142 /* ( buf len -- actlen ) */
144 ext2_files_read( ext2_info_t *mi )
147 char *buf = (char *)cell2pointer(POP());
149 ext2_COMMON *common = mi->common;
150 if (common->type != FILE)
153 RET ( ext2_read( common->file, buf, count ) );
156 /* ( pos.d -- status ) */
158 ext2_files_seek( ext2_info_t *mi )
160 long long pos = DPOP();
162 int whence = SEEK_SET;
164 ext2_COMMON *common = mi->common;
166 if (common->type != FILE)
169 ret = ext2_lseek(common->file, offs, whence);
176 /* ( addr -- size ) */
178 ext2_files_load( ext2_info_t *mi )
180 char *buf = (char *)cell2pointer(POP());
183 ext2_COMMON *common = mi->common;
184 if (common->type != FILE)
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);
192 RET ( ext2_read( common->file, buf, count ) );
197 ext2_files_get_path( ext2_info_t *mi )
199 ext2_COMMON *common = mi->common;
201 if (common->type != FILE)
204 RET( pointer2cell(strdup(common->file->path)) );
209 ext2_files_get_fstype( ext2_info_t *mi )
211 PUSH( pointer2cell(strdup("ext2")) );
214 /* static method, ( pathstr len ihandle -- ) */
216 ext2_files_dir( ext2_info_t *dummy )
220 struct ext2_dir_entry_2 *entry;
221 struct ext2_inode inode;
224 ihandle_t ih = POP();
225 char *path = pop_fstr_copy();
233 volume = ext2_mount(fd);
238 common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
239 common->dir = ext2_opendir(volume, path);
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);
249 forth_printf("%s\n", entry->name);
252 ext2_closedir( common->dir );
253 ext2_umount( volume );
261 /* static method, ( pos.d ih -- flag? ) */
263 ext2_files_probe( ext2_info_t *dummy )
265 ihandle_t ih = POP_ih();
266 long long offs = DPOP();
271 if (ext2_probe(fd, offs)) {
284 ext2_initializer( ext2_info_t *dummy )
286 fword("register-fs-package");
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 },
299 { "get-path", ext2_files_get_path },
300 { "get-fstype", ext2_files_get_fstype },
302 { NULL, ext2_initializer },
308 REGISTER_NODE( ext2 );