This source file includes following definitions.
- isofs_match
- isofs_find_entry
- isofs_lookup
1
2
3
4
5
6
7
8
9 #include <linux/sched.h>
10 #include <linux/iso_fs.h>
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14 #include <linux/fcntl.h>
15 #include <asm/segment.h>
16 #include <linux/malloc.h>
17
18 #include <linux/errno.h>
19
20
21
22
23
24
25
26
27 static int isofs_match(int len,const char * name, const char * compare, int dlen)
28 {
29 if (!compare)
30 return 0;
31
32
33 if (dlen == 1) {
34
35 if (compare[0] == 0) {
36 if (!len)
37 return 1;
38 compare = ".";
39 } else if (compare[0] == 1) {
40 compare = "..";
41 dlen = 2;
42 }
43 }
44 #if 0
45 if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
46 #endif
47
48 if (dlen != len)
49 return 0;
50 return !memcmp(name, compare, len);
51 }
52
53
54
55
56
57
58
59
60
61 static struct buffer_head * isofs_find_entry(struct inode * dir,
62 const char * name, int namelen, unsigned long * ino, unsigned long * ino_back)
63 {
64 unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
65 unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
66 unsigned int block, i, f_pos, offset, inode_number;
67 struct buffer_head * bh;
68 void * cpnt = NULL;
69 unsigned int old_offset;
70 unsigned int backlink;
71 int dlen, rrflag, match;
72 char * dpnt;
73 struct iso_directory_record * de;
74 char c;
75
76 *ino = 0;
77 if (!dir) return NULL;
78
79 if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
80
81 f_pos = 0;
82
83 offset = f_pos & (bufsize - 1);
84 block = isofs_bmap(dir,f_pos >> bufbits);
85
86 if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL;
87
88 while (f_pos < dir->i_size) {
89 de = (struct iso_directory_record *) (bh->b_data + offset);
90 backlink = dir->i_ino;
91 inode_number = (block << bufbits) + (offset & (bufsize - 1));
92
93
94
95
96 if (*((unsigned char *) de) == 0) {
97 brelse(bh);
98 offset = 0;
99 f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
100 + ISOFS_BLOCK_SIZE);
101 block = isofs_bmap(dir,f_pos>>bufbits);
102 if (!block || !(bh = bread(dir->i_dev,block,bufsize)))
103 return 0;
104 continue;
105 }
106
107 old_offset = offset;
108 offset += *((unsigned char *) de);
109 f_pos += *((unsigned char *) de);
110
111
112
113 if (offset >= bufsize) {
114 unsigned int frag1;
115 frag1 = bufsize - old_offset;
116 cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
117 if (!cpnt) return 0;
118 memcpy(cpnt, bh->b_data + old_offset, frag1);
119
120 de = (struct iso_directory_record *) cpnt;
121 brelse(bh);
122 offset = f_pos & (bufsize - 1);
123 block = isofs_bmap(dir,f_pos>>bufbits);
124 if (!block || !(bh = bread(dir->i_dev,block,bufsize))) {
125 kfree(cpnt);
126 return 0;
127 };
128 memcpy((char *)cpnt+frag1, bh->b_data, offset);
129 }
130
131
132
133 if (de->name[0]==0 && de->name_len[0]==1) {
134 inode_number = dir->i_ino;
135 backlink = 0;
136 }
137
138
139
140 if (de->name[0]==1 && de->name_len[0]==1) {
141 #if 0
142 printk("Doing .. (%d %d)",
143 dir->i_sb->s_firstdatazone,
144 dir->i_ino);
145 #endif
146 if((dir->i_sb->u.isofs_sb.s_firstdatazone) != dir->i_ino)
147 inode_number = dir->u.isofs_i.i_backlink;
148 else
149 inode_number = dir->i_ino;
150 backlink = 0;
151 }
152
153 dlen = de->name_len[0];
154 dpnt = de->name;
155
156 rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir);
157 if (rrflag) {
158 if (rrflag == -1) goto out;
159 } else {
160 if(dir->i_sb->u.isofs_sb.s_mapping == 'n') {
161 for (i = 0; i < dlen; i++) {
162 c = dpnt[i];
163 if (c >= 'A' && c <= 'Z') c |= 0x20;
164 if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {
165 dlen -= 2;
166 break;
167 }
168 if (c == ';') c = '.';
169 de->name[i] = c;
170 }
171
172
173 if(dpnt[dlen-1] == '.' && namelen == dlen-1)
174 dlen--;
175 }
176 }
177
178
179
180 match = 0;
181 if( !(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)
182 || dir->i_sb->u.isofs_sb.s_unhide == 'y' )
183 {
184 match = isofs_match(namelen,name,dpnt,dlen);
185 }
186
187 if (cpnt)
188 {
189 kfree(cpnt);
190 cpnt = NULL;
191 }
192
193 if(rrflag) kfree(dpnt);
194 if (match) {
195 if(inode_number == -1) {
196
197 inode_number =
198 isofs_lookup_grandparent(dir,
199 find_rock_ridge_relocation(de,dir));
200 if(inode_number == -1){
201
202 printk("Backlink not properly set %x %lx.\n",
203 isonum_733(de->extent),
204 dir->i_ino);
205 goto out;
206 }
207 }
208 *ino = inode_number;
209 *ino_back = backlink;
210 return bh;
211 }
212 }
213 out:
214 if (cpnt)
215 kfree(cpnt);
216 brelse(bh);
217 return NULL;
218 }
219
220 int isofs_lookup(struct inode * dir,const char * name, int len,
221 struct inode ** result)
222 {
223 unsigned long ino, ino_back;
224 struct buffer_head * bh;
225
226 #ifdef DEBUG
227 printk("lookup: %x %d\n",dir->i_ino, len);
228 #endif
229 *result = NULL;
230 if (!dir)
231 return -ENOENT;
232
233 if (!S_ISDIR(dir->i_mode)) {
234 iput(dir);
235 return -ENOENT;
236 }
237
238 ino = 0;
239
240 if (dcache_lookup(dir, name, len, &ino)) ino_back = dir->i_ino;
241
242 if (!ino) {
243 char *lcname;
244
245
246
247 if (dir->i_sb->u.isofs_sb.s_name_check == 'r'
248 && (lcname = kmalloc(len, GFP_KERNEL)) != NULL) {
249 int i;
250 char c;
251
252 for (i=0; i<len; i++) {
253 c = name[i];
254 if (c >= 'A' && c <= 'Z') c |= 0x20;
255 lcname[i] = c;
256 }
257 bh = isofs_find_entry(dir,lcname,len, &ino, &ino_back);
258 kfree(lcname);
259 } else
260 bh = isofs_find_entry(dir,name,len, &ino, &ino_back);
261
262 if (!bh) {
263 iput(dir);
264 return -ENOENT;
265 }
266 if (ino_back == dir->i_ino)
267 dcache_add(dir, name, len, ino);
268 brelse(bh);
269 }
270
271 if (!(*result = iget(dir->i_sb,ino))) {
272 iput(dir);
273 return -EACCES;
274 }
275
276
277
278
279
280
281
282 if (ino_back && !(*result)->i_pipe && (*result)->i_sb == dir->i_sb) {
283 (*result)->u.isofs_i.i_backlink = ino_back;
284 }
285
286 iput(dir);
287 return 0;
288 }