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