Line data Source code
1 : /*
2 : * linux/fs/isofs/rock.c
3 : *
4 : * (C) 1992, 1993 Eric Youngdale
5 : *
6 : * Rock Ridge Extensions to iso9660
7 : */
8 :
9 : #include <linux/slab.h>
10 : #include <linux/pagemap.h>
11 : #include <linux/smp_lock.h>
12 :
13 : #include "isofs.h"
14 : #include "rock.h"
15 :
16 : /*
17 : * These functions are designed to read the system areas of a directory record
18 : * and extract relevant information. There are different functions provided
19 : * depending upon what information we need at the time. One function fills
20 : * out an inode structure, a second one extracts a filename, a third one
21 : * returns a symbolic link name, and a fourth one returns the extent number
22 : * for the file.
23 : */
24 :
25 : #define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
26 :
27 : struct rock_state {
28 : void *buffer;
29 : unsigned char *chr;
30 : int len;
31 : int cont_size;
32 : int cont_extent;
33 : int cont_offset;
34 : struct inode *inode;
35 : };
36 :
37 : /*
38 : * This is a way of ensuring that we have something in the system
39 : * use fields that is compatible with Rock Ridge. Return zero on success.
40 : */
41 :
42 : static int check_sp(struct rock_ridge *rr, struct inode *inode)
43 : {
44 78 : if (rr->u.SP.magic[0] != 0xbe)
45 26 : return -1;
46 52 : if (rr->u.SP.magic[1] != 0xef)
47 26 : return -1;
48 78 : ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
49 26 : return 0;
50 : }
51 :
52 : static void setup_rock_ridge(struct iso_directory_record *de,
53 : struct inode *inode, struct rock_state *rs)
54 : {
55 52 : rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
56 78 : if (rs->len & 1)
57 52 : (rs->len)++;
58 52 : rs->chr = (unsigned char *)de + rs->len;
59 26 : rs->len = *((unsigned char *)de) - rs->len;
60 52 : if (rs->len < 0)
61 26 : rs->len = 0;
62 :
63 104 : if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
64 78 : rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
65 104 : rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
66 52 : if (rs->len < 0)
67 26 : rs->len = 0;
68 : }
69 52 : }
70 :
71 : static void init_rock_state(struct rock_state *rs, struct inode *inode)
72 : {
73 26 : memset(rs, 0, sizeof(*rs));
74 26 : rs->inode = inode;
75 26 : }
76 :
77 : /*
78 : * Returns 0 if the caller should continue scanning, 1 if the scan must end
79 : * and -ve on error.
80 : */
81 : static int rock_continue(struct rock_state *rs)
82 : {
83 52 : int ret = 1;
84 78 : int blocksize = 1 << rs->inode->i_blkbits;
85 52 : const int min_de_size = offsetof(struct rock_ridge, u);
86 26 :
87 52 : kfree(rs->buffer);
88 26 : rs->buffer = NULL;
89 :
90 208 : if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
91 : (unsigned)rs->cont_size > blocksize ||
92 : (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
93 26 : printk(KERN_NOTICE "rock: corrupted directory entry. "
94 : "extent=%d, offset=%d, size=%d\n",
95 : rs->cont_extent, rs->cont_offset, rs->cont_size);
96 26 : ret = -EIO;
97 26 : goto out;
98 : }
99 :
100 52 : if (rs->cont_extent) {
101 : struct buffer_head *bh;
102 :
103 78 : rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
104 78 : if (!rs->buffer) {
105 26 : ret = -ENOMEM;
106 26 : goto out;
107 : }
108 26 : ret = -EIO;
109 78 : bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
110 52 : if (bh) {
111 78 : memcpy(rs->buffer, bh->b_data + rs->cont_offset,
112 : rs->cont_size);
113 52 : put_bh(bh);
114 52 : rs->chr = rs->buffer;
115 26 : rs->len = rs->cont_size;
116 26 : rs->cont_extent = 0;
117 26 : rs->cont_size = 0;
118 26 : rs->cont_offset = 0;
119 26 : return 0;
120 : }
121 26 : printk("Unable to read rock-ridge attributes\n");
122 : }
123 : out:
124 156 : kfree(rs->buffer);
125 78 : rs->buffer = NULL;
126 130 : return ret;
127 : }
128 :
129 : /*
130 : * We think there's a record of type `sig' at rs->chr. Parse the signature
131 : * and make sure that there's really room for a record of that type.
132 : */
133 : static int rock_check_overflow(struct rock_state *rs, int sig)
134 : {
135 26 : int len;
136 :
137 : switch (sig) {
138 78 : case SIG('S', 'P'):
139 26 : len = sizeof(struct SU_SP_s);
140 26 : break;
141 104 : case SIG('C', 'E'):
142 26 : len = sizeof(struct SU_CE_s);
143 26 : break;
144 104 : case SIG('E', 'R'):
145 26 : len = sizeof(struct SU_ER_s);
146 26 : break;
147 104 : case SIG('R', 'R'):
148 26 : len = sizeof(struct RR_RR_s);
149 26 : break;
150 104 : case SIG('P', 'X'):
151 26 : len = sizeof(struct RR_PX_s);
152 26 : break;
153 104 : case SIG('P', 'N'):
154 26 : len = sizeof(struct RR_PN_s);
155 26 : break;
156 104 : case SIG('S', 'L'):
157 26 : len = sizeof(struct RR_SL_s);
158 26 : break;
159 104 : case SIG('N', 'M'):
160 26 : len = sizeof(struct RR_NM_s);
161 26 : break;
162 104 : case SIG('C', 'L'):
163 26 : len = sizeof(struct RR_CL_s);
164 26 : break;
165 104 : case SIG('P', 'L'):
166 26 : len = sizeof(struct RR_PL_s);
167 26 : break;
168 104 : case SIG('T', 'F'):
169 26 : len = sizeof(struct RR_TF_s);
170 26 : break;
171 104 : case SIG('Z', 'F'):
172 26 : len = sizeof(struct RR_ZF_s);
173 26 : break;
174 52 : default:
175 52 : len = 0;
176 26 : break;
177 : }
178 26 : len += offsetof(struct rock_ridge, u);
179 52 : if (len > rs->len) {
180 26 : printk(KERN_NOTICE "rock: directory entry would overflow "
181 : "storage\n");
182 26 : printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
183 : sig, len, rs->len);
184 26 : return -EIO;
185 : }
186 26 : return 0;
187 : }
188 :
189 : /*
190 : * return length of name field; 0: not found, -1: to be ignored
191 : */
192 : int get_rock_ridge_filename(struct iso_directory_record *de,
193 : char *retname, struct inode *inode)
194 9 : {
195 9 : struct rock_state rs;
196 9 : struct rock_ridge *rr;
197 9 : int sig;
198 18 : int retnamlen = 0;
199 18 : int truncate = 0;
200 18 : int ret = 0;
201 9 :
202 45 : if (!ISOFS_SB(inode->i_sb)->s_rock)
203 18 : return 0;
204 18 : *retname = 0;
205 9 :
206 27 : init_rock_state(&rs, inode);
207 36 : setup_rock_ridge(de, inode, &rs);
208 : repeat:
209 9 :
210 27 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
211 18 : rr = (struct rock_ridge *)rs.chr;
212 9 : /*
213 : * Ignore rock ridge info if rr->len is out of range, but
214 : * don't return -EIO because that would make the file
215 : * invisible.
216 : */
217 27 : if (rr->len < 3)
218 9 : goto out; /* Something got screwed up here */
219 27 : sig = isonum_721(rs.chr);
220 36 : if (rock_check_overflow(&rs, sig))
221 9 : goto eio;
222 18 : rs.chr += rr->len;
223 18 : rs.len -= rr->len;
224 : /*
225 : * As above, just ignore the rock ridge info if rr->len
226 : * is bogus.
227 : */
228 18 : if (rs.len < 0)
229 9 : goto out; /* Something got screwed up here */
230 :
231 : switch (sig) {
232 27 : case SIG('R', 'R'):
233 18 : if ((rr->u.RR.flags[0] & RR_NM) == 0)
234 9 : goto out;
235 9 : break;
236 36 : case SIG('S', 'P'):
237 45 : if (check_sp(rr, inode))
238 9 : goto out;
239 9 : break;
240 36 : case SIG('C', 'E'):
241 27 : rs.cont_extent = isonum_733(rr->u.CE.extent);
242 27 : rs.cont_offset = isonum_733(rr->u.CE.offset);
243 27 : rs.cont_size = isonum_733(rr->u.CE.size);
244 9 : break;
245 36 : case SIG('N', 'M'):
246 18 : if (truncate)
247 9 : break;
248 27 : if (rr->len < 5)
249 9 : break;
250 : /*
251 : * If the flags are 2 or 4, this indicates '.' or '..'.
252 : * We don't want to do anything with this, because it
253 : * screws up the code that calls us. We don't really
254 : * care anyways, since we can just use the non-RR
255 : * name.
256 : */
257 18 : if (rr->u.NM.flags & 6)
258 9 : break;
259 :
260 18 : if (rr->u.NM.flags & ~1) {
261 9 : printk("Unsupported NM flag settings (%d)\n",
262 : rr->u.NM.flags);
263 9 : break;
264 : }
265 36 : if ((strlen(retname) + rr->len - 5) >= 254) {
266 9 : truncate = 1;
267 9 : break;
268 : }
269 18 : strncat(retname, rr->u.NM.name, rr->len - 5);
270 18 : retnamlen += rr->len - 5;
271 9 : break;
272 36 : case SIG('R', 'E'):
273 9 : kfree(rs.buffer);
274 9 : return -1;
275 18 : default:
276 18 : break;
277 : }
278 : }
279 45 : ret = rock_continue(&rs);
280 45 : if (ret == 0)
281 9 : goto repeat;
282 18 : if (ret == 1)
283 9 : return retnamlen; /* If 0, this file did not have a NM field */
284 : out:
285 36 : kfree(rs.buffer);
286 36 : return ret;
287 18 : eio:
288 9 : ret = -EIO;
289 9 : goto out;
290 : }
291 :
292 : static int
293 : parse_rock_ridge_inode_internal(struct iso_directory_record *de,
294 : struct inode *inode, int regard_xa)
295 : {
296 32 : int symlink_len = 0;
297 16 : int cnt, sig;
298 16 : struct inode *reloc;
299 16 : struct rock_ridge *rr;
300 16 : int rootflag;
301 16 : struct rock_state rs;
302 32 : int ret = 0;
303 16 :
304 80 : if (!ISOFS_SB(inode->i_sb)->s_rock)
305 32 : return 0;
306 16 :
307 48 : init_rock_state(&rs, inode);
308 64 : setup_rock_ridge(de, inode, &rs);
309 48 : if (regard_xa) {
310 32 : rs.chr += 14;
311 32 : rs.len -= 14;
312 48 : if (rs.len < 0)
313 32 : rs.len = 0;
314 16 : }
315 16 :
316 16 : repeat:
317 64 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
318 48 : rr = (struct rock_ridge *)rs.chr;
319 32 : /*
320 32 : * Ignore rock ridge info if rr->len is out of range, but
321 16 : * don't return -EIO because that would make the file
322 16 : * invisible.
323 16 : */
324 64 : if (rr->len < 3)
325 32 : goto out; /* Something got screwed up here */
326 64 : sig = isonum_721(rs.chr);
327 80 : if (rock_check_overflow(&rs, sig))
328 32 : goto eio;
329 48 : rs.chr += rr->len;
330 48 : rs.len -= rr->len;
331 16 : /*
332 16 : * As above, just ignore the rock ridge info if rr->len
333 : * is bogus.
334 : */
335 32 : if (rs.len < 0)
336 16 : goto out; /* Something got screwed up here */
337 :
338 : switch (sig) {
339 : #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
340 48 : case SIG('R', 'R'):
341 32 : if ((rr->u.RR.flags[0] &
342 : (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
343 16 : goto out;
344 16 : break;
345 16 : #endif
346 48 : case SIG('S', 'P'):
347 80 : if (check_sp(rr, inode))
348 16 : goto out;
349 16 : break;
350 64 : case SIG('C', 'E'):
351 48 : rs.cont_extent = isonum_733(rr->u.CE.extent);
352 48 : rs.cont_offset = isonum_733(rr->u.CE.offset);
353 48 : rs.cont_size = isonum_733(rr->u.CE.size);
354 16 : break;
355 64 : case SIG('E', 'R'):
356 48 : ISOFS_SB(inode->i_sb)->s_rock = 1;
357 16 : printk(KERN_DEBUG "ISO 9660 Extensions: ");
358 : {
359 : int p;
360 80 : for (p = 0; p < rr->u.ER.len_id; p++)
361 32 : printk("%c", rr->u.ER.data[p]);
362 32 : }
363 16 : printk("\n");
364 16 : break;
365 64 : case SIG('P', 'X'):
366 48 : inode->i_mode = isonum_733(rr->u.PX.mode);
367 32 : inode->i_nlink = isonum_733(rr->u.PX.n_links);
368 32 : inode->i_uid = isonum_733(rr->u.PX.uid);
369 32 : inode->i_gid = isonum_733(rr->u.PX.gid);
370 16 : break;
371 64 : case SIG('P', 'N'):
372 : {
373 : int high, low;
374 48 : high = isonum_733(rr->u.PN.dev_high);
375 48 : low = isonum_733(rr->u.PN.dev_low);
376 : /*
377 : * The Rock Ridge standard specifies that if
378 : * sizeof(dev_t) <= 4, then the high field is
379 : * unused, and the device number is completely
380 : * stored in the low field. Some writers may
381 : * ignore this subtlety,
382 : * and as a result we test to see if the entire
383 : * device number is
384 : * stored in the low field, and use that.
385 : */
386 64 : if ((low & ~0xff) && high == 0) {
387 16 : inode->i_rdev =
388 : MKDEV(low >> 8, low & 0xff);
389 : } else {
390 16 : inode->i_rdev =
391 : MKDEV(high, low);
392 : }
393 : }
394 16 : break;
395 64 : case SIG('T', 'F'):
396 : /*
397 : * Some RRIP writers incorrectly place ctime in the
398 : * TF_CREATE field. Try to handle this correctly for
399 : * either case.
400 : */
401 : /* Rock ridge never appears on a High Sierra disk */
402 16 : cnt = 0;
403 32 : if (rr->u.TF.flags & TF_CREATE) {
404 96 : inode->i_ctime.tv_sec =
405 : iso_date(rr->u.TF.times[cnt++].time,
406 : 0);
407 16 : inode->i_ctime.tv_nsec = 0;
408 : }
409 64 : if (rr->u.TF.flags & TF_MODIFY) {
410 176 : inode->i_mtime.tv_sec =
411 : iso_date(rr->u.TF.times[cnt++].time,
412 : 0);
413 16 : inode->i_mtime.tv_nsec = 0;
414 : }
415 96 : if (rr->u.TF.flags & TF_ACCESS) {
416 256 : inode->i_atime.tv_sec =
417 : iso_date(rr->u.TF.times[cnt++].time,
418 : 0);
419 16 : inode->i_atime.tv_nsec = 0;
420 : }
421 128 : if (rr->u.TF.flags & TF_ATTRIBUTES) {
422 336 : inode->i_ctime.tv_sec =
423 : iso_date(rr->u.TF.times[cnt++].time,
424 : 0);
425 16 : inode->i_ctime.tv_nsec = 0;
426 : }
427 80 : break;
428 64 : case SIG('S', 'L'):
429 : {
430 : int slen;
431 : struct SL_component *slp;
432 : struct SL_component *oldslp;
433 32 : slen = rr->len - 5;
434 16 : slp = &rr->u.SL.link;
435 16 : inode->i_size = symlink_len;
436 48 : while (slen > 1) {
437 32 : rootflag = 0;
438 16 : switch (slp->flags & ~1) {
439 64 : case 0:
440 32 : inode->i_size +=
441 : slp->len;
442 32 : break;
443 80 : case 2:
444 16 : inode->i_size += 1;
445 16 : break;
446 80 : case 4:
447 16 : inode->i_size += 2;
448 16 : break;
449 80 : case 8:
450 16 : rootflag = 1;
451 16 : inode->i_size += 1;
452 16 : break;
453 32 : default:
454 32 : printk("Symlink component flag "
455 : "not implemented\n");
456 16 : }
457 32 : slen -= slp->len + 2;
458 32 : oldslp = slp;
459 32 : slp = (struct SL_component *)
460 : (((char *)slp) + slp->len + 2);
461 :
462 32 : if (slen < 2) {
463 80 : if (((rr->u.SL.
464 : flags & 1) != 0)
465 : &&
466 : ((oldslp->
467 : flags & 1) == 0))
468 16 : inode->i_size +=
469 : 1;
470 16 : break;
471 : }
472 :
473 : /*
474 : * If this component record isn't
475 : * continued, then append a '/'.
476 : */
477 80 : if (!rootflag
478 : && (oldslp->flags & 1) == 0)
479 16 : inode->i_size += 1;
480 : }
481 : }
482 32 : symlink_len = inode->i_size;
483 32 : break;
484 64 : case SIG('R', 'E'):
485 16 : printk(KERN_WARNING "Attempt to read inode for "
486 : "relocated directory\n");
487 16 : goto out;
488 64 : case SIG('C', 'L'):
489 64 : ISOFS_I(inode)->i_first_extent =
490 : isonum_733(rr->u.CL.location);
491 64 : reloc =
492 : isofs_iget(inode->i_sb,
493 : ISOFS_I(inode)->i_first_extent,
494 : 0);
495 64 : if (IS_ERR(reloc)) {
496 48 : ret = PTR_ERR(reloc);
497 16 : goto out;
498 : }
499 16 : inode->i_mode = reloc->i_mode;
500 16 : inode->i_nlink = reloc->i_nlink;
501 16 : inode->i_uid = reloc->i_uid;
502 16 : inode->i_gid = reloc->i_gid;
503 16 : inode->i_rdev = reloc->i_rdev;
504 16 : inode->i_size = reloc->i_size;
505 16 : inode->i_blocks = reloc->i_blocks;
506 16 : inode->i_atime = reloc->i_atime;
507 16 : inode->i_ctime = reloc->i_ctime;
508 16 : inode->i_mtime = reloc->i_mtime;
509 16 : iput(reloc);
510 16 : break;
511 16 : #ifdef CONFIG_ZISOFS
512 : case SIG('Z', 'F'): {
513 : int algo;
514 :
515 : if (ISOFS_SB(inode->i_sb)->s_nocompress)
516 : break;
517 : algo = isonum_721(rr->u.ZF.algorithm);
518 : if (algo == SIG('p', 'z')) {
519 : int block_shift =
520 : isonum_711(&rr->u.ZF.parms[1]);
521 : if (block_shift > 17) {
522 : printk(KERN_WARNING "isofs: "
523 : "Can't handle ZF block "
524 : "size of 2^%d\n",
525 : block_shift);
526 : } else {
527 : /*
528 : * Note: we don't change
529 : * i_blocks here
530 : */
531 : ISOFS_I(inode)->i_file_format =
532 : isofs_file_compressed;
533 : /*
534 : * Parameters to compression
535 : * algorithm (header size,
536 : * block size)
537 : */
538 : ISOFS_I(inode)->i_format_parm[0] =
539 : isonum_711(&rr->u.ZF.parms[0]);
540 : ISOFS_I(inode)->i_format_parm[1] =
541 : isonum_711(&rr->u.ZF.parms[1]);
542 : inode->i_size =
543 : isonum_733(rr->u.ZF.
544 : real_size);
545 : }
546 : } else {
547 : printk(KERN_WARNING
548 : "isofs: Unknown ZF compression "
549 : "algorithm: %c%c\n",
550 : rr->u.ZF.algorithm[0],
551 : rr->u.ZF.algorithm[1]);
552 : }
553 : break;
554 : }
555 : #endif
556 16 : default:
557 32 : break;
558 : }
559 : }
560 80 : ret = rock_continue(&rs);
561 224 : if (ret == 0)
562 16 : goto repeat;
563 32 : if (ret == 1)
564 16 : ret = 0;
565 : out:
566 80 : kfree(rs.buffer);
567 80 : return ret;
568 32 : eio:
569 16 : ret = -EIO;
570 16 : goto out;
571 : }
572 :
573 : static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
574 : {
575 1 : int slen;
576 1 : int rootflag;
577 1 : struct SL_component *oldslp;
578 1 : struct SL_component *slp;
579 3 : slen = rr->len - 5;
580 2 : slp = &rr->u.SL.link;
581 4 : while (slen > 1) {
582 3 : rootflag = 0;
583 2 : switch (slp->flags & ~1) {
584 5 : case 0:
585 3 : if (slp->len > plimit - rpnt)
586 1 : return NULL;
587 3 : memcpy(rpnt, slp->text, slp->len);
588 2 : rpnt += slp->len;
589 1 : break;
590 5 : case 2:
591 2 : if (rpnt >= plimit)
592 1 : return NULL;
593 3 : *rpnt++ = '.';
594 1 : break;
595 5 : case 4:
596 2 : if (2 > plimit - rpnt)
597 1 : return NULL;
598 3 : *rpnt++ = '.';
599 3 : *rpnt++ = '.';
600 1 : break;
601 5 : case 8:
602 2 : if (rpnt >= plimit)
603 1 : return NULL;
604 1 : rootflag = 1;
605 3 : *rpnt++ = '/';
606 1 : break;
607 2 : default:
608 3 : printk("Symlink component flag not implemented (%d)\n",
609 : slp->flags);
610 1 : }
611 2 : slen -= slp->len + 2;
612 2 : oldslp = slp;
613 2 : slp = (struct SL_component *)((char *)slp + slp->len + 2);
614 :
615 2 : if (slen < 2) {
616 : /*
617 : * If there is another SL record, and this component
618 : * record isn't continued, then add a slash.
619 : */
620 7 : if ((!rootflag) && (rr->u.SL.flags & 1) &&
621 : !(oldslp->flags & 1)) {
622 2 : if (rpnt >= plimit)
623 1 : return NULL;
624 3 : *rpnt++ = '/';
625 : }
626 1 : break;
627 : }
628 :
629 : /*
630 : * If this component record isn't continued, then append a '/'.
631 : */
632 5 : if (!rootflag && !(oldslp->flags & 1)) {
633 2 : if (rpnt >= plimit)
634 1 : return NULL;
635 3 : *rpnt++ = '/';
636 : }
637 : }
638 1 : return rpnt;
639 1 : }
640 :
641 : int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
642 : {
643 72 : int result = parse_rock_ridge_inode_internal(de, inode, 0);
644 8 :
645 8 : /*
646 8 : * if rockridge flag was reset and we didn't look for attributes
647 : * behind eventual XA attributes, have a look there
648 : */
649 64 : if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
650 : && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
651 56 : result = parse_rock_ridge_inode_internal(de, inode, 14);
652 : }
653 24 : return result;
654 : }
655 :
656 : /*
657 : * readpage() for symlinks: reads symlink contents into the page and either
658 : * makes it uptodate and returns 0 or returns error (-EIO)
659 : */
660 : static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
661 : {
662 2 : struct inode *inode = page->mapping->host;
663 4 : struct iso_inode_info *ei = ISOFS_I(inode);
664 4 : char *link = kmap(page);
665 2 : unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
666 1 : struct buffer_head *bh;
667 2 : char *rpnt = link;
668 1 : unsigned char *pnt;
669 1 : struct iso_directory_record *raw_de;
670 1 : unsigned long block, offset;
671 1 : int sig;
672 1 : struct rock_ridge *rr;
673 1 : struct rock_state rs;
674 1 : int ret;
675 1 :
676 5 : if (!ISOFS_SB(inode->i_sb)->s_rock)
677 2 : goto error;
678 1 :
679 3 : init_rock_state(&rs, inode);
680 2 : block = ei->i_iget5_block;
681 2 : lock_kernel();
682 3 : bh = sb_bread(inode->i_sb, block);
683 3 : if (!bh)
684 2 : goto out_noread;
685 :
686 1 : offset = ei->i_iget5_offset;
687 1 : pnt = (unsigned char *)bh->b_data + offset;
688 :
689 1 : raw_de = (struct iso_directory_record *)pnt;
690 :
691 : /*
692 : * If we go past the end of the buffer, there is some sort of error.
693 : */
694 2 : if (offset + *pnt > bufsize)
695 1 : goto out_bad_span;
696 :
697 : /*
698 : * Now test for possible Rock Ridge extensions which will override
699 : * some of these numbers in the inode structure.
700 : */
701 :
702 3 : setup_rock_ridge(raw_de, inode, &rs);
703 :
704 1 : repeat:
705 3 : while (rs.len > 2) { /* There may be one byte for padding somewhere */
706 2 : rr = (struct rock_ridge *)rs.chr;
707 4 : if (rr->len < 3)
708 1 : goto out; /* Something got screwed up here */
709 3 : sig = isonum_721(rs.chr);
710 4 : if (rock_check_overflow(&rs, sig))
711 1 : goto out;
712 2 : rs.chr += rr->len;
713 2 : rs.len -= rr->len;
714 2 : if (rs.len < 0)
715 1 : goto out; /* corrupted isofs */
716 :
717 : switch (sig) {
718 3 : case SIG('R', 'R'):
719 2 : if ((rr->u.RR.flags[0] & RR_SL) == 0)
720 1 : goto out;
721 1 : break;
722 4 : case SIG('S', 'P'):
723 5 : if (check_sp(rr, inode))
724 1 : goto out;
725 1 : break;
726 4 : case SIG('S', 'L'):
727 2 : rpnt = get_symlink_chunk(rpnt, rr,
728 : link + (PAGE_SIZE - 1));
729 2 : if (rpnt == NULL)
730 1 : goto out;
731 1 : break;
732 4 : case SIG('C', 'E'):
733 : /* This tells is if there is a continuation record */
734 3 : rs.cont_extent = isonum_733(rr->u.CE.extent);
735 3 : rs.cont_offset = isonum_733(rr->u.CE.offset);
736 3 : rs.cont_size = isonum_733(rr->u.CE.size);
737 1 : default:
738 4 : break;
739 : }
740 : }
741 5 : ret = rock_continue(&rs);
742 6 : if (ret == 0)
743 1 : goto repeat;
744 2 : if (ret < 0)
745 1 : goto fail;
746 :
747 2 : if (rpnt == link)
748 1 : goto fail;
749 2 : brelse(bh);
750 1 : *rpnt = '\0';
751 1 : unlock_kernel();
752 2 : SetPageUptodate(page);
753 2 : kunmap(page);
754 1 : unlock_page(page);
755 1 : return 0;
756 4 :
757 : /* error exit from macro */
758 : out:
759 4 : kfree(rs.buffer);
760 4 : goto fail;
761 1 : out_noread:
762 1 : printk("unable to read i-node block");
763 1 : goto fail;
764 1 : out_bad_span:
765 1 : printk("symlink spans iso9660 blocks\n");
766 : fail:
767 13 : brelse(bh);
768 1 : unlock_kernel();
769 : error:
770 5 : SetPageError(page);
771 2 : kunmap(page);
772 1 : unlock_page(page);
773 1 : return -EIO;
774 : }
775 :
776 1 : const struct address_space_operations isofs_symlink_aops = {
777 : .readpage = rock_ridge_symlink_readpage
778 : };
|