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

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