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

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