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