|
|
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.