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