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 void * cpnt = NULL;
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 & (ISOFS_BUFFER_SIZE(inode) - 1);
80 block = isofs_bmap(inode,(filp->f_pos)>>ISOFS_BUFFER_BITS(inode));
81 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE(inode))))
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 << ISOFS_BUFFER_BITS(inode))+(offset & (ISOFS_BUFFER_SIZE(inode) - 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)>>ISOFS_BUFFER_BITS(inode));
99 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE(inode))))
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
112 if (offset >= ISOFS_BUFFER_SIZE(inode)) {
113 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
114 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE(inode));
115 de = (struct iso_directory_record *) (old_offset + cpnt);
116 brelse(bh);
117 offset = filp->f_pos & (ISOFS_BUFFER_SIZE(inode) - 1);
118 block = isofs_bmap(inode,(filp->f_pos)>> ISOFS_BUFFER_BITS(inode));
119 if (!block || !(bh = bread(inode->i_dev,block,ISOFS_BUFFER_SIZE(inode))))
120 return 0;
121 memcpy(cpnt+ISOFS_BUFFER_SIZE(inode), bh->b_data, ISOFS_BUFFER_SIZE(inode));
122 }
123
124
125
126 rrflag = 0;
127 i = 1;
128 if (de->name_len[0] == 1 && de->name[0] == 0) {
129 put_fs_byte('.',dirent->d_name);
130 inode_number = inode->i_ino;
131 dpnt = ".";
132 }
133
134
135
136 else if (de->name_len[0] == 1 && de->name[0] == 1) {
137 put_fs_byte('.',dirent->d_name);
138 put_fs_byte('.',dirent->d_name+1);
139 i = 2;
140 dpnt = "..";
141 if((inode->i_sb->u.isofs_sb.s_firstdatazone << ISOFS_BUFFER_BITS(inode)) != inode->i_ino)
142 inode_number = inode->u.isofs_i.i_backlink;
143 else
144 inode_number = inode->i_ino;
145
146
147 if(inode_number == -1) {
148 inode_number =
149 isofs_lookup_grandparent(inode,
150 find_rock_ridge_relocation(de, inode));
151 if(inode_number == -1){
152 printk("Backlink not properly set.\n");
153 goto out;
154 };
155 }
156 }
157
158
159
160
161 else {
162 dlen = de->name_len[0];
163 dpnt = de->name;
164 i = dlen;
165 rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, inode);
166 if (rrflag) {
167 if (rrflag == -1) {
168 if (cpnt) {
169 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
170 cpnt = NULL;
171 };
172 continue;
173 };
174 i = dlen;
175 }
176 else
177 if(inode->i_sb->u.isofs_sb.s_mapping == 'n')
178 for (i = 0; i < dlen && i < NAME_MAX; i++) {
179 if (!(c = dpnt[i])) break;
180 if (c >= 'A' && c <= 'Z') c |= 0x20;
181 if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
182 break;
183 if (c == ';') c = '.';
184 dpnt[i] = c;
185 };
186
187 for(j=0; j<i; j++)
188 put_fs_byte(dpnt[j],j+dirent->d_name);
189 };
190 #if 0
191 printk("Nchar: %d\n",i);
192 #endif
193
194 if (i) {
195 while (cache.lock);
196 cache.lock = 1;
197 cache.ino = inode_number;
198 cache.dir = inode->i_ino;
199 cache.dev = inode->i_dev;
200 strncpy(cache.filename, dpnt, i);
201 cache.dlen = dlen;
202 cache.lock = 0;
203 };
204
205 if (rrflag) kfree(dpnt);
206 if (cpnt) {
207 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
208 cpnt = NULL;
209 };
210
211 if (i) {
212 put_fs_long(inode_number, &dirent->d_ino);
213 put_fs_byte(0,i+dirent->d_name);
214 put_fs_word(i,&dirent->d_reclen);
215 brelse(bh);
216 return i;
217 }
218 }
219
220
221 out:
222 if (cpnt)
223 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
224 brelse(bh);
225 return 0;
226 }
227
228
229