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