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

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