root/fs/isofs/rock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_sp
  2. setup_rock_ridge
  3. init_rock_state
  4. rock_continue
  5. rock_check_overflow
  6. get_rock_ridge_filename
  7. parse_rock_ridge_inode_internal
  8. get_symlink_chunk
  9. parse_rock_ridge_inode
  10. rock_ridge_symlink_readpage

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

/* [<][>][^][v][top][bottom][index][help] */