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

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