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

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