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