root/fs/isofs/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. isofs_put_super
  2. parse_options
  3. isofs_get_last_session
  4. isofs_read_super
  5. isofs_statfs
  6. isofs_bmap
  7. isofs_read_inode
  8. isofs_lookup_grandparent
  9. leak_check_malloc
  10. leak_check_free_s
  11. leak_check_bread
  12. leak_check_brelse
  13. init_iso9660_fs
  14. init_module
  15. cleanup_module

   1 /*
   2  *  linux/fs/isofs/inode.c
   3  * 
   4  *  (C) 1991  Linus Torvalds - minix filesystem
   5  *      1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
   6  *      1994  Eberhard Moenkeberg - multi session handling.
   7  *      1995  Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
   8  *
   9  */
  10 
  11 #include <linux/module.h>
  12 
  13 #include <linux/stat.h>
  14 #include <linux/sched.h>
  15 #include <linux/iso_fs.h>
  16 #include <linux/kernel.h>
  17 #include <linux/major.h>
  18 #include <linux/mm.h>
  19 #include <linux/string.h>
  20 #include <linux/locks.h>
  21 #include <linux/malloc.h>
  22 #include <linux/errno.h>
  23 #include <linux/cdrom.h>
  24 
  25 #include <asm/system.h>
  26 #include <asm/segment.h>
  27 
  28 #ifdef LEAK_CHECK
  29 static int check_malloc = 0;
  30 static int check_bread = 0;
  31 #endif
  32 
  33 void isofs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35         lock_super(sb);
  36 
  37 #ifdef LEAK_CHECK
  38         printk("Outstanding mallocs:%d, outstanding buffers: %d\n", 
  39                check_malloc, check_bread);
  40 #endif
  41         sb->s_dev = 0;
  42         unlock_super(sb);
  43         MOD_DEC_USE_COUNT;
  44         return;
  45 }
  46 
  47 static struct super_operations isofs_sops = { 
  48         isofs_read_inode,
  49         NULL,                   /* notify_change */
  50         NULL,                   /* write_inode */
  51         NULL,                   /* put_inode */
  52         isofs_put_super,
  53         NULL,                   /* write_super */
  54         isofs_statfs,
  55         NULL
  56 };
  57 
  58 struct iso9660_options{
  59   char map;
  60   char rock;
  61   char cruft;
  62   char unhide;
  63   unsigned char check;
  64   unsigned char conversion;
  65   unsigned int blocksize;
  66   mode_t mode;
  67   gid_t gid;
  68   uid_t uid;
  69 };
  70 
  71 static int parse_options(char *options, struct iso9660_options * popt)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         char *this_char,*value;
  74 
  75         popt->map = 'n';
  76         popt->rock = 'y';
  77         popt->cruft = 'n';
  78         popt->unhide = 'n';
  79         popt->check = 's';              /* default: strict */
  80         popt->conversion = 'b';         /* default: no conversion */
  81         popt->blocksize = 1024;
  82         popt->mode = S_IRUGO;
  83         popt->gid = 0;
  84         popt->uid = 0;
  85         if (!options) return 1;
  86         for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  87                 if (strncmp(this_char,"norock",6) == 0) {
  88                   popt->rock = 'n';
  89                   continue;
  90                 };
  91                 if (strncmp(this_char,"unhide",6) == 0) {
  92                   popt->unhide = 'y';
  93                   continue;
  94                 };
  95                 if (strncmp(this_char,"cruft",5) == 0) {
  96                   popt->cruft = 'y';
  97                   continue;
  98                 };
  99                 if ((value = strchr(this_char,'=')) != NULL)
 100                         *value++ = 0;
 101                 if (!strcmp(this_char,"map") && value) {
 102                         if (value[0] && !value[1] && strchr("on",*value))
 103                                 popt->map = *value;
 104                         else if (!strcmp(value,"off")) popt->map = 'o';
 105                         else if (!strcmp(value,"normal")) popt->map = 'n';
 106                         else return 0;
 107                 }
 108                 else if (!strcmp(this_char,"check") && value) {
 109                         if (value[0] && !value[1] && strchr("rs",*value))
 110                                 popt->check = *value;
 111                         else if (!strcmp(value,"relaxed")) popt->check = 'r';
 112                         else if (!strcmp(value,"strict")) popt->check = 's';
 113                         else return 0;
 114                 }
 115                 else if (!strcmp(this_char,"conv") && value) {
 116                         if (value[0] && !value[1] && strchr("btma",*value))
 117                                 popt->conversion = *value;
 118                         else if (!strcmp(value,"binary")) popt->conversion = 'b';
 119                         else if (!strcmp(value,"text")) popt->conversion = 't';
 120                         else if (!strcmp(value,"mtext")) popt->conversion = 'm';
 121                         else if (!strcmp(value,"auto")) popt->conversion = 'a';
 122                         else return 0;
 123                 }
 124                 else if (value && 
 125                          (!strcmp(this_char,"block") ||
 126                           !strcmp(this_char,"mode") ||
 127                           !strcmp(this_char,"uid") ||
 128                           !strcmp(this_char,"gid"))) {
 129                   char * vpnt = value;
 130                   unsigned int ivalue;
 131                   ivalue = 0;
 132                   while(*vpnt){
 133                     if(*vpnt <  '0' || *vpnt > '9') break;
 134                     ivalue = ivalue * 10 + (*vpnt - '0');
 135                     vpnt++;
 136                   };
 137                   if (*vpnt) return 0;
 138                   switch(*this_char) {
 139                   case 'b':
 140                     if (   ivalue != 512 
 141                         && ivalue != 1024 
 142                         && ivalue != 2048) return 0;
 143                     popt->blocksize = ivalue;
 144                     break;
 145                   case 'u':
 146                     popt->uid = ivalue;
 147                     break;
 148                   case 'g':
 149                     popt->gid = ivalue;
 150                     break;
 151                   case 'm':
 152                     popt->mode = ivalue;
 153                     break;
 154                   }
 155                 }
 156                 else return 1;
 157         }
 158         return 1;
 159 }
 160 
 161 /*
 162  * look if the driver can tell the multi session redirection value
 163  */
 164 static unsigned int isofs_get_last_session(kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166   struct cdrom_multisession ms_info;
 167   unsigned int vol_desc_start;
 168   struct inode inode_fake;
 169   extern struct file_operations * get_blkfops(unsigned int);
 170   int i;
 171 
 172   vol_desc_start=0;
 173   if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
 174     {
 175       inode_fake.i_rdev=dev;
 176       ms_info.addr_format=CDROM_LBA;
 177       set_fs(KERNEL_DS);
 178       i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
 179                                        NULL,
 180                                        CDROMMULTISESSION,
 181                                        (unsigned long) &ms_info);
 182       set_fs(USER_DS);
 183 #if 0 
 184       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 185       if (i==0)
 186         {
 187           printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
 188           printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 189         }
 190 #endif 0
 191       if ((i==0)&&(ms_info.xa_flag)) vol_desc_start=ms_info.addr.lba;
 192     }
 193   return vol_desc_start;
 194 }
 195 
 196 struct super_block *isofs_read_super(struct super_block *s,void *data,
     /* [previous][next][first][last][top][bottom][index][help] */
 197                                      int silent)
 198 {
 199         struct buffer_head *bh=NULL;
 200         int iso_blknum;
 201         unsigned int blocksize_bits;
 202         int high_sierra;
 203         kdev_t dev = s->s_dev;
 204         unsigned int vol_desc_start;
 205         int orig_zonesize;
 206 
 207         struct iso_volume_descriptor *vdp;
 208         struct hs_volume_descriptor *hdp;
 209 
 210         struct iso_primary_descriptor *pri = NULL;
 211         struct hs_primary_descriptor *h_pri = NULL;
 212 
 213         struct iso_directory_record *rootp;
 214 
 215         struct iso9660_options opt;
 216 
 217         MOD_INC_USE_COUNT;
 218 
 219         if (!parse_options((char *) data,&opt)) {
 220                 s->s_dev = 0;
 221                 MOD_DEC_USE_COUNT;
 222                 return NULL;
 223         }
 224 
 225 #if 0
 226         printk("map = %c\n", opt.map);
 227         printk("rock = %c\n", opt.rock);
 228         printk("check = %c\n", opt.check);
 229         printk("cruft = %c\n", opt.cruft);
 230         printk("unhide = %c\n", opt.unhide);
 231         printk("conversion = %c\n", opt.conversion);
 232         printk("blocksize = %d\n", opt.blocksize);
 233         printk("gid = %d\n", opt.gid);
 234         printk("uid = %d\n", opt.uid);
 235 #endif
 236         
 237         blocksize_bits = 0;
 238         {
 239           int i = opt.blocksize;
 240           while (i != 1){
 241             blocksize_bits++;
 242             i >>=1;
 243           };
 244         };
 245         set_blocksize(dev, opt.blocksize);
 246 
 247         lock_super(s);
 248 
 249         s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 250 
 251         vol_desc_start = isofs_get_last_session(dev);
 252         
 253         for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) {
 254 #if 0
 255                 printk("isofs.inode: iso_blknum=%d\n", iso_blknum);
 256 #endif 0
 257                 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
 258                         s->s_dev = 0;
 259                         printk("isofs_read_super: bread failed, dev "
 260                                "%s iso_blknum %d\n",
 261                                kdevname(dev), iso_blknum);
 262                         unlock_super(s);
 263                         MOD_DEC_USE_COUNT;
 264                         return NULL;
 265                 }
 266 
 267                 vdp = (struct iso_volume_descriptor *)bh->b_data;
 268                 hdp = (struct hs_volume_descriptor *)bh->b_data;
 269 
 270                 
 271                 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
 272                   if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
 273                         goto out;
 274                   if (isonum_711 (hdp->type) == ISO_VD_END)
 275                         goto out;
 276                 
 277                         s->u.isofs_sb.s_high_sierra = 1;
 278                         high_sierra = 1;
 279                         opt.rock = 'n';
 280                         h_pri = (struct hs_primary_descriptor *)vdp;
 281                         break;
 282                 };
 283                 
 284                 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
 285                   if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
 286                         goto out;
 287                   if (isonum_711 (vdp->type) == ISO_VD_END)
 288                         goto out;
 289                 
 290                         pri = (struct iso_primary_descriptor *)vdp;
 291                         break;
 292                 };
 293 
 294                 brelse(bh);
 295               }
 296         if(iso_blknum == vol_desc_start + 100) {
 297                 if (!silent)
 298                         printk("Unable to identify CD-ROM format.\n");
 299                 s->s_dev = 0;
 300                 unlock_super(s);
 301                 MOD_DEC_USE_COUNT;
 302                 return NULL;
 303         };
 304         
 305         
 306         if(high_sierra){
 307           rootp = (struct iso_directory_record *) h_pri->root_directory_record;
 308           if (isonum_723 (h_pri->volume_set_size) != 1) {
 309             printk("Multi-volume disks not (yet) supported.\n");
 310             goto out;
 311           };
 312           s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
 313           s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
 314           s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
 315         } else {
 316           rootp = (struct iso_directory_record *) pri->root_directory_record;
 317           if (isonum_723 (pri->volume_set_size) != 1) {
 318             printk("Multi-volume disks not (yet) supported.\n");
 319             goto out;
 320           };
 321           s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
 322           s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 323           s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 324         }
 325         
 326         s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
 327         
 328         /* RDE: convert log zone size to bit shift */
 329 
 330         orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
 331         switch (s -> u.isofs_sb.s_log_zone_size)
 332           { case  512: s -> u.isofs_sb.s_log_zone_size =  9; break;
 333             case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
 334             case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
 335 
 336             default:
 337               printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
 338               goto out;
 339           }
 340 
 341         /* RDE: data zone now byte offset! */
 342 
 343         s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) + 
 344                                            isonum_711 (rootp->ext_attr_length))
 345                                          << s -> u.isofs_sb.s_log_zone_size);
 346         s->s_magic = ISOFS_SUPER_MAGIC;
 347         
 348         /* The CDROM is read-only, has no nodes (devices) on it, and since
 349            all of the files appear to be owned by root, we really do not want
 350            to allow suid.  (suid or devices will not show up unless we have
 351            Rock Ridge extensions) */
 352         
 353         s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 354         
 355         brelse(bh);
 356         
 357         printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
 358                s->u.isofs_sb.s_max_size, 
 359                1UL << s->u.isofs_sb.s_log_zone_size);
 360         printk(KERN_DEBUG "First datazone:%ld   Root inode number %d\n",
 361                s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
 362                (isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length))
 363                         << s -> u.isofs_sb.s_log_zone_size);
 364         if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
 365         unlock_super(s);
 366         /* set up enough so that it can read an inode */
 367         
 368         /*
 369          * Force the blocksize to 512 for 512 byte sectors.  The file
 370          * read primitives really get it wrong in a bad way if we don't
 371          * do this.
 372          */
 373         if( orig_zonesize < opt.blocksize )
 374           {
 375             opt.blocksize = orig_zonesize;
 376             blocksize_bits = 0;
 377             {
 378               int i = opt.blocksize;
 379               while (i != 1){
 380                 blocksize_bits++;
 381                 i >>=1;
 382               }
 383             }
 384             set_blocksize(dev, opt.blocksize);
 385             printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
 386           }
 387 
 388         s->s_dev = dev;
 389         s->s_op = &isofs_sops;
 390         s->u.isofs_sb.s_mapping = opt.map;
 391         s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
 392         s->u.isofs_sb.s_name_check = opt.check;
 393         s->u.isofs_sb.s_conversion = opt.conversion;
 394         s->u.isofs_sb.s_cruft = opt.cruft;
 395         s->u.isofs_sb.s_unhide = opt.unhide;
 396         s->u.isofs_sb.s_uid = opt.uid;
 397         s->u.isofs_sb.s_gid = opt.gid;
 398         /*
 399          * It would be incredibly stupid to allow people to mark every file on the disk
 400          * as suid, so we merely allow them to set the default permissions.
 401          */
 402         s->u.isofs_sb.s_mode = opt.mode & 0777;
 403         s->s_blocksize = opt.blocksize;
 404         s->s_blocksize_bits = blocksize_bits;
 405         s->s_mounted = iget(s, (isonum_733(rootp->extent) + 
 406                             isonum_711(rootp->ext_attr_length))
 407                                 << s -> u.isofs_sb.s_log_zone_size);
 408         unlock_super(s);
 409 
 410         if (!(s->s_mounted)) {
 411                 s->s_dev = 0;
 412                 printk("get root inode failed\n");
 413                 MOD_DEC_USE_COUNT;
 414                 return NULL;
 415         }
 416 
 417         if(!check_disk_change(s->s_dev)) {
 418           return s;
 419         }
 420  out: /* Kick out for various error conditions */
 421         brelse(bh);
 422         s->s_dev = 0;
 423         unlock_super(s);
 424         MOD_DEC_USE_COUNT;
 425         return NULL;
 426 }
 427 
 428 void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430         struct statfs tmp;
 431 
 432         tmp.f_type = ISOFS_SUPER_MAGIC;
 433         tmp.f_bsize = 1 << ISOFS_BLOCK_BITS;
 434         tmp.f_blocks = sb->u.isofs_sb.s_nzones;
 435         tmp.f_bfree = 0;
 436         tmp.f_bavail = 0;
 437         tmp.f_files = sb->u.isofs_sb.s_ninodes;
 438         tmp.f_ffree = 0;
 439         tmp.f_namelen = NAME_MAX;
 440         memcpy_tofs(buf, &tmp, bufsiz);
 441 }
 442 
 443 int isofs_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445 
 446         if (block<0) {
 447                 printk("_isofs_bmap: block<0");
 448                 return 0;
 449         }
 450         return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
 451 }
 452 
 453 void isofs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 454 {
 455         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 456         struct buffer_head * bh;
 457         struct iso_directory_record * raw_inode;
 458         unsigned char *pnt = NULL;
 459         void *cpnt = NULL;
 460         int high_sierra;
 461         int block;
 462         int volume_seq_no ;
 463         int i;
 464 
 465         block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
 466         if (!(bh=bread(inode->i_dev,block, bufsize))) {
 467           printk("unable to read i-node block");
 468           goto fail;
 469         }
 470         
 471         pnt = ((unsigned char *) bh->b_data
 472                + (inode->i_ino & (bufsize - 1)));
 473         raw_inode = ((struct iso_directory_record *) pnt);
 474         high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 475 
 476         if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 477                 int frag1, offset;
 478 
 479                 offset = (inode->i_ino & (bufsize - 1));
 480                 frag1 = bufsize - offset;
 481                 cpnt = kmalloc(*pnt,GFP_KERNEL);
 482                 if (cpnt == NULL) {
 483                         printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
 484                         brelse(bh);
 485                         goto fail;
 486                 }
 487                 memcpy(cpnt, bh->b_data + offset, frag1);
 488                 brelse(bh);
 489                 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
 490                         kfree(cpnt);
 491                         printk("unable to read i-node block");
 492                         goto fail;
 493                 }
 494                 offset += *pnt - bufsize;
 495                 memcpy((char *)cpnt+frag1, bh->b_data, offset);
 496                 pnt = ((unsigned char *) cpnt);
 497                 raw_inode = ((struct iso_directory_record *) pnt);
 498         }
 499 
 500         if (raw_inode->flags[-high_sierra] & 2) {
 501                 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
 502                 inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
 503                                        the find utility tries to optimize
 504                                        if it is 2, and it screws up.  It is
 505                                        easier to give 1 which tells find to
 506                                        do it the hard way. */
 507         } else {
 508                 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; /* Everybody gets to read the file. */
 509                 inode->i_nlink = 1;
 510                 inode->i_mode |= S_IFREG;
 511 /* If there are no periods in the name, then set the execute permission bit */
 512                 for(i=0; i< raw_inode->name_len[0]; i++)
 513                         if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 514                                 break;
 515                 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
 516                         inode->i_mode |= S_IXUGO; /* execute permission */
 517         }
 518         inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
 519         inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
 520         inode->i_size = isonum_733 (raw_inode->size);
 521 
 522         /* There are defective discs out there - we do this to protect
 523            ourselves.  A cdrom will never contain more than 800Mb */
 524         if((inode->i_size < 0 || inode->i_size > 800000000) &&
 525             inode->i_sb->u.isofs_sb.s_cruft == 'n') {
 526           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 527           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 528         }
 529 
 530 /* Some dipshit decided to store some other bit of information in the high
 531    byte of the file length.  Catch this and holler.  WARNING: this will make
 532    it impossible for a file to be > 16Mb on the CDROM!!!*/
 533 
 534         if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
 535            inode->i_size & 0xff000000){
 536 /*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 537           inode->i_size &= 0x00ffffff;
 538         }
 539         
 540         if (raw_inode->interleave[0]) {
 541                 printk("Interleaved files not (yet) supported.\n");
 542                 inode->i_size = 0;
 543         }
 544 
 545         /* I have no idea what file_unit_size is used for, so
 546            we will flag it for now */
 547         if(raw_inode->file_unit_size[0] != 0){
 548                 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
 549         }
 550 
 551         /* I have no idea what other flag bits are used for, so
 552            we will flag it for now */
 553 #ifdef DEBUG
 554         if((raw_inode->flags[-high_sierra] & ~2)!= 0){
 555                 printk("Unusual flag settings for ISO file (%ld %x).\n",
 556                        inode->i_ino, raw_inode->flags[-high_sierra]);
 557         }
 558 #endif
 559 
 560 #ifdef DEBUG
 561         printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 562                ((int)pnt) & 0x3ff, inode->i_size);
 563 #endif
 564         
 565         inode->i_mtime = inode->i_atime = inode->i_ctime = 
 566           iso_date(raw_inode->date, high_sierra);
 567 
 568         inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
 569                                            isonum_711 (raw_inode->ext_attr_length))
 570           << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
 571         
 572         inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 573         switch (inode->i_sb->u.isofs_sb.s_conversion){
 574         case 'a':
 575           inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
 576           break;
 577         case 'b':
 578           inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
 579           break;
 580         case 't':
 581           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
 582           break;
 583         case 'm':
 584           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
 585           break;
 586         }
 587 
 588 /* Now test for possible Rock Ridge extensions which will override some of
 589    these numbers in the inode structure. */
 590 
 591         if (!high_sierra)
 592           parse_rock_ridge_inode(raw_inode, inode);
 593         
 594 #ifdef DEBUG
 595         printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 596 #endif
 597         brelse(bh);
 598         
 599         inode->i_op = NULL;
 600 
 601         /* get the volume sequence number */
 602         volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
 603 
 604         /* 
 605          * Disable checking if we see any volume number other than 0 or 1.
 606          * We could use the cruft option, but that has multiple purposes, one
 607          * of which is limiting the file size to 16Mb.  Thus we silently allow
 608          * volume numbers of 0 to go through without complaining.
 609          */
 610         if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && 
 611             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 612           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 613           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 614         }
 615 
 616         if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && 
 617             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 618                 printk("Multi volume CD somehow got mounted.\n");
 619         } else {
 620           if (S_ISREG(inode->i_mode))
 621             inode->i_op = &isofs_file_inode_operations;
 622           else if (S_ISDIR(inode->i_mode))
 623             inode->i_op = &isofs_dir_inode_operations;
 624           else if (S_ISLNK(inode->i_mode))
 625             inode->i_op = &isofs_symlink_inode_operations;
 626           else if (S_ISCHR(inode->i_mode))
 627             inode->i_op = &chrdev_inode_operations;
 628           else if (S_ISBLK(inode->i_mode))
 629             inode->i_op = &blkdev_inode_operations;
 630           else if (S_ISFIFO(inode->i_mode))
 631             init_fifo(inode);
 632         }
 633         if (cpnt) {
 634                 kfree (cpnt);
 635                 cpnt = NULL;
 636         }
 637         return;
 638       fail:
 639         /* With a data error we return this information */
 640         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 641         inode->u.isofs_i.i_first_extent = 0;
 642         inode->u.isofs_i.i_backlink = 0xffffffff;
 643         inode->i_size = 0;
 644         inode->i_nlink = 1;
 645         inode->i_uid = inode->i_gid = 0;
 646         inode->i_mode = S_IFREG;  /*Regular file, no one gets to read*/
 647         inode->i_op = NULL;
 648         return;
 649 }
 650 
 651 /* There are times when we need to know the inode number of a parent of
 652    a particular directory.  When control passes through a routine that
 653    has access to the parent information, it fills it into the inode structure,
 654    but sometimes the inode gets flushed out of the queue, and someone
 655    remembers the number.  When they try to open up again, we have lost
 656    the information.  The '..' entry on the disc points to the data area
 657    for a particular inode, so we can follow these links back up, but since
 658    we do not know the inode number, we do not actually know how large the
 659    directory is.  The disc is almost always correct, and there is
 660    enough error checking on the drive itself, but an open ended search
 661    makes me a little nervous.
 662 
 663    The bsd iso filesystem uses the extent number for an inode, and this
 664    would work really nicely for us except that the read_inode function
 665    would not have any clean way of finding the actual directory record
 666    that goes with the file.  If we had such info, then it would pay
 667    to change the inode numbers and eliminate this function.
 668 */
 669 
 670 int isofs_lookup_grandparent(struct inode * parent, int extent)
     /* [previous][next][first][last][top][bottom][index][help] */
 671 {
 672         unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
 673         unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
 674         unsigned int block,offset;
 675         int parent_dir, inode_number;
 676         int old_offset;
 677         void * cpnt = NULL;
 678         int result;
 679         int directory_size;
 680         struct buffer_head * bh;
 681         struct iso_directory_record * de;
 682         
 683         offset = 0;
 684         block = extent << (ISOFS_BLOCK_BITS - bufbits);
 685         if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
 686         
 687         while (1 == 1) {
 688                 de = (struct iso_directory_record *) (bh->b_data + offset);
 689                 if (*((unsigned char *) de) == 0) 
 690                 {
 691                         brelse(bh);
 692                         return -1;
 693                 }
 694                 
 695                 offset += *((unsigned char *) de);
 696 
 697                 if (offset >= bufsize) 
 698                 {
 699                         printk(".. Directory not in first block"
 700                                " of directory.\n");
 701                         brelse(bh);
 702                         return -1;
 703                 }
 704                 
 705                 if (de->name_len[0] == 1 && de->name[0] == 1) 
 706                 {
 707                         parent_dir = find_rock_ridge_relocation(de, parent);
 708                         directory_size = isonum_733 (de->size);
 709                         brelse(bh);
 710                         break;
 711                 }
 712         }
 713 #ifdef DEBUG
 714         printk("Parent dir:%x\n",parent_dir);
 715 #endif
 716         /* Now we know the extent where the parent dir starts on. */
 717         
 718         result = -1;
 719 
 720         offset = 0;
 721         block = parent_dir << (ISOFS_BLOCK_BITS - bufbits);
 722         if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
 723                 return -1;
 724         
 725         for(;;)
 726         {
 727                 de = (struct iso_directory_record *) (bh->b_data + offset);
 728                 inode_number = (block << bufbits)+(offset & (bufsize - 1));
 729                 
 730                 /* If the length byte is zero, we should move on to the next
 731                    CDROM sector.  If we are at the end of the directory, we
 732                    kick out of the while loop. */
 733                 
 734                 if (*((unsigned char *) de) == 0) 
 735                 {
 736                         brelse(bh);
 737                         offset = 0;
 738                         block++;
 739                         directory_size -= bufsize;
 740                         if(directory_size < 0) return -1;
 741                         if((block & 1) && (ISOFS_BLOCK_BITS - bufbits))
 742                           return -1;
 743                         if (!block
 744                             || !(bh = bread(parent->i_dev,block, bufsize)))
 745                                 return -1;
 746                         continue;
 747                 }
 748                 
 749                 /* Make sure that the entire directory record is in the current
 750                    bh block.  If not, we malloc a buffer, and put the two
 751                    halves together, so that we can cleanly read the block.  */
 752 
 753                 old_offset = offset;
 754                 offset += *((unsigned char *) de);
 755 
 756                 if (offset >= bufsize)
 757                 {
 758                         unsigned int frag1;
 759                         frag1 = bufsize - old_offset;
 760                         cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
 761                         if (!cpnt) return -1;
 762                         memcpy(cpnt, bh->b_data + old_offset, frag1);
 763                         de = (struct iso_directory_record *) ((char *)cpnt);
 764                         brelse(bh);
 765                         offset -= bufsize;
 766                         directory_size -= bufsize;
 767                         if(directory_size < 0) return -1;
 768                         block++;
 769                         if(!(bh = bread(parent->i_dev,block,bufsize))) {
 770                                 kfree(cpnt);
 771                                 return -1;
 772                         };
 773                         memcpy((char *)cpnt+frag1, bh->b_data, offset);
 774                 }
 775                 
 776                 if (find_rock_ridge_relocation(de, parent) == extent){
 777                         result = inode_number;
 778                         goto out;
 779                 }
 780                 
 781                 if (cpnt) {
 782                         kfree(cpnt);
 783                         cpnt = NULL;
 784                 }
 785         }
 786 
 787         /* We go here for any condition we cannot handle.
 788            We also drop through to here at the end of the directory. */
 789 
 790  out:
 791         if (cpnt) {
 792                 kfree(cpnt);
 793                 cpnt = NULL;
 794         }
 795         brelse(bh);
 796 #ifdef DEBUG
 797         printk("Resultant Inode %d\n",result);
 798 #endif
 799         return result;
 800 }
 801     
 802 #ifdef LEAK_CHECK
 803 #undef malloc
 804 #undef free_s
 805 #undef bread
 806 #undef brelse
 807 
 808 void * leak_check_malloc(unsigned int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 809   void * tmp;
 810   check_malloc++;
 811   tmp = kmalloc(size, GFP_KERNEL);
 812   return tmp;
 813 }
 814 
 815 void leak_check_free_s(void * obj, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 816   check_malloc--;
 817   return kfree_s(obj, size);
 818 }
 819 
 820 struct buffer_head * leak_check_bread(int dev, int block, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 821   check_bread++;
 822   return bread(dev, block, size);
 823 }
 824 
 825 void leak_check_brelse(struct buffer_head * bh){
     /* [previous][next][first][last][top][bottom][index][help] */
 826   check_bread--;
 827   return brelse(bh);
 828 }
 829 
 830 #endif
 831 
 832 static struct file_system_type iso9660_fs_type = {
 833         isofs_read_super, "iso9660", 1, NULL
 834 };
 835 
 836 int init_iso9660_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 837 {
 838         return register_filesystem(&iso9660_fs_type);
 839 }
 840 
 841 #ifdef MODULE
 842 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 843 {
 844         int status;
 845 
 846         if ((status = init_iso9660_fs()) == 0)
 847                 register_symtab(0);
 848         return status;
 849 }
 850 
 851 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 852 {
 853         unregister_filesystem(&iso9660_fs_type);
 854 }
 855 
 856 #endif
 857 

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