OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [isofs/] [rock.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/*
/*
 *  linux/fs/isofs/rock.c
 *  linux/fs/isofs/rock.c
 *
 *
 *  (C) 1992, 1993  Eric Youngdale
 *  (C) 1992, 1993  Eric Youngdale
 *
 *
 *  Rock Ridge Extensions to iso9660
 *  Rock Ridge Extensions to iso9660
 */
 */
 
 
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/iso_fs.h>
#include <linux/iso_fs.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <asm/page.h>
#include <asm/page.h>
 
 
#include "rock.h"
#include "rock.h"
 
 
/* These functions are designed to read the system areas of a directory record
/* These functions are designed to read the system areas of a directory record
 * and extract relevant information.  There are different functions provided
 * and extract relevant information.  There are different functions provided
 * depending upon what information we need at the time.  One function fills
 * depending upon what information we need at the time.  One function fills
 * out an inode structure, a second one extracts a filename, a third one
 * out an inode structure, a second one extracts a filename, a third one
 * returns a symbolic link name, and a fourth one returns the extent number
 * returns a symbolic link name, and a fourth one returns the extent number
 * for the file. */
 * for the file. */
 
 
#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
 
 
 
 
/* This is a way of ensuring that we have something in the system
/* This is a way of ensuring that we have something in the system
   use fields that is compatible with Rock Ridge */
   use fields that is compatible with Rock Ridge */
#define CHECK_SP(FAIL)                          \
#define CHECK_SP(FAIL)                          \
      if(rr->u.SP.magic[0] != 0xbe) FAIL;        \
      if(rr->u.SP.magic[0] != 0xbe) FAIL;        \
      if(rr->u.SP.magic[1] != 0xef) FAIL;       \
      if(rr->u.SP.magic[1] != 0xef) FAIL;       \
      inode->i_sb->u.isofs_sb.s_rock_offset=rr->u.SP.skip;
      inode->i_sb->u.isofs_sb.s_rock_offset=rr->u.SP.skip;
/* We define a series of macros because each function must do exactly the
/* We define a series of macros because each function must do exactly the
   same thing in certain places.  We use the macros to ensure that everything
   same thing in certain places.  We use the macros to ensure that everything
   is done correctly */
   is done correctly */
 
 
#define CONTINUE_DECLS \
#define CONTINUE_DECLS \
  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
  void * buffer = 0
  void * buffer = 0
 
 
#define CHECK_CE                                \
#define CHECK_CE                                \
      {cont_extent = isonum_733(rr->u.CE.extent); \
      {cont_extent = isonum_733(rr->u.CE.extent); \
      cont_offset = isonum_733(rr->u.CE.offset); \
      cont_offset = isonum_733(rr->u.CE.offset); \
      cont_size = isonum_733(rr->u.CE.size);}
      cont_size = isonum_733(rr->u.CE.size);}
 
 
#define SETUP_ROCK_RIDGE(DE,CHR,LEN)                            \
#define SETUP_ROCK_RIDGE(DE,CHR,LEN)                            \
  {LEN= sizeof(struct iso_directory_record) + DE->name_len[0];   \
  {LEN= sizeof(struct iso_directory_record) + DE->name_len[0];   \
  if(LEN & 1) LEN++;                                            \
  if(LEN & 1) LEN++;                                            \
  CHR = ((unsigned char *) DE) + LEN;                           \
  CHR = ((unsigned char *) DE) + LEN;                           \
  LEN = *((unsigned char *) DE) - LEN;                          \
  LEN = *((unsigned char *) DE) - LEN;                          \
  if (inode->i_sb->u.isofs_sb.s_rock_offset!=-1)                \
  if (inode->i_sb->u.isofs_sb.s_rock_offset!=-1)                \
  {                                                             \
  {                                                             \
     LEN-=inode->i_sb->u.isofs_sb.s_rock_offset;                \
     LEN-=inode->i_sb->u.isofs_sb.s_rock_offset;                \
     CHR+=inode->i_sb->u.isofs_sb.s_rock_offset;                \
     CHR+=inode->i_sb->u.isofs_sb.s_rock_offset;                \
     if (LEN<0) LEN=0;                                          \
     if (LEN<0) LEN=0;                                          \
  }                                                             \
  }                                                             \
}
}
 
 
#define MAYBE_CONTINUE(LABEL,DEV) \
#define MAYBE_CONTINUE(LABEL,DEV) \
  {if (buffer) kfree(buffer); \
  {if (buffer) kfree(buffer); \
  if (cont_extent){ \
  if (cont_extent){ \
    int block, offset, offset1; \
    int block, offset, offset1; \
    struct buffer_head * pbh; \
    struct buffer_head * pbh; \
    buffer = kmalloc(cont_size,GFP_KERNEL); \
    buffer = kmalloc(cont_size,GFP_KERNEL); \
    if (!buffer) goto out; \
    if (!buffer) goto out; \
    block = cont_extent; \
    block = cont_extent; \
    offset = cont_offset; \
    offset = cont_offset; \
    offset1 = 0; \
    offset1 = 0; \
    pbh = sb_bread(DEV->i_sb, block); \
    pbh = sb_bread(DEV->i_sb, block); \
    if(pbh){       \
    if(pbh){       \
      memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
      memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
      brelse(pbh); \
      brelse(pbh); \
      chr = (unsigned char *) buffer; \
      chr = (unsigned char *) buffer; \
      len = cont_size; \
      len = cont_size; \
      cont_extent = 0; \
      cont_extent = 0; \
      cont_size = 0; \
      cont_size = 0; \
      cont_offset = 0; \
      cont_offset = 0; \
      goto LABEL; \
      goto LABEL; \
    }    \
    }    \
    printk("Unable to read rock-ridge attributes\n");    \
    printk("Unable to read rock-ridge attributes\n");    \
  }}
  }}
 
 
/* This is the inner layer of the get filename routine, and is called
/* This is the inner layer of the get filename routine, and is called
   for each system area and continuation record related to the file */
   for each system area and continuation record related to the file */
 
 
int find_rock_ridge_relocation(struct iso_directory_record * de,
int find_rock_ridge_relocation(struct iso_directory_record * de,
                               struct inode * inode) {
                               struct inode * inode) {
  int flag;
  int flag;
  int len;
  int len;
  int retval;
  int retval;
  unsigned char * chr;
  unsigned char * chr;
  CONTINUE_DECLS;
  CONTINUE_DECLS;
  flag = 0;
  flag = 0;
 
 
  /* If this is a '..' then we are looking for the parent, otherwise we
  /* If this is a '..' then we are looking for the parent, otherwise we
     are looking for the child */
     are looking for the child */
 
 
  if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
  if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
  /* Return value if we do not find appropriate record. */
  /* Return value if we do not find appropriate record. */
  retval = isonum_733 (de->extent);
  retval = isonum_733 (de->extent);
 
 
  if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
  if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
 
 
  SETUP_ROCK_RIDGE(de, chr, len);
  SETUP_ROCK_RIDGE(de, chr, len);
 repeat:
 repeat:
  {
  {
    int rrflag, sig;
    int rrflag, sig;
    struct rock_ridge * rr;
    struct rock_ridge * rr;
 
 
    while (len > 1){ /* There may be one byte for padding somewhere */
    while (len > 1){ /* There may be one byte for padding somewhere */
      rr = (struct rock_ridge *) chr;
      rr = (struct rock_ridge *) chr;
      if (rr->len == 0) goto out; /* Something got screwed up here */
      if (rr->len == 0) goto out; /* Something got screwed up here */
      sig = isonum_721(chr);
      sig = isonum_721(chr);
      chr += rr->len;
      chr += rr->len;
      len -= rr->len;
      len -= rr->len;
 
 
      switch(sig){
      switch(sig){
      case SIG('R','R'):
      case SIG('R','R'):
        rrflag = rr->u.RR.flags[0];
        rrflag = rr->u.RR.flags[0];
        if (flag && !(rrflag & RR_PL)) goto out;
        if (flag && !(rrflag & RR_PL)) goto out;
        if (!flag && !(rrflag & RR_CL)) goto out;
        if (!flag && !(rrflag & RR_CL)) goto out;
        break;
        break;
      case SIG('S','P'):
      case SIG('S','P'):
        CHECK_SP(goto out);
        CHECK_SP(goto out);
        break;
        break;
      case SIG('C','L'):
      case SIG('C','L'):
        if (flag == 0) {
        if (flag == 0) {
          retval = isonum_733(rr->u.CL.location);
          retval = isonum_733(rr->u.CL.location);
          goto out;
          goto out;
        }
        }
        break;
        break;
      case SIG('P','L'):
      case SIG('P','L'):
        if (flag != 0) {
        if (flag != 0) {
          retval = isonum_733(rr->u.PL.location);
          retval = isonum_733(rr->u.PL.location);
          goto out;
          goto out;
        }
        }
        break;
        break;
      case SIG('C','E'):
      case SIG('C','E'):
        CHECK_CE; /* This tells is if there is a continuation record */
        CHECK_CE; /* This tells is if there is a continuation record */
        break;
        break;
      default:
      default:
        break;
        break;
      }
      }
    }
    }
  }
  }
  MAYBE_CONTINUE(repeat, inode);
  MAYBE_CONTINUE(repeat, inode);
  return retval;
  return retval;
 out:
 out:
  if(buffer) kfree(buffer);
  if(buffer) kfree(buffer);
  return retval;
  return retval;
}
}
 
 
/* return length of name field; 0: not found, -1: to be ignored */
/* return length of name field; 0: not found, -1: to be ignored */
int get_rock_ridge_filename(struct iso_directory_record * de,
int get_rock_ridge_filename(struct iso_directory_record * de,
                            char * retname, struct inode * inode)
                            char * retname, struct inode * inode)
{
{
  int len;
  int len;
  unsigned char * chr;
  unsigned char * chr;
  CONTINUE_DECLS;
  CONTINUE_DECLS;
  int retnamlen = 0, truncate=0;
  int retnamlen = 0, truncate=0;
 
 
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
  *retname = 0;
  *retname = 0;
 
 
  SETUP_ROCK_RIDGE(de, chr, len);
  SETUP_ROCK_RIDGE(de, chr, len);
 repeat:
 repeat:
  {
  {
    struct rock_ridge * rr;
    struct rock_ridge * rr;
    int sig;
    int sig;
 
 
    while (len > 1){ /* There may be one byte for padding somewhere */
    while (len > 1){ /* There may be one byte for padding somewhere */
      rr = (struct rock_ridge *) chr;
      rr = (struct rock_ridge *) chr;
      if (rr->len == 0) goto out; /* Something got screwed up here */
      if (rr->len == 0) goto out; /* Something got screwed up here */
      sig = isonum_721(chr);
      sig = isonum_721(chr);
      chr += rr->len;
      chr += rr->len;
      len -= rr->len;
      len -= rr->len;
 
 
      switch(sig){
      switch(sig){
      case SIG('R','R'):
      case SIG('R','R'):
        if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
        if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
        break;
        break;
      case SIG('S','P'):
      case SIG('S','P'):
        CHECK_SP(goto out);
        CHECK_SP(goto out);
        break;
        break;
      case SIG('C','E'):
      case SIG('C','E'):
        CHECK_CE;
        CHECK_CE;
        break;
        break;
      case SIG('N','M'):
      case SIG('N','M'):
        if (truncate) break;
        if (truncate) break;
        /*
        /*
         * If the flags are 2 or 4, this indicates '.' or '..'.
         * If the flags are 2 or 4, this indicates '.' or '..'.
         * We don't want to do anything with this, because it
         * We don't want to do anything with this, because it
         * screws up the code that calls us.  We don't really
         * screws up the code that calls us.  We don't really
         * care anyways, since we can just use the non-RR
         * care anyways, since we can just use the non-RR
         * name.
         * name.
         */
         */
        if (rr->u.NM.flags & 6) {
        if (rr->u.NM.flags & 6) {
          break;
          break;
        }
        }
 
 
        if (rr->u.NM.flags & ~1) {
        if (rr->u.NM.flags & ~1) {
          printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
          printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
          break;
          break;
        }
        }
        if((strlen(retname) + rr->len - 5) >= 254) {
        if((strlen(retname) + rr->len - 5) >= 254) {
          truncate = 1;
          truncate = 1;
          break;
          break;
        }
        }
        strncat(retname, rr->u.NM.name, rr->len - 5);
        strncat(retname, rr->u.NM.name, rr->len - 5);
        retnamlen += rr->len - 5;
        retnamlen += rr->len - 5;
        break;
        break;
      case SIG('R','E'):
      case SIG('R','E'):
        if (buffer) kfree(buffer);
        if (buffer) kfree(buffer);
        return -1;
        return -1;
      default:
      default:
        break;
        break;
      }
      }
    }
    }
  }
  }
  MAYBE_CONTINUE(repeat,inode);
  MAYBE_CONTINUE(repeat,inode);
  return retnamlen; /* If 0, this file did not have a NM field */
  return retnamlen; /* If 0, this file did not have a NM field */
 out:
 out:
  if(buffer) kfree(buffer);
  if(buffer) kfree(buffer);
  return 0;
  return 0;
}
}
 
 
int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
                                    struct inode * inode,int regard_xa){
                                    struct inode * inode,int regard_xa){
  int len;
  int len;
  unsigned char * chr;
  unsigned char * chr;
  int symlink_len = 0;
  int symlink_len = 0;
  CONTINUE_DECLS;
  CONTINUE_DECLS;
 
 
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
 
 
  SETUP_ROCK_RIDGE(de, chr, len);
  SETUP_ROCK_RIDGE(de, chr, len);
  if (regard_xa)
  if (regard_xa)
   {
   {
     chr+=14;
     chr+=14;
     len-=14;
     len-=14;
     if (len<0) len=0;
     if (len<0) len=0;
   };
   };
 
 
 repeat:
 repeat:
  {
  {
    int cnt, sig;
    int cnt, sig;
    struct inode * reloc;
    struct inode * reloc;
    struct rock_ridge * rr;
    struct rock_ridge * rr;
    int rootflag;
    int rootflag;
 
 
    while (len > 1){ /* There may be one byte for padding somewhere */
    while (len > 1){ /* There may be one byte for padding somewhere */
      rr = (struct rock_ridge *) chr;
      rr = (struct rock_ridge *) chr;
      if (rr->len == 0) goto out; /* Something got screwed up here */
      if (rr->len == 0) goto out; /* Something got screwed up here */
      sig = isonum_721(chr);
      sig = isonum_721(chr);
      chr += rr->len;
      chr += rr->len;
      len -= rr->len;
      len -= rr->len;
 
 
      switch(sig){
      switch(sig){
#ifndef CONFIG_ZISOFS           /* No flag for SF or ZF */
#ifndef CONFIG_ZISOFS           /* No flag for SF or ZF */
      case SIG('R','R'):
      case SIG('R','R'):
        if((rr->u.RR.flags[0] &
        if((rr->u.RR.flags[0] &
            (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
            (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
        break;
        break;
#endif
#endif
      case SIG('S','P'):
      case SIG('S','P'):
        CHECK_SP(goto out);
        CHECK_SP(goto out);
        break;
        break;
      case SIG('C','E'):
      case SIG('C','E'):
        CHECK_CE;
        CHECK_CE;
        break;
        break;
      case SIG('E','R'):
      case SIG('E','R'):
        inode->i_sb->u.isofs_sb.s_rock = 1;
        inode->i_sb->u.isofs_sb.s_rock = 1;
        printk(KERN_DEBUG "ISO 9660 Extensions: ");
        printk(KERN_DEBUG "ISO 9660 Extensions: ");
        { int p;
        { int p;
          for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
          for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
        }
        }
          printk("\n");
          printk("\n");
        break;
        break;
      case SIG('P','X'):
      case SIG('P','X'):
        inode->i_mode  = isonum_733(rr->u.PX.mode);
        inode->i_mode  = isonum_733(rr->u.PX.mode);
        inode->i_nlink = isonum_733(rr->u.PX.n_links);
        inode->i_nlink = isonum_733(rr->u.PX.n_links);
        inode->i_uid   = isonum_733(rr->u.PX.uid);
        inode->i_uid   = isonum_733(rr->u.PX.uid);
        inode->i_gid   = isonum_733(rr->u.PX.gid);
        inode->i_gid   = isonum_733(rr->u.PX.gid);
        break;
        break;
      case SIG('P','N'):
      case SIG('P','N'):
        { int high, low;
        { int high, low;
          high = isonum_733(rr->u.PN.dev_high);
          high = isonum_733(rr->u.PN.dev_high);
          low = isonum_733(rr->u.PN.dev_low);
          low = isonum_733(rr->u.PN.dev_low);
          /*
          /*
           * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
           * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
           * then the high field is unused, and the device number is completely
           * then the high field is unused, and the device number is completely
           * stored in the low field.  Some writers may ignore this subtlety,
           * stored in the low field.  Some writers may ignore this subtlety,
           * and as a result we test to see if the entire device number is
           * and as a result we test to see if the entire device number is
           * stored in the low field, and use that.
           * stored in the low field, and use that.
           */
           */
          if((low & ~0xff) && high == 0) {
          if((low & ~0xff) && high == 0) {
            inode->i_rdev = MKDEV(low >> 8, low & 0xff);
            inode->i_rdev = MKDEV(low >> 8, low & 0xff);
          } else {
          } else {
            inode->i_rdev = MKDEV(high, low);
            inode->i_rdev = MKDEV(high, low);
          }
          }
        }
        }
        break;
        break;
      case SIG('T','F'):
      case SIG('T','F'):
        /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
        /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
           Try to handle this correctly for either case. */
           Try to handle this correctly for either case. */
        cnt = 0; /* Rock ridge never appears on a High Sierra disk */
        cnt = 0; /* Rock ridge never appears on a High Sierra disk */
        if(rr->u.TF.flags & TF_CREATE)
        if(rr->u.TF.flags & TF_CREATE)
          inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
          inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
        if(rr->u.TF.flags & TF_MODIFY)
        if(rr->u.TF.flags & TF_MODIFY)
          inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
          inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
        if(rr->u.TF.flags & TF_ACCESS)
        if(rr->u.TF.flags & TF_ACCESS)
          inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
          inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
        if(rr->u.TF.flags & TF_ATTRIBUTES)
        if(rr->u.TF.flags & TF_ATTRIBUTES)
          inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
          inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
        break;
        break;
      case SIG('S','L'):
      case SIG('S','L'):
        {int slen;
        {int slen;
         struct SL_component * slp;
         struct SL_component * slp;
         struct SL_component * oldslp;
         struct SL_component * oldslp;
         slen = rr->len - 5;
         slen = rr->len - 5;
         slp = &rr->u.SL.link;
         slp = &rr->u.SL.link;
         inode->i_size = symlink_len;
         inode->i_size = symlink_len;
         while (slen > 1){
         while (slen > 1){
           rootflag = 0;
           rootflag = 0;
           switch(slp->flags &~1){
           switch(slp->flags &~1){
           case 0:
           case 0:
             inode->i_size += slp->len;
             inode->i_size += slp->len;
             break;
             break;
           case 2:
           case 2:
             inode->i_size += 1;
             inode->i_size += 1;
             break;
             break;
           case 4:
           case 4:
             inode->i_size += 2;
             inode->i_size += 2;
             break;
             break;
           case 8:
           case 8:
             rootflag = 1;
             rootflag = 1;
             inode->i_size += 1;
             inode->i_size += 1;
             break;
             break;
           default:
           default:
             printk("Symlink component flag not implemented\n");
             printk("Symlink component flag not implemented\n");
           }
           }
           slen -= slp->len + 2;
           slen -= slp->len + 2;
           oldslp = slp;
           oldslp = slp;
           slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
           slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
 
 
           if(slen < 2) {
           if(slen < 2) {
             if(    ((rr->u.SL.flags & 1) != 0)
             if(    ((rr->u.SL.flags & 1) != 0)
                    && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
                    && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
             break;
             break;
           }
           }
 
 
           /*
           /*
            * If this component record isn't continued, then append a '/'.
            * If this component record isn't continued, then append a '/'.
            */
            */
           if (!rootflag && (oldslp->flags & 1) == 0)
           if (!rootflag && (oldslp->flags & 1) == 0)
                   inode->i_size += 1;
                   inode->i_size += 1;
         }
         }
        }
        }
        symlink_len = inode->i_size;
        symlink_len = inode->i_size;
        break;
        break;
      case SIG('R','E'):
      case SIG('R','E'):
        printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
        printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
        goto out;
        goto out;
      case SIG('C','L'):
      case SIG('C','L'):
        inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
        inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
        reloc = iget(inode->i_sb,
        reloc = iget(inode->i_sb,
                     (inode->u.isofs_i.i_first_extent <<
                     (inode->u.isofs_i.i_first_extent <<
                      inode -> i_sb -> u.isofs_sb.s_log_zone_size));
                      inode -> i_sb -> u.isofs_sb.s_log_zone_size));
        if (!reloc)
        if (!reloc)
                goto out;
                goto out;
        inode->i_mode = reloc->i_mode;
        inode->i_mode = reloc->i_mode;
        inode->i_nlink = reloc->i_nlink;
        inode->i_nlink = reloc->i_nlink;
        inode->i_uid = reloc->i_uid;
        inode->i_uid = reloc->i_uid;
        inode->i_gid = reloc->i_gid;
        inode->i_gid = reloc->i_gid;
        inode->i_rdev = reloc->i_rdev;
        inode->i_rdev = reloc->i_rdev;
        inode->i_size = reloc->i_size;
        inode->i_size = reloc->i_size;
        inode->i_blocks = reloc->i_blocks;
        inode->i_blocks = reloc->i_blocks;
        inode->i_atime = reloc->i_atime;
        inode->i_atime = reloc->i_atime;
        inode->i_ctime = reloc->i_ctime;
        inode->i_ctime = reloc->i_ctime;
        inode->i_mtime = reloc->i_mtime;
        inode->i_mtime = reloc->i_mtime;
        iput(reloc);
        iput(reloc);
        break;
        break;
#ifdef CONFIG_ZISOFS
#ifdef CONFIG_ZISOFS
      case SIG('Z','F'):
      case SIG('Z','F'):
              if ( !inode->i_sb->u.isofs_sb.s_nocompress ) {
              if ( !inode->i_sb->u.isofs_sb.s_nocompress ) {
                      int algo;
                      int algo;
                      algo = isonum_721(rr->u.ZF.algorithm);
                      algo = isonum_721(rr->u.ZF.algorithm);
                      if ( algo == SIG('p','z') ) {
                      if ( algo == SIG('p','z') ) {
                              int block_shift = isonum_711(&rr->u.ZF.parms[1]);
                              int block_shift = isonum_711(&rr->u.ZF.parms[1]);
                              if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
                              if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
                                      printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
                                      printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
                              } else {
                              } else {
                                /* Note: we don't change i_blocks here */
                                /* Note: we don't change i_blocks here */
                                      inode->u.isofs_i.i_file_format = isofs_file_compressed;
                                      inode->u.isofs_i.i_file_format = isofs_file_compressed;
                                /* Parameters to compression algorithm (header size, block size) */
                                /* Parameters to compression algorithm (header size, block size) */
                                      inode->u.isofs_i.i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
                                      inode->u.isofs_i.i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
                                      inode->u.isofs_i.i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
                                      inode->u.isofs_i.i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
                                      inode->i_size = isonum_733(rr->u.ZF.real_size);
                                      inode->i_size = isonum_733(rr->u.ZF.real_size);
                              }
                              }
                      } else {
                      } else {
                              printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
                              printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
                                     rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
                                     rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
                      }
                      }
              }
              }
              break;
              break;
#endif
#endif
      default:
      default:
        break;
        break;
      }
      }
    }
    }
  }
  }
  MAYBE_CONTINUE(repeat,inode);
  MAYBE_CONTINUE(repeat,inode);
  return 0;
  return 0;
 out:
 out:
  if(buffer) kfree(buffer);
  if(buffer) kfree(buffer);
  return 0;
  return 0;
}
}
 
 
static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
{
{
        int slen;
        int slen;
        int rootflag;
        int rootflag;
        struct SL_component *oldslp;
        struct SL_component *oldslp;
        struct SL_component *slp;
        struct SL_component *slp;
        slen = rr->len - 5;
        slen = rr->len - 5;
        slp = &rr->u.SL.link;
        slp = &rr->u.SL.link;
        while (slen > 1) {
        while (slen > 1) {
                rootflag = 0;
                rootflag = 0;
                switch (slp->flags & ~1) {
                switch (slp->flags & ~1) {
                case 0:
                case 0:
                        if (slp->len > plimit - rpnt)
                        if (slp->len > plimit - rpnt)
                                return NULL;
                                return NULL;
                        memcpy(rpnt, slp->text, slp->len);
                        memcpy(rpnt, slp->text, slp->len);
                        rpnt+=slp->len;
                        rpnt+=slp->len;
                        break;
                        break;
                case 2:
                case 2:
                        if (rpnt >= plimit)
                        if (rpnt >= plimit)
                                return NULL;
                                return NULL;
                        *rpnt++='.';
                        *rpnt++='.';
                        break;
                        break;
                case 4:
                case 4:
                        if (2 > plimit - rpnt)
                        if (2 > plimit - rpnt)
                                return NULL;
                                return NULL;
                        *rpnt++='.';
                        *rpnt++='.';
                        *rpnt++='.';
                        *rpnt++='.';
                        break;
                        break;
                case 8:
                case 8:
                        if (rpnt >= plimit)
                        if (rpnt >= plimit)
                                return NULL;
                                return NULL;
                        rootflag = 1;
                        rootflag = 1;
                        *rpnt++='/';
                        *rpnt++='/';
                        break;
                        break;
                default:
                default:
                        printk("Symlink component flag not implemented (%d)\n",
                        printk("Symlink component flag not implemented (%d)\n",
                             slp->flags);
                             slp->flags);
                }
                }
                slen -= slp->len + 2;
                slen -= slp->len + 2;
                oldslp = slp;
                oldslp = slp;
                slp = (struct SL_component *) ((char *) slp + slp->len + 2);
                slp = (struct SL_component *) ((char *) slp + slp->len + 2);
 
 
                if (slen < 2) {
                if (slen < 2) {
                        /*
                        /*
                         * If there is another SL record, and this component
                         * If there is another SL record, and this component
                         * record isn't continued, then add a slash.
                         * record isn't continued, then add a slash.
                         */
                         */
                        if ((!rootflag) && (rr->u.SL.flags & 1) &&
                        if ((!rootflag) && (rr->u.SL.flags & 1) &&
                            !(oldslp->flags & 1)) {
                            !(oldslp->flags & 1)) {
                                if (rpnt >= plimit)
                                if (rpnt >= plimit)
                                        return NULL;
                                        return NULL;
                                *rpnt++='/';
                                *rpnt++='/';
                        }
                        }
                        break;
                        break;
                }
                }
 
 
                /*
                /*
                 * If this component record isn't continued, then append a '/'.
                 * If this component record isn't continued, then append a '/'.
                 */
                 */
                if (!rootflag && !(oldslp->flags & 1)) {
                if (!rootflag && !(oldslp->flags & 1)) {
                        if (rpnt >= plimit)
                        if (rpnt >= plimit)
                                return NULL;
                                return NULL;
                        *rpnt++='/';
                        *rpnt++='/';
                }
                }
        }
        }
        return rpnt;
        return rpnt;
}
}
 
 
int parse_rock_ridge_inode(struct iso_directory_record * de,
int parse_rock_ridge_inode(struct iso_directory_record * de,
                           struct inode * inode)
                           struct inode * inode)
{
{
   int result=parse_rock_ridge_inode_internal(de,inode,0);
   int result=parse_rock_ridge_inode_internal(de,inode,0);
   /* if rockridge flag was reset and we didn't look for attributes
   /* if rockridge flag was reset and we didn't look for attributes
    * behind eventual XA attributes, have a look there */
    * behind eventual XA attributes, have a look there */
   if ((inode->i_sb->u.isofs_sb.s_rock_offset==-1)
   if ((inode->i_sb->u.isofs_sb.s_rock_offset==-1)
       &&(inode->i_sb->u.isofs_sb.s_rock==2))
       &&(inode->i_sb->u.isofs_sb.s_rock==2))
     {
     {
        result=parse_rock_ridge_inode_internal(de,inode,14);
        result=parse_rock_ridge_inode_internal(de,inode,14);
     };
     };
   return result;
   return result;
};
};
 
 
/* readpage() for symlinks: reads symlink contents into the page and either
/* readpage() for symlinks: reads symlink contents into the page and either
   makes it uptodate and returns 0 or returns error (-EIO) */
   makes it uptodate and returns 0 or returns error (-EIO) */
 
 
static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
{
{
        struct inode *inode = page->mapping->host;
        struct inode *inode = page->mapping->host;
        char *link = kmap(page);
        char *link = kmap(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
        struct buffer_head *bh;
        struct buffer_head *bh;
        char *rpnt = link;
        char *rpnt = link;
        unsigned char *pnt;
        unsigned char *pnt;
        struct iso_directory_record *raw_inode;
        struct iso_directory_record *raw_inode;
        CONTINUE_DECLS;
        CONTINUE_DECLS;
        int block;
        int block;
        int sig;
        int sig;
        int len;
        int len;
        unsigned char *chr;
        unsigned char *chr;
        struct rock_ridge *rr;
        struct rock_ridge *rr;
 
 
        if (!inode->i_sb->u.isofs_sb.s_rock)
        if (!inode->i_sb->u.isofs_sb.s_rock)
                panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
                panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
 
 
        block = inode->i_ino >> bufbits;
        block = inode->i_ino >> bufbits;
        lock_kernel();
        lock_kernel();
        bh = sb_bread(inode->i_sb, block);
        bh = sb_bread(inode->i_sb, block);
        if (!bh)
        if (!bh)
                goto out_noread;
                goto out_noread;
 
 
        pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
        pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
 
 
        raw_inode = (struct iso_directory_record *) pnt;
        raw_inode = (struct iso_directory_record *) pnt;
 
 
        /*
        /*
         * If we go past the end of the buffer, there is some sort of error.
         * If we go past the end of the buffer, there is some sort of error.
         */
         */
        if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
        if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
                goto out_bad_span;
                goto out_bad_span;
 
 
        /* Now test for possible Rock Ridge extensions which will override
        /* Now test for possible Rock Ridge extensions which will override
           some of these numbers in the inode structure. */
           some of these numbers in the inode structure. */
 
 
        SETUP_ROCK_RIDGE(raw_inode, chr, len);
        SETUP_ROCK_RIDGE(raw_inode, chr, len);
 
 
      repeat:
      repeat:
        while (len > 1) { /* There may be one byte for padding somewhere */
        while (len > 1) { /* There may be one byte for padding somewhere */
                rr = (struct rock_ridge *) chr;
                rr = (struct rock_ridge *) chr;
                if (rr->len == 0)
                if (rr->len == 0)
                        goto out;       /* Something got screwed up here */
                        goto out;       /* Something got screwed up here */
                sig = isonum_721(chr);
                sig = isonum_721(chr);
                chr += rr->len;
                chr += rr->len;
                len -= rr->len;
                len -= rr->len;
 
 
                switch (sig) {
                switch (sig) {
                case SIG('R', 'R'):
                case SIG('R', 'R'):
                        if ((rr->u.RR.flags[0] & RR_SL) == 0)
                        if ((rr->u.RR.flags[0] & RR_SL) == 0)
                                goto out;
                                goto out;
                        break;
                        break;
                case SIG('S', 'P'):
                case SIG('S', 'P'):
                        CHECK_SP(goto out);
                        CHECK_SP(goto out);
                        break;
                        break;
                case SIG('S', 'L'):
                case SIG('S', 'L'):
                        rpnt = get_symlink_chunk(rpnt, rr,
                        rpnt = get_symlink_chunk(rpnt, rr,
                                                 link + (PAGE_SIZE - 1));
                                                 link + (PAGE_SIZE - 1));
                        if (rpnt == NULL)
                        if (rpnt == NULL)
                                goto out;
                                goto out;
                        break;
                        break;
                case SIG('C', 'E'):
                case SIG('C', 'E'):
                        /* This tells is if there is a continuation record */
                        /* This tells is if there is a continuation record */
                        CHECK_CE;
                        CHECK_CE;
                default:
                default:
                        break;
                        break;
                }
                }
        }
        }
        MAYBE_CONTINUE(repeat, inode);
        MAYBE_CONTINUE(repeat, inode);
 
 
        if (rpnt == link)
        if (rpnt == link)
                goto fail;
                goto fail;
        brelse(bh);
        brelse(bh);
        *rpnt = '\0';
        *rpnt = '\0';
        unlock_kernel();
        unlock_kernel();
        SetPageUptodate(page);
        SetPageUptodate(page);
        kunmap(page);
        kunmap(page);
        UnlockPage(page);
        UnlockPage(page);
        return 0;
        return 0;
 
 
        /* error exit from macro */
        /* error exit from macro */
      out:
      out:
        if (buffer)
        if (buffer)
                kfree(buffer);
                kfree(buffer);
        goto fail;
        goto fail;
      out_noread:
      out_noread:
        printk("unable to read i-node block");
        printk("unable to read i-node block");
        goto fail;
        goto fail;
      out_bad_span:
      out_bad_span:
        printk("symlink spans iso9660 blocks\n");
        printk("symlink spans iso9660 blocks\n");
      fail:
      fail:
        brelse(bh);
        brelse(bh);
        unlock_kernel();
        unlock_kernel();
        SetPageError(page);
        SetPageError(page);
        kunmap(page);
        kunmap(page);
        UnlockPage(page);
        UnlockPage(page);
        return -EIO;
        return -EIO;
}
}
 
 
struct address_space_operations isofs_symlink_aops = {
struct address_space_operations isofs_symlink_aops = {
        readpage:       rock_ridge_symlink_readpage
        readpage:       rock_ridge_symlink_readpage
};
};
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.