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

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

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