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

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