Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[readdir] convert efs

* sanity checks belong before risky operation, not after it
* don't quit as soon as we'd found an entry

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 7aa123a0 52018855

+33 -42
+33 -42
fs/efs/dir.c
··· 7 7 #include <linux/buffer_head.h> 8 8 #include "efs.h" 9 9 10 - static int efs_readdir(struct file *, void *, filldir_t); 10 + static int efs_readdir(struct file *, struct dir_context *); 11 11 12 12 const struct file_operations efs_dir_operations = { 13 13 .llseek = generic_file_llseek, 14 14 .read = generic_read_dir, 15 - .readdir = efs_readdir, 15 + .iterate = efs_readdir, 16 16 }; 17 17 18 18 const struct inode_operations efs_dir_inode_operations = { 19 19 .lookup = efs_lookup, 20 20 }; 21 21 22 - static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { 23 - struct inode *inode = file_inode(filp); 24 - struct buffer_head *bh; 25 - 26 - struct efs_dir *dirblock; 27 - struct efs_dentry *dirslot; 28 - efs_ino_t inodenum; 22 + static int efs_readdir(struct file *file, struct dir_context *ctx) 23 + { 24 + struct inode *inode = file_inode(file); 29 25 efs_block_t block; 30 - int slot, namelen; 31 - char *nameptr; 26 + int slot; 32 27 33 28 if (inode->i_size & (EFS_DIRBSIZE-1)) 34 29 printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); 35 30 36 31 /* work out where this entry can be found */ 37 - block = filp->f_pos >> EFS_DIRBSIZE_BITS; 32 + block = ctx->pos >> EFS_DIRBSIZE_BITS; 38 33 39 34 /* each block contains at most 256 slots */ 40 - slot = filp->f_pos & 0xff; 35 + slot = ctx->pos & 0xff; 41 36 42 37 /* look at all blocks */ 43 38 while (block < inode->i_blocks) { 39 + struct efs_dir *dirblock; 40 + struct buffer_head *bh; 41 + 44 42 /* read the dir block */ 45 43 bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 46 44 ··· 55 57 break; 56 58 } 57 59 58 - while (slot < dirblock->slots) { 59 - if (dirblock->space[slot] == 0) { 60 - slot++; 60 + for (; slot < dirblock->slots; slot++) { 61 + struct efs_dentry *dirslot; 62 + efs_ino_t inodenum; 63 + const char *nameptr; 64 + int namelen; 65 + 66 + if (dirblock->space[slot] == 0) 61 67 continue; 62 - } 63 68 64 69 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 65 70 ··· 73 72 #ifdef DEBUG 74 73 printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen); 75 74 #endif 76 - if (namelen > 0) { 77 - /* found the next entry */ 78 - filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 75 + if (!namelen) 76 + continue; 77 + /* found the next entry */ 78 + ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot; 79 79 80 - /* copy filename and data in dirslot */ 81 - filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN); 82 - 83 - /* sanity check */ 84 - if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { 85 - printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot); 86 - slot++; 87 - continue; 88 - } 89 - 90 - /* store position of next slot */ 91 - if (++slot == dirblock->slots) { 92 - slot = 0; 93 - block++; 94 - } 95 - brelse(bh); 96 - filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 97 - goto out; 80 + /* sanity check */ 81 + if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { 82 + printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot); 83 + continue; 98 84 } 99 - slot++; 85 + 86 + /* copy filename and data in dirslot */ 87 + if (!dir_emit(ctx, nameptr, namelen, inodenum, DT_UNKNOWN)) { 88 + brelse(bh); 89 + return 0; 90 + } 100 91 } 101 92 brelse(bh); 102 93 103 94 slot = 0; 104 95 block++; 105 96 } 106 - 107 - filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 108 - out: 97 + ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot; 109 98 return 0; 110 99 } 111 100