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