This source file includes following definitions.
- isofs_readdir
1
2
3
4
5
6
7
8
9
10
11 #include <linux/errno.h>
12
13 #include <asm/segment.h>
14
15 #include <linux/fs.h>
16 #include <linux/iso_fs.h>
17 #include <linux/kernel.h>
18 #include <linux/stat.h>
19 #include <linux/string.h>
20 #include <linux/mm.h>
21
22 static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
23
24 static struct file_operations isofs_dir_operations = {
25 NULL,
26 NULL,
27 NULL,
28 isofs_readdir,
29 NULL,
30 NULL,
31 NULL,
32 NULL,
33 NULL
34 };
35
36
37
38
39 struct inode_operations isofs_dir_inode_operations = {
40 &isofs_dir_operations,
41 NULL,
42 isofs_lookup,
43 NULL,
44 NULL,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 isofs_bmap,
53 NULL,
54 NULL
55 };
56
57
58
59
60
61 struct lookup_cache cache = {0,};
62
63 static int isofs_readdir(struct inode * inode, struct file * filp,
64 struct dirent * dirent, int count)
65 {
66 unsigned int block,offset,i, j;
67 char c = 0;
68 int inode_number;
69 struct buffer_head * bh;
70 char * cpnt = 0;
71 unsigned int old_offset;
72 int dlen, rrflag;
73 char * dpnt;
74 struct iso_directory_record * de;
75
76 if (!inode || !S_ISDIR(inode->i_mode))
77 return -EBADF;
78
79 offset = filp->f_pos & (BLOCK_SIZE - 1);
80 block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
81 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
82 return 0;
83
84 while (filp->f_pos < inode->i_size) {
85 #ifdef DEBUG
86 printk("Block, offset: %x %x %x\n",block, offset, filp->f_pos);
87 #endif
88 de = (struct iso_directory_record *) (offset + bh->b_data);
89 inode_number = (block << BLOCK_SIZE_BITS)+(offset & (BLOCK_SIZE - 1));
90
91
92
93
94 if (*((char*) de) == 0) {
95 brelse(bh);
96 offset = 0;
97 filp->f_pos =(filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))+ISOFS_BLOCK_SIZE;
98 block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
99 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
100 return 0;
101 continue;
102 }
103
104
105
106
107
108 old_offset = offset;
109 offset += *((unsigned char*) de);
110 filp->f_pos += *((unsigned char*) de);
111 if (offset >= BLOCK_SIZE) {
112 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
113 memcpy(cpnt, bh->b_data, BLOCK_SIZE);
114 de = (struct iso_directory_record *) (old_offset + cpnt);
115 brelse(bh);
116 offset = filp->f_pos & (BLOCK_SIZE - 1);
117 block = isofs_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
118 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE)))
119 return 0;
120 memcpy(cpnt+BLOCK_SIZE, bh->b_data, BLOCK_SIZE);
121 }
122
123
124
125 rrflag = 0;
126 i = 1;
127 if (de->name_len[0] == 1 && de->name[0] == 0) {
128 put_fs_byte('.',dirent->d_name);
129 inode_number = inode->i_ino;
130 dpnt = ".";
131 }
132
133
134
135 else if (de->name_len[0] == 1 && de->name[0] == 1) {
136 put_fs_byte('.',dirent->d_name);
137 put_fs_byte('.',dirent->d_name+1);
138 i = 2;
139 dpnt = "..";
140 if((inode->i_sb->u.isofs_sb.s_firstdatazone << BLOCK_SIZE_BITS) != inode->i_ino)
141 inode_number = inode->u.isofs_i.i_backlink;
142 else
143 inode_number = inode->i_ino;
144
145
146 if(inode_number == -1) {
147 inode_number =
148 isofs_lookup_grandparent(inode,
149 find_rock_ridge_relocation(de, inode));
150 if(inode_number == -1){
151 printk("Backlink not properly set.\n");
152 goto out;
153 };
154 }
155 }
156
157
158
159
160 else {
161 dlen = de->name_len[0];
162 dpnt = de->name;
163 i = dlen;
164 rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, inode);
165 if (rrflag) {
166 if (rrflag == -1) {
167 if (cpnt) {
168 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
169 cpnt = 0;
170 };
171 continue;
172 };
173 i = dlen;
174 }
175 else
176 if(inode->i_sb->u.isofs_sb.s_mapping == 'n')
177 for (i = 0; i < dlen && i < NAME_MAX; i++) {
178 if (!(c = dpnt[i])) break;
179 if (c >= 'A' && c <= 'Z') c |= 0x20;
180 if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
181 break;
182 if (c == ';') c = '.';
183 dpnt[i] = c;
184 };
185
186 for(j=0; j<i; j++)
187 put_fs_byte(dpnt[j],j+dirent->d_name);
188 };
189 #if 0
190 printk("Nchar: %d\n",i);
191 #endif
192
193 if (i) {
194 while (cache.lock);
195 cache.lock = 1;
196 cache.ino = inode_number;
197 cache.dir = inode->i_ino;
198 cache.dev = inode->i_dev;
199 strncpy(cache.filename, dpnt, i);
200 cache.dlen = dlen;
201 cache.lock = 0;
202 };
203
204 if (rrflag) kfree(dpnt);
205 if (cpnt) {
206 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
207 cpnt = 0;
208 };
209
210 if (i) {
211 put_fs_long(inode_number, &dirent->d_ino);
212 put_fs_byte(0,i+dirent->d_name);
213 put_fs_word(i,&dirent->d_reclen);
214 brelse(bh);
215 return i;
216 }
217 }
218
219
220 out:
221 if (cpnt) kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
222 brelse(bh);
223 return 0;
224 }
225
226
227