diff options
Diffstat (limited to 'fs/fat')
-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, | |||
481 | unsigned short opt_shortname = sbi->options.shortname; | 481 | unsigned short opt_shortname = sbi->options.shortname; |
482 | int isvfat = sbi->options.isvfat; | 482 | int isvfat = sbi->options.isvfat; |
483 | int nocase = sbi->options.nocase; | 483 | int nocase = sbi->options.nocase; |
484 | const char *fill_name; | 484 | const char *fill_name = NULL; |
485 | unsigned long inum; | 485 | unsigned long inum; |
486 | unsigned long lpos, dummy, *furrfu = &lpos; | 486 | unsigned long lpos, dummy, *furrfu = &lpos; |
487 | loff_t cpos; | 487 | loff_t cpos; |
488 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len; | 488 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0; |
489 | int ret = 0; | 489 | int ret = 0; |
490 | 490 | ||
491 | lock_super(sb); | 491 | lock_super(sb); |
@@ -516,8 +516,11 @@ get_new: | |||
516 | goto end_of_dir; | 516 | goto end_of_dir; |
517 | parse_record: | 517 | parse_record: |
518 | nr_slots = 0; | 518 | nr_slots = 0; |
519 | /* Check for long filename entry */ | 519 | /* |
520 | if (isvfat) { | 520 | * Check for long filename entry, but if short_only, we don't |
521 | * need to parse long filename. | ||
522 | */ | ||
523 | if (isvfat && !short_only) { | ||
521 | if (de->name[0] == DELETED_FLAG) | 524 | if (de->name[0] == DELETED_FLAG) |
522 | goto record_end; | 525 | goto record_end; |
523 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 526 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) |
@@ -542,6 +545,18 @@ parse_record: | |||
542 | goto parse_record; | 545 | goto parse_record; |
543 | else if (status == PARSE_EOF) | 546 | else if (status == PARSE_EOF) |
544 | goto end_of_dir; | 547 | goto end_of_dir; |
548 | |||
549 | if (nr_slots) { | ||
550 | void *longname = unicode + FAT_MAX_UNI_CHARS; | ||
551 | int size = PATH_MAX - FAT_MAX_UNI_SIZE; | ||
552 | int len = fat_uni_to_x8(sbi, unicode, longname, size); | ||
553 | |||
554 | fill_name = longname; | ||
555 | fill_len = len; | ||
556 | /* !both && !short_only, so we don't need shortname. */ | ||
557 | if (!both) | ||
558 | goto start_filldir; | ||
559 | } | ||
545 | } | 560 | } |
546 | 561 | ||
547 | if (sbi->options.dotsOK) { | 562 | if (sbi->options.dotsOK) { |
@@ -608,6 +623,26 @@ parse_record: | |||
608 | i = last + dotoffset; | 623 | i = last + dotoffset; |
609 | j = last_u; | 624 | j = last_u; |
610 | 625 | ||
626 | if (isvfat) { | ||
627 | bufuname[j] = 0x0000; | ||
628 | i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); | ||
629 | } | ||
630 | if (nr_slots) { | ||
631 | /* hack for fat_ioctl_filldir() */ | ||
632 | struct fat_ioctl_filldir_callback *p = dirent; | ||
633 | |||
634 | p->longname = fill_name; | ||
635 | p->long_len = fill_len; | ||
636 | p->shortname = bufname; | ||
637 | p->short_len = i; | ||
638 | fill_name = NULL; | ||
639 | fill_len = 0; | ||
640 | } else { | ||
641 | fill_name = bufname; | ||
642 | fill_len = i; | ||
643 | } | ||
644 | |||
645 | start_filldir: | ||
611 | lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); | 646 | lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); |
612 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) | 647 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) |
613 | inum = inode->i_ino; | 648 | inum = inode->i_ino; |
@@ -623,34 +658,6 @@ parse_record: | |||
623 | inum = iunique(sb, MSDOS_ROOT_INO); | 658 | inum = iunique(sb, MSDOS_ROOT_INO); |
624 | } | 659 | } |
625 | 660 | ||
626 | if (isvfat) { | ||
627 | bufuname[j] = 0x0000; | ||
628 | i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); | ||
629 | } | ||
630 | |||
631 | fill_name = bufname; | ||
632 | fill_len = i; | ||
633 | if (!short_only && nr_slots) { | ||
634 | void *longname = unicode + FAT_MAX_UNI_CHARS; | ||
635 | int long_len, size = PATH_MAX - FAT_MAX_UNI_SIZE; | ||
636 | |||
637 | long_len = fat_uni_to_x8(sbi, unicode, longname, size); | ||
638 | |||
639 | if (!both) { | ||
640 | fill_name = longname; | ||
641 | fill_len = long_len; | ||
642 | } else { | ||
643 | /* hack for fat_ioctl_filldir() */ | ||
644 | struct fat_ioctl_filldir_callback *p = dirent; | ||
645 | |||
646 | p->longname = longname; | ||
647 | p->long_len = long_len; | ||
648 | p->shortname = bufname; | ||
649 | p->short_len = i; | ||
650 | fill_name = NULL; | ||
651 | fill_len = 0; | ||
652 | } | ||
653 | } | ||
654 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, | 661 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, |
655 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) | 662 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) |
656 | goto fill_failed; | 663 | goto fill_failed; |