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