This source file includes following definitions.
- ext2_dir_read
- ext2_check_dir_entry
- ext2_readdir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <asm/segment.h>
16
17 #include <linux/errno.h>
18 #include <linux/fs.h>
19 #include <linux/ext2_fs.h>
20 #include <linux/sched.h>
21 #include <linux/stat.h>
22
23 #if 0
24 static int ext2_dir_read (struct inode * inode, struct file * filp,
25 char * buf, int count)
26 {
27 return -EISDIR;
28 }
29 #endif
30
31 int ext2_file_read (struct inode *, struct file *, char *, int);
32 static int ext2_readdir (struct inode *, struct file *, struct dirent *, int);
33
34 static struct file_operations ext2_dir_operations = {
35 NULL,
36 ext2_file_read,
37 NULL,
38 ext2_readdir,
39 NULL,
40 ext2_ioctl,
41 NULL,
42 NULL,
43 NULL,
44 file_fsync
45 };
46
47
48
49
50 struct inode_operations ext2_dir_inode_operations = {
51 &ext2_dir_operations,
52 ext2_create,
53 ext2_lookup,
54 ext2_link,
55 ext2_unlink,
56 ext2_symlink,
57 ext2_mkdir,
58 ext2_rmdir,
59 ext2_mknod,
60 ext2_rename,
61 NULL,
62 NULL,
63 NULL,
64 ext2_truncate,
65 ext2_permission
66 };
67
68 int ext2_check_dir_entry (char * function, struct inode * dir,
69 struct ext2_dir_entry * de, struct buffer_head * bh,
70 unsigned long offset)
71 {
72 char * error_msg = NULL;
73
74 if (de->rec_len < EXT2_DIR_REC_LEN(1))
75 error_msg = "rec_len is smaller than minimal";
76 else if (de->rec_len % 4 != 0)
77 error_msg = "rec_len % 4 != 0";
78 else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len))
79 error_msg = "rec_len is too small for name_len";
80 else if (dir && ((char *) de - bh->b_data) + de->rec_len >
81 dir->i_sb->s_blocksize)
82 error_msg = "directory entry across blocks";
83
84 if (error_msg != NULL)
85 ext2_error (dir->i_sb, function, "bad directory entry: %s\n"
86 "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
87 error_msg, offset, de->inode, de->rec_len,
88 de->name_len);
89 return error_msg == NULL ? 1 : 0;
90 }
91
92 static int ext2_readdir (struct inode * inode, struct file * filp,
93 struct dirent * dirent, int count)
94 {
95 unsigned long offset;
96 int i;
97 struct buffer_head * bh;
98 struct ext2_dir_entry * de;
99 struct super_block * sb;
100 int err;
101
102 if (!inode || !S_ISDIR(inode->i_mode))
103 return -EBADF;
104 sb = inode->i_sb;
105 while (filp->f_pos < inode->i_size) {
106 offset = filp->f_pos & (sb->s_blocksize - 1);
107 bh = ext2_bread (inode, (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb),
108 0, &err);
109 if (!bh) {
110 filp->f_pos += sb->s_blocksize - offset;
111 continue;
112 }
113 de = (struct ext2_dir_entry *) (offset + bh->b_data);
114 while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) {
115 if (! ext2_check_dir_entry ("ext2_readdir", inode, de,
116 bh, offset)) {
117 brelse (bh);
118 return 0;
119 }
120 offset += de->rec_len;
121 filp->f_pos += de->rec_len;
122 if (de->inode) {
123 memcpy_tofs (dirent->d_name, de->name,
124 de->name_len);
125 put_fs_long (de->inode, &dirent->d_ino);
126 put_fs_byte (0, de->name_len + dirent->d_name);
127 put_fs_word (de->name_len, &dirent->d_reclen);
128 #ifndef DONT_USE_DCACHE
129 ext2_dcache_add (inode->i_dev, inode->i_ino,
130 de->name, de->name_len,
131 de->inode);
132 #endif
133 i = de->name_len;
134 brelse (bh);
135 if (!IS_RDONLY(inode)) {
136 inode->i_atime = CURRENT_TIME;
137 inode->i_dirt = 1;
138 }
139 return i;
140 }
141 de = (struct ext2_dir_entry *) ((char *) de +
142 de->rec_len);
143 }
144 brelse (bh);
145 }
146 if (!IS_RDONLY(inode)) {
147 inode->i_atime = CURRENT_TIME;
148 inode->i_dirt = 1;
149 }
150 return 0;
151 }