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 inode->i_rdev = ((high << 8) | (low & 0xff)) & 0xffff;
309 };
310 break;
311 case SIG('T','F'):
312
313
314 cnt = 0;
315 if(rr->u.TF.flags & TF_CREATE)
316 inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
317 if(rr->u.TF.flags & TF_MODIFY)
318 inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
319 if(rr->u.TF.flags & TF_ACCESS)
320 inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
321 if(rr->u.TF.flags & TF_ATTRIBUTES)
322 inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
323 break;
324 case SIG('S','L'):
325 {int slen;
326 struct SL_component * slp;
327 slen = rr->len - 5;
328 slp = &rr->u.SL.link;
329 inode->i_size = 0;
330 while (slen > 1){
331 rootflag = 0;
332 switch(slp->flags &~1){
333 case 0:
334 inode->i_size += slp->len;
335 break;
336 case 2:
337 inode->i_size += 1;
338 break;
339 case 4:
340 inode->i_size += 2;
341 break;
342 case 8:
343 rootflag = 1;
344 inode->i_size += 1;
345 break;
346 default:
347 printk("Symlink component flag not implemented\n");
348 };
349 slen -= slp->len + 2;
350 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
351
352 if(slen < 2) break;
353 if(!rootflag) inode->i_size += 1;
354 };
355 };
356 break;
357 case SIG('R','E'):
358 printk("Attempt to read inode for relocated directory\n");
359 goto out;
360 case SIG('C','L'):
361 #ifdef DEBUG
362 printk("RR CL (%x)\n",inode->i_ino);
363 #endif
364 inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
365 inode -> i_sb -> u.isofs_sb.s_log_zone_size;
366 reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
367 inode->i_mode = reloc->i_mode;
368 inode->i_nlink = reloc->i_nlink;
369 inode->i_uid = reloc->i_uid;
370 inode->i_gid = reloc->i_gid;
371 inode->i_rdev = reloc->i_rdev;
372 inode->i_size = reloc->i_size;
373 inode->i_atime = reloc->i_atime;
374 inode->i_ctime = reloc->i_ctime;
375 inode->i_mtime = reloc->i_mtime;
376 iput(reloc);
377 break;
378 default:
379 break;
380 }
381 };
382 }
383 MAYBE_CONTINUE(repeat,inode);
384 return 0;
385 out:
386 if(buffer) kfree(buffer);
387 return 0;
388 }
389
390
391
392
393
394 char * get_rock_ridge_symlink(struct inode * inode)
395 {
396 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
397 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
398 struct buffer_head * bh;
399 unsigned char * pnt;
400 void * cpnt = NULL;
401 char * rpnt;
402 struct iso_directory_record * raw_inode;
403 CONTINUE_DECLS;
404 int block;
405 int sig;
406 int rootflag;
407 int len;
408 unsigned char * chr;
409 struct rock_ridge * rr;
410
411 if (!inode->i_sb->u.isofs_sb.s_rock)
412 panic("Cannot have symlink with high sierra variant of iso filesystem\n");
413
414 rpnt = 0;
415
416 block = inode->i_ino >> bufbits;
417 if (!(bh=bread(inode->i_dev,block, bufsize))) {
418 printk("unable to read i-node block");
419 return NULL;
420 };
421
422 pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
423
424 raw_inode = ((struct iso_directory_record *) pnt);
425
426 if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
427 int frag1, offset;
428
429 offset = (inode->i_ino & (bufsize - 1));
430 frag1 = bufsize - offset;
431 cpnt = kmalloc(*pnt,GFP_KERNEL);
432 if(!cpnt) return NULL;
433 memcpy(cpnt, bh->b_data + offset, frag1);
434 brelse(bh);
435 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
436 kfree(cpnt);
437 printk("unable to read i-node block");
438 return NULL;
439 };
440 offset += *pnt - bufsize;
441 memcpy((char *)cpnt+frag1, bh->b_data, offset);
442 pnt = ((unsigned char *) cpnt);
443 raw_inode = ((struct iso_directory_record *) pnt);
444 };
445
446
447
448
449 SETUP_ROCK_RIDGE(raw_inode, chr, len);
450
451 repeat:
452 while (len > 1){
453 if (rpnt) break;
454 rr = (struct rock_ridge *) chr;
455 if (rr->len == 0) goto out;
456 sig = (chr[0] << 8) + chr[1];
457 chr += rr->len;
458 len -= rr->len;
459
460 switch(sig){
461 case SIG('R','R'):
462 if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
463 break;
464 case SIG('S','P'):
465 CHECK_SP(goto out);
466 break;
467 case SIG('S','L'):
468 {int slen;
469 struct SL_component * slp;
470 slen = rr->len - 5;
471 slp = &rr->u.SL.link;
472 while (slen > 1){
473 if (!rpnt){
474 rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
475 if (!rpnt) goto out;
476 *rpnt = 0;
477 };
478 rootflag = 0;
479 switch(slp->flags &~1){
480 case 0:
481 strncat(rpnt,slp->text, slp->len);
482 break;
483 case 2:
484 strcat(rpnt,".");
485 break;
486 case 4:
487 strcat(rpnt,"..");
488 break;
489 case 8:
490 rootflag = 1;
491 strcat(rpnt,"/");
492 break;
493 default:
494 printk("Symlink component flag not implemented (%d)\n",slen);
495 };
496 slen -= slp->len + 2;
497 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
498
499 if(slen < 2) break;
500 if(!rootflag) strcat(rpnt,"/");
501 };
502 break;
503 default:
504 break;
505 }
506 };
507 };
508 MAYBE_CONTINUE(repeat,inode);
509 brelse(bh);
510
511 if (cpnt) {
512 kfree(cpnt);
513 cpnt = NULL;
514 };
515
516 return rpnt;
517 out:
518 if(buffer) kfree(buffer);
519 return 0;
520 }
521
522
523
524
525
526