home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / isofs / rock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-01  |  12.7 KB  |  510 lines

  1. /*
  2.  *  linux/fs/isofs/rock.c
  3.  *
  4.  *  (C) 1992  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, 
  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,
  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,
  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)
  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.  
  510.