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_iso9660_fs
  14. init_module
  15. cleanup_module

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

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