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