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