aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fat
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-05-22 18:37:16 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:57:01 -0400
commit2c6a2473b800f8eadc94c9a711fee8671dd1a244 (patch)
treed17702018438f68f990301b8dcf4dc87ae692de8 /fs/fat
parentb8227554c951eb144e975c5e741d33f29c29596f (diff)
[readdir] convert fatfs
... pox upon the idiotic ioctls; life would be much easier without those. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/dir.c104
1 files changed, 54 insertions, 50 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 7a6f02caf286..3963ede84eb0 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -543,6 +543,7 @@ end_of_dir:
543EXPORT_SYMBOL_GPL(fat_search_long); 543EXPORT_SYMBOL_GPL(fat_search_long);
544 544
545struct fat_ioctl_filldir_callback { 545struct fat_ioctl_filldir_callback {
546 struct dir_context ctx;
546 void __user *dirent; 547 void __user *dirent;
547 int result; 548 int result;
548 /* for dir ioctl */ 549 /* for dir ioctl */
@@ -552,8 +553,9 @@ struct fat_ioctl_filldir_callback {
552 int short_len; 553 int short_len;
553}; 554};
554 555
555static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, 556static int __fat_readdir(struct inode *inode, struct file *file,
556 filldir_t filldir, int short_only, int both) 557 struct dir_context *ctx, int short_only,
558 struct fat_ioctl_filldir_callback *both)
557{ 559{
558 struct super_block *sb = inode->i_sb; 560 struct super_block *sb = inode->i_sb;
559 struct msdos_sb_info *sbi = MSDOS_SB(sb); 561 struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -564,27 +566,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
564 unsigned char bufname[FAT_MAX_SHORT_SIZE]; 566 unsigned char bufname[FAT_MAX_SHORT_SIZE];
565 int isvfat = sbi->options.isvfat; 567 int isvfat = sbi->options.isvfat;
566 const char *fill_name = NULL; 568 const char *fill_name = NULL;
567 unsigned long inum; 569 int fake_offset = 0;
568 unsigned long lpos, dummy, *furrfu = &lpos;
569 loff_t cpos; 570 loff_t cpos;
570 int short_len = 0, fill_len = 0; 571 int short_len = 0, fill_len = 0;
571 int ret = 0; 572 int ret = 0;
572 573
573 mutex_lock(&sbi->s_lock); 574 mutex_lock(&sbi->s_lock);
574 575
575 cpos = filp->f_pos; 576 cpos = ctx->pos;
576 /* Fake . and .. for the root directory. */ 577 /* Fake . and .. for the root directory. */
577 if (inode->i_ino == MSDOS_ROOT_INO) { 578 if (inode->i_ino == MSDOS_ROOT_INO) {
578 while (cpos < 2) { 579 if (!dir_emit_dots(file, ctx))
579 if (filldir(dirent, "..", cpos+1, cpos, 580 goto out;
580 MSDOS_ROOT_INO, DT_DIR) < 0) 581 if (ctx->pos == 2) {
581 goto out; 582 fake_offset = 1;
582 cpos++;
583 filp->f_pos++;
584 }
585 if (cpos == 2) {
586 dummy = 2;
587 furrfu = &dummy;
588 cpos = 0; 583 cpos = 0;
589 } 584 }
590 } 585 }
@@ -619,7 +614,7 @@ parse_record:
619 int status = fat_parse_long(inode, &cpos, &bh, &de, 614 int status = fat_parse_long(inode, &cpos, &bh, &de,
620 &unicode, &nr_slots); 615 &unicode, &nr_slots);
621 if (status < 0) { 616 if (status < 0) {
622 filp->f_pos = cpos; 617 ctx->pos = cpos;
623 ret = status; 618 ret = status;
624 goto out; 619 goto out;
625 } else if (status == PARSE_INVALID) 620 } else if (status == PARSE_INVALID)
@@ -639,6 +634,19 @@ parse_record:
639 /* !both && !short_only, so we don't need shortname. */ 634 /* !both && !short_only, so we don't need shortname. */
640 if (!both) 635 if (!both)
641 goto start_filldir; 636 goto start_filldir;
637
638 short_len = fat_parse_short(sb, de, bufname,
639 sbi->options.dotsOK);
640 if (short_len == 0)
641 goto record_end;
642 /* hack for fat_ioctl_filldir() */
643 both->longname = fill_name;
644 both->long_len = fill_len;
645 both->shortname = bufname;
646 both->short_len = short_len;
647 fill_name = NULL;
648 fill_len = 0;
649 goto start_filldir;
642 } 650 }
643 } 651 }
644 652
@@ -646,28 +654,21 @@ parse_record:
646 if (short_len == 0) 654 if (short_len == 0)
647 goto record_end; 655 goto record_end;
648 656
649 if (nr_slots) { 657 fill_name = bufname;
650 /* hack for fat_ioctl_filldir() */ 658 fill_len = short_len;
651 struct fat_ioctl_filldir_callback *p = dirent;
652
653 p->longname = fill_name;
654 p->long_len = fill_len;
655 p->shortname = bufname;
656 p->short_len = short_len;
657 fill_name = NULL;
658 fill_len = 0;
659 } else {
660 fill_name = bufname;
661 fill_len = short_len;
662 }
663 659
664start_filldir: 660start_filldir:
665 lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); 661 if (!fake_offset)
666 if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) 662 ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
667 inum = inode->i_ino; 663
668 else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { 664 if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) {
669 inum = parent_ino(filp->f_path.dentry); 665 if (!dir_emit_dot(file, ctx))
666 goto fill_failed;
667 } else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
668 if (!dir_emit_dotdot(file, ctx))
669 goto fill_failed;
670 } else { 670 } else {
671 unsigned long inum;
671 loff_t i_pos = fat_make_i_pos(sb, bh, de); 672 loff_t i_pos = fat_make_i_pos(sb, bh, de);
672 struct inode *tmp = fat_iget(sb, i_pos); 673 struct inode *tmp = fat_iget(sb, i_pos);
673 if (tmp) { 674 if (tmp) {
@@ -675,18 +676,17 @@ start_filldir:
675 iput(tmp); 676 iput(tmp);
676 } else 677 } else
677 inum = iunique(sb, MSDOS_ROOT_INO); 678 inum = iunique(sb, MSDOS_ROOT_INO);
679 if (!dir_emit(ctx, fill_name, fill_len, inum,
680 (de->attr & ATTR_DIR) ? DT_DIR : DT_REG))
681 goto fill_failed;
678 } 682 }
679 683
680 if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
681 (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
682 goto fill_failed;
683
684record_end: 684record_end:
685 furrfu = &lpos; 685 fake_offset = 0;
686 filp->f_pos = cpos; 686 ctx->pos = cpos;
687 goto get_new; 687 goto get_new;
688end_of_dir: 688end_of_dir:
689 filp->f_pos = cpos; 689 ctx->pos = cpos;
690fill_failed: 690fill_failed:
691 brelse(bh); 691 brelse(bh);
692 if (unicode) 692 if (unicode)
@@ -696,10 +696,9 @@ out:
696 return ret; 696 return ret;
697} 697}
698 698
699static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) 699static int fat_readdir(struct file *file, struct dir_context *ctx)
700{ 700{
701 struct inode *inode = file_inode(filp); 701 return __fat_readdir(file_inode(file), file, ctx, 0, NULL);
702 return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
703} 702}
704 703
705#define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \ 704#define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \
@@ -755,20 +754,25 @@ efault: \
755 754
756FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent) 755FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
757 756
758static int fat_ioctl_readdir(struct inode *inode, struct file *filp, 757static int fat_ioctl_readdir(struct inode *inode, struct file *file,
759 void __user *dirent, filldir_t filldir, 758 void __user *dirent, filldir_t filldir,
760 int short_only, int both) 759 int short_only, int both)
761{ 760{
762 struct fat_ioctl_filldir_callback buf; 761 struct fat_ioctl_filldir_callback buf = {
762 .ctx.actor = filldir,
763 .dirent = dirent
764 };
763 int ret; 765 int ret;
764 766
765 buf.dirent = dirent; 767 buf.dirent = dirent;
766 buf.result = 0; 768 buf.result = 0;
767 mutex_lock(&inode->i_mutex); 769 mutex_lock(&inode->i_mutex);
770 buf.ctx.pos = file->f_pos;
768 ret = -ENOENT; 771 ret = -ENOENT;
769 if (!IS_DEADDIR(inode)) { 772 if (!IS_DEADDIR(inode)) {
770 ret = __fat_readdir(inode, filp, &buf, filldir, 773 ret = __fat_readdir(inode, file, &buf.ctx,
771 short_only, both); 774 short_only, both ? &buf : NULL);
775 file->f_pos = buf.ctx.pos;
772 } 776 }
773 mutex_unlock(&inode->i_mutex); 777 mutex_unlock(&inode->i_mutex);
774 if (ret >= 0) 778 if (ret >= 0)
@@ -854,7 +858,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
854const struct file_operations fat_dir_operations = { 858const struct file_operations fat_dir_operations = {
855 .llseek = generic_file_llseek, 859 .llseek = generic_file_llseek,
856 .read = generic_read_dir, 860 .read = generic_read_dir,
857 .readdir = fat_readdir, 861 .iterate = fat_readdir,
858 .unlocked_ioctl = fat_dir_ioctl, 862 .unlocked_ioctl = fat_dir_ioctl,
859#ifdef CONFIG_COMPAT 863#ifdef CONFIG_COMPAT
860 .compat_ioctl = fat_compat_dir_ioctl, 864 .compat_ioctl = fat_compat_dir_ioctl,