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 = 'a';
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 395 {
 396         put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
 397         put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
 398         put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
 399         put_fs_long(0, &buf->f_bfree);
 400         put_fs_long(0, &buf->f_bavail);
 401         put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
 402         put_fs_long(0, &buf->f_ffree);
 403         put_fs_long(NAME_MAX, &buf->f_namelen);
 404         /* Don't know what value to put in buf->f_fsid */
 405 }
 406 
 407 int isofs_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409 
 410         if (block<0) {
 411                 printk("_isofs_bmap: block<0");
 412                 return 0;
 413         }
 414         return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
 415 }
 416 
 417 void isofs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 420         struct buffer_head * bh;
 421         struct iso_directory_record * raw_inode;
 422         unsigned char *pnt = NULL;
 423         void *cpnt = NULL;
 424         int high_sierra;
 425         int block;
 426         int i;
 427 
 428         block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
 429         if (!(bh=bread(inode->i_dev,block, bufsize))) {
 430           printk("unable to read i-node block");
 431           goto fail;
 432         }
 433         
 434         pnt = ((unsigned char *) bh->b_data
 435                + (inode->i_ino & (bufsize - 1)));
 436         raw_inode = ((struct iso_directory_record *) pnt);
 437         high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 438 
 439         if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 440                 int frag1, offset;
 441 
 442                 offset = (inode->i_ino & (bufsize - 1));
 443                 frag1 = bufsize - offset;
 444                 cpnt = kmalloc(*pnt,GFP_KERNEL);
 445                 if (cpnt == NULL) {
 446                         printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
 447                         brelse(bh);
 448                         goto fail;
 449                 }
 450                 memcpy(cpnt, bh->b_data + offset, frag1);
 451                 brelse(bh);
 452                 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
 453                         kfree(cpnt);
 454                         printk("unable to read i-node block");
 455                         goto fail;
 456                 }
 457                 offset += *pnt - bufsize;
 458                 memcpy((char *)cpnt+frag1, bh->b_data, offset);
 459                 pnt = ((unsigned char *) cpnt);
 460                 raw_inode = ((struct iso_directory_record *) pnt);
 461         }
 462 
 463         if (raw_inode->flags[-high_sierra] & 2) {
 464                 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
 465                 inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
 466                                        the find utility tries to optimize
 467                                        if it is 2, and it screws up.  It is
 468                                        easier to give 1 which tells find to
 469                                        do it the hard way. */
 470         } else {
 471                 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; /* Everybody gets to read the file. */
 472                 inode->i_nlink = 1;
 473                 inode->i_mode |= S_IFREG;
 474 /* If there are no periods in the name, then set the execute permission bit */
 475                 for(i=0; i< raw_inode->name_len[0]; i++)
 476                         if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 477                                 break;
 478                 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
 479                         inode->i_mode |= S_IXUGO; /* execute permission */
 480         }
 481         inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
 482         inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
 483         inode->i_size = isonum_733 (raw_inode->size);
 484 
 485         /* There are defective discs out there - we do this to protect
 486            ourselves.  A cdrom will never contain more than 700Mb */
 487         if((inode->i_size < 0 || inode->i_size > 700000000) &&
 488             inode->i_sb->u.isofs_sb.s_cruft == 'n') {
 489           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 490           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 491         }
 492 
 493 /* Some dipshit decided to store some other bit of information in the high
 494    byte of the file length.  Catch this and holler.  WARNING: this will make
 495    it impossible for a file to be > 16Mb on the CDROM!!!*/
 496 
 497         if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
 498            inode->i_size & 0xff000000){
 499 /*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 500           inode->i_size &= 0x00ffffff;
 501         }
 502         
 503         if (raw_inode->interleave[0]) {
 504                 printk("Interleaved files not (yet) supported.\n");
 505                 inode->i_size = 0;
 506         }
 507 
 508         /* I have no idea what file_unit_size is used for, so
 509            we will flag it for now */
 510         if(raw_inode->file_unit_size[0] != 0){
 511                 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
 512         }
 513 
 514         /* I have no idea what other flag bits are used for, so
 515            we will flag it for now */
 516 #ifdef DEBUG
 517         if((raw_inode->flags[-high_sierra] & ~2)!= 0){
 518                 printk("Unusual flag settings for ISO file (%ld %x).\n",
 519                        inode->i_ino, raw_inode->flags[-high_sierra]);
 520         }
 521 #endif
 522 
 523 #ifdef DEBUG
 524         printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 525                ((int)pnt) & 0x3ff, inode->i_size);
 526 #endif
 527         
 528         inode->i_mtime = inode->i_atime = inode->i_ctime = 
 529           iso_date(raw_inode->date, high_sierra);
 530 
 531         inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
 532                                            isonum_711 (raw_inode->ext_attr_length))
 533           << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
 534         
 535         inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 536         switch (inode->i_sb->u.isofs_sb.s_conversion){
 537         case 'a':
 538           inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
 539           break;
 540         case 'b':
 541           inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
 542           break;
 543         case 't':
 544           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
 545           break;
 546         case 'm':
 547           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
 548           break;
 549         }
 550 
 551 /* Now test for possible Rock Ridge extensions which will override some of
 552    these numbers in the inode structure. */
 553 
 554         if (!high_sierra)
 555           parse_rock_ridge_inode(raw_inode, inode);
 556         
 557 #ifdef DEBUG
 558         printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 559 #endif
 560         brelse(bh);
 561         
 562         inode->i_op = NULL;
 563 
 564         /* A volume number of 0 is nonsense.  Disable checking if we see
 565            this */
 566         if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && 
 567             isonum_723 (raw_inode->volume_sequence_number) == 0) {
 568           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 569           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 570         }
 571 
 572         if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && 
 573             isonum_723 (raw_inode->volume_sequence_number) != 1) {
 574                 printk("Multi volume CD somehow got mounted.\n");
 575         } else {
 576           if (S_ISREG(inode->i_mode))
 577             inode->i_op = &isofs_file_inode_operations;
 578           else if (S_ISDIR(inode->i_mode))
 579             inode->i_op = &isofs_dir_inode_operations;
 580           else if (S_ISLNK(inode->i_mode))
 581             inode->i_op = &isofs_symlink_inode_operations;
 582           else if (S_ISCHR(inode->i_mode))
 583             inode->i_op = &chrdev_inode_operations;
 584           else if (S_ISBLK(inode->i_mode))
 585             inode->i_op = &blkdev_inode_operations;
 586           else if (S_ISFIFO(inode->i_mode))
 587             init_fifo(inode);
 588         }
 589         if (cpnt) {
 590                 kfree (cpnt);
 591                 cpnt = NULL;
 592         }
 593         return;
 594       fail:
 595         /* With a data error we return this information */
 596         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 597         inode->u.isofs_i.i_first_extent = 0;
 598         inode->u.isofs_i.i_backlink = 0xffffffff;
 599         inode->i_size = 0;
 600         inode->i_nlink = 1;
 601         inode->i_uid = inode->i_gid = 0;
 602         inode->i_mode = S_IFREG;  /*Regular file, no one gets to read*/
 603         inode->i_op = NULL;
 604         return;
 605 }
 606 
 607 /* There are times when we need to know the inode number of a parent of
 608    a particular directory.  When control passes through a routine that
 609    has access to the parent information, it fills it into the inode structure,
 610    but sometimes the inode gets flushed out of the queue, and someone
 611    remembers the number.  When they try to open up again, we have lost
 612    the information.  The '..' entry on the disc points to the data area
 613    for a particular inode, so we can follow these links back up, but since
 614    we do not know the inode number, we do not actually know how large the
 615    directory is.  The disc is almost always correct, and there is
 616    enough error checking on the drive itself, but an open ended search
 617    makes me a little nervous.
 618 
 619    The bsd iso filesystem uses the extent number for an inode, and this
 620    would work really nicely for us except that the read_inode function
 621    would not have any clean way of finding the actual directory record
 622    that goes with the file.  If we had such info, then it would pay
 623    to change the inode numbers and eliminate this function.
 624 */
 625 
 626 int isofs_lookup_grandparent(struct inode * parent, int extent)
     /* [previous][next][first][last][top][bottom][index][help] */
 627 {
 628         unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
 629         unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
 630         unsigned int block,offset;
 631         int parent_dir, inode_number;
 632         int old_offset;
 633         void * cpnt = NULL;
 634         int result;
 635         int directory_size;
 636         struct buffer_head * bh;
 637         struct iso_directory_record * de;
 638         
 639         offset = 0;
 640         block = extent << (ISOFS_BLOCK_BITS - bufbits);
 641         if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
 642         
 643         while (1 == 1) {
 644                 de = (struct iso_directory_record *) (bh->b_data + offset);
 645                 if (*((unsigned char *) de) == 0) 
 646                 {
 647                         brelse(bh);
 648                         return -1;
 649                 }
 650                 
 651                 offset += *((unsigned char *) de);
 652 
 653                 if (offset >= bufsize) 
 654                 {
 655                         printk(".. Directory not in first block"
 656                                " of directory.\n");
 657                         brelse(bh);
 658                         return -1;
 659                 }
 660                 
 661                 if (de->name_len[0] == 1 && de->name[0] == 1) 
 662                 {
 663                         parent_dir = find_rock_ridge_relocation(de, parent);
 664                         directory_size = isonum_733 (de->size);
 665                         brelse(bh);
 666                         break;
 667                 }
 668         }
 669 #ifdef DEBUG
 670         printk("Parent dir:%x\n",parent_dir);
 671 #endif
 672         /* Now we know the extent where the parent dir starts on. */
 673         
 674         result = -1;
 675 
 676         offset = 0;
 677         block = parent_dir << (ISOFS_BLOCK_BITS - bufbits);
 678         if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
 679                 return -1;
 680         
 681         for(;;)
 682         {
 683                 de = (struct iso_directory_record *) (bh->b_data + offset);
 684                 inode_number = (block << bufbits)+(offset & (bufsize - 1));
 685                 
 686                 /* If the length byte is zero, we should move on to the next
 687                    CDROM sector.  If we are at the end of the directory, we
 688                    kick out of the while loop. */
 689                 
 690                 if (*((unsigned char *) de) == 0) 
 691                 {
 692                         brelse(bh);
 693                         offset = 0;
 694                         block++;
 695                         directory_size -= bufsize;
 696                         if(directory_size < 0) return -1;
 697                         if((block & 1) && (ISOFS_BLOCK_BITS - bufbits))
 698                           return -1;
 699                         if (!block
 700                             || !(bh = bread(parent->i_dev,block, bufsize)))
 701                                 return -1;
 702                         continue;
 703                 }
 704                 
 705                 /* Make sure that the entire directory record is in the current
 706                    bh block.  If not, we malloc a buffer, and put the two
 707                    halves together, so that we can cleanly read the block.  */
 708 
 709                 old_offset = offset;
 710                 offset += *((unsigned char *) de);
 711 
 712                 if (offset >= bufsize)
 713                 {
 714                         unsigned int frag1;
 715                         frag1 = bufsize - old_offset;
 716                         cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
 717                         if (!cpnt) return -1;
 718                         memcpy(cpnt, bh->b_data + old_offset, frag1);
 719                         de = (struct iso_directory_record *) ((char *)cpnt);
 720                         brelse(bh);
 721                         offset -= bufsize;
 722                         directory_size -= bufsize;
 723                         if(directory_size < 0) return -1;
 724                         block++;
 725                         if(!(bh = bread(parent->i_dev,block,bufsize))) {
 726                                 kfree(cpnt);
 727                                 return -1;
 728                         };
 729                         memcpy((char *)cpnt+frag1, bh->b_data, offset);
 730                 }
 731                 
 732                 if (find_rock_ridge_relocation(de, parent) == extent){
 733                         result = inode_number;
 734                         goto out;
 735                 }
 736                 
 737                 if (cpnt) {
 738                         kfree(cpnt);
 739                         cpnt = NULL;
 740                 }
 741         }
 742 
 743         /* We go here for any condition we cannot handle.
 744            We also drop through to here at the end of the directory. */
 745 
 746  out:
 747         if (cpnt) {
 748                 kfree(cpnt);
 749                 cpnt = NULL;
 750         }
 751         brelse(bh);
 752 #ifdef DEBUG
 753         printk("Resultant Inode %d\n",result);
 754 #endif
 755         return result;
 756 }
 757     
 758 #ifdef LEAK_CHECK
 759 #undef malloc
 760 #undef free_s
 761 #undef bread
 762 #undef brelse
 763 
 764 void * leak_check_malloc(unsigned int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 765   void * tmp;
 766   check_malloc++;
 767   tmp = kmalloc(size, GFP_KERNEL);
 768   return tmp;
 769 }
 770 
 771 void leak_check_free_s(void * obj, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 772   check_malloc--;
 773   return kfree_s(obj, size);
 774 }
 775 
 776 struct buffer_head * leak_check_bread(int dev, int block, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 777   check_bread++;
 778   return bread(dev, block, size);
 779 }
 780 
 781 void leak_check_brelse(struct buffer_head * bh){
     /* [previous][next][first][last][top][bottom][index][help] */
 782   check_bread--;
 783   return brelse(bh);
 784 }
 785 
 786 #endif
 787 
 788 #ifdef MODULE
 789 
 790 char kernel_version[] = UTS_RELEASE;
 791 
 792 static struct file_system_type iso9660_fs_type = {
 793         isofs_read_super, "iso9660", 1, NULL
 794 };
 795 
 796 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 797 {
 798         register_filesystem(&iso9660_fs_type);
 799         return 0;
 800 }
 801 
 802 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 803 {
 804         unregister_filesystem(&iso9660_fs_type);
 805 }
 806 
 807 #endif
 808 

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