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

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