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 #ifdef MODULE
  12 #include <linux/module.h>
  13 #include <linux/version.h>
  14 #else
  15 #define MOD_INC_USE_COUNT
  16 #define MOD_DEC_USE_COUNT
  17 #endif
  18 
  19 #include <linux/stat.h>
  20 #include <linux/sched.h>
  21 #include <linux/iso_fs.h>
  22 #include <linux/kernel.h>
  23 #include <linux/major.h>
  24 #include <linux/mm.h>
  25 #include <linux/string.h>
  26 #include <linux/locks.h>
  27 #include <linux/malloc.h>
  28 #include <linux/errno.h>
  29 #include <linux/cdrom.h>
  30 
  31 #include <asm/system.h>
  32 #include <asm/segment.h>
  33 
  34 #ifdef LEAK_CHECK
  35 static int check_malloc = 0;
  36 static int check_bread = 0;
  37 #endif
  38 
  39 void isofs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  40 {
  41         lock_super(sb);
  42 
  43 #ifdef LEAK_CHECK
  44         printk("Outstanding mallocs:%d, outstanding buffers: %d\n", 
  45                check_malloc, check_bread);
  46 #endif
  47         sb->s_dev = 0;
  48         unlock_super(sb);
  49         MOD_DEC_USE_COUNT;
  50         return;
  51 }
  52 
  53 static struct super_operations isofs_sops = { 
  54         isofs_read_inode,
  55         NULL,                   /* notify_change */
  56         NULL,                   /* write_inode */
  57         NULL,                   /* put_inode */
  58         isofs_put_super,
  59         NULL,                   /* write_super */
  60         isofs_statfs,
  61         NULL
  62 };
  63 
  64 struct iso9660_options{
  65   char map;
  66   char rock;
  67   char cruft;
  68   char unhide;
  69   unsigned char conversion;
  70   unsigned int blocksize;
  71   mode_t mode;
  72   gid_t gid;
  73   uid_t uid;
  74 };
  75 
  76 static int parse_options(char *options, struct iso9660_options * popt)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         char *this_char,*value;
  79 
  80         popt->map = 'n';
  81         popt->rock = 'y';
  82         popt->cruft = 'n';
  83         popt->unhide = 'n';
  84         popt->conversion = 'b';         /* default: no conversion */
  85         popt->blocksize = 1024;
  86         popt->mode = S_IRUGO;
  87         popt->gid = 0;
  88         popt->uid = 0;
  89         if (!options) return 1;
  90         for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  91                 if (strncmp(this_char,"norock",6) == 0) {
  92                   popt->rock = 'n';
  93                   continue;
  94                 };
  95                 if (strncmp(this_char,"unhide",6) == 0) {
  96                   popt->unhide = 'y';
  97                   continue;
  98                 };
  99                 if (strncmp(this_char,"cruft",5) == 0) {
 100                   popt->cruft = 'y';
 101                   continue;
 102                 };
 103                 if ((value = strchr(this_char,'=')) != NULL)
 104                         *value++ = 0;
 105                 if (!strcmp(this_char,"map") && value) {
 106                         if (value[0] && !value[1] && strchr("on",*value))
 107                                 popt->map = *value;
 108                         else if (!strcmp(value,"off")) popt->map = 'o';
 109                         else if (!strcmp(value,"normal")) popt->map = 'n';
 110                         else return 0;
 111                 }
 112                 else if (!strcmp(this_char,"conv") && value) {
 113                         if (value[0] && !value[1] && strchr("btma",*value))
 114                                 popt->conversion = *value;
 115                         else if (!strcmp(value,"binary")) popt->conversion = 'b';
 116                         else if (!strcmp(value,"text")) popt->conversion = 't';
 117                         else if (!strcmp(value,"mtext")) popt->conversion = 'm';
 118                         else if (!strcmp(value,"auto")) popt->conversion = 'a';
 119                         else return 0;
 120                 }
 121                 else if (value && 
 122                          (!strcmp(this_char,"block") ||
 123                           !strcmp(this_char,"mode") ||
 124                           !strcmp(this_char,"uid") ||
 125                           !strcmp(this_char,"gid"))) {
 126                   char * vpnt = value;
 127                   unsigned int ivalue;
 128                   ivalue = 0;
 129                   while(*vpnt){
 130                     if(*vpnt <  '0' || *vpnt > '9') break;
 131                     ivalue = ivalue * 10 + (*vpnt - '0');
 132                     vpnt++;
 133                   };
 134                   if (*vpnt) return 0;
 135                   switch(*this_char) {
 136                   case 'b':
 137                     if (ivalue != 1024 && ivalue != 2048) return 0;
 138                     popt->blocksize = ivalue;
 139                     break;
 140                   case 'u':
 141                     popt->uid = ivalue;
 142                     break;
 143                   case 'g':
 144                     popt->gid = ivalue;
 145                     break;
 146                   case 'm':
 147                     popt->mode = ivalue;
 148                     break;
 149                   }
 150                 }
 151                 else return 0;
 152         }
 153         return 1;
 154 }
 155 
 156 /*
 157  * look if the driver can tell the multi session redirection value
 158  */
 159 static unsigned int isofs_get_last_session(kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   struct cdrom_multisession ms_info;
 162   unsigned int vol_desc_start;
 163   struct inode inode_fake;
 164   extern struct file_operations * get_blkfops(unsigned int);
 165   int i;
 166 
 167   vol_desc_start=0;
 168   if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
 169     {
 170       inode_fake.i_rdev=dev;
 171       ms_info.addr_format=CDROM_LBA;
 172       set_fs(KERNEL_DS);
 173       i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
 174                                        NULL,
 175                                        CDROMMULTISESSION,
 176                                        (unsigned long) &ms_info);
 177       set_fs(USER_DS);
 178 #if 0 
 179       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 180       if (i==0)
 181         {
 182           printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
 183           printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 184         }
 185 #endif 0
 186       if ((i==0)&&(ms_info.xa_flag)) vol_desc_start=ms_info.addr.lba;
 187     }
 188   return vol_desc_start;
 189 }
 190 
 191 struct super_block *isofs_read_super(struct super_block *s,void *data,
     /* [previous][next][first][last][top][bottom][index][help] */
 192                                      int silent)
 193 {
 194         struct buffer_head *bh=NULL;
 195         int iso_blknum;
 196         unsigned int blocksize_bits;
 197         int high_sierra;
 198         kdev_t dev = s->s_dev;
 199         unsigned int vol_desc_start;
 200 
 201         struct iso_volume_descriptor *vdp;
 202         struct hs_volume_descriptor *hdp;
 203 
 204         struct iso_primary_descriptor *pri = NULL;
 205         struct hs_primary_descriptor *h_pri = NULL;
 206 
 207         struct iso_directory_record *rootp;
 208 
 209         struct iso9660_options opt;
 210 
 211         MOD_INC_USE_COUNT;
 212 
 213         if (!parse_options((char *) data,&opt)) {
 214                 s->s_dev = 0;
 215                 MOD_DEC_USE_COUNT;
 216                 return NULL;
 217         }
 218 
 219 #if 0
 220         printk("map = %c\n", opt.map);
 221         printk("rock = %c\n", opt.rock);
 222         printk("cruft = %c\n", opt.cruft);
 223         printk("unhide = %c\n", opt.unhide);
 224         printk("conversion = %c\n", opt.conversion);
 225         printk("blocksize = %d\n", opt.blocksize);
 226         printk("gid = %d\n", opt.gid);
 227         printk("uid = %d\n", opt.uid);
 228 #endif
 229         
 230         blocksize_bits = 0;
 231         {
 232           int i = opt.blocksize;
 233           while (i != 1){
 234             blocksize_bits++;
 235             i >>=1;
 236           };
 237         };
 238         set_blocksize(dev, opt.blocksize);
 239 
 240         lock_super(s);
 241 
 242         s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 243 
 244         vol_desc_start = isofs_get_last_session(dev);
 245         
 246         for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) {
 247 #if 0
 248                 printk("isofs.inode: iso_blknum=%d\n", iso_blknum);
 249 #endif 0
 250                 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
 251                         s->s_dev = 0;
 252                         printk("isofs_read_super: bread failed, dev "
 253                                "%s iso_blknum %d\n",
 254                                kdevname(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 number */
 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] */