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