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