Ignore more junk files.
[linux-2.6/linux-mips.git] / fs / isofs / dir.c
blob1b99acb1995ce3d7344bf03fe3410a57635c1cd1
1 /*
2 * linux/fs/isofs/dir.c
4 * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem.
6 * (C) 1991 Linus Torvalds - minix filesystem
8 * Steve Beynon : Missing last directory entries fixed
9 * (stephen@askone.demon.co.uk) : 21st June 1996
11 * isofs directory handling functions
13 #include <linux/errno.h>
14 #include <linux/fs.h>
15 #include <linux/iso_fs.h>
16 #include <linux/kernel.h>
17 #include <linux/stat.h>
18 #include <linux/string.h>
19 #include <linux/mm.h>
20 #include <linux/malloc.h>
21 #include <linux/sched.h>
22 #include <linux/locks.h>
23 #include <linux/config.h>
25 #include <asm/uaccess.h>
27 static int isofs_readdir(struct file *, void *, filldir_t);
29 struct file_operations isofs_dir_operations =
31 read: generic_read_dir,
32 readdir: isofs_readdir,
36 * directories can handle most operations...
38 struct inode_operations isofs_dir_inode_operations =
40 lookup: isofs_lookup,
43 static int isofs_name_translate(char * old, int len, char * new)
45 int i, c;
47 for (i = 0; i < len; i++) {
48 c = old[i];
49 if (!c)
50 break;
51 if (c >= 'A' && c <= 'Z')
52 c |= 0x20; /* lower case */
54 /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
55 if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
56 break;
58 /* Drop trailing ';1' */
59 if (c == ';' && i == len - 2 && old[i + 1] == '1')
60 break;
62 /* Convert remaining ';' to '.' */
63 if (c == ';')
64 c = '.';
66 new[i] = c;
68 return i;
71 /* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
72 int get_acorn_filename(struct iso_directory_record * de,
73 char * retname, struct inode * inode)
75 int std;
76 unsigned char * chr;
77 int retnamlen = isofs_name_translate(de->name,
78 de->name_len[0], retname);
79 if (retnamlen == 0) return 0;
80 std = sizeof(struct iso_directory_record) + de->name_len[0];
81 if (std & 1) std++;
82 if ((*((unsigned char *) de) - std) != 32) return retnamlen;
83 chr = ((unsigned char *) de) + std;
84 if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen;
85 if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!';
86 if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
87 && ((chr[12] & 0xf0) == 0xf0))
89 retname[retnamlen] = ',';
90 sprintf(retname+retnamlen+1, "%3.3x",
91 ((chr[12] & 0xf) << 8) | chr[11]);
92 retnamlen += 4;
94 return retnamlen;
98 * This should _really_ be cleaned up some day..
100 static int do_isofs_readdir(struct inode *inode, struct file *filp,
101 void *dirent, filldir_t filldir,
102 char * tmpname, struct iso_directory_record * tmpde)
104 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
105 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
106 unsigned int block, offset;
107 int inode_number = 0; /* Quiet GCC */
108 struct buffer_head *bh;
109 int len;
110 int map;
111 int high_sierra;
112 int first_de = 1;
113 char *p = NULL; /* Quiet GCC */
114 struct iso_directory_record *de;
116 if (filp->f_pos >= inode->i_size)
117 return 0;
119 offset = filp->f_pos & (bufsize - 1);
120 block = isofs_bmap(inode, filp->f_pos >> bufbits);
121 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
123 if (!block)
124 return 0;
126 if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
127 return 0;
129 while (filp->f_pos < inode->i_size) {
130 int de_len;
131 #ifdef DEBUG
132 printk("Block, offset, f_pos: %x %x %x\n",
133 block, offset, filp->f_pos);
134 printk("inode->i_size = %x\n",inode->i_size);
135 #endif
136 /* Next directory_record on next CDROM sector */
137 if (offset >= bufsize) {
138 #ifdef DEBUG
139 printk("offset >= bufsize\n");
140 #endif
141 brelse(bh);
142 offset = 0;
143 block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
144 if (!block)
145 return 0;
146 bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
147 if (!bh)
148 return 0;
149 continue;
152 de = (struct iso_directory_record *) (bh->b_data + offset);
153 if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
155 de_len = *(unsigned char *) de;
156 #ifdef DEBUG
157 printk("de_len = %d\n", de_len);
158 #endif
161 /* If the length byte is zero, we should move on to the next
162 CDROM sector. If we are at the end of the directory, we
163 kick out of the while loop. */
165 if (de_len == 0) {
166 brelse(bh);
167 filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
168 + ISOFS_BLOCK_SIZE);
169 offset = 0;
171 if (filp->f_pos >= inode->i_size)
172 return 0;
174 block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
175 if (!block)
176 return 0;
177 bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
178 if (!bh)
179 return 0;
180 continue;
183 offset += de_len;
184 if (offset > bufsize) {
186 * This would only normally happen if we had
187 * a buggy cdrom image. All directory
188 * entries should terminate with a null size
189 * or end exactly at the end of the sector.
191 printk("next_offset (%x) > bufsize (%lx)\n",
192 offset,bufsize);
193 break;
196 if(de->flags[-high_sierra] & 0x80) {
197 first_de = 0;
198 filp->f_pos += de_len;
199 continue;
201 first_de = 1;
203 /* Handle the case of the '.' directory */
204 if (de->name_len[0] == 1 && de->name[0] == 0) {
205 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
206 break;
207 filp->f_pos += de_len;
208 continue;
211 len = 0;
213 /* Handle the case of the '..' directory */
214 if (de->name_len[0] == 1 && de->name[0] == 1) {
215 inode_number = filp->f_dentry->d_parent->d_inode->i_ino;
216 if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
217 break;
218 filp->f_pos += de_len;
219 continue;
222 /* Handle everything else. Do name translation if there
223 is no Rock Ridge NM field. */
224 if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
225 /* Do not report hidden or associated files */
226 if (de->flags[-high_sierra] & 5) {
227 filp->f_pos += de_len;
228 continue;
232 map = 1;
233 if (inode->i_sb->u.isofs_sb.s_rock) {
234 len = get_rock_ridge_filename(de, tmpname, inode);
235 if (len != 0) {
236 p = tmpname;
237 map = 0;
240 if (map) {
241 #ifdef CONFIG_JOLIET
242 if (inode->i_sb->u.isofs_sb.s_joliet_level) {
243 len = get_joliet_filename(de, inode, tmpname);
244 p = tmpname;
245 } else
246 #endif
247 if (inode->i_sb->u.isofs_sb.s_mapping == 'a') {
248 len = get_acorn_filename(de, tmpname, inode);
249 p = tmpname;
250 } else
251 if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
252 len = isofs_name_translate(de->name,
253 de->name_len[0], tmpname);
254 p = tmpname;
255 } else {
256 p = de->name;
257 len = de->name_len[0];
260 if (len > 0) {
261 if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0)
262 break;
264 filp->f_pos += de_len;
266 continue;
268 brelse(bh);
269 return 0;
273 * Handle allocation of temporary space for name translation and
274 * handling split directory entries.. The real work is done by
275 * "do_isofs_readdir()".
277 static int isofs_readdir(struct file *filp,
278 void *dirent, filldir_t filldir)
280 int result;
281 char * tmpname;
282 struct iso_directory_record * tmpde;
283 struct inode *inode = filp->f_dentry->d_inode;
285 tmpname = (char *) __get_free_page(GFP_KERNEL);
286 if (!tmpname)
287 return -ENOMEM;
288 tmpde = (struct iso_directory_record *) (tmpname+1024);
290 result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
292 free_page((unsigned long) tmpname);
293 return result;