Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dir.c
Go to the documentation of this file.
1 /*
2  * dir.c
3  *
4  * Copyright (c) 1999 Al Smith
5  */
6 
7 #include <linux/buffer_head.h>
8 #include "efs.h"
9 
10 static int efs_readdir(struct file *, void *, filldir_t);
11 
13  .llseek = generic_file_llseek,
14  .read = generic_read_dir,
15  .readdir = efs_readdir,
16 };
17 
19  .lookup = efs_lookup,
20 };
21 
22 static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
23  struct inode *inode = filp->f_path.dentry->d_inode;
24  struct buffer_head *bh;
25 
26  struct efs_dir *dirblock;
27  struct efs_dentry *dirslot;
28  efs_ino_t inodenum;
30  int slot, namelen;
31  char *nameptr;
32 
33  if (inode->i_size & (EFS_DIRBSIZE-1))
34  printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n");
35 
36  /* work out where this entry can be found */
37  block = filp->f_pos >> EFS_DIRBSIZE_BITS;
38 
39  /* each block contains at most 256 slots */
40  slot = filp->f_pos & 0xff;
41 
42  /* look at all blocks */
43  while (block < inode->i_blocks) {
44  /* read the dir block */
45  bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
46 
47  if (!bh) {
48  printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
49  break;
50  }
51 
52  dirblock = (struct efs_dir *) bh->b_data;
53 
54  if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
55  printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
56  brelse(bh);
57  break;
58  }
59 
60  while (slot < dirblock->slots) {
61  if (dirblock->space[slot] == 0) {
62  slot++;
63  continue;
64  }
65 
66  dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
67 
68  inodenum = be32_to_cpu(dirslot->inode);
69  namelen = dirslot->namelen;
70  nameptr = dirslot->name;
71 
72 #ifdef DEBUG
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);
74 #endif
75  if (namelen > 0) {
76  /* found the next entry */
77  filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
78 
79  /* copy filename and data in dirslot */
80  filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
81 
82  /* sanity check */
83  if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
84  printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
85  slot++;
86  continue;
87  }
88 
89  /* store position of next slot */
90  if (++slot == dirblock->slots) {
91  slot = 0;
92  block++;
93  }
94  brelse(bh);
95  filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
96  goto out;
97  }
98  slot++;
99  }
100  brelse(bh);
101 
102  slot = 0;
103  block++;
104  }
105 
106  filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
107 out:
108  return 0;
109 }
110