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 = sb->s_blocksize;
 434         tmp.f_blocks = (sb->u.isofs_sb.s_nzones
 435                   << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
 436         tmp.f_bfree = 0;
 437         tmp.f_bavail = 0;
 438         tmp.f_files = sb->u.isofs_sb.s_ninodes;
 439         tmp.f_ffree = 0;
 440         tmp.f_namelen = NAME_MAX;
 441         memcpy_tofs(buf, &tmp, bufsiz);
 442 }
 443 
 444 int isofs_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446 
 447         if (block<0) {
 448                 printk("_isofs_bmap: block<0");
 449                 return 0;
 450         }
 451         return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
 452 }
 453 
 454 void isofs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 455 {
 456         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 457         struct buffer_head * bh;
 458         struct iso_directory_record * raw_inode;
 459         unsigned char *pnt = NULL;
 460         void *cpnt = NULL;
 461         int high_sierra;
 462         int block;
 463         int volume_seq_no ;
 464         int i;
 465 
 466         block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
 467         if (!(bh=bread(inode->i_dev,block, bufsize))) {
 468           printk("unable to read i-node block");
 469           goto fail;
 470         }
 471         
 472         pnt = ((unsigned char *) bh->b_data
 473                + (inode->i_ino & (bufsize - 1)));
 474         raw_inode = ((struct iso_directory_record *) pnt);
 475         high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 476 
 477         if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 478                 int frag1, offset;
 479 
 480                 offset = (inode->i_ino & (bufsize - 1));
 481                 frag1 = bufsize - offset;
 482                 cpnt = kmalloc(*pnt,GFP_KERNEL);
 483                 if (cpnt == NULL) {
 484                         printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
 485                         brelse(bh);
 486                         goto fail;
 487                 }
 488                 memcpy(cpnt, bh->b_data + offset, frag1);
 489                 brelse(bh);
 490                 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
 491                         kfree(cpnt);
 492                         printk("unable to read i-node block");
 493                         goto fail;
 494                 }
 495                 offset += *pnt - bufsize;
 496                 memcpy((char *)cpnt+frag1, bh->b_data, offset);
 497                 pnt = ((unsigned char *) cpnt);
 498                 raw_inode = ((struct iso_directory_record *) pnt);
 499         }
 500 
 501         if (raw_inode->flags[-high_sierra] & 2) {
 502                 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
 503                 inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
 504                                        the find utility tries to optimize
 505                                        if it is 2, and it screws up.  It is
 506                                        easier to give 1 which tells find to
 507                                        do it the hard way. */
 508         } else {
 509                 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; /* Everybody gets to read the file. */
 510                 inode->i_nlink = 1;
 511                 inode->i_mode |= S_IFREG;
 512 /* If there are no periods in the name, then set the execute permission bit */
 513                 for(i=0; i< raw_inode->name_len[0]; i++)
 514                         if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 515                                 break;
 516                 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
 517                         inode->i_mode |= S_IXUGO; /* execute permission */
 518         }
 519         inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
 520         inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
 521         inode->i_size = isonum_733 (raw_inode->size);
 522 
 523         /* There are defective discs out there - we do this to protect
 524            ourselves.  A cdrom will never contain more than 800Mb */
 525         if((inode->i_size < 0 || inode->i_size > 800000000) &&
 526             inode->i_sb->u.isofs_sb.s_cruft == 'n') {
 527           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 528           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 529         }
 530 
 531 /* Some dipshit decided to store some other bit of information in the high
 532    byte of the file length.  Catch this and holler.  WARNING: this will make
 533    it impossible for a file to be > 16Mb on the CDROM!!!*/
 534 
 535         if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
 536            inode->i_size & 0xff000000){
 537 /*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 538           inode->i_size &= 0x00ffffff;
 539         }
 540         
 541         if (raw_inode->interleave[0]) {
 542                 printk("Interleaved files not (yet) supported.\n");
 543                 inode->i_size = 0;
 544         }
 545 
 546         /* I have no idea what file_unit_size is used for, so
 547            we will flag it for now */
 548         if(raw_inode->file_unit_size[0] != 0){
 549                 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
 550         }
 551 
 552         /* I have no idea what other flag bits are used for, so
 553            we will flag it for now */
 554 #ifdef DEBUG
 555         if((raw_inode->flags[-high_sierra] & ~2)!= 0){
 556                 printk("Unusual flag settings for ISO file (%ld %x).\n",
 557                        inode->i_ino, raw_inode->flags[-high_sierra]);
 558         }
 559 #endif
 560 
 561 #ifdef DEBUG
 562         printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 563                ((int)pnt) & 0x3ff, inode->i_size);
 564 #endif
 565         
 566         inode->i_mtime = inode->i_atime = inode->i_ctime = 
 567           iso_date(raw_inode->date, high_sierra);
 568 
 569         inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
 570                                            isonum_711 (raw_inode->ext_attr_length))
 571           << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
 572         
 573         inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 574         switch (inode->i_sb->u.isofs_sb.s_conversion){
 575         case 'a':
 576           inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
 577           break;
 578         case 'b':
 579           inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
 580           break;
 581         case 't':
 582           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
 583           break;
 584         case 'm':
 585           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
 586           break;
 587         }
 588 
 589 /* Now test for possible Rock Ridge extensions which will override some of
 590    these numbers in the inode structure. */
 591 
 592         if (!high_sierra)
 593           parse_rock_ridge_inode(raw_inode, inode);
 594         
 595 #ifdef DEBUG
 596         printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 597 #endif
 598         brelse(bh);
 599         
 600         inode->i_op = NULL;
 601 
 602         /* get the volume sequence number */
 603         volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
 604 
 605         /* 
 606          * Disable checking if we see any volume number other than 0 or 1.
 607          * We could use the cruft option, but that has multiple purposes, one
 608          * of which is limiting the file size to 16Mb.  Thus we silently allow
 609          * volume numbers of 0 to go through without complaining.
 610          */
 611         if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && 
 612             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 613           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 614           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 615         }
 616 
 617         if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && 
 618             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 619                 printk("Multi volume CD somehow got mounted.\n");
 620         } else {
 621           if (S_ISREG(inode->i_mode))
 622             inode->i_op = &isofs_file_inode_operations;
 623           else if (S_ISDIR(inode->i_mode))
 624             inode->i_op = &isofs_dir_inode_operations;
 625           else if (S_ISLNK(inode->i_mode))
 626             inode->i_op = &isofs_symlink_inode_operations;
 627           else if (S_ISCHR(inode->i_mode))
 628             inode->i_op = &chrdev_inode_operations;
 629           else if (S_ISBLK(inode->i_mode))
 630             inode->i_op = &blkdev_inode_operations;
 631           else if (S_ISFIFO(inode->i_mode))
 632             init_fifo(inode);
 633         }
 634         if (cpnt) {
 635                 kfree (cpnt);
 636                 cpnt = NULL;
 637         }
 638         return;
 639       fail:
 640         /* With a data error we return this information */
 641         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 642         inode->u.isofs_i.i_first_extent = 0;
 643         inode->u.isofs_i.i_backlink = 0xffffffff;
 644         inode->i_size = 0;
 645         inode->i_nlink = 1;
 646         inode->i_uid = inode->i_gid = 0;
 647         inode->i_mode = S_IFREG;  /*Regular file, no one gets to read*/
 648         inode->i_op = NULL;
 649         return;
 650 }
 651 
 652 /* There are times when we need to know the inode number of a parent of
 653    a particular directory.  When control passes through a routine that
 654    has access to the parent information, it fills it into the inode structure,
 655    but sometimes the inode gets flushed out of the queue, and someone
 656    remembers the number.  When they try to open up again, we have lost
 657    the information.  The '..' entry on the disc points to the data area
 658    for a particular inode, so we can follow these links back up, but since
 659    we do not know the inode number, we do not actually know how large the
 660    directory is.  The disc is almost always correct, and there is
 661    enough error checking on the drive itself, but an open ended search
 662    makes me a little nervous.
 663 
 664    The bsd iso filesystem uses the extent number for an inode, and this
 665    would work really nicely for us except that the read_inode function
 666    would not have any clean way of finding the actual directory record
 667    that goes with the file.  If we had such info, then it would pay
 668    to change the inode numbers and eliminate this function.
 669 */
 670 
 671 int isofs_lookup_grandparent(struct inode * parent, int extent)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673         unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
 674         unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
 675         unsigned int block,offset;
 676         int parent_dir, inode_number;
 677         int old_offset;
 678         void * cpnt = NULL;
 679         int result;
 680         int directory_size;
 681         struct buffer_head * bh;
 682         struct iso_directory_record * de;
 683         
 684         offset = 0;
 685         block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
 686         if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
 687         
 688         while (1 == 1) {
 689                 de = (struct iso_directory_record *) (bh->b_data + offset);
 690                 if (*((unsigned char *) de) == 0) 
 691                 {
 692                         brelse(bh);
 693                         printk("Directory .. not found\n");
 694                         return -1;
 695                 }
 696                 
 697                 offset += *((unsigned char *) de);
 698 
 699                 if (offset >= bufsize) 
 700                 {
 701                         printk(".. Directory not in first block"
 702                                " of directory.\n");
 703                         brelse(bh);
 704                         return -1;
 705                 }
 706                 
 707                 if (de->name_len[0] == 1 && de->name[0] == 1) 
 708                 {
 709                         parent_dir = find_rock_ridge_relocation(de, parent);
 710                         directory_size = isonum_733 (de->size);
 711                         brelse(bh);
 712                         break;
 713                 }
 714         }
 715 #ifdef DEBUG
 716         printk("Parent dir:%x\n",parent_dir);
 717 #endif
 718         /* Now we know the extent where the parent dir starts on. */
 719         
 720         result = -1;
 721 
 722         offset = 0;
 723         block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits);
 724         if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
 725         {
 726                 return -1;
 727         }
 728         
 729         for(;;)
 730         {
 731                 de = (struct iso_directory_record *) (bh->b_data + offset);
 732                 inode_number = (block << bufbits)+(offset & (bufsize - 1));
 733                 
 734                 /* If the length byte is zero, we should move on to the next
 735                    CDROM sector.  If we are at the end of the directory, we
 736                    kick out of the while loop. */
 737                 
 738                 if (*((unsigned char *) de) == 0) 
 739                 {
 740                         brelse(bh);
 741                         offset = 0;
 742                         block++;
 743                         directory_size -= bufsize;
 744                         if(directory_size < 0) return -1;
 745                         if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1)
 746                         {
 747                                 return -1;
 748                         }
 749                         if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2)
 750                         {
 751                                 return -1;
 752                         }
 753                         if (!block
 754                             || !(bh = bread(parent->i_dev,block, bufsize)))
 755                         {
 756                                 return -1;
 757                         }
 758                         continue;
 759                 }
 760                 
 761                 /* Make sure that the entire directory record is in the current
 762                    bh block.  If not, we malloc a buffer, and put the two
 763                    halves together, so that we can cleanly read the block.  */
 764 
 765                 old_offset = offset;
 766                 offset += *((unsigned char *) de);
 767 
 768                 if (offset >= bufsize)
 769                 {
 770                         unsigned int frag1;
 771                         frag1 = bufsize - old_offset;
 772                         cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
 773                         if (!cpnt) return -1;
 774                         memcpy(cpnt, bh->b_data + old_offset, frag1);
 775                         de = (struct iso_directory_record *) ((char *)cpnt);
 776                         brelse(bh);
 777                         offset -= bufsize;
 778                         directory_size -= bufsize;
 779                         if(directory_size < 0) 
 780                         {
 781                                 printk("Directory size < 0\n");
 782                                 return -1;
 783                         }
 784                         block++;
 785                         if(!(bh = bread(parent->i_dev,block,bufsize))) {
 786                                 kfree(cpnt);
 787                                 return -1;
 788                         };
 789                         memcpy((char *)cpnt+frag1, bh->b_data, offset);
 790                 }
 791                 
 792                 if (find_rock_ridge_relocation(de, parent) == extent){
 793                         result = inode_number;
 794                         goto out;
 795                 }
 796                 
 797                 if (cpnt) {
 798                         kfree(cpnt);
 799                         cpnt = NULL;
 800                 }
 801         }
 802 
 803         /* We go here for any condition we cannot handle.
 804            We also drop through to here at the end of the directory. */
 805 
 806  out:
 807         if (cpnt) {
 808                 kfree(cpnt);
 809                 cpnt = NULL;
 810         }
 811         brelse(bh);
 812 #ifdef DEBUG
 813         printk("Resultant Inode %d\n",result);
 814 #endif
 815         return result;
 816 }
 817     
 818 #ifdef LEAK_CHECK
 819 #undef malloc
 820 #undef free_s
 821 #undef bread
 822 #undef brelse
 823 
 824 void * leak_check_malloc(unsigned int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 825   void * tmp;
 826   check_malloc++;
 827   tmp = kmalloc(size, GFP_KERNEL);
 828   return tmp;
 829 }
 830 
 831 void leak_check_free_s(void * obj, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 832   check_malloc--;
 833   return kfree_s(obj, size);
 834 }
 835 
 836 struct buffer_head * leak_check_bread(int dev, int block, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 837   check_bread++;
 838   return bread(dev, block, size);
 839 }
 840 
 841 void leak_check_brelse(struct buffer_head * bh){
     /* [previous][next][first][last][top][bottom][index][help] */
 842   check_bread--;
 843   return brelse(bh);
 844 }
 845 
 846 #endif
 847 
 848 static struct file_system_type iso9660_fs_type = {
 849         isofs_read_super, "iso9660", 1, NULL
 850 };
 851 
 852 int init_iso9660_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         return register_filesystem(&iso9660_fs_type);
 855 }
 856 
 857 #ifdef MODULE
 858 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 859 {
 860         int status;
 861 
 862         if ((status = init_iso9660_fs()) == 0)
 863                 register_symtab(0);
 864         return status;
 865 }
 866 
 867 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 868 {
 869         unregister_filesystem(&iso9660_fs_type);
 870 }
 871 
 872 #endif
 873 

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