diff options
-rw-r--r-- | fs/fat/dir.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 96a1cad30da4..4c35477bc94c 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -481,11 +481,11 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, unsigned short opt_shortname = sbi->options.shortname; int isvfat = sbi->options.isvfat; int nocase = sbi->options.nocase; - const char *fill_name; + const char *fill_name = NULL; unsigned long inum; unsigned long lpos, dummy, *furrfu = &lpos; loff_t cpos; - int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len; + int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0; int ret = 0; lock_super(sb); @@ -516,8 +516,11 @@ get_new: goto end_of_dir; parse_record: nr_slots = 0; - /* Check for long filename entry */ - if (isvfat) { + /* + * Check for long filename entry, but if short_only, we don't + * need to parse long filename. + */ + if (isvfat && !short_only) { if (de->name[0] == DELETED_FLAG) goto record_end; if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) @@ -542,6 +545,18 @@ parse_record: goto parse_record; else if (status == PARSE_EOF) goto end_of_dir; + + if (nr_slots) { + void *longname = unicode + FAT_MAX_UNI_CHARS; + int size = PATH_MAX - FAT_MAX_UNI_SIZE; + int len = fat_uni_to_x8(sbi, unicode, longname, size); + + fill_name = longname; + fill_len = len; + /* !both && !short_only, so we don't need shortname. */ + if (!both) + goto start_filldir; + } } if (sbi->options.dotsOK) { @@ -608,6 +623,26 @@ parse_record: i = last + dotoffset; j = last_u; + if (isvfat) { + bufuname[j] = 0x0000; + i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); + } + if (nr_slots) { + /* hack for fat_ioctl_filldir() */ + struct fat_ioctl_filldir_callback *p = dirent; + + p->longname = fill_name; + p->long_len = fill_len; + p->shortname = bufname; + p->short_len = i; + fill_name = NULL; + fill_len = 0; + } else { + fill_name = bufname; + fill_len = i; + } + +start_filldir: lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) inum = inode->i_ino; @@ -623,34 +658,6 @@ parse_record: inum = iunique(sb, MSDOS_ROOT_INO); } - if (isvfat) { - bufuname[j] = 0x0000; - i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); - } - - fill_name = bufname; - fill_len = i; - if (!short_only && nr_slots) { - void *longname = unicode + FAT_MAX_UNI_CHARS; - int long_len, size = PATH_MAX - FAT_MAX_UNI_SIZE; - - long_len = fat_uni_to_x8(sbi, unicode, longname, size); - - if (!both) { - fill_name = longname; - fill_len = long_len; - } else { - /* hack for fat_ioctl_filldir() */ - struct fat_ioctl_filldir_callback *p = dirent; - - p->longname = longname; - p->long_len = long_len; - p->shortname = bufname; - p->short_len = i; - fill_name = NULL; - fill_len = 0; - } - } if (filldir(dirent, fill_name, fill_len, *furrfu, inum, (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) goto fill_failed; |