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