root/fs/isofs/rock.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_rock_ridge_relocation
  2. get_rock_ridge_filename
  3. parse_rock_ridge_inode
  4. get_rock_ridge_symlink

   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/stat.h>
  10 #include <linux/sched.h>
  11 #include <linux/iso_fs.h>
  12 #include <linux/string.h>
  13 #include <linux/mm.h>
  14 #include <linux/malloc.h>
  15 
  16 #include "rock.h"
  17 
  18 /* These functions are designed to read the system areas of a directory record
  19  * and extract relevant information.  There are different functions provided
  20  * depending upon what information we need at the time.  One function fills
  21  * out an inode structure, a second one extracts a filename, a third one
  22  * returns a symbolic link name, and a fourth one returns the extent number
  23  * for the file. */
  24 
  25 #define SIG(A,B) ((A << 8) | B)
  26 
  27 
  28 /* This is a way of ensuring that we have something in the system
  29    use fields that is compatible with Rock Ridge */
  30 #define CHECK_SP(FAIL)                          \
  31       if(rr->u.SP.magic[0] != 0xbe) FAIL;       \
  32       if(rr->u.SP.magic[1] != 0xef) FAIL;
  33 
  34 /* We define a series of macros because each function must do exactly the
  35    same thing in certain places.  We use the macros to ensure that everything
  36    is done correctly */
  37 
  38 #define CONTINUE_DECLS \
  39   int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
  40   void * buffer = 0
  41 
  42 #define CHECK_CE                                \
  43       {cont_extent = isonum_733(rr->u.CE.extent); \
  44       cont_offset = isonum_733(rr->u.CE.offset); \
  45       cont_size = isonum_733(rr->u.CE.size);}
  46 
  47 #define SETUP_ROCK_RIDGE(DE,CHR,LEN)                            \
  48   {LEN= sizeof(struct iso_directory_record) + DE->name_len[0];  \
  49   if(LEN & 1) LEN++;                                            \
  50   CHR = ((unsigned char *) DE) + LEN;                           \
  51   LEN = *((unsigned char *) DE) - LEN;}
  52 
  53 #define MAYBE_CONTINUE(LABEL,DEV) \
  54   {if (buffer) kfree(buffer); \
  55   if (cont_extent){ \
  56     int block, offset, offset1; \
  57     struct buffer_head * bh; \
  58     buffer = kmalloc(cont_size,GFP_KERNEL); \
  59     if (!buffer) goto out; \
  60     block = cont_extent; \
  61     offset = cont_offset; \
  62     offset1 = 0; \
  63     if(ISOFS_BUFFER_SIZE(DEV) == 1024) {     \
  64       block <<= 1;    \
  65       if (offset >= 1024) block++; \
  66       offset &= 1023; \
  67       if(offset + cont_size >= 1024) { \
  68           bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \
  69           if(!bh) {printk("Unable to read continuation Rock Ridge record\n"); \
  70                      kfree(buffer); \
  71                      buffer = NULL; } else { \
  72             memcpy(buffer, bh->b_data + offset, 1024 - offset); \
  73             brelse(bh); \
  74             offset1 = 1024 - offset; \
  75             offset = 0;} \
  76       }  \
  77     };     \
  78     if(buffer) { \
  79       bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
  80       if(bh){       \
  81         memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \
  82         brelse(bh); \
  83         chr = (unsigned char *) buffer; \
  84         len = cont_size; \
  85         cont_extent = 0; \
  86         cont_size = 0; \
  87         cont_offset = 0; \
  88         goto LABEL; \
  89       };    \
  90     } \
  91     printk("Unable to read rock-ridge attributes\n");    \
  92   }}
  93 
  94 /* This is the inner layer of the get filename routine, and is called
  95    for each system area and continuation record related to the file */
  96 
  97 int find_rock_ridge_relocation(struct iso_directory_record * de, 
     /* [previous][next][first][last][top][bottom][index][help] */
  98                                struct inode * inode) {
  99   int flag;
 100   int len;
 101   int retval;
 102   unsigned char * chr;
 103   CONTINUE_DECLS;
 104   flag = 0;
 105   
 106   /* If this is a '..' then we are looking for the parent, otherwise we
 107      are looking for the child */
 108   
 109   if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
 110   /* Return value if we do not find appropriate record. */
 111   retval = isonum_733 (de->extent);
 112   
 113   if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
 114 
 115   SETUP_ROCK_RIDGE(de, chr, len);
 116  repeat:
 117   {
 118     int rrflag, sig;
 119     struct rock_ridge * rr;
 120     
 121     while (len > 1){ /* There may be one byte for padding somewhere */
 122       rr = (struct rock_ridge *) chr;
 123       if (rr->len == 0) goto out; /* Something got screwed up here */
 124       sig = (chr[0] << 8) + chr[1];
 125       chr += rr->len; 
 126       len -= rr->len;
 127 
 128       switch(sig){
 129       case SIG('R','R'):
 130         rrflag = rr->u.RR.flags[0];
 131         if (flag && !(rrflag & RR_PL)) goto out;
 132         if (!flag && !(rrflag & RR_CL)) goto out;
 133         break;
 134       case SIG('S','P'):
 135         CHECK_SP(goto out);
 136         break;
 137       case SIG('C','L'):
 138 #ifdef DEBUG
 139         printk("RR: CL\n");
 140 #endif
 141         if (flag == 0) {
 142           retval = isonum_733(rr->u.CL.location);
 143           goto out;
 144         };
 145         break;
 146       case SIG('P','L'):
 147 #ifdef DEBUG
 148         printk("RR: PL\n");
 149 #endif
 150         if (flag != 0) {
 151           retval = isonum_733(rr->u.PL.location);
 152           goto out;
 153         };
 154         break;
 155       case SIG('C','E'):
 156         CHECK_CE; /* This tells is if there is a continuation record */
 157         break;
 158       default:
 159         break;
 160       }
 161     };
 162   };
 163   MAYBE_CONTINUE(repeat, inode);
 164   return retval;
 165  out:
 166   if(buffer) kfree(buffer);
 167   return retval;
 168 }
 169 
 170 int get_rock_ridge_filename(struct iso_directory_record * de,
     /* [previous][next][first][last][top][bottom][index][help] */
 171                            char ** name, int * namlen, struct inode * inode)
 172 {
 173   int len;
 174   unsigned char * chr;
 175   CONTINUE_DECLS;
 176   char * retname = NULL;
 177   int retnamlen = 0, truncate=0;
 178  
 179   if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
 180 
 181   SETUP_ROCK_RIDGE(de, chr, len);
 182  repeat:
 183   {
 184     struct rock_ridge * rr;
 185     int sig;
 186     
 187     while (len > 1){ /* There may be one byte for padding somewhere */
 188       rr = (struct rock_ridge *) chr;
 189       if (rr->len == 0) goto out; /* Something got screwed up here */
 190       sig = (chr[0] << 8) + chr[1];
 191       chr += rr->len; 
 192       len -= rr->len;
 193 
 194       switch(sig){
 195       case SIG('R','R'):
 196         if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
 197         break;
 198       case SIG('S','P'):
 199         CHECK_SP(goto out);
 200         break;
 201       case SIG('C','E'):
 202         CHECK_CE;
 203         break;
 204       case SIG('N','M'):
 205         if (truncate) break;
 206         if (rr->u.NM.flags & ~1) {
 207           printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
 208           break;
 209         };
 210         if (!retname){
 211           retname = (char *) kmalloc (255,GFP_KERNEL);
 212           /* This may be a waste, but we only
 213              need this for a moment.  The layers
 214              that call this function should
 215              deallocate the mem fairly soon
 216              after control is returned */
 217 
 218           if (!retname) goto out;
 219           *retname = 0; /* Zero length string */
 220           retnamlen = 0;
 221         };
 222         if((strlen(retname) + rr->len - 5) >= 254) {
 223           truncate = 1;
 224           break;
 225         };
 226         strncat(retname, rr->u.NM.name, rr->len - 5);
 227         retnamlen += rr->len - 5;
 228         break;
 229       case SIG('R','E'):
 230 #ifdef DEBUG
 231         printk("RR: RE (%x)\n", inode->i_ino);
 232 #endif
 233         if (buffer) kfree(buffer);
 234         if (retname) kfree(retname);
 235         return -1;
 236       default:
 237         break;
 238       }
 239     };
 240   }
 241   MAYBE_CONTINUE(repeat,inode);
 242   if(retname){
 243     *name = retname;
 244     *namlen = retnamlen;
 245     return 1;
 246   };
 247   return 0;  /* This file did not have a NM field */
 248  out:
 249   if(buffer) kfree(buffer);
 250   if (retname) kfree(retname);
 251   return 0;
 252 }
 253 
 254 int parse_rock_ridge_inode(struct iso_directory_record * de,
     /* [previous][next][first][last][top][bottom][index][help] */
 255                            struct inode * inode){
 256   int len;
 257   unsigned char * chr;
 258   int symlink_len = 0;
 259   CONTINUE_DECLS;
 260 
 261   if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
 262 
 263   SETUP_ROCK_RIDGE(de, chr, len);
 264  repeat:
 265   {
 266     int cnt, sig;
 267     struct inode * reloc;
 268     struct rock_ridge * rr;
 269     int rootflag;
 270     
 271     while (len > 1){ /* There may be one byte for padding somewhere */
 272       rr = (struct rock_ridge *) chr;
 273       if (rr->len == 0) goto out; /* Something got screwed up here */
 274       sig = (chr[0] << 8) + chr[1];
 275       chr += rr->len; 
 276       len -= rr->len;
 277       
 278       switch(sig){
 279       case SIG('R','R'):
 280         if((rr->u.RR.flags[0] & 
 281             (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
 282         break;
 283       case SIG('S','P'):
 284         CHECK_SP(goto out);
 285         break;
 286       case SIG('C','E'):
 287         CHECK_CE;
 288         break;
 289       case SIG('E','R'):
 290         printk("ISO9660 Extensions: ");
 291         { int p;
 292           for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
 293         };
 294           printk("\n");
 295         break;
 296       case SIG('P','X'):
 297         inode->i_mode  = isonum_733(rr->u.PX.mode);
 298         inode->i_nlink = isonum_733(rr->u.PX.n_links);
 299         inode->i_uid   = isonum_733(rr->u.PX.uid);
 300         inode->i_gid   = isonum_733(rr->u.PX.gid);
 301         break;
 302       case SIG('P','N'):
 303         { int high, low;
 304           high = isonum_733(rr->u.PN.dev_high);
 305           low = isonum_733(rr->u.PN.dev_low);
 306           /*
 307            * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
 308            * then the high field is unused, and the device number is completely
 309            * stored in the low field.  Some writers may ignore this subtlety,
 310            * and as a result we test to see if the entire device number is
 311            * stored in the low field, and use that.
 312            */
 313           if((low & ~0xff) && high == 0) {
 314             inode->i_rdev = MKDEV(low >> 8, low & 0xff);
 315           } else {
 316             inode->i_rdev = MKDEV(high, low);
 317           }
 318         };
 319         break;
 320       case SIG('T','F'):
 321         /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
 322            Try and handle this correctly for either case. */
 323         cnt = 0; /* Rock ridge never appears on a High Sierra disk */
 324         if(rr->u.TF.flags & TF_CREATE) 
 325           inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
 326         if(rr->u.TF.flags & TF_MODIFY) 
 327           inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
 328         if(rr->u.TF.flags & TF_ACCESS) 
 329           inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
 330         if(rr->u.TF.flags & TF_ATTRIBUTES) 
 331           inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
 332         break;
 333       case SIG('S','L'):
 334         {int slen;
 335          struct SL_component * slp;
 336          slen = rr->len - 5;
 337          slp = &rr->u.SL.link;
 338          inode->i_size = symlink_len;
 339          while (slen > 1){
 340            rootflag = 0;
 341            switch(slp->flags &~1){
 342            case 0:
 343              inode->i_size += slp->len;
 344              break;
 345            case 2:
 346              inode->i_size += 1;
 347              break;
 348            case 4:
 349              inode->i_size += 2;
 350              break;
 351            case 8:
 352              rootflag = 1;
 353              inode->i_size += 1;
 354              break;
 355            default:
 356              printk("Symlink component flag not implemented\n");
 357            };
 358            slen -= slp->len + 2;
 359            slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
 360 
 361            if(slen < 2) break;
 362            if(!rootflag) inode->i_size += 1;
 363          }
 364         }
 365         symlink_len = inode->i_size;
 366         break;
 367       case SIG('R','E'):
 368         printk("Attempt to read inode for relocated directory\n");
 369         goto out;
 370       case SIG('C','L'):
 371 #ifdef DEBUG
 372         printk("RR CL (%x)\n",inode->i_ino);
 373 #endif
 374         inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
 375                 inode -> i_sb -> u.isofs_sb.s_log_zone_size;
 376         reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
 377         inode->i_mode = reloc->i_mode;
 378         inode->i_nlink = reloc->i_nlink;
 379         inode->i_uid = reloc->i_uid;
 380         inode->i_gid = reloc->i_gid;
 381         inode->i_rdev = reloc->i_rdev;
 382         inode->i_size = reloc->i_size;
 383         inode->i_atime = reloc->i_atime;
 384         inode->i_ctime = reloc->i_ctime;
 385         inode->i_mtime = reloc->i_mtime;
 386         iput(reloc);
 387         break;
 388       default:
 389         break;
 390       }
 391     };
 392   }
 393   MAYBE_CONTINUE(repeat,inode);
 394   return 0;
 395  out:
 396   if(buffer) kfree(buffer);
 397   return 0;
 398 }
 399 
 400 
 401 /* Returns the name of the file that this inode is symlinked to.  This is
 402    in malloc'd memory, so it needs to be freed, once we are through with it */
 403 
 404 char * get_rock_ridge_symlink(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 405 {
 406   unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 407   unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
 408   struct buffer_head * bh;
 409   unsigned char * pnt;
 410   void * cpnt = NULL;
 411   char * rpnt;
 412   struct iso_directory_record * raw_inode;
 413   CONTINUE_DECLS;
 414   int block;
 415   int sig;
 416   int rootflag;
 417   int len;
 418   unsigned char * chr;
 419   struct rock_ridge * rr;
 420   
 421   if (!inode->i_sb->u.isofs_sb.s_rock)
 422     panic("Cannot have symlink with high sierra variant of iso filesystem\n");
 423 
 424   rpnt = 0;
 425   
 426   block = inode->i_ino >> bufbits;
 427   if (!(bh=bread(inode->i_dev,block, bufsize))) {
 428     printk("unable to read i-node block");
 429     return NULL;
 430   };
 431   
 432   pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
 433   
 434   raw_inode = ((struct iso_directory_record *) pnt);
 435   
 436   if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 437     int frag1, offset;
 438     
 439     offset = (inode->i_ino & (bufsize - 1));
 440     frag1 = bufsize - offset;
 441     cpnt = kmalloc(*pnt,GFP_KERNEL);
 442     if(!cpnt) return NULL;
 443     memcpy(cpnt, bh->b_data + offset, frag1);
 444     brelse(bh);
 445     if (!(bh = bread(inode->i_dev,++block, bufsize))) {
 446       kfree(cpnt);
 447       printk("unable to read i-node block");
 448       return NULL;
 449     };
 450     offset += *pnt - bufsize;
 451     memcpy((char *)cpnt+frag1, bh->b_data, offset);
 452     pnt = ((unsigned char *) cpnt);
 453     raw_inode = ((struct iso_directory_record *) pnt);
 454   };
 455   
 456   /* Now test for possible Rock Ridge extensions which will override some of
 457      these numbers in the inode structure. */
 458   
 459   SETUP_ROCK_RIDGE(raw_inode, chr, len);
 460   
 461  repeat:
 462   while (len > 1){ /* There may be one byte for padding somewhere */
 463     rr = (struct rock_ridge *) chr;
 464     if (rr->len == 0) goto out; /* Something got screwed up here */
 465     sig = (chr[0] << 8) + chr[1];
 466     chr += rr->len; 
 467     len -= rr->len;
 468     
 469     switch(sig){
 470     case SIG('R','R'):
 471       if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
 472       break;
 473     case SIG('S','P'):
 474       CHECK_SP(goto out);
 475       break;
 476     case SIG('S','L'):
 477       {int slen;
 478        struct SL_component * slp;
 479        slen = rr->len - 5;
 480        slp = &rr->u.SL.link;
 481        while (slen > 1){
 482          if (!rpnt){
 483            rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
 484            if (!rpnt) goto out;
 485            *rpnt = 0;
 486          };
 487          rootflag = 0;
 488          switch(slp->flags &~1){
 489          case 0:
 490            strncat(rpnt,slp->text, slp->len);
 491            break;
 492          case 2:
 493            strcat(rpnt,".");
 494            break;
 495          case 4:
 496            strcat(rpnt,"..");
 497            break;
 498          case 8:
 499            rootflag = 1;
 500            strcat(rpnt,"/");
 501            break;
 502          default:
 503            printk("Symlink component flag not implemented (%d)\n",slen);
 504          };
 505          slen -= slp->len + 2;
 506          slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
 507 
 508          if(slen < 2) break;
 509          if(!rootflag) strcat(rpnt,"/");
 510        };
 511        break;
 512      case SIG('C','E'):
 513        CHECK_CE; /* This tells is if there is a continuation record */
 514        break;
 515      default:
 516        break;
 517      }
 518     };
 519   };
 520   MAYBE_CONTINUE(repeat,inode);
 521   brelse(bh);
 522   
 523   if (cpnt) {
 524     kfree(cpnt);
 525     cpnt = NULL;
 526   };
 527 
 528   return rpnt;
 529  out:
 530   if(buffer) kfree(buffer);
 531   return 0;
 532 }
 533 
 534 
 535 
 536 
 537 
 538 

/* [previous][next][first][last][top][bottom][index][help] */