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

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