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