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