fs/fat: cleanups + readdir implementation
Subsystems (2)
v2 cover fs/fat: cleanups + readdir implementation
Introduce directory traversal iterators, and implement fs_readdir() which is needed by EFI_LOADER.
The part re-working fat.c to use the directory iterators itself is nearly a 2:1 negative diffstat, and a pretty big cleanup. I fixed one or two other small issues along the way. It hasn't really been tested with a wide variaty of different fat filesystems (if someone has a collection of disk images to test with somewhere, let me know), but it seems at least not worse than what it is replacing.
Sorry, I realized I forgot to re-send this series. Small cleanup and fixed a couple bugs, compared to v1.
v2: fix a couple issues (partition is whole disk, and traversing ".."
up to root directory)
Rob Clark (8):
fs/fat: split out helper to init fsdata
fs/fat: introduce new director iterators
fat/fs: convert to directory iterators
fs: add fs_readdir()
fs/fat: implement opendir/readdir/closedir
fat/fs: remove a bunch of dead code
fat/fs: move ls to generic implementation
fs/fat: fix case for FAT shortnames
disk/part.c | 31 +- fs/fat/Makefile | 4 - fs/fat/fat.c | 1025 +++++++++++++++++++++------------------------------- fs/fat/fat_write.c | 4 +- fs/fat/file.c | 183 ---------- fs/fs.c | 124 ++++++- include/fat.h | 35 +- include/fs.h | 55 +++ include/part.h | 4 + 9 files changed, 622 insertions(+), 843 deletions(-) delete mode 100644 fs/fat/file.c
Signature · 1 line
2.13.5
PATCH v2 1/8 fs/fat: split out helper to init fsdata
Want to re-use this in fat dirent iterator in next patch.
--- fs/fat/fat.c | 73 +++++++++++++++++++++++++++++++++++------------------------ include/fat.h | 1 + 2 files changed, 44 insertions(+), 30 deletions(-)
fs/fat/fat.c +43 -30
@@ -808,35 +808,17 @@ exit:return ret; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] -__aligned(ARCH_DMA_MINALIGN) ; - -int do_fat_read_at (const char *filename,loff_t pos,void *buffer, -loff_t maxsize,int dols,int dogetsize,loff_t *size) +static int get_fs_info (fsdata *mydata) { -char fnamecopy[2048 ];boot_sector bs;volume_info volinfo; -fsdata datablock; -fsdata *mydata = &datablock; -dir_entry *dentptr =NULL ; -__u16 prevcksum =0xffff ; -char *subname ="" ; -__u32 cursect; -int idx, isdir =0 ; -int files =0 , dirs =0 ; -int ret =-1 ; -int firsttime;__u32 root_cluster =0 ; -__u32 read_blk; -int rootdir_size =0 ; -int buffer_blk_cnt; -int do_read; -__u8 *dir_ptr; +int ret; -if (read_bootsectandvi (&bs, &volinfo, &mydata->fatsize)) { + ret =read_bootsectandvi (&bs, &volinfo, &mydata->fatsize); +if (ret) {debug ("Error: reading boot sector\n" ); -return -1 ; +return ret; }if (mydata->fatsize ==32 ) {
@@ -848,8 +830,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->fat_sect = bs.reserved; - cursect = mydata->rootdir_sect - = mydata->fat_sect + mydata->fatlength * bs.fats; + mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats; mydata->sect_size = (bs.sector_size[1 ] <<8 ) + bs.sector_size[0 ]; mydata->clust_size = bs.cluster_size;
@@ -863,12 +844,12 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size *2 ); }else { - rootdir_size = ((bs.dir_entries[1 ] * (int )256 + - bs.dir_entries[0 ]) * -sizeof (dir_entry)) / - mydata->sect_size; + mydata->rootdir_size = ((bs.dir_entries[1 ] * (int )256 + + bs.dir_entries[0 ]) * +sizeof (dir_entry)) / + mydata->sect_size; mydata->data_begin = mydata->rootdir_sect + - rootdir_size - + mydata->rootdir_size - (mydata->clust_size *2 ); }
@@ -893,6 +874,38 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,debug ("Sector size: %d, cluster size: %d\n" , mydata->sect_size, mydata->clust_size); +return 0 ; +} + +__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] +__aligned(ARCH_DMA_MINALIGN) ; + +int do_fat_read_at (const char *filename,loff_t pos,void *buffer, +loff_t maxsize,int dols,int dogetsize,loff_t *size) +{ +char fnamecopy[2048 ]; +fsdata datablock; +fsdata *mydata = &datablock; +dir_entry *dentptr =NULL ; +__u16 prevcksum =0xffff ; +char *subname ="" ; +__u32 cursect; +int idx, isdir =0 ; +int files =0 , dirs =0 ; +int ret =-1 ; +int firsttime; +__u32 root_cluster =0 ; +__u32 read_blk; +int rootdir_size =0 ; +int buffer_blk_cnt; +int do_read; +__u8 *dir_ptr; + +if (get_fs_info (mydata)) +return -1 ; + + cursect = mydata->rootdir_sect; +/* "cwd" is always the root... */ while (ISDIRDELIM (*filename)) filename++;
include/fat.h +1 -0
@@ -174,6 +174,7 @@ typedef struct {__u16 clust_size;/* Size of clusters in sectors */ int data_begin;/* The sector of the first cluster, can be negative */ int fatbufnum;/* Used by get_fatent, init to -1 */ +int rootdir_size; } fsdata;typedef int (file_detectfs_func )(void );
Signature · 1 line
2.13.5
PATCH v2 1/8 fs/fat: split out helper to init fsdata
Quoted 3 lines · Rob Clark
Want to re-use this in fat dirent iterator in next patch.
Signed-off-by Rob Clark <[email protected]>
Quoted 130 lines
--- fs/fat/fat.c | 73 +++++++++++++++++++++++++++++++++++------------------------ include/fat.h | 1 + 2 files changed, 44 insertions(+), 30 deletions(-)fs/fat/fat.c +43
-30@@ -808,35 +808,17 @@ exit:return ret; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] -__aligned(ARCH_DMA_MINALIGN) ; - -int do_fat_read_at (const char *filename,loff_t pos,void *buffer, -loff_t maxsize,int dols,int dogetsize,loff_t *size) +static int get_fs_info (fsdata *mydata) { -char fnamecopy[2048 ];boot_sector bs;volume_info volinfo; -fsdata datablock; -fsdata *mydata = &datablock; -dir_entry *dentptr =NULL ; -__u16 prevcksum =0xffff ; -char *subname ="" ; -__u32 cursect; -int idx, isdir =0 ; -int files =0 , dirs =0 ; -int ret =-1 ; -int firsttime;__u32 root_cluster =0 ; -__u32 read_blk; -int rootdir_size =0 ; -int buffer_blk_cnt; -int do_read; -__u8 *dir_ptr; +int ret; -if (read_bootsectandvi (&bs, &volinfo, &mydata->fatsize)) { + ret =read_bootsectandvi (&bs, &volinfo, &mydata->fatsize); +if (ret) {debug ("Error: reading boot sector\n" ); -return -1 ; +return ret; }if (mydata->fatsize ==32 ) {@@ -848,8 +830,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->fat_sect = bs.reserved; - cursect = mydata->rootdir_sect - = mydata->fat_sect + mydata->fatlength * bs.fats; + mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats; mydata->sect_size = (bs.sector_size[1 ] <<8 ) + bs.sector_size[0 ]; mydata->clust_size = bs.cluster_size;@@ -863,12 +844,12 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size *2 ); }else { - rootdir_size = ((bs.dir_entries[1 ] * (int )256 + - bs.dir_entries[0 ]) * -sizeof (dir_entry)) / - mydata->sect_size; + mydata->rootdir_size = ((bs.dir_entries[1 ] * (int )256 + + bs.dir_entries[0 ]) * +sizeof (dir_entry)) / + mydata->sect_size; mydata->data_begin = mydata->rootdir_sect + - rootdir_size - + mydata->rootdir_size - (mydata->clust_size *2 ); }@@ -893,6 +874,38 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,debug ("Sector size: %d, cluster size: %d\n" , mydata->sect_size, mydata->clust_size); +return 0 ; +} + +__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] +__aligned(ARCH_DMA_MINALIGN) ; + +int do_fat_read_at (const char *filename,loff_t pos,void *buffer, +loff_t maxsize,int dols,int dogetsize,loff_t *size) +{ +char fnamecopy[2048 ]; +fsdata datablock; +fsdata *mydata = &datablock; +dir_entry *dentptr =NULL ; +__u16 prevcksum =0xffff ; +char *subname ="" ; +__u32 cursect; +int idx, isdir =0 ; +int files =0 , dirs =0 ; +int ret =-1 ; +int firsttime; +__u32 root_cluster =0 ; +__u32 read_blk; +int rootdir_size =0 ; +int buffer_blk_cnt; +int do_read; +__u8 *dir_ptr; + +if (get_fs_info (mydata)) +return -1 ; + + cursect = mydata->rootdir_sect; +/* "cwd" is always the root... */ while (ISDIRDELIM (*filename)) filename++;include/fat.h +1
-0@@ -174,6 +174,7 @@ typedef struct {__u16 clust_size;/* Size of clusters in sectors */ int data_begin;/* The sector of the first cluster, can be negative */ int fatbufnum;/* Used by get_fatent, init to -1 */ +int rootdir_size; } fsdata;typedef int (file_detectfs_func )(void );
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 1/8 fs/fat: split out helper to init fsdata
Quoted 9 lines · Łukasz Majewski
Quoted 4 lines · Rob Clark
Want to re-use this in fat dirent iterator in next patch.
Signed-off-by Rob Clark <[email protected]>Reviewed-by Łukasz Majewski <[email protected]>
thanks
btw, is there some way to make get_maintainers.pl to find your @denx.de address instead of the @samsung address which bounces? (Sorry, I hadn't realized you had a new addr, so you were missed from CC on some of the patches, I think.)
BR,
-R
PATCH v2 1/8 fs/fat: split out helper to init fsdata
Quoted 11 lines · Rob Clark
Quoted 9 lines · Łukasz Majewski
Quoted 4 lines · Rob Clark
Want to re-use this in fat dirent iterator in next patch.
Signed-off-by Rob Clark <[email protected]>Reviewed-by Łukasz Majewski <[email protected]>
Quoted 6 lines
thanks
btw, is there some way to make get_maintainers.pl to find your @denx.de address instead of the @samsung address which bounces? (Sorry, I hadn't realized you had a new addr, so you were missed from CC on some of the patches, I think.)
I've updated git-mailrc entry (about which I've forgotten).
However, get_maintainer looks for people making changes to the file(s) to which patch is applied.
Hence, you see my old address.
Quoted 4 lines
BR,
-R
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 1/8 fs/fat: split out helper to init fsdata
In reply to Rob ClarkHi Rob,
Quoted 8 lines · Rob Clark
Want to re-use this in fat dirent iterator in next patch.
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 73 +++++++++++++++++++++++++++++++++++------------------------ include/fat.h | 1 + 2 files changed, 44 insertions(+), 30 deletions(-)
But please add a comment to the new structure memory you added.
PATCH v2 2/8 fs/fat: introduce new director iterators
In reply to Rob ClarkUntangle directory traversal into a simple iterator, to replace the existing multi-purpose do_fat_read_at() + get_dentfromdir().
--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)
fs/fat/fat.c +326 -0
@@ -1245,6 +1245,332 @@ exit:return ret; } + +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct { +fsdata *fsdata; +unsigned cursect; +dir_entry *dent; +int remaining;/* remaining dent's in current cluster */ +int last_cluster; +int is_root; + +/* current iterator position values: */ +char l_name[VFAT_MAXLEN_BYTES ]; +char s_name[14 ]; +char *name;/* l_name if there is one, else s_name */ + +u8 block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ; +}fat_itr ; + +static int fat_itr_isdir (fat_itr *itr); + +/** +* fat_itr_root() - initialize an iterator to start at the root +* directory +* +* @itr: iterator to initialize +* @fsdata: filesystem data for the partition +* @return 0 on success, else -errno +*/ +static int fat_itr_root (fat_itr *itr,fsdata *fsdata) +{ +if (get_fs_info (fsdata)) +return -ENXIO ; + + itr->fsdata = fsdata; + itr->cursect = fsdata->rootdir_sect; + itr->dent =NULL ; + itr->remaining =0 ; + itr->last_cluster =0 ; + itr->is_root =1 ; + +return 0 ; +} + +/** +* fat_itr_child() - initialize an iterator to descend into a sub- +* directory +* +* Initializes 'itr' to iterate the contents of the directory at +* the current cursor position of 'parent'. It is an error to +* call this if the current cursor of 'parent' is pointing at a +* regular file. +* +* Note that 'itr' and 'parent' can be the same pointer if you do +* not need to preserve 'parent' after this call, which is useful +* for traversing directory structure to resolve a file/directory. +* +* @itr: iterator to initialize +* @parent: the iterator pointing at a directory entry in the +* parent directory of the directory to iterate +*/ +static void fat_itr_child (fat_itr *itr,fat_itr *parent) +{ +fsdata *mydata = parent->fsdata;/* for silly macros */ +unsigned clustnum =START (parent->dent); + +assert (fat_itr_isdir (parent)); + + itr->fsdata = parent->fsdata; +if (clustnum >0 ) { + itr->cursect = itr->fsdata->data_begin + + (clustnum * itr->fsdata->clust_size); + }else { + itr->cursect = parent->fsdata->rootdir_sect; + } + itr->dent =NULL ; + itr->remaining =0 ; + itr->last_cluster =0 ; + itr->is_root =0 ; +} + +static void *next_cluster (fat_itr *itr) +{ +fsdata *mydata = itr->fsdata;/* for silly macros */ +int ret; + +/* have we reached the end? */ +if (itr->last_cluster) +return NULL ; + +debug ("FAT read(sect=%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n" , + itr->cursect, itr->fsdata->clust_size,DIRENTSPERBLOCK ); + +/* +* NOTE: do_fat_read_at() had complicated logic to deal w/ +* vfat names that span multiple clusters in the fat16 case, +* which get_dentfromdir() probably also needed (and was +* missing). And not entirely sure what fat32 didn't have +* the same issue.. We solve that by only caring about one +* dent at a time and iteratively constructing the vfat long +* name. +*/ + ret =disk_read (itr->cursect, itr->fsdata->clust_size, + itr->block); +if (ret <0 ) { +debug ("Error: reading block\n" ); +return NULL ; + } + +if (itr->is_root && itr->fsdata->fatsize !=32 ) { + itr->cursect++; +if (itr->cursect - itr->fsdata->rootdir_sect >= + itr->fsdata->rootdir_size) { +debug ("cursect: 0x%x\n" , itr->cursect); + itr->last_cluster =1 ; + } + }else { + itr->cursect =get_fatent (itr->fsdata, itr->cursect); +if (CHECK_CLUST (itr->cursect, itr->fsdata->fatsize)) { +debug ("cursect: 0x%x\n" , itr->cursect); + itr->last_cluster =1 ; + } + } + +return itr->block; +} + +static dir_entry *next_dent (fat_itr *itr) +{ +if (itr->remaining ==0 ) { +struct dir_entry *dent =next_cluster (itr); + +/* have we reached the last cluster? */ +if (!dent) +return NULL ; + + itr->remaining = itr->fsdata->sect_size /sizeof (dir_entry) -1 ; + itr->dent = dent; + }else { + itr->remaining--; + itr->dent++; + } + +/* have we reached the last valid entry? */ +if (itr->dent->name[0 ] ==0 ) +return NULL ; + +return itr->dent; +} + +static dir_entry *extract_vfat_name (fat_itr *itr) +{ +struct dir_entry *dent = itr->dent; +int seqn = itr->dent->name[0 ] & ~LAST_LONG_ENTRY_MASK ; +u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum; +int n =0 ; + +while (seqn--) { +char buf[13 ]; +int idx =0 ; + +slot2str ((dir_slot *)dent, buf, &idx); + +/* shift accumulated long-name up and copy new part in: */ +memmove (itr->l_name + idx, itr->l_name, n); +memcpy (itr->l_name, buf, idx); + n += idx; + + dent =next_dent (itr); +if (!dent) +return NULL ; + } + + itr->l_name[n] ='\0' ; + + chksum =mkcksum (dent->name, dent->ext); + +/* checksum mismatch could mean deleted file, etc.. skip it: */ +if (chksum != alias_checksum) { +debug ("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n" , + chksum, alias_checksum, itr->l_name, dent->name, dent->ext); +return NULL ; + } + +return dent; +} + +/** +* fat_itr_next() - step to the next entry in a directory +* +* Must be called once on a new iterator before the cursor is valid. +* +* @itr: the iterator to iterate +* @return boolean, 1 if success or 0 if no more entries in the +* current directory +*/ +static int fat_itr_next (fat_itr *itr) +{ +dir_entry *dent; + + itr->name =NULL ; + +while (1 ) { + dent =next_dent (itr); +if (!dent) +return 0 ; + +if (dent->name[0 ] ==DELETED_FLAG || + dent->name[0 ] == aRING) +continue ; + +if (dent->attr &ATTR_VOLUME ) { +if (vfat_enabled && + (dent->attr &ATTR_VFAT ) ==ATTR_VFAT && + (dent->name[0 ] &LAST_LONG_ENTRY_MASK )) { + dent =extract_vfat_name (itr); +if (!dent) +continue ; + itr->name = itr->l_name; +break ; + }else { +/* Volume label or VFAT entry, skip */ +continue ; + } + } + +break ; + } + +get_name (dent, itr->s_name); +if (!itr->name) + itr->name = itr->s_name; + +return 1 ; +} + +/** +* fat_itr_isdir() - is current cursor position pointing to a directory +* +* @itr: the iterator +* @return true if cursor is at a directory +*/ +static int fat_itr_isdir (fat_itr *itr) +{ +return !!(itr->dent->attr &ATTR_DIR ); +} + +/* +* Helpers: +*/ + +#define TYPE_FILE 0x1 +#define TYPE_DIR 0x2 +#define TYPE_ANY (TYPE_FILE | TYPE_DIR) + +/** +* fat_itr_resolve() - traverse directory structure to resolve the +* requested path. +* +* Traverse directory structure to the requested path. If the specified +* path is to a directory, this will descend into the directory and +* leave it iterator at the start of the directory. If the path is to a +* file, it will leave the iterator in the parent directory with current +* cursor at file's entry in the directory. +* +* @itr: iterator initialized to root +* @path: the requested path +* @type: bitmask of allowable file types +* @return 0 on success or -errno +*/ +static int fat_itr_resolve (fat_itr *itr,const char *path,unsigned type) +{ +const char *next; + +/* chomp any extra leading slashes: */ +while (path[0 ] &&ISDIRDELIM (path[0 ])) + path++; + +/* are we at the end? */ +if (strlen (path) ==0 ) { +if (!(type &TYPE_DIR )) +return -ENOENT ; +return 0 ; + } + +/* find length of next path entry: */ + next = path; +while (next[0 ] && !ISDIRDELIM (next[0 ])) + next++; + +while (fat_itr_next (itr)) { +int match =0 ; + +/* check both long and short name: */ +if (!strncasecmp (path, itr->name, next - path)) + match =1 ; +else if (itr->name != itr->s_name && + !strncasecmp (path, itr->s_name, (next - path))) + match =1 ; + +if (!match) +continue ; + +if (fat_itr_isdir (itr)) { +/* recurse into directory: */ +fat_itr_child (itr, itr); +return fat_itr_resolve (itr, next, type); + }else if (next[0 ]) { +/* +* If next is not empty then we have a case +* like: /path/to/realfile/nonsense +*/ +debug ("bad trailing path: %s\n" , next); +return -ENOENT ; + }else if (!(type &TYPE_FILE )) { +return -ENOTDIR ; + }else { +return 0 ; + } + } + +return -ENOENT ; +} +int do_fat_read (const char *filename,void *buffer,loff_t maxsize,int dols,loff_t *actread) {
Signature · 1 line
2.13.5
PATCH v2 2/8 fs/fat: introduce new director iterators
Quoted 4 lines · Rob Clark
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose
do_fat_read_at()+get_dentfromdir().Signed-off-by Rob Clark <[email protected]>
Quoted 342 lines
--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)fs/fat/fat.c +326
-0@@ -1245,6 +1245,332 @@ exit:return ret; } + +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct { +fsdata *fsdata; +unsigned cursect; +dir_entry *dent; +int remaining;/* remaining dent's in current cluster */ +int last_cluster; +int is_root; + +/* current iterator position values: */ +char l_name[VFAT_MAXLEN_BYTES ]; +char s_name[14 ]; +char *name;/* l_name if there is one, else s_name */ + +u8 block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ; +}fat_itr ; + +static int fat_itr_isdir (fat_itr *itr); + +/** +* fat_itr_root() - initialize an iterator to start at the root +* directory +* +* @itr: iterator to initialize +* @fsdata: filesystem data for the partition +* @return 0 on success, else -errno +*/ +static int fat_itr_root (fat_itr *itr,fsdata *fsdata) +{ +if (get_fs_info (fsdata)) +return -ENXIO ; + + itr->fsdata = fsdata; + itr->cursect = fsdata->rootdir_sect; + itr->dent =NULL ; + itr->remaining =0 ; + itr->last_cluster =0 ; + itr->is_root =1 ; + +return 0 ; +} + +/** +* fat_itr_child() - initialize an iterator to descend into a sub- +* directory +* +* Initializes 'itr' to iterate the contents of the directory at +* the current cursor position of 'parent'. It is an error to +* call this if the current cursor of 'parent' is pointing at a +* regular file. +* +* Note that 'itr' and 'parent' can be the same pointer if you do +* not need to preserve 'parent' after this call, which is useful +* for traversing directory structure to resolve a file/directory. +* +* @itr: iterator to initialize +* @parent: the iterator pointing at a directory entry in the +* parent directory of the directory to iterate +*/ +static void fat_itr_child (fat_itr *itr,fat_itr *parent) +{ +fsdata *mydata = parent->fsdata;/* for silly macros */ +unsigned clustnum =START (parent->dent); + +assert (fat_itr_isdir (parent)); + + itr->fsdata = parent->fsdata; +if (clustnum >0 ) { + itr->cursect = itr->fsdata->data_begin + + (clustnum * itr->fsdata->clust_size); + }else { + itr->cursect = parent->fsdata->rootdir_sect; + } + itr->dent =NULL ; + itr->remaining =0 ; + itr->last_cluster =0 ; + itr->is_root =0 ; +} + +static void *next_cluster (fat_itr *itr) +{ +fsdata *mydata = itr->fsdata;/* for silly macros */ +int ret; + +/* have we reached the end? */ +if (itr->last_cluster) +return NULL ; + +debug ("FAT read(sect=%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n" , + itr->cursect, itr->fsdata->clust_size,DIRENTSPERBLOCK ); + +/* +* NOTE: do_fat_read_at() had complicated logic to deal w/ +* vfat names that span multiple clusters in the fat16 case, +* which get_dentfromdir() probably also needed (and was +* missing). And not entirely sure what fat32 didn't have +* the same issue.. We solve that by only caring about one +* dent at a time and iteratively constructing the vfat long +* name. +*/ + ret =disk_read (itr->cursect, itr->fsdata->clust_size, + itr->block); +if (ret <0 ) { +debug ("Error: reading block\n" ); +return NULL ; + } + +if (itr->is_root && itr->fsdata->fatsize !=32 ) { + itr->cursect++; +if (itr->cursect - itr->fsdata->rootdir_sect >= + itr->fsdata->rootdir_size) { +debug ("cursect: 0x%x\n" , itr->cursect); + itr->last_cluster =1 ; + } + }else { + itr->cursect =get_fatent (itr->fsdata, itr->cursect); +if (CHECK_CLUST (itr->cursect, itr->fsdata->fatsize)) { +debug ("cursect: 0x%x\n" , itr->cursect); + itr->last_cluster =1 ; + } + } + +return itr->block; +} + +static dir_entry *next_dent (fat_itr *itr) +{ +if (itr->remaining ==0 ) { +struct dir_entry *dent =next_cluster (itr); + +/* have we reached the last cluster? */ +if (!dent) +return NULL ; + + itr->remaining = itr->fsdata->sect_size /sizeof (dir_entry) -1 ; + itr->dent = dent; + }else { + itr->remaining--; + itr->dent++; + } + +/* have we reached the last valid entry? */ +if (itr->dent->name[0 ] ==0 ) +return NULL ; + +return itr->dent; +} + +static dir_entry *extract_vfat_name (fat_itr *itr) +{ +struct dir_entry *dent = itr->dent; +int seqn = itr->dent->name[0 ] & ~LAST_LONG_ENTRY_MASK ; +u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum; +int n =0 ; + +while (seqn--) { +char buf[13 ]; +int idx =0 ; + +slot2str ((dir_slot *)dent, buf, &idx); + +/* shift accumulated long-name up and copy new part in: */ +memmove (itr->l_name + idx, itr->l_name, n); +memcpy (itr->l_name, buf, idx); + n += idx; + + dent =next_dent (itr); +if (!dent) +return NULL ; + } + + itr->l_name[n] ='\0' ; + + chksum =mkcksum (dent->name, dent->ext); + +/* checksum mismatch could mean deleted file, etc.. skip it: */ +if (chksum != alias_checksum) { +debug ("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n" , + chksum, alias_checksum, itr->l_name, dent->name, dent->ext); +return NULL ; + } + +return dent; +} + +/** +* fat_itr_next() - step to the next entry in a directory +* +* Must be called once on a new iterator before the cursor is valid. +* +* @itr: the iterator to iterate +* @return boolean, 1 if success or 0 if no more entries in the +* current directory +*/ +static int fat_itr_next (fat_itr *itr) +{ +dir_entry *dent; + + itr->name =NULL ; + +while (1 ) { + dent =next_dent (itr); +if (!dent) +return 0 ; + +if (dent->name[0 ] ==DELETED_FLAG || + dent->name[0 ] == aRING) +continue ; + +if (dent->attr &ATTR_VOLUME ) { +if (vfat_enabled && + (dent->attr &ATTR_VFAT ) ==ATTR_VFAT && + (dent->name[0 ] &LAST_LONG_ENTRY_MASK )) { + dent =extract_vfat_name (itr); +if (!dent) +continue ; + itr->name = itr->l_name; +break ; + }else { +/* Volume label or VFAT entry, skip */ +continue ; + } + } + +break ; + } + +get_name (dent, itr->s_name); +if (!itr->name) + itr->name = itr->s_name; + +return 1 ; +} + +/** +* fat_itr_isdir() - is current cursor position pointing to a directory +* +* @itr: the iterator +* @return true if cursor is at a directory +*/ +static int fat_itr_isdir (fat_itr *itr) +{ +return !!(itr->dent->attr &ATTR_DIR ); +} + +/* +* Helpers: +*/ + +#define TYPE_FILE 0x1 +#define TYPE_DIR 0x2 +#define TYPE_ANY (TYPE_FILE | TYPE_DIR) + +/** +* fat_itr_resolve() - traverse directory structure to resolve the +* requested path. +* +* Traverse directory structure to the requested path. If the specified +* path is to a directory, this will descend into the directory and +* leave it iterator at the start of the directory. If the path is to a +* file, it will leave the iterator in the parent directory with current +* cursor at file's entry in the directory. +* +* @itr: iterator initialized to root +* @path: the requested path +* @type: bitmask of allowable file types +* @return 0 on success or -errno +*/ +static int fat_itr_resolve (fat_itr *itr,const char *path,unsigned type) +{ +const char *next; + +/* chomp any extra leading slashes: */ +while (path[0 ] &&ISDIRDELIM (path[0 ])) + path++; + +/* are we at the end? */ +if (strlen (path) ==0 ) { +if (!(type &TYPE_DIR )) +return -ENOENT ; +return 0 ; + } + +/* find length of next path entry: */ + next = path; +while (next[0 ] && !ISDIRDELIM (next[0 ])) + next++; + +while (fat_itr_next (itr)) { +int match =0 ; + +/* check both long and short name: */ +if (!strncasecmp (path, itr->name, next - path)) + match =1 ; +else if (itr->name != itr->s_name && + !strncasecmp (path, itr->s_name, (next - path))) + match =1 ; + +if (!match) +continue ; + +if (fat_itr_isdir (itr)) { +/* recurse into directory: */ +fat_itr_child (itr, itr); +return fat_itr_resolve (itr, next, type); + }else if (next[0 ]) { +/* +* If next is not empty then we have a case +* like: /path/to/realfile/nonsense +*/ +debug ("bad trailing path: %s\n" , next); +return -ENOENT ; + }else if (!(type &TYPE_FILE )) { +return -ENOTDIR ; + }else { +return 0 ; + } + } + +return -ENOENT ; +} +int do_fat_read (const char *filename,void *buffer,loff_t maxsize,int dols,loff_t *actread) {
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 2/8 fs/fat: introduce new director iterators
In reply to Rob ClarkHi Rob,
Quoted 13 lines · Rob Clark
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose
do_fat_read_at()+get_dentfromdir().Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)fs/fat/fat.c +0
-0
fs/fat/fat.c exit: · line 1253
Quoted 9 lines
fs/fat/fat.c +6
-0@@ -1245,6 +1245,332 @@ exit:return ret; } + +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct {
Please avoid using a typedef here. It seems like it could just be a struct.
Also pleaee add a comment about what the struct is for
fs/fat/fat.c exit: · line 1266
Quoted 13 lines
fs/fat/fat.c +13
-0+fsdata *fsdata; +unsigned cursect; +dir_entry *dent; +int remaining;/* remaining dent's in current cluster */ +int last_cluster; +int is_root; + +/* current iterator position values: */ +char l_name[VFAT_MAXLEN_BYTES ]; +char s_name[14 ]; +char *name;/* l_name if there is one, else s_name */ + +u8 block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ;
Some members are missing comments.
Also I'm not too sure how the alignment works here. I don't see you creating one of these objects in this patch, but could you add a comment to the struct about how to create one? Do you use memalign()?
PATCH v2 2/8 fs/fat: introduce new director iterators
Quoted 19 lines · Simon Glass
Hi Rob,
Quoted 16 lines · Rob Clark
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose
do_fat_read_at()+get_dentfromdir().Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)fs/fat/fat.c +0
-0@@ -1245,6 +1245,332 @@ exit:return ret; }
Quoted 8 lines
fs/fat/fat.c exit: · line 1253
Quoted 6 lines
fs/fat/fat.c +6
-0+ +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct {Please avoid using a typedef here. It seems like it could just be a struct.
I'm typically not a fan of 'typedef struct' but that seems to be the style that fs/fat code was already using, and "when in Rome..."
Quoted 18 lines
Also pleaee add a comment about what the struct is for
fs/fat/fat.c exit: · line 1266
Quoted 13 lines
fs/fat/fat.c +13
-0+fsdata *fsdata; +unsigned cursect; +dir_entry *dent; +int remaining;/* remaining dent's in current cluster */ +int last_cluster; +int is_root; + +/* current iterator position values: */ +char l_name[VFAT_MAXLEN_BYTES ]; +char s_name[14 ]; +char *name;/* l_name if there is one, else s_name */ + +u8 block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ;Some members are missing comments.
Quoted 3 lines
Also I'm not too sure how the alignment works here. I don't see you creating one of these objects in this patch, but could you add a comment to the struct about how to create one? Do you use
memalign()?
I was just creating them on the stack normally.. expecting the compiler to dtrt because of the __aligned() on block[].
BR,
-R
PATCH v2 2/8 fs/fat: introduce new director iterators
Hi Rob,
Quoted 29 lines · Rob Clark
Quoted 19 lines · Simon Glass
Hi Rob,
Quoted 16 lines · Rob Clark
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose
do_fat_read_at()+get_dentfromdir().Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)fs/fat/fat.c +0
-0@@ -1245,6 +1245,332 @@ exit:return ret; }Quoted 8 lines
fs/fat/fat.c exit: · line 1253
Quoted 6 lines
fs/fat/fat.c +6
-0+ +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct {Please avoid using a typedef here. It seems like it could just be a struct.
Quoted 2 lines
I'm typically not a fan of 'typedef struct' but that seems to be the style that fs/fat code was already using, and "when in Rome..."
Sure, but let's move to Venice as it is less dusty.
Quoted 19 lines
Quoted 19 lines
Also pleaee add a comment about what the struct is for
fs/fat/fat.c exit: · line 1266
Quoted 13 lines
fs/fat/fat.c +13
-0+fsdata *fsdata; +unsigned cursect; +dir_entry *dent; +int remaining;/* remaining dent's in current cluster */ +int last_cluster; +int is_root; + +/* current iterator position values: */ +char l_name[VFAT_MAXLEN_BYTES ]; +char s_name[14 ]; +char *name;/* l_name if there is one, else s_name */ + +u8 block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ;Some members are missing comments.
Quoted 6 lines
Quoted 3 lines
Also I'm not too sure how the alignment works here. I don't see you creating one of these objects in this patch, but could you add a comment to the struct about how to create one? Do you use
memalign()?I was just creating them on the stack normally.. expecting the compiler to dtrt because of the
__aligned()on block[].
Well I think that works. OK.
Regards,
Simon
PATCH v2 2/8 fs/fat: introduce new director iterators
Quoted 32 lines · Simon Glass
Hi Rob,
Quoted 29 lines · Rob Clark
Quoted 27 lines · Simon Glass
Hi Rob,
Quoted 13 lines · Rob Clark
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose
do_fat_read_at()+get_dentfromdir().Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+)fs/fat/fat.c +0
-0fs/fat/fat.c exit: · line 1253
Quoted 9 lines
fs/fat/fat.c +6
-0@@ -1245,6 +1245,332 @@ exit:return ret; } + +/* +* Directory iterator, to simplify filesystem traversal +*/ + +typedef struct {Please avoid using a typedef here. It seems like it could just be a struct.
Quoted 5 lines
Quoted 2 lines
I'm typically not a fan of 'typedef struct' but that seems to be the style that fs/fat code was already using, and "when in Rome..."
Sure, but let's move to Venice as it is less dusty.
I'm not a huge fan of mixing styles.. but what I'd propose instead is this:
It turns out fat_write.c needs a lot of work for SCT too (ability to write files in subdirectories, and write files w/ !=0 offset), so that we can actually see the test results.. and before converting write paths to use the new directory iterator, I was considering re-organizing the code a bit, ie. move directory traversal code to fs/fat/dir.c or util.c, move most of include/fat.h into a private header, dropping the #include "fat.c" hack, etc. That would be a good time for flag-day cleanups like untypedef'ifying and perhaps cleaning up all the #define macros that implicitly depend on having a 'mydata' var.
So I'd suggest to leave it as-is for now, and change things to 'struct foo' as part of the re-org.
That leaves FS_DIR in the later readdir patch.. I could change that to 'struct fs_dir_stream'. That makes it not match the posix API it is modelled after as closely, but maybe that is ok.
BR,
-R
PATCH v2 3/8 fat/fs: convert to directory iterators
In reply to Rob ClarkAnd drop a whole lot of ugly code!
--- fs/fat/fat.c | 723 ++++++---------------------------------------------------- include/fat.h | 6 - 2 files changed, 75 insertions(+), 654 deletions(-)
fs/fat/fat.c +75 -648
@@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) }/* -* Get the first occurence of a directory delimiter ('/' or '\') in a string. -* Return index into string if found, -1 otherwise. -*/ -static int dirdelim (char *str) -{ -char *start = str; - -while (*str !='\0' ) { -if (ISDIRDELIM (*str)) -return str - start; - str++; - } -return -1 ; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name (dir_entry *dirent,char *s_name)
@@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)return 0 ; } -/* -* Extract the full long filename starting at 'retdent' (which is really -* a slot) into 'l_name'. If successful also copy the real directory entry -* into 'retdent' -* Return 0 on success, -1 otherwise. -*/ -static int -get_vfatname (fsdata *mydata,int curclust,__u8 *cluster, -dir_entry *retdent,char *l_name) -{ -dir_entry *realdent; -dir_slot *slotptr = (dir_slot *)retdent; -__u8 *buflimit = cluster + mydata->sect_size * ((curclust ==0 ) ? -PREFETCH_BLOCKS : - mydata->clust_size); -__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ; -int idx =0 ; - -if (counter >VFAT_MAXSEQ ) { -debug ("Error: VFAT name is too long\n" ); -return -1 ; - } - -while ((__u8 *)slotptr < buflimit) { -if (counter ==0 ) -break ; -if (((slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ) != counter) -return -1 ; - slotptr++; - counter--; - } - -if ((__u8 *)slotptr >= buflimit) { -dir_slot *slotptr2; - -if (curclust ==0 ) -return -1 ; - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return -1 ; - } - -if (get_cluster (mydata, curclust, get_contents_vfatname_block, - mydata->clust_size * mydata->sect_size) !=0 ) { -debug ("Error: reading directory block\n" ); -return -1 ; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; -while (counter >0 ) { -if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK ) - &0xff ) != counter) -return -1 ; - slotptr2++; - counter--; - } - -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; -while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; -slot2str (slotptr2, l_name, &idx); - } - }else { -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - -do { - slotptr--; -if (slot2str (slotptr, l_name, &idx)) -break ; - }while (!(slotptr->id &LAST_LONG_ENTRY_MASK )); - - l_name[idx] ='\0' ; -if (*l_name ==DELETED_FLAG ) - *l_name ='\0' ; -else if (*l_name == aRING) - *l_name =DELETED_FLAG ; -downcase (l_name); - -/* Return the real directory entry */ -memcpy (retdent, realdent,sizeof (dir_entry)); - -return 0 ; -} -/* Calculate short name checksum */ static __u8 mkcksum (const char name[8 ],const char ext[3 ]) {
@@ -572,170 +467,11 @@ static __u8 mkcksum(const char name[8], const char ext[3])return ret; } -/* -* Get the directory entry associated with 'filename' from the directory -* starting at 'startsect' -*/ +// These should probably DIAF.. __u8 get_dentfromdir_block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ; - -static dir_entry *get_dentfromdir (fsdata *mydata,int startsect, -char *filename,dir_entry *retdent, -int dols) -{ -__u16 prevcksum =0xffff ; -__u32 curclust =START (retdent); -int files =0 , dirs =0 ; - -debug ("get_dentfromdir: %s\n" , filename); - -while (1 ) { -dir_entry *dentptr; - -int i; - -if (get_cluster (mydata, curclust, get_dentfromdir_block, - mydata->clust_size * mydata->sect_size) !=0 ) { -debug ("Error: reading directory block\n" ); -return NULL ; - } - - dentptr = (dir_entry *)get_dentfromdir_block; - -for (i =0 ; i <DIRENTSPERCLUST ; i++) { -char s_name[14 ], l_name[VFAT_MAXLEN_BYTES ]; - - l_name[0 ] ='\0' ; -if (dentptr->name[0 ] ==DELETED_FLAG ) { - dentptr++; -continue ; - } -if ((dentptr->attr &ATTR_VOLUME )) { -if (vfat_enabled && - (dentptr->attr &ATTR_VFAT ) ==ATTR_VFAT && - (dentptr->name[0 ] &LAST_LONG_ENTRY_MASK )) { - prevcksum = ((dir_slot *)dentptr)->alias_checksum; -get_vfatname (mydata, curclust, - get_dentfromdir_block, - dentptr, l_name); -if (dols) { -int isdir; -char dirc; -int doit =0 ; - - isdir = (dentptr->attr &ATTR_DIR ); - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (l_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - l_name, - dirc); - }else { -printf (" %s%c\n" , - l_name, - dirc); - } - } - dentptr++; -continue ; - } -debug ("vfatname: |%s|\n" , l_name); - }else { -/* Volume label or VFAT entry */ - dentptr++; -continue ; - } - } -if (dentptr->name[0 ] ==0 ) { -if (dols) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - } -debug ("Dentname == NULL - %d\n" , i); -return NULL ; - } -if (vfat_enabled) { -__u8 csum =mkcksum (dentptr->name, dentptr->ext); -if (dols && csum == prevcksum) { - prevcksum =0xffff ; - dentptr++; -continue ; - } - } - -get_name (dentptr, s_name); -if (dols) { -int isdir = (dentptr->attr &ATTR_DIR ); -char dirc; -int doit =0 ; - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (s_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } - -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - s_name, dirc); - }else { -printf (" %s%c\n" , - s_name, dirc); - } - } - - dentptr++; -continue ; - } - -if (strcmp (filename, s_name) - &&strcmp (filename, l_name)) { -debug ("Mismatch: |%s|%s|\n" , s_name, l_name); - dentptr++; -continue ; - } - -memcpy (retdent, dentptr,sizeof (dir_entry)); - -debug ("DentName: %s" , s_name); -debug (", start: 0x%x" ,START (dentptr)); -debug (", size: 0x%x %s\n" , -FAT2CPU32 (dentptr->size), - (dentptr->attr &ATTR_DIR ) ?"(DIR)" :"" ); - -return retdent; - } - - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return NULL ; - } - } - -return NULL ; -} +__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] +__aligned(ARCH_DMA_MINALIGN) ;/* * Read boot sector and volume info from a FAT filesystem
@@ -877,374 +613,6 @@ static int get_fs_info(fsdata *mydata)return 0 ; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] -__aligned(ARCH_DMA_MINALIGN) ; - -int do_fat_read_at (const char *filename,loff_t pos,void *buffer, -loff_t maxsize,int dols,int dogetsize,loff_t *size) -{ -char fnamecopy[2048 ]; -fsdata datablock; -fsdata *mydata = &datablock; -dir_entry *dentptr =NULL ; -__u16 prevcksum =0xffff ; -char *subname ="" ; -__u32 cursect; -int idx, isdir =0 ; -int files =0 , dirs =0 ; -int ret =-1 ; -int firsttime; -__u32 root_cluster =0 ; -__u32 read_blk; -int rootdir_size =0 ; -int buffer_blk_cnt; -int do_read; -__u8 *dir_ptr; - -if (get_fs_info (mydata)) -return -1 ; - - cursect = mydata->rootdir_sect; - -/* "cwd" is always the root... */ -while (ISDIRDELIM (*filename)) - filename++; - -/* Make a copy of the filename and convert it to lowercase */ -strcpy (fnamecopy, filename); -downcase (fnamecopy); - -root_reparse: -if (*fnamecopy =='\0' ) { -if (!dols) - goto exit; - - dols =LS_ROOT ; - }else if ((idx =dirdelim (fnamecopy)) >=0 ) { - isdir =1 ; - fnamecopy[idx] ='\0' ; - subname = fnamecopy + idx +1 ; - -/* Handle multiple delimiters */ -while (ISDIRDELIM (*subname)) - subname++; - }else if (dols) { - isdir =1 ; - } - - buffer_blk_cnt =0 ; - firsttime =1 ; -while (1 ) { -int i; - -if (mydata->fatsize ==32 || firsttime) { - dir_ptr = do_fat_read_at_block; - firsttime =0 ; - }else { -/** -* FAT16 sector buffer modification: -* Each loop, the second buffered block is moved to -* the buffer begin, and two next sectors are read -* next to the previously moved one. So the sector -* buffer keeps always 3 sectors for fat16. -* And the current sector is the buffer second sector -* beside the "firsttime" read, when it is the first one. -* -* PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1] -* n = computed root dir sector -* loop | cursect-1 | cursect | cursect+1 | -* 0 | sector n+0 | sector n+1 | none | -* 1 | none | sector n+0 | sector n+1 | -* 0 | sector n+1 | sector n+2 | sector n+3 | -* 1 | sector n+3 | ... -*/ - dir_ptr = (do_fat_read_at_block + mydata->sect_size); -memcpy (do_fat_read_at_block, dir_ptr, mydata->sect_size); - } - - do_read =1 ; - -if (mydata->fatsize ==32 && buffer_blk_cnt) - do_read =0 ; - -if (do_read) { - read_blk = (mydata->fatsize ==32 ) ? - mydata->clust_size :PREFETCH_BLOCKS ; - -debug ("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n" , - cursect, read_blk, mydata->clust_size,DIRENTSPERBLOCK ); - -if (disk_read (cursect, read_blk, dir_ptr) <0 ) { -debug ("Error: reading rootdir block\n" ); - goto exit; - } - - dentptr = (dir_entry *)dir_ptr; - } - -for (i =0 ; i <DIRENTSPERBLOCK ; i++) { -char s_name[14 ], l_name[VFAT_MAXLEN_BYTES ]; -__u8 csum; - - l_name[0 ] ='\0' ; -if (dentptr->name[0 ] ==DELETED_FLAG ) { - dentptr++; -continue ; - } - -if (vfat_enabled) - csum =mkcksum (dentptr->name, dentptr->ext); - -if (dentptr->attr &ATTR_VOLUME ) { -if (vfat_enabled && - (dentptr->attr &ATTR_VFAT ) ==ATTR_VFAT && - (dentptr->name[0 ] &LAST_LONG_ENTRY_MASK )) { - prevcksum = - ((dir_slot *)dentptr)->alias_checksum; - -get_vfatname (mydata, - root_cluster, - dir_ptr, - dentptr, l_name); - -if (dols ==LS_ROOT ) { -char dirc; -int doit =0 ; -int isdir = - (dentptr->attr &ATTR_DIR ); - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (l_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - l_name, - dirc); - }else { -printf (" %s%c\n" , - l_name, - dirc); - } - } - dentptr++; -continue ; - } -debug ("Rootvfatname: |%s|\n" , - l_name); - }else { -/* Volume label or VFAT entry */ - dentptr++; -continue ; - } - }else if (dentptr->name[0 ] ==0 ) { -debug ("RootDentname == NULL - %d\n" , i); -if (dols ==LS_ROOT ) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - ret =0 ; - } - goto exit; - } -else if (vfat_enabled && - dols ==LS_ROOT && csum == prevcksum) { - prevcksum =0xffff ; - dentptr++; -continue ; - } - -get_name (dentptr, s_name); - -if (dols ==LS_ROOT ) { -int isdir = (dentptr->attr &ATTR_DIR ); -char dirc; -int doit =0 ; - -if (isdir) { - dirc ='/' ; -if (s_name[0 ] !=0 ) { - dirs++; - doit =1 ; - } - }else { - dirc =' ' ; -if (s_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - s_name, dirc); - }else { -printf (" %s%c\n" , - s_name, dirc); - } - } - dentptr++; -continue ; - } - -if (strcmp (fnamecopy, s_name) - &&strcmp (fnamecopy, l_name)) { -debug ("RootMismatch: |%s|%s|\n" , s_name, - l_name); - dentptr++; -continue ; - } - -if (isdir && !(dentptr->attr &ATTR_DIR )) - goto exit; - -debug ("RootName: %s" , s_name); -debug (", start: 0x%x" ,START (dentptr)); -debug (", size: 0x%x %s\n" , -FAT2CPU32 (dentptr->size), - isdir ?"(DIR)" :"" ); - - goto rootdir_done;/* We got a match */ - } -debug ("END LOOP: buffer_blk_cnt=%d clust_size=%d\n" , buffer_blk_cnt, - mydata->clust_size); - -/* -* On FAT32 we must fetch the FAT entries for the next -* root directory clusters when a cluster has been -* completely processed. -*/ - ++buffer_blk_cnt; -int rootdir_end =0 ; -if (mydata->fatsize ==32 ) { -if (buffer_blk_cnt == mydata->clust_size) { -int nxtsect =0 ; -int nxt_clust =0 ; - - nxt_clust =get_fatent (mydata, root_cluster); - rootdir_end =CHECK_CLUST (nxt_clust,32 ); - - nxtsect = mydata->data_begin + - (nxt_clust * mydata->clust_size); - - root_cluster = nxt_clust; - - cursect = nxtsect; - buffer_blk_cnt =0 ; - } - }else { -if (buffer_blk_cnt ==PREFETCH_BLOCKS ) - buffer_blk_cnt =0 ; - - rootdir_end = (++cursect - mydata->rootdir_sect >= - rootdir_size); - } - -/* If end of rootdir reached */ -if (rootdir_end) { -if (dols ==LS_ROOT ) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - *size =0 ; - } - goto exit; - } - } -rootdir_done: - - firsttime =1 ; - -while (isdir) { -int startsect = mydata->data_begin - +START (dentptr) * mydata->clust_size; -dir_entry dent; -char *nextname =NULL ; - - dent = *dentptr; - dentptr = &dent; - - idx =dirdelim (subname); - -if (idx >=0 ) { - subname[idx] ='\0' ; - nextname = subname + idx +1 ; -/* Handle multiple delimiters */ -while (ISDIRDELIM (*nextname)) - nextname++; -if (dols && *nextname =='\0' ) - firsttime =0 ; - }else { -if (dols && firsttime) { - firsttime =0 ; - }else { - isdir =0 ; - } - } - -if (get_dentfromdir (mydata, startsect, subname, dentptr, - isdir ?0 : dols) ==NULL ) { -if (dols && !isdir) - *size =0 ; - goto exit; - } - -if (isdir && !(dentptr->attr &ATTR_DIR )) - goto exit; - -/* -* If we are looking for a directory, and found a directory -* type entry, and the entry is for the root directory (as -* denoted by a cluster number of 0), jump back to the start -* of the function, since at least on FAT12/16, the root dir -* lives in a hard-coded location and needs special handling -* to parse, rather than simply following the cluster linked -* list in the FAT, like other directories. -*/ -if (isdir && (dentptr->attr &ATTR_DIR ) && !START (dentptr)) { -/* -* Modify the filename to remove the prefix that gets -* back to the root directory, so the initial root dir -* parsing code can continue from where we are without -* confusion. -*/ -strcpy (fnamecopy, nextname ?:"" ); -/* -* Set up state the same way as the function does when -* first started. This is required for the root dir -* parsing code operates in its expected environment. -*/ - subname ="" ; - cursect = mydata->rootdir_sect; - isdir =0 ; - goto root_reparse; - } - -if (idx >=0 ) - subname = nextname; - } - -if (dogetsize) { - *size =FAT2CPU32 (dentptr->size); - ret =0 ; - }else { - ret =get_contents (mydata, dentptr, pos, buffer, maxsize, size); - } -debug ("Size: %u, got: %llu\n" ,FAT2CPU32 (dentptr->size), *size); - -exit: -free (mydata->fatbuf); -return ret; -} -/* * Directory iterator, to simplify filesystem traversal
@@ -1571,12 +939,6 @@ static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type)return -ENOENT ; } -int do_fat_read (const char *filename,void *buffer,loff_t maxsize,int dols, -loff_t *actread) -{ -return do_fat_read_at (filename,0 , buffer, maxsize, dols,0 , actread); -} -int file_fat_detectfs (void ) {boot_sector bs;
@@ -1641,31 +1003,96 @@ int file_fat_detectfs(void)int file_fat_ls (const char *dir) { -loff_t size; +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int files =0 , dirs =0 ; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, dir,TYPE_DIR ); +if (ret) +return ret; + +while (fat_itr_next (itr)) { +if (fat_itr_isdir (itr)) { +printf (" %s/\n" , itr->name); + dirs++; + }else { +printf (" %8u %s\n" , +FAT2CPU32 (itr->dent->size), + itr->name); + files++; + } + } + +printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); -return do_fat_read (dir,NULL ,0 ,LS_YES , &size); +return 0 ; }int fat_exists (const char *filename) { +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock;int ret; -loff_t size; - ret =do_fat_read_at (filename,0 ,NULL ,0 ,LS_NO ,1 , &size); + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_ANY );return ret ==0 ; }int fat_size (const char *filename,loff_t *size) { -return do_fat_read_at (filename,0 ,NULL ,0 ,LS_NO ,1 , size); +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_FILE ); +if (ret) { +/* +* Directories don't have size, but fs_size() is not +* expected to fail if passed a directory path: +*/ +fat_itr_root (itr, &fsdata); +if (!fat_itr_resolve (itr, filename,TYPE_DIR )) { + *size =0 ; +return 0 ; + } +return ret; + } + + *size =FAT2CPU32 (itr->dent->size); + +return 0 ; }int file_fat_read_at (const char *filename,loff_t pos,void *buffer,loff_t maxsize,loff_t *actread) { +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_FILE ); +if (ret) +return ret; +printf ("reading %s\n" , filename); -return do_fat_read_at (filename, pos, buffer, maxsize,LS_NO ,0 , - actread); +return get_contents (&fsdata, itr->dent, pos, buffer, maxsize, actread); }int file_fat_read (const char *filename,void *buffer,int maxsize)
include/fat.h +0 -6
@@ -58,12 +58,6 @@*/ #define LAST_LONG_ENTRY_MASK 0x40 -/* Flags telling whether we should read a file or list a directory */ -#define LS_NO 0 -#define LS_YES 1 -#define LS_DIR 1 -#define LS_ROOT 2 -#define ISDIRDELIM (c) ((c) == '/' || (c) == '\\')#define FSTYPE_NONE (-1)
Signature · 1 line
2.13.5
PATCH v2 3/8 fat/fs: convert to directory iterators
Quoted 1 line · Rob Clark
And drop a whole lot of ugly code!
+1
Quoted 814 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 723 ++++++---------------------------------------------------- include/fat.h | 6 - 2 files changed, 75 insertions(+), 654 deletions(-)fs/fat/fat.c +75
-648@@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) }/* -* Get the first occurence of a directory delimiter ('/' or '\') in a string. -* Return index into string if found, -1 otherwise. -*/ -static int dirdelim (char *str) -{ -char *start = str; - -while (*str !='\0' ) { -if (ISDIRDELIM (*str)) -return str - start; - str++; - } -return -1 ; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name (dir_entry *dirent,char *s_name)@@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)return 0 ; } -/* -* Extract the full long filename starting at 'retdent' (which is really -* a slot) into 'l_name'. If successful also copy the real directory entry -* into 'retdent' -* Return 0 on success, -1 otherwise. -*/ -static int -get_vfatname (fsdata *mydata,int curclust,__u8 *cluster, -dir_entry *retdent,char *l_name) -{ -dir_entry *realdent; -dir_slot *slotptr = (dir_slot *)retdent; -__u8 *buflimit = cluster + mydata->sect_size * ((curclust ==0 ) ? -PREFETCH_BLOCKS : - mydata->clust_size); -__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ; -int idx =0 ; - -if (counter >VFAT_MAXSEQ ) { -debug ("Error: VFAT name is too long\n" ); -return -1 ; - } - -while ((__u8 *)slotptr < buflimit) { -if (counter ==0 ) -break ; -if (((slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ) != counter) -return -1 ; - slotptr++; - counter--; - } - -if ((__u8 *)slotptr >= buflimit) { -dir_slot *slotptr2; - -if (curclust ==0 ) -return -1 ; - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return -1 ; - } - -if (get_cluster (mydata, curclust, get_contents_vfatname_block, - mydata->clust_size * mydata->sect_size) !=0 ) { -debug ("Error: reading directory block\n" ); -return -1 ; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; -while (counter >0 ) { -if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK ) - &0xff ) != counter) -return -1 ; - slotptr2++; - counter--; - } - -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; -while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; -slot2str (slotptr2, l_name, &idx); - } - }else { -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - -do { - slotptr--; -if (slot2str (slotptr, l_name, &idx)) -break ; - }while (!(slotptr->id &LAST_LONG_ENTRY_MASK )); - - l_name[idx] ='\0' ; -if (*l_name ==DELETED_FLAG ) - *l_name ='\0' ; -else if (*l_name == aRING) - *l_name =DELETED_FLAG ; -downcase (l_name); - -/* Return the real directory entry */ -memcpy (retdent, realdent,sizeof (dir_entry)); - -return 0 ; -} -/* Calculate short name checksum */ static __u8 mkcksum (const char name[8 ],const char ext[3 ]) {@@ -572,170 +467,11 @@ static __u8 mkcksum(const char name[8], const char ext[3])return ret; } -/* -* Get the directory entry associated with 'filename' from the directory -* starting at 'startsect' -*/ +// These should probably DIAF.. __u8 get_dentfromdir_block[MAX_CLUSTSIZE ]__aligned(ARCH_DMA_MINALIGN) ; - -static dir_entry *get_dentfromdir (fsdata *mydata,int startsect, -char *filename,dir_entry *retdent, -int dols) -{ -__u16 prevcksum =0xffff ; -__u32 curclust =START (retdent); -int files =0 , dirs =0 ; - -debug ("get_dentfromdir: %s\n" , filename); - -while (1 ) { -dir_entry *dentptr; - -int i; - -if (get_cluster (mydata, curclust, get_dentfromdir_block, - mydata->clust_size * mydata->sect_size) !=0 ) { -debug ("Error: reading directory block\n" ); -return NULL ; - } - - dentptr = (dir_entry *)get_dentfromdir_block; - -for (i =0 ; i <DIRENTSPERCLUST ; i++) { -char s_name[14 ], l_name[VFAT_MAXLEN_BYTES ]; - - l_name[0 ] ='\0' ; -if (dentptr->name[0 ] ==DELETED_FLAG ) { - dentptr++; -continue ; - } -if ((dentptr->attr &ATTR_VOLUME )) { -if (vfat_enabled && - (dentptr->attr &ATTR_VFAT ) ==ATTR_VFAT && - (dentptr->name[0 ] &LAST_LONG_ENTRY_MASK )) { - prevcksum = ((dir_slot *)dentptr)->alias_checksum; -get_vfatname (mydata, curclust, - get_dentfromdir_block, - dentptr, l_name); -if (dols) { -int isdir; -char dirc; -int doit =0 ; - - isdir = (dentptr->attr &ATTR_DIR ); - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (l_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - l_name, - dirc); - }else { -printf (" %s%c\n" , - l_name, - dirc); - } - } - dentptr++; -continue ; - } -debug ("vfatname: |%s|\n" , l_name); - }else { -/* Volume label or VFAT entry */ - dentptr++; -continue ; - } - } -if (dentptr->name[0 ] ==0 ) { -if (dols) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - } -debug ("Dentname == NULL - %d\n" , i); -return NULL ; - } -if (vfat_enabled) { -__u8 csum =mkcksum (dentptr->name, dentptr->ext); -if (dols && csum == prevcksum) { - prevcksum =0xffff ; - dentptr++; -continue ; - } - } - -get_name (dentptr, s_name); -if (dols) { -int isdir = (dentptr->attr &ATTR_DIR ); -char dirc; -int doit =0 ; - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (s_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } - -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - s_name, dirc); - }else { -printf (" %s%c\n" , - s_name, dirc); - } - } - - dentptr++; -continue ; - } - -if (strcmp (filename, s_name) - &&strcmp (filename, l_name)) { -debug ("Mismatch: |%s|%s|\n" , s_name, l_name); - dentptr++; -continue ; - } - -memcpy (retdent, dentptr,sizeof (dir_entry)); - -debug ("DentName: %s" , s_name); -debug (", start: 0x%x" ,START (dentptr)); -debug (", size: 0x%x %s\n" , -FAT2CPU32 (dentptr->size), - (dentptr->attr &ATTR_DIR ) ?"(DIR)" :"" ); - -return retdent; - } - - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return NULL ; - } - } - -return NULL ; -} +__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] +__aligned(ARCH_DMA_MINALIGN) ;/* * Read boot sector and volume info from a FAT filesystem @@ -877,374 +613,6 @@ static int get_fs_info(fsdata *mydata)return 0 ; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE ] -__aligned(ARCH_DMA_MINALIGN) ; - -int do_fat_read_at (const char *filename,loff_t pos,void *buffer, -loff_t maxsize,int dols,int dogetsize,loff_t *size) -{ -char fnamecopy[2048 ]; -fsdata datablock; -fsdata *mydata = &datablock; -dir_entry *dentptr =NULL ; -__u16 prevcksum =0xffff ; -char *subname ="" ; -__u32 cursect; -int idx, isdir =0 ; -int files =0 , dirs =0 ; -int ret =-1 ; -int firsttime; -__u32 root_cluster =0 ; -__u32 read_blk; -int rootdir_size =0 ; -int buffer_blk_cnt; -int do_read; -__u8 *dir_ptr; - -if (get_fs_info (mydata)) -return -1 ; - - cursect = mydata->rootdir_sect; - -/* "cwd" is always the root... */ -while (ISDIRDELIM (*filename)) - filename++; - -/* Make a copy of the filename and convert it to lowercase */ -strcpy (fnamecopy, filename); -downcase (fnamecopy); - -root_reparse: -if (*fnamecopy =='\0' ) { -if (!dols) - goto exit; - - dols =LS_ROOT ; - }else if ((idx =dirdelim (fnamecopy)) >=0 ) { - isdir =1 ; - fnamecopy[idx] ='\0' ; - subname = fnamecopy + idx +1 ; - -/* Handle multiple delimiters */ -while (ISDIRDELIM (*subname)) - subname++; - }else if (dols) { - isdir =1 ; - } - - buffer_blk_cnt =0 ; - firsttime =1 ; -while (1 ) { -int i; - -if (mydata->fatsize ==32 || firsttime) { - dir_ptr = do_fat_read_at_block; - firsttime =0 ; - }else { -/** -* FAT16 sector buffer modification: -* Each loop, the second buffered block is moved to -* the buffer begin, and two next sectors are read -* next to the previously moved one. So the sector -* buffer keeps always 3 sectors for fat16. -* And the current sector is the buffer second sector -* beside the "firsttime" read, when it is the first one. -* -* PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1] -* n = computed root dir sector -* loop | cursect-1 | cursect | cursect+1 | -* 0 | sector n+0 | sector n+1 | none | -* 1 | none | sector n+0 | sector n+1 | -* 0 | sector n+1 | sector n+2 | sector n+3 | -* 1 | sector n+3 | ... -*/ - dir_ptr = (do_fat_read_at_block + mydata->sect_size); -memcpy (do_fat_read_at_block, dir_ptr, mydata->sect_size); - } - - do_read =1 ; - -if (mydata->fatsize ==32 && buffer_blk_cnt) - do_read =0 ; - -if (do_read) { - read_blk = (mydata->fatsize ==32 ) ? - mydata->clust_size :PREFETCH_BLOCKS ; - -debug ("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n" , - cursect, read_blk, mydata->clust_size,DIRENTSPERBLOCK ); - -if (disk_read (cursect, read_blk, dir_ptr) <0 ) { -debug ("Error: reading rootdir block\n" ); - goto exit; - } - - dentptr = (dir_entry *)dir_ptr; - } - -for (i =0 ; i <DIRENTSPERBLOCK ; i++) { -char s_name[14 ], l_name[VFAT_MAXLEN_BYTES ]; -__u8 csum; - - l_name[0 ] ='\0' ; -if (dentptr->name[0 ] ==DELETED_FLAG ) { - dentptr++; -continue ; - } - -if (vfat_enabled) - csum =mkcksum (dentptr->name, dentptr->ext); - -if (dentptr->attr &ATTR_VOLUME ) { -if (vfat_enabled && - (dentptr->attr &ATTR_VFAT ) ==ATTR_VFAT && - (dentptr->name[0 ] &LAST_LONG_ENTRY_MASK )) { - prevcksum = - ((dir_slot *)dentptr)->alias_checksum; - -get_vfatname (mydata, - root_cluster, - dir_ptr, - dentptr, l_name); - -if (dols ==LS_ROOT ) { -char dirc; -int doit =0 ; -int isdir = - (dentptr->attr &ATTR_DIR ); - -if (isdir) { - dirs++; - dirc ='/' ; - doit =1 ; - }else { - dirc =' ' ; -if (l_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - l_name, - dirc); - }else { -printf (" %s%c\n" , - l_name, - dirc); - } - } - dentptr++; -continue ; - } -debug ("Rootvfatname: |%s|\n" , - l_name); - }else { -/* Volume label or VFAT entry */ - dentptr++; -continue ; - } - }else if (dentptr->name[0 ] ==0 ) { -debug ("RootDentname == NULL - %d\n" , i); -if (dols ==LS_ROOT ) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - ret =0 ; - } - goto exit; - } -else if (vfat_enabled && - dols ==LS_ROOT && csum == prevcksum) { - prevcksum =0xffff ; - dentptr++; -continue ; - } - -get_name (dentptr, s_name); - -if (dols ==LS_ROOT ) { -int isdir = (dentptr->attr &ATTR_DIR ); -char dirc; -int doit =0 ; - -if (isdir) { - dirc ='/' ; -if (s_name[0 ] !=0 ) { - dirs++; - doit =1 ; - } - }else { - dirc =' ' ; -if (s_name[0 ] !=0 ) { - files++; - doit =1 ; - } - } -if (doit) { -if (dirc ==' ' ) { -printf (" %8u %s%c\n" , -FAT2CPU32 (dentptr->size), - s_name, dirc); - }else { -printf (" %s%c\n" , - s_name, dirc); - } - } - dentptr++; -continue ; - } - -if (strcmp (fnamecopy, s_name) - &&strcmp (fnamecopy, l_name)) { -debug ("RootMismatch: |%s|%s|\n" , s_name, - l_name); - dentptr++; -continue ; - } - -if (isdir && !(dentptr->attr &ATTR_DIR )) - goto exit; - -debug ("RootName: %s" , s_name); -debug (", start: 0x%x" ,START (dentptr)); -debug (", size: 0x%x %s\n" , -FAT2CPU32 (dentptr->size), - isdir ?"(DIR)" :"" ); - - goto rootdir_done;/* We got a match */ - } -debug ("END LOOP: buffer_blk_cnt=%d clust_size=%d\n" , buffer_blk_cnt, - mydata->clust_size); - -/* -* On FAT32 we must fetch the FAT entries for the next -* root directory clusters when a cluster has been -* completely processed. -*/ - ++buffer_blk_cnt; -int rootdir_end =0 ; -if (mydata->fatsize ==32 ) { -if (buffer_blk_cnt == mydata->clust_size) { -int nxtsect =0 ; -int nxt_clust =0 ; - - nxt_clust =get_fatent (mydata, root_cluster); - rootdir_end =CHECK_CLUST (nxt_clust,32 ); - - nxtsect = mydata->data_begin + - (nxt_clust * mydata->clust_size); - - root_cluster = nxt_clust; - - cursect = nxtsect; - buffer_blk_cnt =0 ; - } - }else { -if (buffer_blk_cnt ==PREFETCH_BLOCKS ) - buffer_blk_cnt =0 ; - - rootdir_end = (++cursect - mydata->rootdir_sect >= - rootdir_size); - } - -/* If end of rootdir reached */ -if (rootdir_end) { -if (dols ==LS_ROOT ) { -printf ("\n%d file(s), %d dir(s)\n\n" , - files, dirs); - *size =0 ; - } - goto exit; - } - } -rootdir_done: - - firsttime =1 ; - -while (isdir) { -int startsect = mydata->data_begin - +START (dentptr) * mydata->clust_size; -dir_entry dent; -char *nextname =NULL ; - - dent = *dentptr; - dentptr = &dent; - - idx =dirdelim (subname); - -if (idx >=0 ) { - subname[idx] ='\0' ; - nextname = subname + idx +1 ; -/* Handle multiple delimiters */ -while (ISDIRDELIM (*nextname)) - nextname++; -if (dols && *nextname =='\0' ) - firsttime =0 ; - }else { -if (dols && firsttime) { - firsttime =0 ; - }else { - isdir =0 ; - } - } - -if (get_dentfromdir (mydata, startsect, subname, dentptr, - isdir ?0 : dols) ==NULL ) { -if (dols && !isdir) - *size =0 ; - goto exit; - } - -if (isdir && !(dentptr->attr &ATTR_DIR )) - goto exit; - -/* -* If we are looking for a directory, and found a directory -* type entry, and the entry is for the root directory (as -* denoted by a cluster number of 0), jump back to the start -* of the function, since at least on FAT12/16, the root dir -* lives in a hard-coded location and needs special handling -* to parse, rather than simply following the cluster linked -* list in the FAT, like other directories. -*/ -if (isdir && (dentptr->attr &ATTR_DIR ) && !START (dentptr)) { -/* -* Modify the filename to remove the prefix that gets -* back to the root directory, so the initial root dir -* parsing code can continue from where we are without -* confusion. -*/ -strcpy (fnamecopy, nextname ?:"" ); -/* -* Set up state the same way as the function does when -* first started. This is required for the root dir -* parsing code operates in its expected environment. -*/ - subname ="" ; - cursect = mydata->rootdir_sect; - isdir =0 ; - goto root_reparse; - } - -if (idx >=0 ) - subname = nextname; - } - -if (dogetsize) { - *size =FAT2CPU32 (dentptr->size); - ret =0 ; - }else { - ret =get_contents (mydata, dentptr, pos, buffer, maxsize, size); - } -debug ("Size: %u, got: %llu\n" ,FAT2CPU32 (dentptr->size), *size); - -exit: -free (mydata->fatbuf); -return ret; -} -/* * Directory iterator, to simplify filesystem traversal @@ -1571,12 +939,6 @@ static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type)return -ENOENT ; } -int do_fat_read (const char *filename,void *buffer,loff_t maxsize,int dols, -loff_t *actread) -{ -return do_fat_read_at (filename,0 , buffer, maxsize, dols,0 , actread); -} -int file_fat_detectfs (void ) {boot_sector bs;@@ -1641,31 +1003,96 @@ int file_fat_detectfs(void)int file_fat_ls (const char *dir) { -loff_t size; +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int files =0 , dirs =0 ; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, dir,TYPE_DIR ); +if (ret) +return ret; + +while (fat_itr_next (itr)) { +if (fat_itr_isdir (itr)) { +printf (" %s/\n" , itr->name); + dirs++; + }else { +printf (" %8u %s\n" , +FAT2CPU32 (itr->dent->size), + itr->name); + files++; + } + } + +printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); -return do_fat_read (dir,NULL ,0 ,LS_YES , &size); +return 0 ; }int fat_exists (const char *filename) { +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock;int ret; -loff_t size; - ret =do_fat_read_at (filename,0 ,NULL ,0 ,LS_NO ,1 , &size); + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_ANY );return ret ==0 ; }int fat_size (const char *filename,loff_t *size) { -return do_fat_read_at (filename,0 ,NULL ,0 ,LS_NO ,1 , size); +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_FILE ); +if (ret) { +/* +* Directories don't have size, but fs_size() is not +* expected to fail if passed a directory path: +*/ +fat_itr_root (itr, &fsdata); +if (!fat_itr_resolve (itr, filename,TYPE_DIR )) { + *size =0 ; +return 0 ; + } +return ret; + } + + *size =FAT2CPU32 (itr->dent->size); + +return 0 ; }int file_fat_read_at (const char *filename,loff_t pos,void *buffer,loff_t maxsize,loff_t *actread) { +fsdata fsdata; +fat_itr itrblock, *itr = &itrblock; +int ret; + + ret =fat_itr_root (itr, &fsdata); +if (ret) +return ret; + + ret =fat_itr_resolve (itr, filename,TYPE_FILE ); +if (ret) +return ret; +printf ("reading %s\n" , filename); -return do_fat_read_at (filename, pos, buffer, maxsize,LS_NO ,0 , - actread); +return get_contents (&fsdata, itr->dent, pos, buffer, maxsize, actread); }int file_fat_read (const char *filename,void *buffer,int maxsize)include/fat.h +0
-6@@ -58,12 +58,6 @@*/ #define LAST_LONG_ENTRY_MASK 0x40 -/* Flags telling whether we should read a file or list a directory */ -#define LS_NO 0 -#define LS_YES 1 -#define LS_DIR 1 -#define LS_ROOT 2 -#define ISDIRDELIM (c) ((c) == '/' || (c) == '\\')#define FSTYPE_NONE (-1)
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 3/8 fat/fs: convert to directory iterators
Hi Rob,
Quoted 3 lines · Łukasz Majewski
Quoted 2 lines · Rob Clark
And drop a whole lot of ugly code!
:-)
Quoted 146 lines
+1
Reviewed-by Łukasz Majewski <[email protected]>Quoted 138 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 723 ++++++---------------------------------------------------- include/fat.h | 6 - 2 files changed, 75 insertions(+), 654 deletions(-)fs/fat/fat.c +0
-1@@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) }/* -* Get the first occurence of a directory delimiter ('/' or '\') in a string.
- * Return index into string if found, -1 otherwise.
- */fs/fat/fat.c +0
-15-static int dirdelim (char *str) -{ -char *start = str; - -while (*str !='\0' ) { -if (ISDIRDELIM (*str)) -return str - start; - str++; - } -return -1 ; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name (dir_entry *dirent,char *s_name)@@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)return 0 ; } -/* -* Extract the full long filename starting at 'retdent' (which is really -* a slot) into 'l_name'. If successful also copy the real directory entry
- * into 'retdent'
- * Return 0 on success, -1 otherwise.
- */fs/fat/fat.c +0
-9-static int -get_vfatname (fsdata *mydata,int curclust,__u8 *cluster, -dir_entry *retdent,char *l_name) -{ -dir_entry *realdent; -dir_slot *slotptr = (dir_slot *)retdent; - __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? - PREFETCH_BLOCKS : -
mydata->clust_size);fs/fat/fat.c +0
-12-__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ; -int idx =0 ; - -if (counter >VFAT_MAXSEQ ) { -debug ("Error: VFAT name is too long\n" ); -return -1 ; - } - -while ((__u8 *)slotptr < buflimit) { -if (counter ==0 ) -break ; - if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) !=counter)
fs/fat/fat.c +0
-18-return -1 ; - slotptr++; - counter--; - } - -if ((__u8 *)slotptr >= buflimit) { -dir_slot *slotptr2; - -if (curclust ==0 ) -return -1 ; - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return -1 ; - } - - if (get_cluster(mydata, curclust,
get_contents_vfatname_block,
-mydata->clust_size*mydata->sect_size) !=
0) {fs/fat/fat.c +0
-43-debug ("Error: reading directory block\n" ); -return -1 ; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; -while (counter >0 ) { -if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK ) - &0xff ) != counter) -return -1 ; - slotptr2++; - counter--; - } - -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; -while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; -slot2str (slotptr2, l_name, &idx); - } - }else { -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - -do { - slotptr--; -if (slot2str (slotptr, l_name, &idx)) -break ; - }while (!(slotptr->id &LAST_LONG_ENTRY_MASK )); - - l_name[idx] ='\0' ; -if (*l_name ==DELETED_FLAG ) - *l_name ='\0' ; -else if (*l_name == aRING) - *l_name =DELETED_FLAG ; -downcase (l_name); - -/* Return the real directory entry */ -memcpy (retdent, realdent,sizeof (dir_entry)); - -return 0 ; -} -/* Calculate short name checksum */ static __u8 mkcksum (const char name[8 ],const char ext[3 ]) {@@ -572,170 +467,11 @@ static __u8 mkcksum(const char name[8], const char
Quoted 8 lines
fs/fat/fat.c static __u8 mkcksum(const char name[8], const char ext[3]) · line 470
Quoted 8 lines
fs/fat/fat.c +1
-3ext[3])return ret; } -/* -* Get the directory entry associated with 'filename' from the directory -* starting at 'startsect' -*/ +// These should probably DIAF..
Can you use /* ?
Perhaps a TODO here would help - are you suggesting using malloc()?
Did this patch go through patman/checkpatch?
Regards,
Simon
PATCH v2 3/8 fat/fs: convert to directory iterators
Quoted 166 lines · Simon Glass
Hi Rob,
Quoted 3 lines · Łukasz Majewski
Quoted 2 lines · Rob Clark
And drop a whole lot of ugly code!
:-)
Quoted 146 lines
+1
Reviewed-by Łukasz Majewski <[email protected]>Quoted 138 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 723 ++++++---------------------------------------------------- include/fat.h | 6 - 2 files changed, 75 insertions(+), 654 deletions(-)fs/fat/fat.c +0
-1@@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) }/* -* Get the first occurence of a directory delimiter ('/' or '\') in a string.
- * Return index into string if found, -1 otherwise.
- */fs/fat/fat.c +0
-15-static int dirdelim (char *str) -{ -char *start = str; - -while (*str !='\0' ) { -if (ISDIRDELIM (*str)) -return str - start; - str++; - } -return -1 ; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name (dir_entry *dirent,char *s_name)@@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)return 0 ; } -/* -* Extract the full long filename starting at 'retdent' (which is really -* a slot) into 'l_name'. If successful also copy the real directory entry
- * into 'retdent'
- * Return 0 on success, -1 otherwise.
- */fs/fat/fat.c +0
-9-static int -get_vfatname (fsdata *mydata,int curclust,__u8 *cluster, -dir_entry *retdent,char *l_name) -{ -dir_entry *realdent; -dir_slot *slotptr = (dir_slot *)retdent; - __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? - PREFETCH_BLOCKS : -
mydata->clust_size);fs/fat/fat.c +0
-12-__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK ) &0xff ; -int idx =0 ; - -if (counter >VFAT_MAXSEQ ) { -debug ("Error: VFAT name is too long\n" ); -return -1 ; - } - -while ((__u8 *)slotptr < buflimit) { -if (counter ==0 ) -break ; - if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) !=counter)
fs/fat/fat.c +0
-18-return -1 ; - slotptr++; - counter--; - } - -if ((__u8 *)slotptr >= buflimit) { -dir_slot *slotptr2; - -if (curclust ==0 ) -return -1 ; - curclust =get_fatent (mydata, curclust); -if (CHECK_CLUST (curclust, mydata->fatsize)) { -debug ("curclust: 0x%x\n" , curclust); -printf ("Invalid FAT entry\n" ); -return -1 ; - } - - if (get_cluster(mydata, curclust,
get_contents_vfatname_block,
-mydata->clust_size*mydata->sect_size) !=
0) {fs/fat/fat.c +0
-43-debug ("Error: reading directory block\n" ); -return -1 ; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; -while (counter >0 ) { -if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK ) - &0xff ) != counter) -return -1 ; - slotptr2++; - counter--; - } - -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; -while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; -slot2str (slotptr2, l_name, &idx); - } - }else { -/* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - -do { - slotptr--; -if (slot2str (slotptr, l_name, &idx)) -break ; - }while (!(slotptr->id &LAST_LONG_ENTRY_MASK )); - - l_name[idx] ='\0' ; -if (*l_name ==DELETED_FLAG ) - *l_name ='\0' ; -else if (*l_name == aRING) - *l_name =DELETED_FLAG ; -downcase (l_name); - -/* Return the real directory entry */ -memcpy (retdent, realdent,sizeof (dir_entry)); - -return 0 ; -} -/* Calculate short name checksum */ static __u8 mkcksum (const char name[8 ],const char ext[3 ]) {@@ -572,170 +467,11 @@ static __u8 mkcksum(const char name[8], const charQuoted 8 lines
fs/fat/fat.c static __u8 mkcksum(const char name[8], const char ext[3]) · line 470
Quoted 8 lines
fs/fat/fat.c +1
-3ext[3])return ret; } -/* -* Get the directory entry associated with 'filename' from the directory -* starting at 'startsect' -*/ +// These should probably DIAF.. Can you use /* ?
Quoted 1 line
Perhaps a TODO here would help - are you suggesting using
malloc()?
I'll convert to /* TODO .. */
I didn't mean to use malloc, but iirc at least some of this goes away when fat_write.c gets converted to use directory iterators.. I think these are only used directly or indirectly by do_fat_write()..
I may have to tackle fat_write.c in the near future for UEFI SCT test suite (un)fortunately.. might be after next merge-window but I think that TODO can be tackled in the near future.
BR,
-R
Quoted 4 lines
Did this patch go through patman/checkpatch?
Regards,
Simon
PATCH v2 4/8 fs: add fs_readdir()
In reply to Rob ClarkNeeded to support efi file protocol. The fallback.efi loader wants to be able to read the contents of the /EFI directory to find an OS to boot.
Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other fs APIs, this is stateful (ie. state is held in the FS_DIR "directory stream"), to avoid re-traversing of the directory structure at each step. The directory stream must be released with closedir() when it is no longer needed.
--- disk/part.c | 31 ++++++++++++-------- fs/fs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 55 +++++++++++++++++++++++++++++++++++ include/part.h | 4 +++ 4 files changed, 169 insertions(+), 12 deletions(-)
disk/part.c +19 -12
@@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part,return -1 ; } +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info) +{ + info->start =0 ; + info->size = dev_desc->lba; + info->blksz = dev_desc->blksz; + info->bootable =0 ; +strcpy ((char *)info->type,BOOT_PART_TYPE ); +strcpy ((char *)info->name,"Whole Disk" ); +#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) + info->uuid[0 ] =0 ; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0 ] =0 ; +#endif + +return 0 ; +} +int blk_get_device_by_str (const char *ifname,const char *dev_hwpart_str,struct blk_desc **dev_desc) {
@@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, (*dev_desc)->log2blksz =LOG2 ((*dev_desc)->blksz); - info->start =0 ; - info->size = (*dev_desc)->lba; - info->blksz = (*dev_desc)->blksz; - info->bootable =0 ; -strcpy ((char *)info->type,BOOT_PART_TYPE ); -strcpy ((char *)info->name,"Whole Disk" ); -#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) - info->uuid[0 ] =0 ; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID - info->type_guid[0 ] =0 ; -#endif +part_get_info_whole_disk (*dev_desc, info); ret =0 ; goto cleanup;
fs/fs.c +91 -0
151 lines not on this page · raw message
include/fs.h +55 -0
67 lines not on this page · raw message
include/part.h +4 -0
@@ -98,6 +98,7 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);/* disk/part.c */ int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info); +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info);void part_print (struct blk_desc *dev_desc);void part_init (struct blk_desc *dev_desc);void dev_print (struct blk_desc *dev_desc);
@@ -203,6 +204,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }static inline int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info) {return -1 ; } +static inline int part_get_info_whole_disk (struct blk_desc *dev_desc, +disk_partition_t *info) +{return -1 ; }static inline void part_print (struct blk_desc *dev_desc) {}static inline void part_init (struct blk_desc *dev_desc) {}static inline void dev_print (struct blk_desc *dev_desc) {}
Signature · 1 line
2.13.5
PATCH v2 4/8 fs: add fs_readdir()
Quoted 10 lines · Rob Clark
Needed to support efi file protocol. The fallback.efi loader wants to be able to read the contents of the /EFI directory to find an OS to boot.
Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other fs APIs, this is stateful (ie. state is held in the
FS_DIR"directory stream"), to avoid re-traversing of the directory structure at each step. The directory stream must be released withclosedir()when it is no longer needed.
Quoted 318 lines
Signed-off-by Rob Clark <[email protected]>--- disk/part.c | 31 ++++++++++++-------- fs/fs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 55 +++++++++++++++++++++++++++++++++++ include/part.h | 4 +++ 4 files changed, 169 insertions(+), 12 deletions(-)disk/part.c +19
-12@@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part,return -1 ; } +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info) +{ + info->start =0 ; + info->size = dev_desc->lba; + info->blksz = dev_desc->blksz; + info->bootable =0 ; +strcpy ((char *)info->type,BOOT_PART_TYPE ); +strcpy ((char *)info->name,"Whole Disk" ); +#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) + info->uuid[0 ] =0 ; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0 ] =0 ; +#endif + +return 0 ; +} +int blk_get_device_by_str (const char *ifname,const char *dev_hwpart_str,struct blk_desc **dev_desc) {@@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, (*dev_desc)->log2blksz =LOG2 ((*dev_desc)->blksz); - info->start =0 ; - info->size = (*dev_desc)->lba; - info->blksz = (*dev_desc)->blksz; - info->bootable =0 ; -strcpy ((char *)info->type,BOOT_PART_TYPE ); -strcpy ((char *)info->name,"Whole Disk" ); -#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) - info->uuid[0 ] =0 ; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID - info->type_guid[0 ] =0 ; -#endif +part_get_info_whole_disk (*dev_desc, info); ret =0 ; goto cleanup;fs/fs.c +91
-0@@ -21,6 +21,7 @@DECLARE_GLOBAL_DATA_PTR ;static struct blk_desc *fs_dev_desc; +static int fs_dev_part;static disk_partition_t fs_partition;static int fs_type =FS_TYPE_ANY ;@@ -69,6 +70,11 @@ static inline int fs_uuid_unsupported(char *uuid_str)return -1 ; } +static inline int fs_opendir_unsupported (const char *filename,FS_DIR **dirp) +{ +return -EACCES ; +} +struct fstype_info {int fstype;char *name;@@ -92,6 +98,9 @@ struct fstype_info { loff_t len, loff_t *actwrite);void (*close)(void );int (*uuid)(char *uuid_str); +int (*opendir)(const char *filename,FS_DIR **dirp); +int (*readdir)(FS_DIR *dirp); +void (*closedir)(FS_DIR *dirp); };static struct fstype_info fstypes[] = {@@ -112,6 +121,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_FS_EXT4 @@ -131,6 +141,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_SANDBOX @@ -146,6 +157,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_sandbox, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_CMD_UBIFS @@ -161,6 +173,7 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif {@@ -175,6 +188,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, };@@ -228,6 +242,31 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)if (!info->probe (fs_dev_desc, &fs_partition)) { fs_type = info->fstype; + fs_dev_part = part; +return 0 ; + } + } + +return -1 ; +} + +/* set current blk device w/ blk_desc + partition # */ +int fs_set_blk_dev2 (struct blk_desc *desc,int part) +{ +struct fstype_info *info; +int ret, i; + +if (part >=1 ) + ret =part_get_info (desc, part, &fs_partition); +else + ret =part_get_info_whole_disk (desc, &fs_partition); +if (ret) +return ret; + fs_dev_desc = desc; + +for (i =0 , info = fstypes; i <ARRAY_SIZE (fstypes); i++, info++) { +if (!info->probe (fs_dev_desc, &fs_partition)) { + fs_type = info->fstype;return 0 ; } }@@ -334,6 +373,58 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,return ret; } +FS_DIR *fs_opendir (const char *filename) +{ +struct fstype_info *info =fs_get_info (fs_type); +FS_DIR *dirp =NULL ; +int ret; + + ret = info->opendir (filename, &dirp); +fs_close (); +if (ret) { + errno = -ret; +return NULL ; + } + + dirp->desc = fs_dev_desc; + dirp->part = fs_dev_part; + +return dirp; +} + +struct fs_dirent *fs_readdir (FS_DIR *dirp) +{ +struct fstype_info *info; +int ret; + +fs_set_blk_dev2 (dirp->desc, dirp->part); + info =fs_get_info (fs_type); + +memset (&dirp->dirent,0 ,sizeof (dirp->dirent)); + + ret = info->readdir (dirp); +fs_close (); +if (ret) +return NULL ; + +return &dirp->dirent;; +} + +void fs_closedir (FS_DIR *dirp) +{ +struct fstype_info *info; + +if (!dirp) +return ; + +fs_set_blk_dev2 (dirp->desc, dirp->part); + info =fs_get_info (fs_type); + + info->closedir (dirp); +fs_close (); +} + +int do_size (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[],int fstype) {include/fs.h +55
-0@@ -26,6 +26,8 @@*/ int fs_set_blk_dev (const char *ifname,const char *dev_part_str,int fstype); +int fs_set_blk_dev2 (struct blk_desc *desc,int part); +/* * Print the list of files on the partition previously set by fs_set_blk_dev(), * in directory "dirname". @@ -78,6 +80,59 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,int fs_write (const char *filename,ulong addr,loff_t offset,loff_t len,loff_t *actwrite); +/* Add additional FS_DT_* as supported by additional filesystems:*/ +#define FS_DT_DIR 0x4/* directory */ +#define FS_DT_REG 0x8/* regular file */ + +/* +* A directory entry. +*/ +struct fs_dirent { +unsigned type;/* one of FS_DT_* */ +loff_t size; +char name[256 ]; +}; + +typedef struct _FS_DIR FS_DIR ; + +/* +* fs_opendir - Open a directory +* +* @filename: the path to directory to open +* @return a pointer to the directory stream or NULL on error and errno +* set appropriately +*/ +FS_DIR *fs_opendir (const char *filename); + +/* +* fs_readdir - Read the next directory entry in the directory stream. +* +* @dirp: the directory stream +* @return the next directory entry (only valid until next fs_readdir() or +* fs_closedir() call, do not attempt to free()) or NULL if the end of +* the directory is reached. +*/ +struct fs_dirent *fs_readdir (FS_DIR *dirp); + +/* +* fs_closedir - close a directory stream +* +* @dirp: the directory stream +*/ +void fs_closedir (FS_DIR *dirp); + +/* +* private to fs implementations, would be in fs.c but we need to let +* implementations subclass: +*/ + +struct _FS_DIR { +struct fs_dirent dirent; +/* private to fs layer: */ +struct blk_desc *desc; +int part; +}; +/* * Common implementation for various filesystem commands, optionally limited * to a specific filesystem type via the fstype parameter. include/part.h +4
-0@@ -98,6 +98,7 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);/* disk/part.c */ int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info); +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info);void part_print (struct blk_desc *dev_desc);void part_init (struct blk_desc *dev_desc);void dev_print (struct blk_desc *dev_desc);@@ -203,6 +204,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }static inline int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info) {return -1 ; } +static inline int part_get_info_whole_disk (struct blk_desc *dev_desc, +disk_partition_t *info) +{return -1 ; }static inline void part_print (struct blk_desc *dev_desc) {}static inline void part_init (struct blk_desc *dev_desc) {}static inline void dev_print (struct blk_desc *dev_desc) {}
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 4/8 fs: add fs_readdir()
Hi Rob,
Quoted 35 lines · Łukasz Majewski
Quoted 11 lines · Rob Clark
Needed to support efi file protocol. The fallback.efi loader wants to be able to read the contents of the /EFI directory to find an OS to boot.
Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other fs APIs, this is stateful (ie. state is held in the
FS_DIR"directory stream"), to avoid re-traversing of the directory structure at each step. The directory stream must be released withclosedir()when it is no longer needed.Reviewed-by Łukasz Majewski <[email protected]>Quoted 19 lines
Signed-off-by Rob Clark <[email protected]>--- disk/part.c | 31 ++++++++++++-------- fs/fs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 55 +++++++++++++++++++++++++++++++++++ include/part.h | 4 +++ 4 files changed, 169 insertions(+), 12 deletions(-)disk/part.c +0
-0@@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part, return -1 ; } +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info)
Quoted 8 lines
disk/part.c int part_get_info(struct blk_desc *dev_desc, int part, · line 342
Quoted 8 lines
disk/part.c +8
-0+{ + info->start =0 ; + info->size = dev_desc->lba; + info->blksz = dev_desc->blksz; + info->bootable =0 ; +strcpy ((char *)info->type,BOOT_PART_TYPE ); +strcpy ((char *)info->name,"Whole Disk" ); +#if CONFIG_IS_ENABLED (PARTITION_UUIDS )
Can you use if() instead of #if for this one? And below. It helps to reduce the number of code paths at build-time.
Quoted 3 lines
disk/part.c int part_get_info(struct blk_desc *dev_desc, int part, · line 345
Quoted 3 lines
disk/part.c +3
-0+ info->uuid[0 ] =0 ; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID
Here too. And below.
Quoted 49 lines
Quoted 49 lines
disk/part.c +6
-0+ info->type_guid[0 ] =0 ; +#endif + +return 0 ; +} + int blk_get_device_by_str(const char *ifname, const char
*dev_hwpart_str,
structblk_desc**dev_desc)
{disk/part.c +1
-11@@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, constchar *dev_part_str, (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); - info->start =0 ; - info->size = (*dev_desc)->lba; - info->blksz = (*dev_desc)->blksz; - info->bootable =0 ; -strcpy ((char *)info->type,BOOT_PART_TYPE ); -strcpy ((char *)info->name,"Whole Disk" ); -#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) - info->uuid[0 ] =0 ; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID - info->type_guid[0 ] =0 ; -#endif +part_get_info_whole_disk (*dev_desc, info); ret =0 ; goto cleanup;fs/fs.c +1
-0@@ -21,6 +21,7 @@DECLARE_GLOBAL_DATA_PTR ;static struct blk_desc *fs_dev_desc; +static int fs_dev_part;static disk_partition_t fs_partition;static int fs_type =FS_TYPE_ANY ; @@ -69,6 +70,11 @@ static inline int fs_uuid_unsupported(char *uuid_str) return -1;}
+static inline int fs_opendir_unsupported(const char *filename,FS_DIR
**dirp)fs/fs.c +4
-0+{ +return -EACCES ; +} +struct fstype_info {int fstype;
Quoted 8 lines
fs/fs.c struct fstype_info { · line 103
Quoted 8 lines
char *name;fs/fs.c +3
-0@@ -92,6 +98,9 @@ struct fstype_info { loff_t len, loff_t *actwrite);void (*close)(void );int (*uuid)(char *uuid_str); +int (*opendir)(const char *filename,FS_DIR **dirp); +int (*readdir)(FS_DIR *dirp); +void (*closedir)(FS_DIR *dirp);
Please comment these. Also can you use struct instead of typedef?
Quoted 47 lines
Quoted 47 lines
fs/fs.c +5
-0};static struct fstype_info fstypes[] = {@@ -112,6 +121,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_FS_EXT4 @@ -131,6 +141,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_SANDBOX @@ -146,6 +157,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_sandbox, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_CMD_UBIFS @@ -161,6 +173,7 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif {@@ -175,6 +188,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, }; @@ -228,6 +242,31 @@ int fs_set_blk_dev(const char *ifname, const char
*dev_part_str, int fstype)if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype;fs/fs.c +2
-0+ fs_dev_part = part; +return 0 ;
Quoted 8 lines
fs/fs.c int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) · line 254
Quoted 8 lines
fs/fs.c +8
-0+ } + } + +return -1 ; +} + +/* set current blk device w/ blk_desc + partition # */ +int fs_set_blk_dev2 (struct blk_desc *desc,int part)
Please add a full function comment in the header file. See fs_set_blk() which has a comment.
Also '2' is a bad name. How about a _with_part suffix, or something like that?
[...]
Quoted 9 lines
include/fs.h line 29
Quoted 9 lines
include/fs.h +0
-0@@ -26,6 +26,8 @@*/ int fs_set_blk_dev (const char *ifname,const char *dev_part_str,int fstype); +int fs_set_blk_dev2(struct blk_desc *desc, int part);
Comment goes above this.
Quoted 11 lines
Quoted 11 lines
include/fs.h +1
-0+/* * Print the list of files on the partition previously set by
fs_set_blk_dev(),
* in directory "dirname".include/fs.h +0
-0@@ -78,6 +80,59 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,loff_t *actwrite); +/* Add additional FS_DT_* as supported by additional filesystems:*/
Quoted 8 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 91
Quoted 8 lines
include/fs.h +8
-0+#define FS_DT_DIR 0x4/* directory */ +#define FS_DT_REG 0x8/* regular file */ + +/* +* A directory entry. +*/ +struct fs_dirent { +unsigned type;/* one of FS_DT_* */
Is that a mask (so both can be set) or something else? If it is a mask please say so.
Quoted 1 line
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 92
Quoted 1 line
include/fs.h +1
-0+loff_t size;
comment for this. Is it size of the file in bytes?
Quoted 5 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 97
Quoted 5 lines
include/fs.h +5
-0+char name[256 ]; +}; + +typedef struct _FS_DIR FS_DIR ; +
Please drop the typedef as it doesn't seem necessary
Quoted 25 lines
Quoted 25 lines
include/fs.h +14
-0+/* +* fs_opendir - Open a directory +* +* @filename: the path to directory to open +* @return a pointer to the directory stream or NULL on error and errno +* set appropriately +*/ +FS_DIR *fs_opendir (const char *filename); + +/* +* fs_readdir - Read the next directory entry in the directory stream. +* +* @dirp: the directory stream +* @return the next directory entry (only valid until next fs_readdir() or
+ *fs_closedir()call, do not attempt tofree()) or NULL if the end of
+ * the directory is reached.
+ */include/fs.h +7
-0+struct fs_dirent *fs_readdir (FS_DIR *dirp); + +/* +* fs_closedir - close a directory stream +* +* @dirp: the directory stream +*/
Quoted 8 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 129
Quoted 8 lines
include/fs.h +8
-0+void fs_closedir (FS_DIR *dirp); + +/* +* private to fs implementations, would be in fs.c but we need to let +* implementations subclass: +*/ + +struct _FS_DIR {
Lower case for struct names. Also please add struct member comments.
Quoted 13 lines
Quoted 13 lines
include/fs.h +6
-0+struct fs_dirent dirent; +/* private to fs layer: */ +struct blk_desc *desc; +int part; +}; +/* * Common implementation for various filesystem commands, optionally limited
* to a specific filesystem type via the fstype parameter.include/part.h +0
-1--- a/include/part.h
Quoted 8 lines
include/part.h int host_get_dev_err(int dev, struct blk_desc · line 103
Quoted 8 lines
+++
b/include/part.hinclude/part.h +1
-0@@ -98,6 +98,7 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);/* disk/part.c */ int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info); +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info);
Please fully comment new functions here.
Quoted 6 lines
Quoted 6 lines
include/part.h +0
-0void part_print (struct blk_desc *dev_desc);void part_init(struct blk_desc *dev_desc); void dev_print(struct blk_desc *dev_desc);include/part.h +0
-0@@ -203,6 +204,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } static inline int part_get_info(struct blk_desc *dev_desc, int part,
Quoted 8 lines
include/part.h static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } · line 212
Quoted 8 lines
include/part.h +3
-0disk_partition_t *info) { return -1; } +static inline int part_get_info_whole_disk (struct blk_desc *dev_desc, +disk_partition_t *info) +{return -1 ; }static inline void part_print (struct blk_desc *dev_desc) {}static inline void part_init (struct blk_desc *dev_desc) {}static inline void dev_print (struct blk_desc *dev_desc) {}
Regards,
Simon
PATCH v2 4/8 fs: add fs_readdir()
Quoted 41 lines · Simon Glass
Hi Rob,
Quoted 38 lines · Łukasz Majewski
Quoted 11 lines · Rob Clark
Needed to support efi file protocol. The fallback.efi loader wants to be able to read the contents of the /EFI directory to find an OS to boot.
Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other fs APIs, this is stateful (ie. state is held in the
FS_DIR"directory stream"), to avoid re-traversing of the directory structure at each step. The directory stream must be released withclosedir()when it is no longer needed.Reviewed-by Łukasz Majewski <[email protected]>Quoted 22 lines
Signed-off-by Rob Clark <[email protected]>--- disk/part.c | 31 ++++++++++++-------- fs/fs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 55 +++++++++++++++++++++++++++++++++++ include/part.h | 4 +++ 4 files changed, 169 insertions(+), 12 deletions(-)disk/part.c +3
-0@@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part, return -1 ; } +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) +{ + info->start = 0; + info->size = dev_desc->lba;
Quoted 8 lines
Quoted 5 lines
disk/part.c int part_get_info(struct blk_desc *dev_desc, int part, · line 342
Quoted 5 lines
disk/part.c +5
-0+ info->blksz = dev_desc->blksz; + info->bootable =0 ; +strcpy ((char *)info->type,BOOT_PART_TYPE ); +strcpy ((char *)info->name,"Whole Disk" ); +#if CONFIG_IS_ENABLED (PARTITION_UUIDS )Can you use
if()instead of #if for this one? And below. It helps to reduce the number of code paths at build-time.
I don't think so, at least not without dropping the corresponding #ifdef in disk_partition_t
Quoted 5 lines
Quoted 3 lines
disk/part.c int part_get_info(struct blk_desc *dev_desc, int part, · line 345
Quoted 3 lines
disk/part.c +3
-0+ info->uuid[0 ] =0 ; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID Here too. And below.
same thing
Quoted 51 lines
Quoted 51 lines
Quoted 51 lines
disk/part.c +6
-0+ info->type_guid[0 ] =0 ; +#endif + +return 0 ; +} + int blk_get_device_by_str(const char *ifname, const char
*dev_hwpart_str,
structblk_desc**dev_desc)
{disk/part.c +1
-11@@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, constchar *dev_part_str, (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); - info->start =0 ; - info->size = (*dev_desc)->lba; - info->blksz = (*dev_desc)->blksz; - info->bootable =0 ; -strcpy ((char *)info->type,BOOT_PART_TYPE ); -strcpy ((char *)info->name,"Whole Disk" ); -#if CONFIG_IS_ENABLED (PARTITION_UUIDS ) - info->uuid[0 ] =0 ; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID - info->type_guid[0 ] =0 ; -#endif +part_get_info_whole_disk (*dev_desc, info); ret =0 ; goto cleanup;fs/fs.c +1
-0@@ -21,6 +21,7 @@DECLARE_GLOBAL_DATA_PTR ;static struct blk_desc *fs_dev_desc; +static int fs_dev_part;static disk_partition_t fs_partition;static int fs_type =FS_TYPE_ANY ; @@ -69,6 +70,11 @@ static inline int fs_uuid_unsupported(char *uuid_str) return -1;}
+static inline int fs_opendir_unsupported(const char *filename,FS_DIR
**dirp)fs/fs.c +4
-0+{ +return -EACCES ; +} +struct fstype_info {int fstype;char *name;@@ -92,6 +98,9 @@ struct fstype_info {
Quoted 8 lines
Quoted 6 lines
fs/fs.c struct fstype_info { · line 103
Quoted 6 lines
fs/fs.c +3
-0loff_t len, loff_t *actwrite);void (*close)(void );int (*uuid)(char *uuid_str); +int (*opendir)(const char *filename,FS_DIR **dirp); +int (*readdir)(FS_DIR *dirp); +void (*closedir)(FS_DIR *dirp);Please comment these. Also can you use struct instead of typedef?
typedef-struct-caps here was based on how posix readdir() works. I guess we can deviate, it isn't 100% clone of readdir().. but I figured it was more clear to be more similar to posix.
Quoted 59 lines
Quoted 47 lines
Quoted 47 lines
fs/fs.c +5
-0};static struct fstype_info fstypes[] = {@@ -112,6 +121,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_FS_EXT4 @@ -131,6 +141,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_SANDBOX @@ -146,6 +157,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_sandbox, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif #ifdef CONFIG_CMD_UBIFS @@ -161,6 +173,7 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, },#endif {@@ -175,6 +188,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, }; @@ -228,6 +242,31 @@ int fs_set_blk_dev(const char *ifname, const char
*dev_part_str, int fstype)if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype;fs/fs.c +2
-0+ fs_dev_part = part; +return 0 ;Quoted 8 lines
fs/fs.c int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) · line 254
Quoted 8 lines
fs/fs.c +8
-0+ } + } + +return -1 ; +} + +/* set current blk device w/ blk_desc + partition # */ +int fs_set_blk_dev2 (struct blk_desc *desc,int part)Please add a full function comment in the header file. See
fs_set_blk()which has a comment.
Quoted 1 line
Also '2' is a bad name. How about a
_with_partsuffix, or something like that?
yeah, "2" was me running out of creativity.. _with_part sounds reasonable.
Quoted 28 lines
[...]
Quoted 9 lines
include/fs.h line 29
Quoted 9 lines
include/fs.h +0
-0@@ -26,6 +26,8 @@*/ int fs_set_blk_dev (const char *ifname,const char *dev_part_str,int fstype); +int fs_set_blk_dev2(struct blk_desc *desc, int part);Comment goes above this.
Quoted 14 lines
Quoted 14 lines
include/fs.h +1
-0+/* * Print the list of files on the partition previously set by
fs_set_blk_dev(),
* in directory "dirname".include/fs.h +3
-0@@ -78,6 +80,59 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,loff_t *actwrite); +/* Add additional FS_DT_* as supported by additional filesystems:*/ +#define FS_DT_DIR 0x4/* directory */ +#define FS_DT_REG 0x8/* regular file */ +
Quoted 8 lines
Quoted 5 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 91
Quoted 5 lines
include/fs.h +5
-0+/* +* A directory entry. +*/ +struct fs_dirent { +unsigned type;/* one of FS_DT_* */ Is that a mask (so both can be set) or something else? If it is a mask please say so.
It is not a mask, despite how the corresponding readdir() DT_* are defined. They match DT_* constants, or rather the subset of them that make sense (ie. we don't have pipes or sockets.. maybe at some point when someone implements this for ext4 it would be worth adding FS_DT_LNK for symlinks)
BR,
-R
Quoted 89 lines
Quoted 1 line
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 92
Quoted 1 line
include/fs.h +1
-0+loff_t size;comment for this. Is it size of the file in bytes?
Quoted 5 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 97
Quoted 5 lines
include/fs.h +5
-0+char name[256 ]; +}; + +typedef struct _FS_DIR FS_DIR ; +Please drop the typedef as it doesn't seem necessary
Quoted 25 lines
Quoted 25 lines
include/fs.h +14
-0+/* +* fs_opendir - Open a directory +* +* @filename: the path to directory to open +* @return a pointer to the directory stream or NULL on error and errno +* set appropriately +*/ +FS_DIR *fs_opendir (const char *filename); + +/* +* fs_readdir - Read the next directory entry in the directory stream. +* +* @dirp: the directory stream +* @return the next directory entry (only valid until next fs_readdir() or
+ *fs_closedir()call, do not attempt tofree()) or NULL if the end of
+ * the directory is reached.
+ */include/fs.h +7
-0+struct fs_dirent *fs_readdir (FS_DIR *dirp); + +/* +* fs_closedir - close a directory stream +* +* @dirp: the directory stream +*/ Quoted 8 lines
include/fs.h int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, · line 129
Quoted 8 lines
include/fs.h +8
-0+void fs_closedir (FS_DIR *dirp); + +/* +* private to fs implementations, would be in fs.c but we need to let +* implementations subclass: +*/ + +struct _FS_DIR {Lower case for struct names. Also please add struct member comments.
Quoted 13 lines
Quoted 13 lines
include/fs.h +6
-0+struct fs_dirent dirent; +/* private to fs layer: */ +struct blk_desc *desc; +int part; +}; +/* * Common implementation for various filesystem commands, optionally limited
* to a specific filesystem type via the fstype parameter.include/part.h +0
-1--- a/include/part.hQuoted 8 lines
include/part.h int host_get_dev_err(int dev, struct blk_desc · line 103
Quoted 8 lines
+++
b/include/part.hinclude/part.h +1
-0@@ -98,6 +98,7 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);/* disk/part.c */ int part_get_info (struct blk_desc *dev_desc,int part,disk_partition_t *info); +int part_get_info_whole_disk (struct blk_desc *dev_desc,disk_partition_t *info);Please fully comment new functions here.
Quoted 6 lines
Quoted 6 lines
include/part.h +0
-0void part_print (struct blk_desc *dev_desc);void part_init(struct blk_desc *dev_desc); void dev_print(struct blk_desc *dev_desc);include/part.h +0
-0@@ -203,6 +204,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } static inline int part_get_info(struct blk_desc *dev_desc, int part,Quoted 8 lines
include/part.h static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } · line 212
Quoted 8 lines
include/part.h +3
-0disk_partition_t *info) { return -1; } +static inline int part_get_info_whole_disk (struct blk_desc *dev_desc, +disk_partition_t *info) +{return -1 ; }static inline void part_print (struct blk_desc *dev_desc) {}static inline void part_init (struct blk_desc *dev_desc) {}static inline void dev_print (struct blk_desc *dev_desc) {}Regards,
Simon
PATCH v2 5/8 fs/fat: implement opendir/readdir/closedir
In reply to Rob ClarkImplement the readdir interface using the directory iterators.
--- fs/fat/fat.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
fs/fat/fat.c +56 -0
@@ -14,6 +14,7 @@#include <config.h> #include <exports.h> #include <fat.h> +#include <fs.h> #include <asm/byteorder.h> #include <part.h> #include <malloc.h>
@@ -1119,6 +1120,61 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,return ret; } +typedef struct { +FS_DIR parent; +fsdata fsdata; +fat_itr itr; +}fat_dir ; + +int fat_opendir (const char *filename,FS_DIR **dirp) +{ +fat_dir *dir =malloc (sizeof (*dir)); +int ret; + +if (!dir) +return -ENOMEM ; + + ret =fat_itr_root (&dir->itr, &dir->fsdata); +if (ret) + goto fail; + + ret =fat_itr_resolve (&dir->itr, filename,TYPE_DIR ); +if (ret) + goto fail; + + *dirp = (FS_DIR *)dir; +return 0 ; + +fail: +free (dir); +return ret; +} + +int fat_readdir (FS_DIR *dirp) +{ +fat_dir *dir = (fat_dir *)dirp; +struct fs_dirent *dent = &dirp->dirent; + +if (!fat_itr_next (&dir->itr)) +return -ENOENT ; + +strcpy (dent->name, dir->itr.name); +if (fat_itr_isdir (&dir->itr)) { + dent->type =FS_DT_DIR ; + }else { + dent->type =FS_DT_REG ; + dent->size =FAT2CPU32 (dir->itr.dent->size); + } + +return 0 ; +} + +void fat_closedir (FS_DIR *dirp) +{ +fat_dir *dir = (fat_dir *)dirp; +free (dir); +} +void fat_close (void ) { }
Signature · 1 line
2.13.5
PATCH v2 5/8 fs/fat: implement opendir/readdir/closedir
Quoted 2 lines · Rob Clark
Implement the readdir interface using the directory iterators.
Quoted 80 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)fs/fat/fat.c +56
-0@@ -14,6 +14,7 @@#include <config.h> #include <exports.h> #include <fat.h> +#include <fs.h> #include <asm/byteorder.h> #include <part.h> #include <malloc.h> @@ -1119,6 +1120,61 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,return ret; } +typedef struct { +FS_DIR parent; +fsdata fsdata; +fat_itr itr; +}fat_dir ; + +int fat_opendir (const char *filename,FS_DIR **dirp) +{ +fat_dir *dir =malloc (sizeof (*dir)); +int ret; + +if (!dir) +return -ENOMEM ; + + ret =fat_itr_root (&dir->itr, &dir->fsdata); +if (ret) + goto fail; + + ret =fat_itr_resolve (&dir->itr, filename,TYPE_DIR ); +if (ret) + goto fail; + + *dirp = (FS_DIR *)dir; +return 0 ; + +fail: +free (dir); +return ret; +} + +int fat_readdir (FS_DIR *dirp) +{ +fat_dir *dir = (fat_dir *)dirp; +struct fs_dirent *dent = &dirp->dirent; + +if (!fat_itr_next (&dir->itr)) +return -ENOENT ; + +strcpy (dent->name, dir->itr.name); +if (fat_itr_isdir (&dir->itr)) { + dent->type =FS_DT_DIR ; + }else { + dent->type =FS_DT_REG ; + dent->size =FAT2CPU32 (dir->itr.dent->size); + } + +return 0 ; +} + +void fat_closedir (FS_DIR *dirp) +{ +fat_dir *dir = (fat_dir *)dirp; +free (dir); +} +void fat_close (void ) { }
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 5/8 fs/fat: implement opendir/readdir/closedir
In reply to Rob ClarkQuoted 20 lines · Rob Clark
Implement the readdir interface using the directory iterators.
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)fs/fat/fat.c +1
-0@@ -14,6 +14,7 @@#include <config.h> #include <exports.h> #include <fat.h> +#include <fs.h> #include <asm/byteorder.h> #include <part.h> #include <malloc.h>
fs/fat/fat.c int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, · line 1128
Quoted 9 lines
fs/fat/fat.c +6
-0@@ -1119,6 +1120,61 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,return ret; } +typedef struct { +FS_DIR parent; +fsdata fsdata; +fat_itr itr; +}fat_dir ; +
Please drop the typedef.
This is a really nice implementation now.
PATCH v2 6/8 fat/fs: remove a bunch of dead code
In reply to Rob ClarkSpotted by chance, when trying to remove file_fat_ls(), I noticed there were some dead users of the API.
--- fs/fat/Makefile | 4 -- fs/fat/file.c | 183 -------------------------------------------------------- include/fat.h | 20 ------- 3 files changed, 207 deletions(-) delete mode 100644 fs/fat/file.c
fs/fat/Makefile +0 -4
@@ -5,7 +5,3 @@ obj-$(CONFIG_FS_FAT) := fat.o obj-$(CONFIG_FAT_WRITE):= fat_write.o - -ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_FS_FAT) += file.o -endif
fs/fat/file.c deleted +0 -183
183 lines not on this page · raw message
include/fat.h +0 -20
@@ -171,25 +171,6 @@ typedef struct {int rootdir_size; } fsdata; -typedef int (file_detectfs_func )(void ); -typedef int (file_ls_func )(const char *dir); -typedef int (file_read_func )(const char *filename,void *buffer, -int maxsize); - -struct filesystem { -file_detectfs_func *detect; -file_ls_func *ls; -file_read_func *read; -const char name[12 ]; -}; - -/* FAT tables */ -file_detectfs_func file_fat_detectfs; -file_ls_func file_fat_ls; -file_read_func file_fat_read; - -/* Currently this doesn't check if the dir exists or is valid... */ -int file_cd (const char *path);int file_fat_detectfs (void );int file_fat_ls (const char *dir);int fat_exists (const char *filename);
@@ -197,7 +178,6 @@ int fat_size(const char *filename, loff_t *size);int file_fat_read_at (const char *filename,loff_t pos,void *buffer,loff_t maxsize,loff_t *actread);int file_fat_read (const char *filename,void *buffer,int maxsize); -const char *file_getfsname (int idx);int fat_set_blk_dev (struct blk_desc *rbdd,disk_partition_t *info);int fat_register_device (struct blk_desc *dev_desc,int part_no);
Signature · 1 line
2.13.5
PATCH v2 6/8 fat/fs: remove a bunch of dead code
Quoted 11 lines · Rob Clark
Spotted by chance, when trying to remove
file_fat_ls(), I noticed there were some dead users of the API.Signed-off-by Rob Clark <[email protected]>Acked-by Stefan Brüns <[email protected]>--- fs/fat/Makefile | 4 -- fs/fat/file.c | 183 -------------------------------------------------------- include/fat.h | 20 ------- 3 files changed, 207 deletions(-) delete mode 100644 fs/fat/file.c
PATCH v2 7/8 fat/fs: move ls to generic implementation
In reply to Rob ClarkAdd a generic implementation of 'ls' using opendir/readdir/closedir, and replace fat's custom implementation. Other filesystems should move to the generic implementation after they add opendir/readdir/closedir support.
--- fs/fat/fat.c | 32 -------------------------------- fs/fs.c | 35 +++++++++++++++++++++++++++++++++-- include/fat.h | 5 ++++- 3 files changed, 37 insertions(+), 35 deletions(-)
fs/fat/fat.c +0 -32
@@ -1002,38 +1002,6 @@ int file_fat_detectfs(void)return 0 ; } -int file_fat_ls (const char *dir) -{ -fsdata fsdata; -fat_itr itrblock, *itr = &itrblock; -int files =0 , dirs =0 ; -int ret; - - ret =fat_itr_root (itr, &fsdata); -if (ret) -return ret; - - ret =fat_itr_resolve (itr, dir,TYPE_DIR ); -if (ret) -return ret; - -while (fat_itr_next (itr)) { -if (fat_itr_isdir (itr)) { -printf (" %s/\n" , itr->name); - dirs++; - }else { -printf (" %8u %s\n" , -FAT2CPU32 (itr->dent->size), - itr->name); - files++; - } - } - -printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); - -return 0 ; -} -int fat_exists (const char *filename) {fsdata fsdata;
fs/fs.c +33 -2
@@ -37,6 +37,35 @@ static inline int fs_ls_unsupported(const char *dirname)return -1 ; } +/* generic implementation of ls in terms of opendir/readdir/closedir */ +__maybe_unused +static int fs_ls_generic (const char *dirname) +{ +FS_DIR *dirp; +struct fs_dirent *dent; +int files =0 , dirs =0 ; + + dirp =fs_opendir (dirname); +if (!dirp) +return -errno; + +while ((dent =fs_readdir (dirp))) { +if (dent->type ==FS_DT_DIR ) { +printf (" %s/\n" , dent->name); + dirs++; + }else { +printf (" %8lld %s\n" , dent->size, dent->name); + files++; + } + } + +fs_closedir (dirp); + +printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); + +return 0 ; +} +static inline int fs_exists_unsupported (const char *filename) {return 0 ;
@@ -111,7 +140,7 @@ static struct fstype_info fstypes[] = { .null_dev_desc_ok = false, .probe = fat_set_blk_dev, .close = fat_close, - .ls = file_fat_ls, + .ls = fs_ls_generic, .exists = fat_exists, .size = fat_size, .read = fat_read_file,
@@ -121,7 +150,9 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, - .opendir = fs_opendir_unsupported, + .opendir = fat_opendir, + .readdir = fat_readdir, + .closedir = fat_closedir, },#endif #ifdef CONFIG_FS_EXT4
include/fat.h +4 -1
@@ -11,6 +11,7 @@#define _FAT_H_#include <asm/byteorder.h> +#include <fs.h> #define CONFIG_SUPPORT_VFAT /* Maximum Long File Name length supported here is 128 UTF-16 code units */
@@ -172,7 +173,6 @@ typedef struct { } fsdata;int file_fat_detectfs (void ); -int file_fat_ls (const char *dir);int fat_exists (const char *filename);int fat_size (const char *filename,loff_t *size); int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
@@ -185,5 +185,8 @@ int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actwrite);int fat_read_file (const char *filename,void *buf,loff_t offset,loff_t len,loff_t *actread); +int fat_opendir (const char *filename,FS_DIR **dirp); +int fat_readdir (FS_DIR *dirp); +void fat_closedir (FS_DIR *dirp);void fat_close (void );#endif /* _FAT_H_ */
Signature · 1 line
2.13.5
PATCH v2 7/8 fat/fs: move ls to generic implementation
Quoted 5 lines · Rob Clark
Add a generic implementation of 'ls' using opendir/readdir/closedir, and replace fat's custom implementation. Other filesystems should move to the generic implementation after they add opendir/readdir/closedir support.
Quoted 140 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 32 -------------------------------- fs/fs.c | 35 +++++++++++++++++++++++++++++++++-- include/fat.h | 5 ++++- 3 files changed, 37 insertions(+), 35 deletions(-)fs/fat/fat.c +0
-32@@ -1002,38 +1002,6 @@ int file_fat_detectfs(void)return 0 ; } -int file_fat_ls (const char *dir) -{ -fsdata fsdata; -fat_itr itrblock, *itr = &itrblock; -int files =0 , dirs =0 ; -int ret; - - ret =fat_itr_root (itr, &fsdata); -if (ret) -return ret; - - ret =fat_itr_resolve (itr, dir,TYPE_DIR ); -if (ret) -return ret; - -while (fat_itr_next (itr)) { -if (fat_itr_isdir (itr)) { -printf (" %s/\n" , itr->name); - dirs++; - }else { -printf (" %8u %s\n" , -FAT2CPU32 (itr->dent->size), - itr->name); - files++; - } - } - -printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); - -return 0 ; -} -int fat_exists (const char *filename) {fsdata fsdata;fs/fs.c +33
-2@@ -37,6 +37,35 @@ static inline int fs_ls_unsupported(const char *dirname)return -1 ; } +/* generic implementation of ls in terms of opendir/readdir/closedir */ +__maybe_unused +static int fs_ls_generic (const char *dirname) +{ +FS_DIR *dirp; +struct fs_dirent *dent; +int files =0 , dirs =0 ; + + dirp =fs_opendir (dirname); +if (!dirp) +return -errno; + +while ((dent =fs_readdir (dirp))) { +if (dent->type ==FS_DT_DIR ) { +printf (" %s/\n" , dent->name); + dirs++; + }else { +printf (" %8lld %s\n" , dent->size, dent->name); + files++; + } + } + +fs_closedir (dirp); + +printf ("\n%d file(s), %d dir(s)\n\n" , files, dirs); + +return 0 ; +} +static inline int fs_exists_unsupported (const char *filename) {return 0 ;@@ -111,7 +140,7 @@ static struct fstype_info fstypes[] = { .null_dev_desc_ok = false, .probe = fat_set_blk_dev, .close = fat_close, - .ls = file_fat_ls, + .ls = fs_ls_generic, .exists = fat_exists, .size = fat_size, .read = fat_read_file,@@ -121,7 +150,9 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, - .opendir = fs_opendir_unsupported, + .opendir = fat_opendir, + .readdir = fat_readdir, + .closedir = fat_closedir, },#endif #ifdef CONFIG_FS_EXT4 include/fat.h +4
-1@@ -11,6 +11,7 @@#define _FAT_H_#include <asm/byteorder.h> +#include <fs.h> #define CONFIG_SUPPORT_VFAT /* Maximum Long File Name length supported here is 128 UTF-16 code units */ @@ -172,7 +173,6 @@ typedef struct { } fsdata;int file_fat_detectfs (void ); -int file_fat_ls (const char *dir);int fat_exists (const char *filename);int fat_size (const char *filename,loff_t *size); int file_fat_read_at(const char *filename, loff_t pos, void *buffer,@@ -185,5 +185,8 @@ int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actwrite);int fat_read_file (const char *filename,void *buf,loff_t offset,loff_t len,loff_t *actread); +int fat_opendir (const char *filename,FS_DIR **dirp); +int fat_readdir (FS_DIR *dirp); +void fat_closedir (FS_DIR *dirp);void fat_close (void );#endif /* _FAT_H_ */
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 7/8 fat/fs: move ls to generic implementation
In reply to Rob ClarkQuoted 11 lines · Rob Clark
Add a generic implementation of 'ls' using opendir/readdir/closedir, and replace fat's custom implementation. Other filesystems should move to the generic implementation after they add opendir/readdir/closedir support.
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 32 -------------------------------- fs/fs.c | 35 +++++++++++++++++++++++++++++++++-- include/fat.h | 5 ++++- 3 files changed, 37 insertions(+), 35 deletions(-)
So if all filesystems implement this interface then we could move this to function to the fs layer?
PATCH v2 7/8 fat/fs: move ls to generic implementation
Quoted 13 lines · Simon Glass
Quoted 11 lines · Rob Clark
Add a generic implementation of 'ls' using opendir/readdir/closedir, and replace fat's custom implementation. Other filesystems should move to the generic implementation after they add opendir/readdir/closedir support.
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 32 -------------------------------- fs/fs.c | 35 +++++++++++++++++++++++++++++++++-- include/fat.h | 5 ++++- 3 files changed, 37 insertions(+), 35 deletions(-)
Quoted 4 lines
Reviewed-by Simon Glass <[email protected]>So if all filesystems implement this interface then we could move this to function to the fs layer?
yes.. there are some slight differences in output for other fs's but I guess since u-boot doesn't make that easy for a script to capture we can probably ignore it..
BR,
-R
PATCH v2 8/8 fs/fat: fix case for FAT shortnames
In reply to Rob ClarkNoticed when comparing our output to linux. There are some lcase bits which control whether filename and/or extension should be downcase'd.
--- fs/fat/fat.c | 17 ++++++++++++----- fs/fat/fat_write.c | 4 ++-- include/fat.h | 3 +++ 3 files changed, 17 insertions(+), 7 deletions(-)
fs/fat/fat.c +12 -5
@@ -29,11 +29,13 @@ static const int vfat_enabled = 0;#endif /* -* Convert a string to lowercase. +* Convert a string to lowercase. Converts at most 'len' characters, +* 'len' may be larger than the length of 'str' if 'str' is NULL +* terminated. */ -static void downcase (char *str) +static void downcase (char *str,size_t len) { -while (*str !='\0' ) { +while (*str !='\0' && len--) { *str =tolower (*str); str++; }
@@ -131,10 +133,16 @@ static void get_name(dir_entry *dirent, char *s_name) ptr = s_name;while (*ptr && *ptr !=' ' ) ptr++; +if (dirent->lcase &CASE_LOWER_BASE ) +downcase (s_name, (unsigned )(ptr - s_name));if (dirent->ext[0 ] && dirent->ext[0 ] !=' ' ) { +char *ext; + *ptr ='.' ; - ptr++; + ext = ++ptr;memcpy (ptr, dirent->ext,3 ); +if (dirent->lcase &CASE_LOWER_EXT ) +downcase (ext,3 ); ptr[3 ] ='\0' ;while (*ptr && *ptr !=' ' ) ptr++;
@@ -144,7 +152,6 @@ static void get_name(dir_entry *dirent, char *s_name) *s_name ='\0' ; else if (*s_name == aRING) *s_name = DELETED_FLAG; -downcase (s_name); }static int flush_dirty_fat_buffer (fsdata *mydata);
fs/fat/fat_write.c +2 -2
@@ -345,7 +345,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, *l_name ='\0' ; else if (*l_name == aRING) *l_name = DELETED_FLAG; -downcase (l_name); +downcase (l_name, ~0 );/* Return the real directory entry */ *retdent = realdent;
@@ -981,7 +981,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,memcpy (l_filename, filename, name_len); l_filename[name_len] =0 ;/* terminate the string */ -downcase (l_filename); +downcase (l_filename, ~0 ); startsect = mydata->rootdir_sect; retdent = find_directory_entry(mydata, startsect,
include/fat.h +3 -0
@@ -128,6 +128,9 @@ typedef struct volume_info/* Boot sign comes last, 2 bytes */ } volume_info; +#define CASE_LOWER_BASE 8/* base is lower case */ +#define CASE_LOWER_EXT 16/* extension is lower case */ + typedef struct dir_entry { char name[8],ext[3]; /* Name and extension */ __u8 attr; /* Attribute bits */
Signature · 1 line
2.13.5
PATCH v2 8/8 fs/fat: fix case for FAT shortnames
Quoted 2 lines · Rob Clark
Noticed when comparing our output to linux. There are some lcase bits which control whether filename and/or extension should be downcase'd.
Quoted 92 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 17 ++++++++++++----- fs/fat/fat_write.c | 4 ++-- include/fat.h | 3 +++ 3 files changed, 17 insertions(+), 7 deletions(-)fs/fat/fat.c +12
-5@@ -29,11 +29,13 @@ static const int vfat_enabled = 0;#endif /* -* Convert a string to lowercase. +* Convert a string to lowercase. Converts at most 'len' characters, +* 'len' may be larger than the length of 'str' if 'str' is NULL +* terminated. */ -static void downcase (char *str) +static void downcase (char *str,size_t len) { -while (*str !='\0' ) { +while (*str !='\0' && len--) { *str =tolower (*str); str++; }@@ -131,10 +133,16 @@ static void get_name(dir_entry *dirent, char *s_name) ptr = s_name;while (*ptr && *ptr !=' ' ) ptr++; +if (dirent->lcase &CASE_LOWER_BASE ) +downcase (s_name, (unsigned )(ptr - s_name));if (dirent->ext[0 ] && dirent->ext[0 ] !=' ' ) { +char *ext; + *ptr ='.' ; - ptr++; + ext = ++ptr;memcpy (ptr, dirent->ext,3 ); +if (dirent->lcase &CASE_LOWER_EXT ) +downcase (ext,3 ); ptr[3 ] ='\0' ;while (*ptr && *ptr !=' ' ) ptr++;@@ -144,7 +152,6 @@ static void get_name(dir_entry *dirent, char *s_name) *s_name ='\0' ; else if (*s_name == aRING) *s_name = DELETED_FLAG; -downcase (s_name); }static int flush_dirty_fat_buffer (fsdata *mydata);fs/fat/fat_write.c +2
-2@@ -345,7 +345,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, *l_name ='\0' ; else if (*l_name == aRING) *l_name = DELETED_FLAG; -downcase (l_name); +downcase (l_name, ~0 );/* Return the real directory entry */ *retdent = realdent;@@ -981,7 +981,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,memcpy (l_filename, filename, name_len); l_filename[name_len] =0 ;/* terminate the string */ -downcase (l_filename); +downcase (l_filename, ~0 ); startsect = mydata->rootdir_sect; retdent = find_directory_entry(mydata, startsect,include/fat.h +3
-0@@ -128,6 +128,9 @@ typedef struct volume_info/* Boot sign comes last, 2 bytes */ } volume_info; +#define CASE_LOWER_BASE 8/* base is lower case */ +#define CASE_LOWER_EXT 16/* extension is lower case */ + typedef struct dir_entry { char name[8],ext[3]; /* Name and extension */ __u8 attr; /* Attribute bits */
Signature · 9 lines
Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PATCH v2 8/8 fs/fat: fix case for FAT shortnames
Hi Rob,
Quoted 42 lines · Łukasz Majewski
Quoted 3 lines · Rob Clark
Noticed when comparing our output to linux. There are some lcase bits which control whether filename and/or extension should be downcase'd.
Reviewed-by Łukasz Majewski <[email protected]>Quoted 33 lines
Signed-off-by Rob Clark <[email protected]>--- fs/fat/fat.c | 17 ++++++++++++----- fs/fat/fat_write.c | 4 ++-- include/fat.h | 3 +++ 3 files changed, 17 insertions(+), 7 deletions(-)fs/fat/fat.c +5
-3@@ -29,11 +29,13 @@ static const int vfat_enabled = 0;#endif /* -* Convert a string to lowercase. +* Convert a string to lowercase. Converts at most 'len' characters, +* 'len' may be larger than the length of 'str' if 'str' is NULL +* terminated. */ -static void downcase (char *str) +static void downcase (char *str,size_t len) { -while (*str !='\0' ) { +while (*str !='\0' && len--) { *str =tolower (*str); str++; }@@ -131,10 +133,16 @@ static void get_name(dir_entry *dirent, char *s_name) ptr = s_name;while (*ptr && *ptr !=' ' ) ptr++;
Quoted 8 lines
fs/fat/fat.c static void get_name(dir_entry *dirent, char *s_name) · line 142
Quoted 8 lines
fs/fat/fat.c +5
-1+if (dirent->lcase &CASE_LOWER_BASE ) +downcase (s_name, (unsigned )(ptr - s_name));if (dirent->ext[0 ] && dirent->ext[0 ] !=' ' ) { +char *ext; + *ptr ='.' ; - ptr++; + ext = ++ptr;
I think this would be clearer as:
*ptr++ = '.'; ext = ptr;
But given that you only use ext once, can you just drop it?
Quoted 16 lines
Quoted 16 lines
fs/fat/fat.c +2
-0memcpy (ptr, dirent->ext,3 ); +if (dirent->lcase &CASE_LOWER_EXT ) +downcase (ext,3 ); ptr[3 ] ='\0' ;while (*ptr && *ptr !=' ' )ptr++;fs/fat/fat.c +0
-1@@ -144,7 +152,6 @@ static void get_name(dir_entry *dirent, char *s_name) *s_name ='\0' ; else if (*s_name == aRING) *s_name = DELETED_FLAG; -downcase (s_name); }static int flush_dirty_fat_buffer (fsdata *mydata);fs/fat/fat_write.c +0
-1--- a/fs/fat/fat_write.c
Quoted 8 lines
fs/fat/fat_write.c get_long_file_name(fsdata *mydata, int curclust, __u8 · line 349
Quoted 8 lines
+++
b/fs/fat/fat_write.cfs/fat/fat_write.c +1
-1@@ -345,7 +345,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, *l_name ='\0' ; else if (*l_name == aRING) *l_name = DELETED_FLAG; -downcase (l_name); +downcase (l_name, ~0 );
Could this be INT_MAX to indicate all? I think ~0 is a bit obscure
Quoted 8 lines
fs/fat/fat_write.c static int do_fat_write(const char *filename, void · line 984
Quoted 8 lines
fs/fat/fat_write.c +1
-1/* Return the real directory entry */ *retdent = realdent;@@ -981,7 +981,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,memcpy (l_filename, filename, name_len); l_filename[name_len] =0 ;/* terminate the string */ -downcase (l_filename); +downcase (l_filename, ~0 );
here also
Quoted 11 lines
include/fat.h typedef struct volume_info · line 131
Quoted 11 lines
fs/fat/fat_write.c +0
-0startsect = mydata->rootdir_sect; retdent = find_directory_entry(mydata, startsect,include/fat.h +1
-0@@ -128,6 +128,9 @@ typedef struct volume_info/* Boot sign comes last, 2 bytes */ } volume_info; +#define CASE_LOWER_BASE 8 /* base is lower case */ +#define CASE_LOWER_EXT 16/* extension is lower case */
Where are these two used? If they are flags can you mention somewhere what uses them?
Quoted 6 lines
include/fat.h typedef struct volume_info · line 136
Quoted 5 lines
include/fat.h +1
-0+ typedef struct dir_entry { char name[8],ext[3]; /* Name and extension */ __u8 attr; /* Attribute bits */
Regards,
Simon