This source file includes following definitions.
- parent_inode_number
- isofs_name_translate
- do_isofs_readdir
- isofs_readdir
1
2
3
4
5
6
7
8
9
10
11 #include <linux/errno.h>
12 #include <linux/fs.h>
13 #include <linux/iso_fs.h>
14 #include <linux/kernel.h>
15 #include <linux/stat.h>
16 #include <linux/string.h>
17 #include <linux/mm.h>
18 #include <linux/malloc.h>
19 #include <linux/sched.h>
20 #include <linux/locks.h>
21
22 #include <asm/segment.h>
23
24 static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
25
26 static struct file_operations isofs_dir_operations =
27 {
28 NULL,
29 NULL,
30 NULL,
31 isofs_readdir,
32 NULL,
33 NULL,
34 NULL,
35 NULL,
36 NULL
37 };
38
39
40
41
42 struct inode_operations isofs_dir_inode_operations =
43 {
44 &isofs_dir_operations,
45 NULL,
46 isofs_lookup,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 isofs_bmap,
57 NULL,
58 NULL
59 };
60
61 static int parent_inode_number(struct inode * inode, struct iso_directory_record * de)
62 {
63 int inode_number = inode->i_ino;
64
65 if ((inode->i_sb->u.isofs_sb.s_firstdatazone) != inode->i_ino)
66 inode_number = inode->u.isofs_i.i_backlink;
67
68 if (inode_number != -1)
69 return inode_number;
70
71
72 return isofs_lookup_grandparent(inode, find_rock_ridge_relocation(de, inode));
73 }
74
75 static int isofs_name_translate(char * old, int len, char * new)
76 {
77 int i, c;
78
79 for (i = 0; i < len; i++) {
80 c = old[i];
81 if (!c)
82 break;
83 if (c >= 'A' && c <= 'Z')
84 c |= 0x20;
85
86
87 if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
88 break;
89
90
91 if (c == ';' && i == len - 2 && old[i + 1] == '1')
92 break;
93
94
95 if (c == ';')
96 c = '.';
97
98 new[i] = c;
99 }
100 return i;
101 }
102
103
104
105
106 static int do_isofs_readdir(struct inode *inode, struct file *filp,
107 void *dirent, filldir_t filldir,
108 char * tmpname, struct iso_directory_record * tmpde)
109 {
110 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
111 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
112 unsigned int block, offset;
113 int inode_number;
114 struct buffer_head *bh;
115 int len, rrflag;
116 int high_sierra = 0;
117 char *name;
118 struct iso_directory_record *de;
119
120 offset = filp->f_pos & (bufsize - 1);
121 block = isofs_bmap(inode, filp->f_pos >> bufbits);
122
123 if (!block)
124 return 0;
125
126 if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
127 return 0;
128
129 while (filp->f_pos < inode->i_size) {
130 int de_len, next_offset;
131 #ifdef DEBUG
132 printk("Block, offset, f_pos: %x %x %x\n",
133 block, offset, filp->f_pos);
134 #endif
135
136 if (offset >= bufsize) {
137 brelse(bh);
138 offset = 0;
139 block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
140 if (!block)
141 return 0;
142 bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
143 if (!bh)
144 return 0;
145 continue;
146 }
147
148 de = (struct iso_directory_record *) (bh->b_data + offset);
149 inode_number = (block << bufbits) + (offset & (bufsize - 1));
150
151 de_len = *(unsigned char *) de;
152
153
154
155
156
157 if (de_len == 0) {
158 brelse(bh);
159 filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
160 + ISOFS_BLOCK_SIZE);
161 offset = 0;
162 block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
163 if (!block)
164 return 0;
165 bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
166 if (!bh)
167 return 0;
168 continue;
169 }
170
171
172
173
174 next_offset = offset + de_len;
175 if (next_offset > bufsize) {
176 next_offset &= (bufsize - 1);
177 memcpy(tmpde, de, bufsize - offset);
178 brelse(bh);
179 block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
180 if (!block)
181 return 0;
182 bh = breada(inode->i_dev, block, bufsize, filp->f_pos+de_len, inode->i_size);
183 if (!bh)
184 return 0;
185 memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
186 de = tmpde;
187 }
188 offset = next_offset;
189
190
191 if (de->name_len[0] == 1 && de->name[0] == 0) {
192 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
193 break;
194 filp->f_pos += de_len;
195 continue;
196 }
197
198
199 if (de->name_len[0] == 1 && de->name[0] == 1) {
200 inode_number = parent_inode_number(inode, de);
201 if (inode_number == -1)
202 break;
203 if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
204 break;
205 filp->f_pos += de_len;
206 continue;
207 }
208
209
210
211
212 if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
213
214 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
215 if (de->flags[-high_sierra] & 5) {
216 filp->f_pos += de_len;
217 continue;
218 }
219 }
220
221
222 len = de->name_len[0];
223 name = de->name;
224 rrflag = get_rock_ridge_filename(de, &name, &len, inode);
225 if (rrflag) {
226
227 if (rrflag == 1) {
228 rrflag = filldir(dirent, name, len, filp->f_pos, inode_number);
229 dcache_add(inode, name, len, inode_number);
230 kfree(name);
231 if (rrflag < 0)
232 break;
233 }
234 filp->f_pos += de_len;
235 continue;
236 }
237
238 if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
239 len = isofs_name_translate(name, len, tmpname);
240 if (filldir(dirent, tmpname, len, filp->f_pos, inode_number) < 0)
241 break;
242 dcache_add(inode, tmpname, len, inode_number);
243 filp->f_pos += de_len;
244 continue;
245 }
246
247 if (filldir(dirent, name, len, filp->f_pos, inode_number) < 0)
248 break;
249
250 dcache_add(inode, name, len, inode_number);
251 filp->f_pos += de_len;
252 continue;
253 }
254 brelse(bh);
255 return 0;
256 }
257
258
259
260
261
262
263 static int isofs_readdir(struct inode *inode, struct file *filp,
264 void *dirent, filldir_t filldir)
265 {
266 int result;
267 char * tmpname;
268 struct iso_directory_record * tmpde;
269
270 if (!inode || !S_ISDIR(inode->i_mode))
271 return -EBADF;
272
273 tmpname = (char *) __get_free_page(GFP_KERNEL);
274 if (!tmpname)
275 return -ENOMEM;
276 tmpde = (struct iso_directory_record *) (tmpname+256);
277
278 result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
279
280 free_page((unsigned long) tmpname);
281 return result;
282 }