From: Liu Aleaxander Date: Fri, 28 Aug 2009 10:27:51 +0000 (+0800) Subject: Core: vfs-dir stuff re-implemented X-Git-Tag: syslinux-4.00-pre3~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c29a8049d462815774bbce8f80a8471a985bafcd;p=profile%2Fivi%2Fsyslinux.git Core: vfs-dir stuff re-implemented We fist make it simple, as told by hpa. Here're the changes: 1, The DIR structure changed, just a file pointer included. 2. So, the open/close/read-dir stuff in com32/lib/ changed again. 3. We read one stuff from every readdir call. Signed-off-by: Liu Aleaxander --- diff --git a/com32/include/dirent.h b/com32/include/dirent.h index 0fc2e13..d2bfd62 100644 --- a/com32/include/dirent.h +++ b/com32/include/dirent.h @@ -22,11 +22,10 @@ struct dirent { char d_name[NAME_MAX + 1]; }; +struct file; + typedef struct { - uint16_t dd_stat; - uint16_t dd_sect; - uint64_t dd_offset; - char dd_name[NAME_MAX + 1]; + struct file *dd_dir; } DIR; __extern DIR *opendir(const char *); diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c index dcf1704..9e43dd4 100644 --- a/com32/lib/closedir.c +++ b/com32/lib/closedir.c @@ -16,15 +16,13 @@ int closedir(DIR * dir) int rv = -1; if (dir) { - /* - com32sys_t regs; - memset(®s, 0, sizeof regs); - regs.eax.w[0] = 0x0022; - regs.esi.l = OFFS_WRT(dir, 0); - __com32.cs_intcall(0x22, ®s, ®s); - */ - free(dir); - rv = 0; + com32sys_t regs; + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0022; + regs.esi.l = (uint32_t)dir; + __com32.cs_intcall(0x22, ®s, ®s); + free(dir); + rv = 0; } return rv; diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c index 669a04a..70f74c1 100644 --- a/com32/lib/opendir.c +++ b/com32/lib/opendir.c @@ -27,12 +27,9 @@ DIR *opendir(const char *pathname) if (!(regs.eflags.l & EFLAGS_CF)) { /* Initialization: malloc() then zero */ newdir = calloc(1, sizeof(DIR)); - strcpy(newdir->dd_name, pathname); - newdir->dd_sect = regs.eax.l; - newdir->dd_offset = 0; - newdir->dd_stat = 0; + newdir->dd_dir = (struct file *)regs.eax.l; } - + /* We're done */ return newdir; } diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c index 7fca476..6c95bd6 100644 --- a/com32/lib/readdir.c +++ b/com32/lib/readdir.c @@ -13,16 +13,14 @@ struct dirent *readdir(DIR * dir) { - struct dirent *newde = NULL;; + struct dirent *newde; com32sys_t regs; - if ((dir !=NULL) && (dir->dd_sect != 0) && (dir->dd_stat != 0xffff)) { memset(®s, 0, sizeof(regs)); regs.eax.w[0] = 0x0021; regs.esi.l = (uint32_t)dir; __com32.cs_intcall(0x22, ®s, ®s); newde = (struct dirent *)(regs.eax.l); - } return newde; } diff --git a/com32/modules/dir.c b/com32/modules/dir.c index a3c9815..badc37d 100644 --- a/com32/modules/dir.c +++ b/com32/modules/dir.c @@ -20,6 +20,7 @@ int main(int argc, char *argv[]) } dir = opendir(argv[1]); + printf("back from in main ...? \n"); if (dir == NULL) { printf("Unable to read dir: %s\n", argv[1]); return 0; diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index c634a94..862497b 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -428,8 +428,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) filepos = 0; d = opendir(filestr); if (d != NULL) { - printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, - d->dd_offset); + //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset); de = readdir(d); while (de != NULL) { filepos++; diff --git a/core/comboot.inc b/core/comboot.inc index b078aa5..7f9b3a9 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -900,6 +900,7 @@ comapi_getcwd: ; INT 22h AX=0020h Open directory ; %if IS_SYSLINUX + global comapi_opendir comapi_opendir: mov es,P_ES mov si,P_SI @@ -909,8 +910,6 @@ comapi_opendir: cmp eax,0 jz comapi_err ; Found nothing mov P_EAX,eax - mov P_CX,SECTOR_SIZE - mov P_SI,si clc ret %else @@ -933,7 +932,10 @@ comapi_readdir equ comapi_err ; ; INT 22h AX=0022h Close directory ; -comapi_closedir equ comapi_close +comapi_closedir: + mov esi,P_ESI ; The address of DIR structure + pm_call closedir + ret ; ; INT 22h AX=0023h Query shuffler size diff --git a/core/dir.c b/core/dir.c index 0701125..1bc8a26 100644 --- a/core/dir.c +++ b/core/dir.c @@ -4,42 +4,15 @@ #include #include -/* The dir log structure, to log the status of the dir_buf. */ -struct dir_log { - int offset; /* how far from the dir_buf */ - int index; /* which dir entry have we go */ -}; -static struct dir_log log = {0, 0}; - -/* The dir buffer used by fill_dir to store the newly read dirs*/ -#define DB_SIZE 2048 -char dir_buf[DB_SIZE]; +extern struct fs_info *this_fs; +/* + * open dir, return the file structure pointer in _eax_, or NULL if failed + */ void opendir(com32sys_t *regs) { - int ds = regs->ds; /* save ds */ - - regs->ds = regs->es; - regs->es = ds; - mangle_name(regs); - regs->ds = ds; /* restore ds */ - searchdir(regs); -} - -/* - * Fill the dir buffer; return 1 for not full, 0 for full - */ -int fill_dir(struct dirent *de) -{ - int de_len = de->d_reclen; - if (log.offset + de_len <= DB_SIZE) { - memcpy(dir_buf + log.offset, de, de_len); - log.offset += de_len; - log.index ++; - return 1; - } - - return 0; + this_fs->fs_ops->opendir(regs); + regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]); } /* @@ -50,35 +23,22 @@ int fill_dir(struct dirent *de) */ void readdir(com32sys_t *regs) { - extern struct fs_info *this_fs; - DIR *dir = (DIR *)regs->esi.l; + DIR *dir = (DIR *)regs->esi.l; struct dirent *de = NULL; - static int offset; - - /* If we haven't fill the dir buffer, fill it */ - if (log.index == 0) { - this_fs->fs_ops->readdir(this_fs, dir); - if (log.offset == 0) { - regs->eax.l = 0; - return; - } - offset = 0; /* reset the _offset_ */ - } - - if (offset < log.offset) { - de = (struct dirent *)(dir_buf + offset); - offset += de->d_reclen; - } - if (offset >= log.offset) /* reach the end of buffer, reset it */ - memset(&log, 0, sizeof log); + if (dir->dd_dir) + de = this_fs->fs_ops->readdir(dir->dd_dir); + else + de = NULL; + /* Return the newly read de in _eax_ register */ regs->eax.l = (uint32_t)de; } void closedir(com32sys_t *regs) { - regs->esi.w[0] = 0; + DIR *dir = (DIR *)regs->esi.l; + _close_file(dir->dd_dir); } diff --git a/core/extern.inc b/core/extern.inc index 37024ec..20adb76 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -17,6 +17,6 @@ extern unmangle_name, close_file ; dir.c - extern opendir, readdir, readdir + extern opendir, readdir, closedir %endif ; EXTERN_INC diff --git a/core/fs.c b/core/fs.c index 1730378..b6e112a 100644 --- a/core/fs.c +++ b/core/fs.c @@ -9,7 +9,18 @@ struct fs_info *this_fs = NULL; struct fs_info fs; /* Actual file structures (we don't have malloc yet...) */ -static struct file Files[MAX_OPEN]; +struct file files[MAX_OPEN]; +/* + * Convert between a 16-bit file handle and a file structure + */ +inline uint16_t file_to_handle(struct file *file) +{ + return file ? (file - files)+1 : 0; +} +inline struct file *handle_to_file(uint16_t handle) +{ + return handle ? &files[handle-1] : NULL; +} /* * Get an empty file structure @@ -17,7 +28,7 @@ static struct file Files[MAX_OPEN]; static struct file *alloc_file(void) { int i; - struct file *file = Files; + struct file *file = files; for (i = 0; i < MAX_OPEN; i++) { if (!file->open_file) @@ -36,25 +47,13 @@ static inline void free_file(struct file *file) memset(file, 0, sizeof *file); } -static void _close_file(struct file *file) +void _close_file(struct file *file) { if (file->open_file) file->fs->fs_ops->close_file(file); free_file(file); } -/* - * Convert between a 16-bit file handle and a file structure - */ -static inline uint16_t file_to_handle(struct file *file) -{ - return file ? (file - Files)+1 : 0; -} -static inline struct file *handle_to_file(uint16_t handle) -{ - return handle ? &Files[handle-1] : NULL; -} - void load_config(com32sys_t *regs) { this_fs->fs_ops->load_config(regs); diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index f219995..a254042 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -659,12 +659,7 @@ static void vfat_searchdir(char *filename, struct file *file) if (attr & 0x10) { found_dir: open_file = alloc_fill_dir(dir_sector); - /* - * for dir, we use the file->file_len to store the sector number - * where the dir is. - */ - file_len = dir_sector; - } else if ((attr & 0x18) || (file_len == 0)) { + } else if ((attr & 0x18) || (file_len == 0)) { fail: file_len = 0; open_file = NULL; @@ -677,14 +672,22 @@ static void vfat_searchdir(char *filename, struct file *file) file->open_file = open_file; } - - +/* + * The open dir function, just call the searchdir function directly. + * I don't think we need call the mangle_name function first + */ +void vfat_opendir(com32sys_t *regs) +{ + char *src = MK_PTR(regs->es, regs->esi.w[0]); + char *dst = MK_PTR(regs->ds, regs->edi.w[0]); + strcpy(dst, src); + searchdir(regs); +} /* - * read one file from a directory - * return 1 if error, or 0 if success + * read one file from a directory; return the newly read de structure */ -void vfat_readdir(struct fs_info *fs, DIR *dir) +struct dirent* vfat_readdir(struct file *dir) { uint32_t sector, sec_off; /* make it to be 1 to check if we have met a long name entry before */ @@ -693,32 +696,33 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) uint8_t checksum = 0; uint8_t entries_left; int i; - int not_full = 1; - struct dirent de; + static struct dirent de; char *de_name = de.d_name; struct cache_struct *cs; struct fat_dir_entry *fat_dir; - struct fat_long_name_entry *long_dir; - - sector = dir->dd_sect; - sec_off = dir->dd_offset; + struct fat_long_name_entry *long_dir; + struct open_file_t *file = dir->open_file; + struct fs_info *fs = dir->fs; + + sector = file->file_sector; + sec_off = file->file_bytesleft; if (!sector) - return 1; + return NULL; entries_left = (SECTOR_SIZE - sec_off) >> 5; cs = get_cache_block(this_fs->fs_dev, sector); fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ - while (not_full) { + while (1) { if (!entries_left) { sector = nextsector(fs, sector); if (!sector) - goto end; + return NULL; cs = get_cache_block(fs->fs_dev, sector); fat_dir = (struct fat_dir_entry *)cs->data; } if (fat_dir->name[0] == 0) - goto end; + return NULL; if (fat_dir->attr == FAT_ATTR_LONG_NAME) { /* it's a long name */ long_dir = (struct fat_long_name_entry *)fat_dir; @@ -747,13 +751,10 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) if (!id) { /* Got a long name match */ - //if (get_checksum(fat_dir->name) != checksum) - //goto next_entry; + if (get_checksum(fat_dir->name) != checksum) + goto next_entry; - /* reset _id_ and _checksum_ */ - id = 1; - checksum = 0; - goto fill; + break; } if (fat_dir->attr & FAT_ATTR_VOLUME_ID || @@ -777,33 +778,29 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) else *de_name = '\0'; - fill: - de.d_type = fat_dir->attr; - de.d_reclen = DIR_REC_LEN(de.d_name); - not_full = fill_dir(&de); - de_name = de.d_name; /* reset the de_name pointer */ + break; } next_entry: entries_left --; fat_dir ++; } - - /* dir buffer filled, now it's time to update the DIR structure */ + + /* found what we want, fill the de structure */ + de.d_reclen = DIR_REC_LEN(de.d_name); + de.d_type = fat_dir->attr; + + /* update the DIR structure */ + entries_left--; if (!entries_left) { - sector = nextsector(fs, sector); - if (!sector) - return 1; - dir->dd_offset = 0; + sector = nextsector(fs, sector); + file->file_bytesleft = 0; } else { - dir->dd_offset = SECTOR_SIZE - (entries_left << 5); + file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); } - dir->dd_sect = sector; - return; - - end: - /* Reach the end of this directory */ - dir->dd_stat = -1; + file->file_sector = sector; + + return &de; } static void vfat_load_config(com32sys_t *regs) @@ -898,5 +895,6 @@ const struct fs_ops vfat_fs_ops = { .mangle_name = vfat_mangle_name, .unmangle_name = generic_unmangle_name, .load_config = vfat_load_config, + .opendir = vfat_opendir, .readdir = vfat_readdir }; diff --git a/core/include/dir.h b/core/include/dir.h index 454ca48..04f0d09 100644 --- a/core/include/dir.h +++ b/core/include/dir.h @@ -6,6 +6,7 @@ #include #include #include "disk.h" +#include "fs.h" struct dirent { uint32_t d_ino; @@ -15,18 +16,13 @@ struct dirent { char d_name[256]; }; +struct file; + typedef struct { - uint16_t dd_stat; - uint16_t dd_sect; - sector_t dd_offset; - char dd_name[256]; + struct file *dd_dir; } DIR; #define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 -/* - * funtions - */ -int fill_dir(struct dirent *); #endif /* dir.h */ diff --git a/core/include/fs.h b/core/include/fs.h index d16a568..a8b0294 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -52,7 +52,8 @@ struct fs_ops { void (*load_config)(com32sys_t *); /* the _dir_ stuff */ - void (*readdir)(struct fs_info *, DIR *); + void (*opendir)(com32sys_t *); + struct dirent * (*readdir)(struct file *); }; enum dev_type {CHS, EDD}; @@ -92,7 +93,8 @@ static inline bool not_whitespace(char c) */ void mangle_name(com32sys_t *); void searchdir(com32sys_t *); - - +void _close_file(struct file *); +inline uint16_t file_to_handle(struct file *); +inline struct file *handle_to_file(uint16_t); #endif /* FS_H */