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

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