root/fs/isofs/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. isofs_put_super
  2. parse_options
  3. isofs_read_super
  4. isofs_statfs
  5. isofs_bmap
  6. isofs_read_inode
  7. isofs_lookup_grandparent
  8. leak_check_malloc
  9. leak_check_free_s
  10. leak_check_bread
  11. leak_check_brelse
  12. init_module
  13. cleanup_module

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

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