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

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