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

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