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