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;
 255              iso_blknum < vol_desc_start+100; iso_blknum++) {
 256                 int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
 257 
 258                 if (!(bh = bread(dev,b,opt.blocksize))) {
 259                         s->s_dev = 0;
 260                         printk("isofs_read_super: bread failed, dev "
 261                                "%s iso_blknum %d block %d\n",
 262                                kdevname(dev), iso_blknum, b);
 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         if(high_sierra){
 307           rootp = (struct iso_directory_record *) h_pri->root_directory_record;
 308           if (isonum_723 (h_pri->volume_set_size) != 1) {
 309 #ifndef  MULTI_VOLUME 
 310             printk("Multi-volume disks not (yet) supported.\n");
 311             goto out;
 312 #endif
 313           }
 314           s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
 315           s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
 316           s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
 317         } else {
 318           rootp = (struct iso_directory_record *) pri->root_directory_record;
 319           if (isonum_723 (pri->volume_set_size) != 1) {
 320 #ifndef MULTI_VOLUME
 321             printk("Multi-volume disks not (yet) supported.\n");
 322             goto out;
 323 #endif
 324           }
 325           s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
 326           s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 327           s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 328         }
 329         
 330         s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
 331         
 332         /* RDE: convert log zone size to bit shift */
 333 
 334         orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
 335         switch (s -> u.isofs_sb.s_log_zone_size)
 336           { case  512: s -> u.isofs_sb.s_log_zone_size =  9; break;
 337             case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
 338             case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
 339 
 340             default:
 341               printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
 342               goto out;
 343           }
 344 
 345         /* RDE: data zone now byte offset! */
 346 
 347         s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) + 
 348                                            isonum_711 (rootp->ext_attr_length))
 349                                          << s -> u.isofs_sb.s_log_zone_size);
 350         s->s_magic = ISOFS_SUPER_MAGIC;
 351         
 352         /* The CDROM is read-only, has no nodes (devices) on it, and since
 353            all of the files appear to be owned by root, we really do not want
 354            to allow suid.  (suid or devices will not show up unless we have
 355            Rock Ridge extensions) */
 356         
 357         s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 358         
 359         brelse(bh);
 360         
 361         printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
 362                s->u.isofs_sb.s_max_size, 
 363                1UL << s->u.isofs_sb.s_log_zone_size);
 364         printk(KERN_DEBUG "First datazone:%ld   Root inode number %d\n",
 365                s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
 366                (isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length))
 367                         << s -> u.isofs_sb.s_log_zone_size);
 368         if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
 369         unlock_super(s);
 370         /* set up enough so that it can read an inode */
 371         
 372         /*
 373          * Force the blocksize to 512 for 512 byte sectors.  The file
 374          * read primitives really get it wrong in a bad way if we don't
 375          * do this.
 376          */
 377         if( orig_zonesize < opt.blocksize )
 378           {
 379             opt.blocksize = orig_zonesize;
 380             blocksize_bits = 0;
 381             {
 382               int i = opt.blocksize;
 383               while (i != 1){
 384                 blocksize_bits++;
 385                 i >>=1;
 386               }
 387             }
 388             set_blocksize(dev, opt.blocksize);
 389             printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
 390           }
 391 
 392         s->s_dev = dev;
 393         s->s_op = &isofs_sops;
 394         s->u.isofs_sb.s_mapping = opt.map;
 395         s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
 396         s->u.isofs_sb.s_name_check = opt.check;
 397         s->u.isofs_sb.s_conversion = opt.conversion;
 398         s->u.isofs_sb.s_cruft = opt.cruft;
 399         s->u.isofs_sb.s_unhide = opt.unhide;
 400         s->u.isofs_sb.s_uid = opt.uid;
 401         s->u.isofs_sb.s_gid = opt.gid;
 402         /*
 403          * It would be incredibly stupid to allow people to mark every file on the disk
 404          * as suid, so we merely allow them to set the default permissions.
 405          */
 406         s->u.isofs_sb.s_mode = opt.mode & 0777;
 407         s->s_blocksize = opt.blocksize;
 408         s->s_blocksize_bits = blocksize_bits;
 409         s->s_mounted = iget(s, (isonum_733(rootp->extent) + 
 410                             isonum_711(rootp->ext_attr_length))
 411                                 << s -> u.isofs_sb.s_log_zone_size);
 412         unlock_super(s);
 413 
 414         if (!(s->s_mounted)) {
 415                 s->s_dev = 0;
 416                 printk("get root inode failed\n");
 417                 MOD_DEC_USE_COUNT;
 418                 return NULL;
 419         }
 420 
 421         if(!check_disk_change(s->s_dev)) {
 422           return s;
 423         }
 424  out: /* Kick out for various error conditions */
 425         brelse(bh);
 426         s->s_dev = 0;
 427         unlock_super(s);
 428         MOD_DEC_USE_COUNT;
 429         return NULL;
 430 }
 431 
 432 void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 433 {
 434         struct statfs tmp;
 435 
 436         tmp.f_type = ISOFS_SUPER_MAGIC;
 437         tmp.f_bsize = sb->s_blocksize;
 438         tmp.f_blocks = (sb->u.isofs_sb.s_nzones
 439                   << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
 440         tmp.f_bfree = 0;
 441         tmp.f_bavail = 0;
 442         tmp.f_files = sb->u.isofs_sb.s_ninodes;
 443         tmp.f_ffree = 0;
 444         tmp.f_namelen = NAME_MAX;
 445         memcpy_tofs(buf, &tmp, bufsiz);
 446 }
 447 
 448 int isofs_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450 
 451         if (block<0) {
 452                 printk("_isofs_bmap: block<0");
 453                 return 0;
 454         }
 455         return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
 456 }
 457 
 458 void isofs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 461         struct buffer_head * bh;
 462         struct iso_directory_record * raw_inode;
 463         unsigned char *pnt = NULL;
 464         void *cpnt = NULL;
 465         int high_sierra;
 466         int block;
 467         int volume_seq_no ;
 468         int i;
 469 
 470         block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
 471         if (!(bh=bread(inode->i_dev,block, bufsize))) {
 472           printk("unable to read i-node block");
 473           goto fail;
 474         }
 475         
 476         pnt = ((unsigned char *) bh->b_data
 477                + (inode->i_ino & (bufsize - 1)));
 478         raw_inode = ((struct iso_directory_record *) pnt);
 479         high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 480 
 481         if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 482                 int frag1, offset;
 483 
 484                 offset = (inode->i_ino & (bufsize - 1));
 485                 frag1 = bufsize - offset;
 486                 cpnt = kmalloc(*pnt,GFP_KERNEL);
 487                 if (cpnt == NULL) {
 488                         printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
 489                         brelse(bh);
 490                         goto fail;
 491                 }
 492                 memcpy(cpnt, bh->b_data + offset, frag1);
 493                 brelse(bh);
 494                 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
 495                         kfree(cpnt);
 496                         printk("unable to read i-node block");
 497                         goto fail;
 498                 }
 499                 offset += *pnt - bufsize;
 500                 memcpy((char *)cpnt+frag1, bh->b_data, offset);
 501                 pnt = ((unsigned char *) cpnt);
 502                 raw_inode = ((struct iso_directory_record *) pnt);
 503         }
 504 
 505         if (raw_inode->flags[-high_sierra] & 2) {
 506                 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
 507                 inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
 508                                        the find utility tries to optimize
 509                                        if it is 2, and it screws up.  It is
 510                                        easier to give 1 which tells find to
 511                                        do it the hard way. */
 512         } else {
 513                 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; /* Everybody gets to read the file. */
 514                 inode->i_nlink = 1;
 515                 inode->i_mode |= S_IFREG;
 516 /* If there are no periods in the name, then set the execute permission bit */
 517                 for(i=0; i< raw_inode->name_len[0]; i++)
 518                         if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 519                                 break;
 520                 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
 521                         inode->i_mode |= S_IXUGO; /* execute permission */
 522         }
 523         inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
 524         inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
 525         inode->i_size = isonum_733 (raw_inode->size);
 526 
 527         /* There are defective discs out there - we do this to protect
 528            ourselves.  A cdrom will never contain more than 800Mb */
 529         if((inode->i_size < 0 || inode->i_size > 800000000) &&
 530             inode->i_sb->u.isofs_sb.s_cruft == 'n') {
 531           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 532           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 533         }
 534 
 535 /* Some dipshit decided to store some other bit of information in the high
 536    byte of the file length.  Catch this and holler.  WARNING: this will make
 537    it impossible for a file to be > 16Mb on the CDROM!!!*/
 538 
 539         if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
 540            inode->i_size & 0xff000000){
 541 /*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 542           inode->i_size &= 0x00ffffff;
 543         }
 544         
 545         if (raw_inode->interleave[0]) {
 546                 printk("Interleaved files not (yet) supported.\n");
 547                 inode->i_size = 0;
 548         }
 549 
 550         /* I have no idea what file_unit_size is used for, so
 551            we will flag it for now */
 552         if(raw_inode->file_unit_size[0] != 0){
 553                 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
 554         }
 555 
 556         /* I have no idea what other flag bits are used for, so
 557            we will flag it for now */
 558 #ifdef DEBUG
 559         if((raw_inode->flags[-high_sierra] & ~2)!= 0){
 560                 printk("Unusual flag settings for ISO file (%ld %x).\n",
 561                        inode->i_ino, raw_inode->flags[-high_sierra]);
 562         }
 563 #endif
 564 
 565 #ifdef DEBUG
 566         printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 567                ((int)pnt) & 0x3ff, inode->i_size);
 568 #endif
 569         
 570         inode->i_mtime = inode->i_atime = inode->i_ctime = 
 571           iso_date(raw_inode->date, high_sierra);
 572 
 573         inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
 574                                            isonum_711 (raw_inode->ext_attr_length))
 575           << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
 576         
 577         inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 578         switch (inode->i_sb->u.isofs_sb.s_conversion){
 579         case 'a':
 580           inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
 581           break;
 582         case 'b':
 583           inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
 584           break;
 585         case 't':
 586           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
 587           break;
 588         case 'm':
 589           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
 590           break;
 591         }
 592 
 593 /* Now test for possible Rock Ridge extensions which will override some of
 594    these numbers in the inode structure. */
 595 
 596         if (!high_sierra)
 597           parse_rock_ridge_inode(raw_inode, inode);
 598         
 599 #ifdef DEBUG
 600         printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 601 #endif
 602         brelse(bh);
 603         
 604         inode->i_op = NULL;
 605 
 606         /* get the volume sequence number */
 607         volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
 608 
 609         /* 
 610          * Disable checking if we see any volume number other than 0 or 1.
 611          * We could use the cruft option, but that has multiple purposes, one
 612          * of which is limiting the file size to 16Mb.  Thus we silently allow
 613          * volume numbers of 0 to go through without complaining.
 614          */
 615         if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && 
 616             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 617           printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
 618           inode->i_sb->u.isofs_sb.s_cruft = 'y';
 619         }
 620 
 621 #ifndef MULTI_VOLUME
 622         if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && 
 623             (volume_seq_no != 0) && (volume_seq_no != 1)) {
 624                 printk("Multi volume CD somehow got mounted.\n");
 625         } else
 626 #endif  
 627         {
 628           if (S_ISREG(inode->i_mode))
 629             inode->i_op = &isofs_file_inode_operations;
 630           else if (S_ISDIR(inode->i_mode))
 631             inode->i_op = &isofs_dir_inode_operations;
 632           else if (S_ISLNK(inode->i_mode))
 633             inode->i_op = &isofs_symlink_inode_operations;
 634           else if (S_ISCHR(inode->i_mode))
 635             inode->i_op = &chrdev_inode_operations;
 636           else if (S_ISBLK(inode->i_mode))
 637             inode->i_op = &blkdev_inode_operations;
 638           else if (S_ISFIFO(inode->i_mode))
 639             init_fifo(inode);
 640         }
 641         if (cpnt) {
 642                 kfree (cpnt);
 643                 cpnt = NULL;
 644         }
 645         return;
 646       fail:
 647         /* With a data error we return this information */
 648         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 649         inode->u.isofs_i.i_first_extent = 0;
 650         inode->u.isofs_i.i_backlink = 0xffffffff;
 651         inode->i_size = 0;
 652         inode->i_nlink = 1;
 653         inode->i_uid = inode->i_gid = 0;
 654         inode->i_mode = S_IFREG;  /*Regular file, no one gets to read*/
 655         inode->i_op = NULL;
 656         return;
 657 }
 658 
 659 /* There are times when we need to know the inode number of a parent of
 660    a particular directory.  When control passes through a routine that
 661    has access to the parent information, it fills it into the inode structure,
 662    but sometimes the inode gets flushed out of the queue, and someone
 663    remembers the number.  When they try to open up again, we have lost
 664    the information.  The '..' entry on the disc points to the data area
 665    for a particular inode, so we can follow these links back up, but since
 666    we do not know the inode number, we do not actually know how large the
 667    directory is.  The disc is almost always correct, and there is
 668    enough error checking on the drive itself, but an open ended search
 669    makes me a little nervous.
 670 
 671    The bsd iso filesystem uses the extent number for an inode, and this
 672    would work really nicely for us except that the read_inode function
 673    would not have any clean way of finding the actual directory record
 674    that goes with the file.  If we had such info, then it would pay
 675    to change the inode numbers and eliminate this function.
 676 */
 677 
 678 int isofs_lookup_grandparent(struct inode * parent, int extent)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680         unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
 681         unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
 682         unsigned int block,offset;
 683         int parent_dir, inode_number;
 684         int old_offset;
 685         void * cpnt = NULL;
 686         int result;
 687         int directory_size;
 688         struct buffer_head * bh;
 689         struct iso_directory_record * de;
 690         
 691         offset = 0;
 692         block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
 693         if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
 694         
 695         while (1 == 1) {
 696                 de = (struct iso_directory_record *) (bh->b_data + offset);
 697                 if (*((unsigned char *) de) == 0) 
 698                 {
 699                         brelse(bh);
 700                         printk("Directory .. not found\n");
 701                         return -1;
 702                 }
 703                 
 704                 offset += *((unsigned char *) de);
 705 
 706                 if (offset >= bufsize) 
 707                 {
 708                         printk(".. Directory not in first block"
 709                                " of directory.\n");
 710                         brelse(bh);
 711                         return -1;
 712                 }
 713                 
 714                 if (de->name_len[0] == 1 && de->name[0] == 1) 
 715                 {
 716                         parent_dir = find_rock_ridge_relocation(de, parent);
 717                         directory_size = isonum_733 (de->size);
 718                         brelse(bh);
 719                         break;
 720                 }
 721         }
 722 #ifdef DEBUG
 723         printk("Parent dir:%x\n",parent_dir);
 724 #endif
 725         /* Now we know the extent where the parent dir starts on. */
 726         
 727         result = -1;
 728 
 729         offset = 0;
 730         block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits);
 731         if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
 732         {
 733                 return -1;
 734         }
 735         
 736         for(;;)
 737         {
 738                 de = (struct iso_directory_record *) (bh->b_data + offset);
 739                 inode_number = (block << bufbits)+(offset & (bufsize - 1));
 740                 
 741                 /* If the length byte is zero, we should move on to the next
 742                    CDROM sector.  If we are at the end of the directory, we
 743                    kick out of the while loop. */
 744                 
 745                 if (*((unsigned char *) de) == 0) 
 746                 {
 747                         brelse(bh);
 748                         offset = 0;
 749                         block++;
 750                         directory_size -= bufsize;
 751                         if(directory_size < 0) return -1;
 752                         if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1)
 753                         {
 754                                 return -1;
 755                         }
 756                         if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2)
 757                         {
 758                                 return -1;
 759                         }
 760                         if (!block
 761                             || !(bh = bread(parent->i_dev,block, bufsize)))
 762                         {
 763                                 return -1;
 764                         }
 765                         continue;
 766                 }
 767                 
 768                 /* Make sure that the entire directory record is in the current
 769                    bh block.  If not, we malloc a buffer, and put the two
 770                    halves together, so that we can cleanly read the block.  */
 771 
 772                 old_offset = offset;
 773                 offset += *((unsigned char *) de);
 774 
 775                 if (offset >= bufsize)
 776                 {
 777                         unsigned int frag1;
 778                         frag1 = bufsize - old_offset;
 779                         cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
 780                         if (!cpnt) return -1;
 781                         memcpy(cpnt, bh->b_data + old_offset, frag1);
 782                         de = (struct iso_directory_record *) ((char *)cpnt);
 783                         brelse(bh);
 784                         offset -= bufsize;
 785                         directory_size -= bufsize;
 786                         if(directory_size < 0) 
 787                         {
 788                                 printk("Directory size < 0\n");
 789                                 return -1;
 790                         }
 791                         block++;
 792                         if(!(bh = bread(parent->i_dev,block,bufsize))) {
 793                                 kfree(cpnt);
 794                                 return -1;
 795                         }
 796                         memcpy((char *)cpnt+frag1, bh->b_data, offset);
 797                 }
 798                 
 799                 if (find_rock_ridge_relocation(de, parent) == extent){
 800                         result = inode_number;
 801                         goto out;
 802                 }
 803                 
 804                 if (cpnt) {
 805                         kfree(cpnt);
 806                         cpnt = NULL;
 807                 }
 808         }
 809 
 810         /* We go here for any condition we cannot handle.
 811            We also drop through to here at the end of the directory. */
 812 
 813  out:
 814         if (cpnt) {
 815                 kfree(cpnt);
 816                 cpnt = NULL;
 817         }
 818         brelse(bh);
 819 #ifdef DEBUG
 820         printk("Resultant Inode %d\n",result);
 821 #endif
 822         return result;
 823 }
 824     
 825 #ifdef LEAK_CHECK
 826 #undef malloc
 827 #undef free_s
 828 #undef bread
 829 #undef brelse
 830 
 831 void * leak_check_malloc(unsigned int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 832   void * tmp;
 833   check_malloc++;
 834   tmp = kmalloc(size, GFP_KERNEL);
 835   return tmp;
 836 }
 837 
 838 void leak_check_free_s(void * obj, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 839   check_malloc--;
 840   return kfree_s(obj, size);
 841 }
 842 
 843 struct buffer_head * leak_check_bread(int dev, int block, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 844   check_bread++;
 845   return bread(dev, block, size);
 846 }
 847 
 848 void leak_check_brelse(struct buffer_head * bh){
     /* [previous][next][first][last][top][bottom][index][help] */
 849   check_bread--;
 850   return brelse(bh);
 851 }
 852 
 853 #endif
 854 
 855 static struct file_system_type iso9660_fs_type = {
 856         isofs_read_super, "iso9660", 1, NULL
 857 };
 858 
 859 int init_iso9660_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 860 {
 861         return register_filesystem(&iso9660_fs_type);
 862 }
 863 
 864 #ifdef MODULE
 865 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 866 {
 867         int status;
 868 
 869         if ((status = init_iso9660_fs()) == 0)
 870                 register_symtab(0);
 871         return status;
 872 }
 873 
 874 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 875 {
 876         unregister_filesystem(&iso9660_fs_type);
 877 }
 878 
 879 #endif
 880 

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