~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/isofs/rock.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.10 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.83 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.153 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.200 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.200 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.76 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp