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

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