This source file includes following definitions.
- find_rock_ridge_relocation
- get_rock_ridge_filename
- parse_rock_ridge_inode
- get_rock_ridge_symlink
1
2
3
4
5
6
7
8 #include <linux/config.h>
9 #include <linux/stat.h>
10 #include <linux/sched.h>
11 #include <linux/iso_fs.h>
12 #include <linux/string.h>
13 #include <linux/mm.h>
14
15 #include "rock.h"
16
17
18
19
20
21
22
23
24 #define SIG(A,B) ((A << 8) | B)
25
26
27
28
29 #define CHECK_SP(FAIL) \
30 if(rr->u.SP.magic[0] != 0xbe) FAIL; \
31 if(rr->u.SP.magic[1] != 0xef) FAIL;
32
33
34
35
36
37 #define CONTINUE_DECLS \
38 int cont_extent = 0, cont_offset = 0, cont_size = 0; \
39 char * buffer = 0
40
41 #define CHECK_CE \
42 {cont_extent = isonum_733(rr->u.CE.extent); \
43 cont_offset = isonum_733(rr->u.CE.offset); \
44 cont_size = isonum_733(rr->u.CE.size);}
45
46 #define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
47 {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
48 if(LEN & 1) LEN++; \
49 CHR = ((unsigned char *) DE) + LEN; \
50 LEN = *((unsigned char *) DE) - LEN;}
51
52 #define MAYBE_CONTINUE(LABEL,DEV) \
53 {if (buffer) kfree(buffer); \
54 if (cont_extent){ \
55 int block, offset; \
56 struct buffer_head * bh; \
57 buffer = kmalloc(cont_size,GFP_KERNEL); \
58 block = cont_extent << 1; \
59 offset = cont_offset; \
60 if (offset >= 1024) block++; \
61 offset &= 1023; \
62 bh = bread(DEV, block, 1024); \
63 memcpy(buffer, bh->b_data, cont_size); \
64 brelse(bh); \
65 chr = buffer; \
66 len = cont_size; \
67 cont_extent = 0; \
68 cont_size = 0; \
69 cont_offset = 0; \
70 goto LABEL; \
71 }}
72
73
74
75
76
77 int find_rock_ridge_relocation(struct iso_directory_record * de,
78 struct inode * inode) {
79 int flag;
80 int len;
81 int retval;
82 unsigned char * chr;
83 CONTINUE_DECLS;
84 flag = 0;
85
86
87
88
89 if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
90
91 retval = isonum_733 (de->extent);
92
93 if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
94
95 SETUP_ROCK_RIDGE(de, chr, len);
96 repeat:
97 {
98 int rrflag, sig;
99 struct rock_ridge * rr;
100
101 while (len > 1){
102 rr = (struct rock_ridge *) chr;
103 if (rr->len == 0) goto out;
104 sig = (chr[0] << 8) + chr[1];
105 chr += rr->len;
106 len -= rr->len;
107
108 switch(sig){
109 case SIG('R','R'):
110 rrflag = rr->u.RR.flags[0];
111 if (flag && !(rrflag & RR_PL)) goto out;
112 if (!flag && !(rrflag & RR_CL)) goto out;
113 break;
114 case SIG('S','P'):
115 CHECK_SP(goto out);
116 break;
117 case SIG('C','L'):
118 printk("RR: CL\n");
119 if (flag == 0) {
120 retval = isonum_733(rr->u.CL.location);
121 goto out;
122 };
123 break;
124 case SIG('P','L'):
125 printk("RR: PL\n");
126 if (flag != 0) {
127 retval = isonum_733(rr->u.PL.location);
128 goto out;
129 };
130 break;
131 case SIG('C','E'):
132 CHECK_CE;
133 break;
134 default:
135 break;
136 }
137 };
138 };
139 MAYBE_CONTINUE(repeat, inode->i_dev);
140 return retval;
141 out:
142 if(buffer) kfree(buffer);
143 return retval;
144 }
145
146 int get_rock_ridge_filename(struct iso_directory_record * de,
147 char ** name, int * namlen, struct inode * inode)
148 {
149 int len;
150 unsigned char * chr;
151 CONTINUE_DECLS;
152 char * retname = NULL;
153 int retnamlen = 0, truncate=0;
154
155 if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
156
157 SETUP_ROCK_RIDGE(de, chr, len);
158 repeat:
159 {
160 struct rock_ridge * rr;
161 int sig;
162
163 while (len > 1){
164 rr = (struct rock_ridge *) chr;
165 if (rr->len == 0) goto out;
166 sig = (chr[0] << 8) + chr[1];
167 chr += rr->len;
168 len -= rr->len;
169
170 switch(sig){
171 case SIG('R','R'):
172 if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
173 break;
174 case SIG('S','P'):
175 CHECK_SP(goto out);
176 break;
177 case SIG('C','E'):
178 CHECK_CE;
179 break;
180 case SIG('N','M'):
181 if (truncate) break;
182 if (rr->u.NM.flags & ~1) {
183 printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
184 break;
185 };
186 if (!retname){
187 retname = (char *) kmalloc (255,GFP_KERNEL);
188
189
190
191
192
193
194 *retname = 0;
195 retnamlen = 0;
196 };
197 if((strlen(retname) + rr->len - 5) >= 254) {
198 truncate = 1;
199 break;
200 };
201 strncat(retname, rr->u.NM.name, rr->len - 5);
202 retnamlen += rr->len - 5;
203 break;
204 case SIG('R','E'):
205 printk("RR: RE (%x)\n", inode->i_ino);
206 if (buffer) kfree(buffer);
207 if (retname) kfree(retname);
208 return -1;
209 default:
210 break;
211 }
212 };
213 }
214 MAYBE_CONTINUE(repeat,inode->i_dev);
215 if(retname){
216 *name = retname;
217 *namlen = retnamlen;
218 return 1;
219 };
220 return 0;
221 out:
222 if(buffer) kfree(buffer);
223 if (retname) kfree(retname);
224 return 0;
225 }
226
227 int parse_rock_ridge_inode(struct iso_directory_record * de,
228 struct inode * inode){
229 int len;
230 unsigned char * chr;
231 CONTINUE_DECLS;
232
233 if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
234
235 SETUP_ROCK_RIDGE(de, chr, len);
236 repeat:
237 {
238 int cnt, sig;
239 struct inode * reloc;
240 struct rock_ridge * rr;
241
242 while (len > 1){
243 rr = (struct rock_ridge *) chr;
244 if (rr->len == 0) goto out;
245 sig = (chr[0] << 8) + chr[1];
246 chr += rr->len;
247 len -= rr->len;
248
249 switch(sig){
250 case SIG('R','R'):
251 if((rr->u.RR.flags[0] &
252 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
253 break;
254 case SIG('S','P'):
255 CHECK_SP(goto out);
256 break;
257 case SIG('C','E'):
258 CHECK_CE;
259 break;
260 case SIG('E','R'):
261 printk("ISO9660 Extensions: ");
262 { int p;
263 for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
264 };
265 printk("\n");
266 break;
267 case SIG('P','X'):
268 inode->i_mode = isonum_733(rr->u.PX.mode);
269 inode->i_nlink = isonum_733(rr->u.PX.n_links);
270 inode->i_uid = isonum_733(rr->u.PX.uid);
271 inode->i_gid = isonum_733(rr->u.PX.gid);
272 break;
273 case SIG('P','N'):
274 { int high, low;
275 high = isonum_733(rr->u.PN.dev_high);
276 low = isonum_733(rr->u.PN.dev_low);
277 inode->i_rdev = ((high << 8) | (low && 0xff)) & 0xffff;
278 };
279 break;
280 case SIG('T','F'):
281 cnt = 0;
282 if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
283 if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
284 if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
285 break;
286 case SIG('S','L'):
287 {int slen;
288 struct SL_component * slp;
289 slen = rr->len - 5;
290 slp = &rr->u.SL.link;
291 while (slen > 1){
292 switch(slp->flags &~1){
293 case 0:
294 inode->i_size += slp->len;
295 break;
296 case 2:
297 inode->i_size += 1;
298 break;
299 case 4:
300 inode->i_size += 2;
301 break;
302 case 8:
303 inode->i_size += 1;
304 break;
305 default:
306 printk("Symlink component flag not implemented\n");
307 };
308 slen -= slp->len + 2;
309 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
310
311 if(slen < 2) break;
312 inode->i_size += 1;
313 };
314 };
315 break;
316 case SIG('R','E'):
317 printk("Attempt to read inode for relocated directory\n");
318 goto out;
319 case SIG('C','L'):
320 printk("RR CL (%x)\n",inode->i_ino);
321 inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
322 reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent << ISOFS_BLOCK_BITS);
323 inode->i_mode = reloc->i_mode;
324 inode->i_nlink = reloc->i_nlink;
325 inode->i_uid = reloc->i_uid;
326 inode->i_gid = reloc->i_gid;
327 inode->i_rdev = reloc->i_rdev;
328 inode->i_size = reloc->i_size;
329 inode->i_atime = reloc->i_atime;
330 inode->i_ctime = reloc->i_ctime;
331 inode->i_mtime = reloc->i_mtime;
332 iput(reloc);
333 break;
334 default:
335 break;
336 }
337 };
338 }
339 MAYBE_CONTINUE(repeat,inode->i_dev);
340 return 0;
341 out:
342 if(buffer) kfree(buffer);
343 return 0;
344 }
345
346
347
348
349
350 char * get_rock_ridge_symlink(struct inode * inode)
351 {
352 struct buffer_head * bh;
353 unsigned char * pnt, *cpnt = 0;
354 char * rpnt;
355 struct iso_directory_record * raw_inode;
356 CONTINUE_DECLS;
357 int block;
358 int sig;
359 int len;
360 char * chr;
361 struct rock_ridge * rr;
362
363 if (!inode->i_sb->u.isofs_sb.s_rock)
364 panic("Cannot have symlink with high sierra variant of iso filesystem\n");
365
366 rpnt = 0;
367
368 block = inode->i_ino >> ISOFS_BUFFER_BITS;
369 if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
370 panic("unable to read i-node block");
371
372 pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
373
374 raw_inode = ((struct iso_directory_record *) pnt);
375
376 if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
377 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
378 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
379 brelse(bh);
380 if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
381 panic("unable to read i-node block");
382 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
383 pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
384 raw_inode = ((struct iso_directory_record *) pnt);
385 };
386
387
388
389
390 SETUP_ROCK_RIDGE(raw_inode, chr, len);
391
392 repeat:
393 while (len > 1){
394 if (rpnt) break;
395 rr = (struct rock_ridge *) chr;
396 if (rr->len == 0) goto out;
397 sig = (chr[0] << 8) + chr[1];
398 chr += rr->len;
399 len -= rr->len;
400
401 switch(sig){
402 case SIG('R','R'):
403 if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
404 break;
405 case SIG('S','P'):
406 CHECK_SP(goto out);
407 break;
408 case SIG('S','L'):
409 {int slen;
410 struct SL_component * slp;
411 slen = rr->len - 5;
412 slp = &rr->u.SL.link;
413 while (slen > 1){
414 if (!rpnt){
415 rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
416 *rpnt = 0;
417 };
418 switch(slp->flags &~1){
419 case 0:
420 strncat(rpnt,slp->text, slp->len);
421 break;
422 case 2:
423 strcat(rpnt,".");
424 break;
425 case 4:
426 strcat(rpnt,"..");
427 break;
428 case 8:
429 strcpy(rpnt,"/");
430 break;
431 default:
432 printk("Symlink component flag not implemented (%d)\n",slen);
433 };
434 slen -= slp->len + 2;
435 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
436
437 if(slen < 2) break;
438 strcat(rpnt,"/");
439 };
440 break;
441 default:
442 break;
443 }
444 };
445 };
446 MAYBE_CONTINUE(repeat,inode->i_dev);
447 brelse(bh);
448
449 if (cpnt) {
450 kfree(cpnt);
451 cpnt = 0;
452 };
453 return rpnt;
454 out:
455 if(buffer) kfree(buffer);
456 return 0;
457 }
458
459
460
461
462
463