4 * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 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>
15 #include <linux/iso_fs.h>
16 #include <linux/kernel.h>
17 #include <linux/stat.h>
18 #include <linux/string.h>
20 #include <linux/malloc.h>
21 #include <linux/sched.h>
22 #include <linux/locks.h>
24 #include <asm/uaccess.h>
26 static int isofs_readdir(struct file
*, void *, filldir_t
);
28 static struct file_operations isofs_dir_operations
=
30 NULL
, /* lseek - default */
32 NULL
, /* write - bad */
33 isofs_readdir
, /* readdir */
34 NULL
, /* poll - default */
35 NULL
, /* ioctl - default */
36 NULL
, /* no special open code */
37 NULL
, /* no special release code */
42 * directories can handle most operations...
44 struct inode_operations isofs_dir_inode_operations
=
46 &isofs_dir_operations
, /* default directory file-ops */
48 isofs_lookup
, /* lookup */
57 NULL
, /* follow_link */
60 isofs_bmap
, /* bmap */
65 static int isofs_name_translate(char * old
, int len
, char * new)
69 for (i
= 0; i
< len
; i
++) {
73 if (c
>= 'A' && c
<= 'Z')
74 c
|= 0x20; /* lower case */
76 /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
77 if (c
== '.' && i
== len
- 3 && old
[i
+ 1] == ';' && old
[i
+ 2] == '1')
80 /* Drop trailing ';1' */
81 if (c
== ';' && i
== len
- 2 && old
[i
+ 1] == '1')
84 /* Convert remaining ';' to '.' */
94 * This should _really_ be cleaned up some day..
96 static int do_isofs_readdir(struct inode
*inode
, struct file
*filp
,
97 void *dirent
, filldir_t filldir
,
98 char * tmpname
, struct iso_directory_record
* tmpde
)
100 unsigned long bufsize
= ISOFS_BUFFER_SIZE(inode
);
101 unsigned char bufbits
= ISOFS_BUFFER_BITS(inode
);
102 unsigned int block
, offset
;
104 struct buffer_head
*bh
;
108 struct iso_directory_record
*de
;
110 if( filp
->f_pos
>= inode
->i_size
) {
115 offset
= filp
->f_pos
& (bufsize
- 1);
116 block
= isofs_bmap(inode
, filp
->f_pos
>> bufbits
);
121 if (!(bh
= breada(inode
->i_dev
, block
, bufsize
, filp
->f_pos
, inode
->i_size
)))
124 while (filp
->f_pos
< inode
->i_size
) {
127 printk("Block, offset, f_pos: %x %x %x\n",
128 block
, offset
, filp
->f_pos
);
129 printk("inode->i_size = %x\n",inode
->i_size
);
131 de
= (struct iso_directory_record
*) (bh
->b_data
+ offset
);
132 inode_number
= (block
<< bufbits
) + (offset
& (bufsize
- 1));
134 de_len
= *(unsigned char *) de
;
136 printk("de_len = %ld\n", de_len
);
140 /* If the length byte is zero, we should move on to the next
141 CDROM sector. If we are at the end of the directory, we
142 kick out of the while loop. */
144 if ((de_len
== 0) || (offset
== bufsize
) ) {
146 filp
->f_pos
= ((filp
->f_pos
& ~(ISOFS_BLOCK_SIZE
- 1))
149 if( filp
->f_pos
>= inode
->i_size
)
154 block
= isofs_bmap(inode
, (filp
->f_pos
) >> bufbits
);
157 bh
= breada(inode
->i_dev
, block
, bufsize
, filp
->f_pos
, inode
->i_size
);
164 if (offset
> bufsize
) {
166 * This would only normally happen if we had
167 * a buggy cdrom image. All directory
168 * entries should terminate with a null size
169 * or end exactly at the end of the sector.
171 printk("next_offset (%x) > bufsize (%lx)\n",
176 /* Handle the case of the '.' directory */
177 if (de
->name_len
[0] == 1 && de
->name
[0] == 0) {
178 if (filldir(dirent
, ".", 1, filp
->f_pos
, inode
->i_ino
) < 0)
180 filp
->f_pos
+= de_len
;
184 /* Handle the case of the '..' directory */
185 if (de
->name_len
[0] == 1 && de
->name
[0] == 1) {
186 inode_number
= filp
->f_dentry
->d_parent
->d_inode
->i_ino
;
187 if (filldir(dirent
, "..", 2, filp
->f_pos
, inode_number
) < 0)
189 filp
->f_pos
+= de_len
;
193 /* Handle everything else. Do name translation if there
194 is no Rock Ridge NM field. */
196 if (inode
->i_sb
->u
.isofs_sb
.s_unhide
== 'n') {
197 /* Do not report hidden or associated files */
198 high_sierra
= inode
->i_sb
->u
.isofs_sb
.s_high_sierra
;
199 if (de
->flags
[-high_sierra
] & 5) {
200 filp
->f_pos
+= de_len
;
205 /* Check Rock Ridge name translation.. */
206 len
= de
->name_len
[0];
208 rrflag
= get_rock_ridge_filename(de
, &name
, &len
, inode
);
210 /* rrflag == 1 means that we have a new name (kmalloced) */
212 rrflag
= filldir(dirent
, name
, len
, filp
->f_pos
, inode_number
);
213 kfree(name
); /* this was allocated in get_r_r_filename.. */
217 filp
->f_pos
+= de_len
;
221 if (inode
->i_sb
->u
.isofs_sb
.s_mapping
== 'n') {
222 len
= isofs_name_translate(name
, len
, tmpname
);
223 if (filldir(dirent
, tmpname
, len
, filp
->f_pos
, inode_number
) < 0)
225 filp
->f_pos
+= de_len
;
229 if (filldir(dirent
, name
, len
, filp
->f_pos
, inode_number
) < 0)
232 filp
->f_pos
+= de_len
;
240 * Handle allocation of temporary space for name translation and
241 * handling split directory entries.. The real work is done by
242 * "do_isofs_readdir()".
244 static int isofs_readdir(struct file
*filp
,
245 void *dirent
, filldir_t filldir
)
249 struct iso_directory_record
* tmpde
;
250 struct inode
*inode
= filp
->f_dentry
->d_inode
;
252 if (!inode
|| !S_ISDIR(inode
->i_mode
))
255 tmpname
= (char *) __get_free_page(GFP_KERNEL
);
258 tmpde
= (struct iso_directory_record
*) (tmpname
+256);
260 result
= do_isofs_readdir(inode
, filp
, dirent
, filldir
, tmpname
, tmpde
);
262 free_page((unsigned long) tmpname
);