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