diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/dir.c ./linux/fs/isofs/dir.c --- ../linux-2.2.18pre23/linux/fs/isofs/dir.c Mon Sep 4 19:39:22 2000 +++ ./linux/fs/isofs/dir.c Mon Nov 27 00:52:45 2000 @@ -67,14 +67,18 @@ NULL /* permission */ }; -static int isofs_name_translate(char * old, int len, char * new) +int isofs_name_translate(struct iso_directory_record *de, char *new, + struct inode *inode) { - int i, c; + char * old = de->name; + int len = de->name_len[0]; + int i; for (i = 0; i < len; i++) { - c = old[i]; + unsigned char c = old[i]; if (!c) break; + if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */ @@ -101,8 +105,7 @@ { int std; unsigned char * chr; - int retnamlen = isofs_name_translate(de->name, - de->name_len[0], retname); + int retnamlen = isofs_name_translate(de, retname, inode); if (retnamlen == 0) return 0; std = sizeof(struct iso_directory_record) + de->name_len[0]; if (std & 1) std++; @@ -122,7 +125,9 @@ } /* - * This should _really_ be cleaned up some day.. + * Read directory and call the filldir() argument until either + * all entries were handled, or filldir() returns an error. + * Return 0. */ static int do_isofs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir, @@ -132,7 +137,7 @@ unsigned char bufbits = ISOFS_BUFFER_BITS(inode); unsigned int block, offset; int inode_number = 0; /* Quiet GCC */ - struct buffer_head *bh; + struct buffer_head *bh = NULL; int len; int map; int high_sierra; @@ -140,78 +145,59 @@ char *p = NULL; /* Quiet GCC */ struct iso_directory_record *de; - if (filp->f_pos >= inode->i_size) - return 0; - offset = filp->f_pos & (bufsize - 1); - block = isofs_bmap(inode, filp->f_pos >> bufbits); + block = filp->f_pos >> bufbits; high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; - if (!block) - return 0; - - if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size))) - return 0; - while (filp->f_pos < inode->i_size) { int de_len; -#ifdef DEBUG - printk("Block, offset, f_pos: %x %x %x\n", - block, offset, filp->f_pos); - printk("inode->i_size = %x\n",inode->i_size); -#endif + + if (!bh) { + bh = isofs_bread(inode, bufsize, block); + if (!bh) + return 0; + } + de = (struct iso_directory_record *) (bh->b_data + offset); - if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1)); + if (first_de) + inode_number = (bh->b_blocknr << bufbits) + offset; - /* Check boundaries and get length. by GO! */ - if (offset < bufsize) de_len = *(unsigned char *) de; -#ifdef DEBUG - if (offset < bufsize) printk("de_len = %ld\n", de_len); - else printk("Move to next sector\n"); -#endif - + de_len = *(unsigned char *) de; /* If the length byte is zero, we should move on to the next CDROM sector. If we are at the end of the directory, we kick out of the while loop. */ - if ((offset >= bufsize) || (de_len == 0) ) { + if (de_len == 0) { brelse(bh); - if (offset >= bufsize) { /*Check first. by GO!*/ - offset -= bufsize; - filp->f_pos += offset; - } else { - filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); - offset = 0; - } - - if (filp->f_pos >= inode->i_size) - return 0; - - block = isofs_bmap(inode, (filp->f_pos) >> bufbits); - if (!block) - return 0; - bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size); - if (!bh) - return 0; + bh = NULL; + filp->f_pos = (filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) + + ISOFS_BLOCK_SIZE; + block = filp->f_pos >> bufbits; + offset = 0; continue; } - offset += de_len; - if (offset > bufsize) { - /* - * This would only normally happen if we had - * a buggy cdrom image. All directory - * entries should terminate with a null size - * or end exactly at the end of the sector. - */ - printk("next_offset (%x) > bufsize (%lx)\n", - offset,bufsize); - break; + offset += de_len; + + /* Make sure we have a full directory entry */ + if (offset >= bufsize) { + int slop = bufsize - offset + de_len; + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; + brelse(bh); + bh = NULL; + if (offset) { + bh = isofs_bread(inode, bufsize, block); + if (!bh) + return 0; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } - if(de->flags[-high_sierra] & 0x80) { + if (de->flags[-high_sierra] & 0x80) { first_de = 0; filp->f_pos += de_len; continue; @@ -250,7 +236,7 @@ map = 1; if (inode->i_sb->u.isofs_sb.s_rock) { len = get_rock_ridge_filename(de, tmpname, inode); - if (len != 0) { + if (len != 0) { /* may be -1 */ p = tmpname; map = 0; } @@ -258,7 +244,7 @@ if (map) { #ifdef CONFIG_JOLIET if (inode->i_sb->u.isofs_sb.s_joliet_level) { - len = get_joliet_filename(de, inode, tmpname); + len = get_joliet_filename(de, tmpname, inode); p = tmpname; } else #endif @@ -267,8 +253,7 @@ p = tmpname; } else if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { - len = isofs_name_translate(de->name, - de->name_len[0], tmpname); + len = isofs_name_translate(de, tmpname, inode); p = tmpname; } else { p = de->name; @@ -283,7 +268,8 @@ continue; } - brelse(bh); + if (bh) + brelse(bh); return 0; } @@ -296,17 +282,17 @@ void *dirent, filldir_t filldir) { int result; - char * tmpname; + char * page; struct iso_directory_record * tmpde; struct inode *inode = filp->f_dentry->d_inode; - tmpname = (char *) __get_free_page(GFP_KERNEL); - if (!tmpname) + page = (char *) __get_free_page(GFP_KERNEL); + if (!page) return -ENOMEM; - tmpde = (struct iso_directory_record *) (tmpname+1024); + tmpde = (struct iso_directory_record *) (page+1024); - result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde); + result = do_isofs_readdir(inode, filp, dirent, filldir, page, tmpde); - free_page((unsigned long) tmpname); + free_page((unsigned long) page); return result; } diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/inode.c ./linux/fs/isofs/inode.c --- ../linux-2.2.18pre23/linux/fs/isofs/inode.c Mon Sep 4 19:39:22 2000 +++ ./linux/fs/isofs/inode.c Mon Nov 27 00:57:23 2000 @@ -54,7 +54,7 @@ static int isofs_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b); #endif -void isofs_put_super(struct super_block *sb) +static void isofs_put_super(struct super_block *sb) { #ifdef CONFIG_JOLIET if (sb->u.isofs_sb.s_nls_iocharset) { @@ -72,6 +72,9 @@ return; } +static void isofs_read_inode(struct inode *); +static int isofs_statfs (struct super_block *, struct statfs *, int); + static struct super_operations isofs_sops = { isofs_read_inode, NULL, /* write_inode */ @@ -452,7 +455,7 @@ (unsigned long) &ms_info); set_fs(old_fs); #if 0 - printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i); + printk("isofs.inode: CDROMMULTISESSION: rc=%d\n", i); if (i==0) { printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no"); @@ -474,8 +477,8 @@ * Note: a check_disk_change() has been done immediately prior * to this call, so we don't need to check again. */ -struct super_block *isofs_read_super(struct super_block *s, void *data, - int silent) +static struct super_block *isofs_read_super(struct super_block *s, void *data, + int silent) { kdev_t dev = s->s_dev; struct buffer_head * bh = NULL, *pri_bh = NULL; @@ -521,15 +524,13 @@ * that value. */ blocksize = get_hardblocksize(dev); - if( (blocksize != 0) - && (blocksize > opt.blocksize) ) - { + if (blocksize > opt.blocksize) { /* * Force the blocksize we are going to use to be the * hardware blocksize. */ opt.blocksize = blocksize; - } + } blocksize_bits = 0; { @@ -625,9 +626,7 @@ pri_bh = NULL; root_found: - brelse(pri_bh); - - if (joliet_level && opt.rock == 'n') { + if (joliet_level && (pri == NULL || opt.rock == 'n')) { /* This is the case of Joliet with the norock mount flag. * A disc with both Joliet and Rock Ridge is handled later */ @@ -724,6 +723,7 @@ * We're all done using the volume descriptor, and may need * to change the device blocksize, so release the buffer now. */ + brelse(pri_bh); brelse(bh); /* @@ -776,8 +776,9 @@ s->u.isofs_sb.s_gid = opt.gid; s->u.isofs_sb.s_utf8 = opt.utf8; /* - * It would be incredibly stupid to allow people to mark every file on the disk - * as suid, so we merely allow them to set the default permissions. + * It would be incredibly stupid to allow people to mark every file + * on the disk as suid, so we merely allow them to set the default + * permissions. */ s->u.isofs_sb.s_mode = opt.mode & 0777; @@ -880,8 +881,8 @@ return NULL; } -int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz) -{ +static int +isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz) { struct statfs tmp; tmp.f_type = ISOFS_SUPER_MAGIC; @@ -896,6 +897,15 @@ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } +struct buffer_head *isofs_bread(struct inode *inode, unsigned int bufsize, + unsigned int block) +{ + unsigned int blknr = isofs_bmap(inode, block); + if (!blknr) + return NULL; + return bread(inode->i_dev, blknr, bufsize); +} + int isofs_bmap(struct inode * inode,int block) { off_t b_off, offset, size; @@ -942,10 +952,6 @@ firstext = inode->u.isofs_i.i_first_extent; size = inode->u.isofs_i.i_section_size; nextino = inode->u.isofs_i.i_next_section_ino; -#ifdef DEBUG - printk("first inode: inode=%x nextino=%x firstext=%u size=%lu\n", - inode->i_ino, nextino, firstext, size); -#endif i = 0; if (nextino) { while(b_off >= offset + size) { @@ -956,10 +962,6 @@ if(!ino) return 0; firstext = ino->u.isofs_i.i_first_extent; size = ino->u.isofs_i.i_section_size; -#ifdef DEBUG - printk("read inode: inode=%lu ino=%lu nextino=%lu firstext=%u size=%lu\n", - inode->i_ino, nextino, ino->u.isofs_i.i_next_section_ino, firstext, size); -#endif nextino = ino->u.isofs_i.i_next_section_ino; iput(ino); @@ -971,10 +973,6 @@ } } } -#ifdef DEBUG - printk("isofs_bmap: mapped inode:block %x:%d to block %lu\n", - inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode)); -#endif return firstext + ((b_off - offset) >> ISOFS_BUFFER_BITS(inode)); } @@ -995,118 +993,144 @@ static int isofs_read_level3_size(struct inode * inode) { - unsigned long ino = inode->i_ino; + unsigned long f_pos = inode->i_ino; unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; struct buffer_head * bh = NULL; - int block = 0; + unsigned long block, offset; int i = 0; int more_entries = 0; - void *cpnt; - struct iso_directory_record * raw_inode; + struct iso_directory_record * tmpde = NULL; inode->i_size = 0; inode->u.isofs_i.i_next_section_ino = 0; + + block = f_pos >> ISOFS_BUFFER_BITS(inode); + offset = f_pos & (bufsize-1); + do { - unsigned char *pnt; - unsigned int reclen; - int offset = (ino & (bufsize - 1)); - - cpnt = NULL; - /* Check whether to update our buffer */ - if (block != ino >> ISOFS_BUFFER_BITS(inode)) { - block = ino >> ISOFS_BUFFER_BITS(inode); + struct iso_directory_record * de; + unsigned int de_len; + + if (!bh) { brelse(bh); bh = bread(inode->i_dev, block, bufsize); if (!bh) goto out_noread; } - pnt = ((unsigned char *) bh->b_data + offset); - /* - * Note: this is invariant even if the record - * spans buffers and must be copied ... - */ - reclen = *pnt; - /* N.B. this test doesn't trigger the i++ code ... */ - if(reclen == 0) { - ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE; + de = (struct iso_directory_record *) (bh->b_data + offset); + de_len = *(unsigned char *) de; + + if (de_len == 0) { + brelse(bh); + bh = NULL; + f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); + block = f_pos >> ISOFS_BUFFER_BITS(inode); + offset = 0; continue; } - raw_inode = ((struct iso_directory_record *) pnt); - /* Check whether the raw inode spans the buffer ... */ - if (offset + reclen > bufsize){ - int frag1 = bufsize - offset; - - cpnt = kmalloc(reclen, GFP_KERNEL); - if (cpnt == NULL) - goto out_nomem; - memcpy(cpnt, pnt, frag1); + offset += de_len; + + /* Make sure we have a full directory entry */ + if (offset >= bufsize) { + int slop = bufsize - offset + de_len; + if (!tmpde) { + tmpde = kmalloc(256, GFP_KERNEL); + if (!tmpde) + goto out_nomem; + } + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; brelse(bh); - bh = bread(inode->i_dev, ++block, bufsize); - if (!bh) - goto out_noread; - offset += reclen - bufsize; - memcpy((char *)cpnt+frag1, bh->b_data, offset); - raw_inode = ((struct iso_directory_record *) cpnt); + bh = NULL; + if (offset) { + bh = bread(inode->i_dev, ++block, bufsize); + if (!bh) + goto out_noread; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } - inode->i_size += isonum_733 (raw_inode->size); - if(i == 1) inode->u.isofs_i.i_next_section_ino = ino; + inode->i_size += isonum_733 (de->size); + if(i == 1) + inode->u.isofs_i.i_next_section_ino = f_pos; + + more_entries = de->flags[-high_sierra] & 0x80; + + f_pos += de_len; - more_entries = raw_inode->flags[-high_sierra] & 0x80; - - ino += reclen; - if (cpnt) - kfree (cpnt); i++; if(i > 100) goto out_toomany; } while(more_entries); out: - brelse(bh); + if (tmpde) + kfree(tmpde); + if (bh) + brelse(bh); return 0; out_nomem: - printk(KERN_INFO "ISOFS: NoMem ISO inode %lu\n", inode->i_ino); - brelse(bh); - return 1; + if (bh) + brelse(bh); + return -ENOMEM; + out_noread: - printk(KERN_INFO "ISOFS: unable to read i-node block %d\n", block); - if (cpnt) - kfree(cpnt); - return 1; + printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); + if (tmpde) + kfree(tmpde); + return -EIO; + out_toomany: printk(KERN_INFO "isofs_read_level3_size: " "More than 100 file sections ?!?, aborting...\n" "isofs_read_level3_size: inode=%lu ino=%lu\n", - inode->i_ino, ino); + inode->i_ino, f_pos); goto out; } -void isofs_read_inode(struct inode * inode) +static void isofs_read_inode(struct inode * inode) { struct super_block *sb = inode->i_sb; unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode); int high_sierra = sb->u.isofs_sb.s_high_sierra; - struct buffer_head * bh; - struct iso_directory_record * raw_inode; - unsigned char *pnt; - int volume_seq_no, i; + struct buffer_head * bh = NULL; + struct iso_directory_record * de; + struct iso_directory_record * tmpde = NULL; + unsigned int de_len; + int volume_seq_no, i, offset; bh = bread(inode->i_dev, block, bufsize); - if (!bh) { - printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); - goto fail; - } + if (!bh) + goto out_badread; - pnt = ((unsigned char *) bh->b_data - + (inode->i_ino & (bufsize - 1))); - raw_inode = ((struct iso_directory_record *) pnt); + offset = (inode->i_ino & (bufsize - 1)); + de = (struct iso_directory_record *) (bh->b_data + offset); + de_len = *(unsigned char *) de; + + if (offset + de_len > bufsize){ + int frag1 = bufsize - offset; + + tmpde = kmalloc(de_len, GFP_KERNEL); + if (tmpde == NULL) { + printk(KERN_INFO "isofs_read_inode: out of memory\n"); + goto fail; + } + memcpy(tmpde, bh->b_data + offset, frag1); + brelse(bh); + bh = bread(inode->i_dev, ++block, bufsize); + if (!bh) + goto out_badread; + memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1); + de = tmpde; + } - if (raw_inode->flags[-high_sierra] & 2) { + if (de->flags[-high_sierra] & 2) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 1; /* Set to 1. We know there are 2, but the find utility tries to optimize @@ -1121,10 +1145,10 @@ /* If there are no periods in the name, * then set the execute permission bit */ - for(i=0; i< raw_inode->name_len[0]; i++) - if(raw_inode->name[i]=='.' || raw_inode->name[i]==';') + for(i=0; i< de->name_len[0]; i++) + if(de->name[i]=='.' || de->name[i]==';') break; - if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') + if(i == de->name_len[0] || de->name[i] == ';') inode->i_mode |= S_IXUGO; /* execute permission */ } inode->i_uid = inode->i_sb->u.isofs_sb.s_uid; @@ -1132,49 +1156,54 @@ inode->i_blocks = inode->i_blksize = 0; - inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size); - if(raw_inode->flags[-high_sierra] & 0x80) { + inode->u.isofs_i.i_section_size = isonum_733 (de->size); + if(de->flags[-high_sierra] & 0x80) { if(isofs_read_level3_size(inode)) goto fail; } else { - inode->i_size = isonum_733 (raw_inode->size); + inode->i_size = isonum_733 (de->size); } /* There are defective discs out there - we do this to protect ourselves. A cdrom will never contain more than 800Mb .. but a DVD may be up to 1Gig (Ulrich Habel) */ + if((inode->i_size < 0 || inode->i_size > 1073741824) && - inode->i_sb->u.isofs_sb.s_cruft == 'n') { - printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n"); - inode->i_sb->u.isofs_sb.s_cruft = 'y'; + inode->i_sb->u.isofs_sb.s_cruft == 'n') { + printk(KERN_WARNING "Warning: defective cdrom. " + "Enabling \"cruft\" mount option.\n"); + inode->i_sb->u.isofs_sb.s_cruft = 'y'; } -/* Some dipshit decided to store some other bit of information in the high - byte of the file length. Catch this and holler. WARNING: this will make - it impossible for a file to be > 16Mb on the CDROM!!!*/ + /* + * Some dipshit decided to store some other bit of information + * in the high byte of the file length. Catch this and holler. + * WARNING: this will make it impossible for a file to be > 16MB + * on the CDROM. + */ if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && inode->i_size & 0xff000000){ -/* printk("Illegal format on cdrom. Pester manufacturer.\n"); */ - inode->i_size &= 0x00ffffff; + inode->i_size &= 0x00ffffff; } - if (raw_inode->interleave[0]) { + if (de->interleave[0]) { printk("Interleaved files not (yet) supported.\n"); inode->i_size = 0; } /* I have no idea what file_unit_size is used for, so we will flag it for now */ - if(raw_inode->file_unit_size[0] != 0){ - printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino); + if (de->file_unit_size[0] != 0){ + printk("File unit size != 0 for ISO file (%ld).\n", + inode->i_ino); } /* I have no idea what other flag bits are used for, so we will flag it for now */ #ifdef DEBUG - if((raw_inode->flags[-high_sierra] & ~2)!= 0){ + if ((de->flags[-high_sierra] & ~2)!= 0){ printk("Unusual flag settings for ISO file (%ld %x).\n", - inode->i_ino, raw_inode->flags[-high_sierra]); + inode->i_ino, de->flags[-high_sierra]); } #endif @@ -1184,32 +1213,25 @@ #endif inode->i_mtime = inode->i_atime = inode->i_ctime = - iso_date(raw_inode->date, high_sierra); + iso_date(de->date, high_sierra); - inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + - isonum_711 (raw_inode->ext_attr_length)); + inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) + + isonum_711 (de->ext_attr_length)); -/* Now test for possible Rock Ridge extensions which will override some of - these numbers in the inode structure. */ + /* + * Now test for possible Rock Ridge extensions which will override + * some of these numbers in the inode structure. + */ if (!high_sierra) { - parse_rock_ridge_inode(raw_inode, inode); - /* hmm..if we want uid or gid set, override the rock ridge setting */ - test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid); - test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid); + parse_rock_ridge_inode(de, inode); + /* if we want uid/gid set, override the rock ridge setting */ + test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid); + test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid); } -#ifdef DEBUG - printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent); -#endif - /* get the volume sequence number */ - volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ; - - /* - * All done with buffer ... no more references to buffer memory! - */ - brelse(bh); + volume_seq_no = isonum_723 (de->volume_sequence_number) ; /* * Disable checking if we see any volume number other than 0 or 1. @@ -1219,8 +1241,10 @@ */ if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && (volume_seq_no != 0) && (volume_seq_no != 1)) { - printk("Warning: defective cdrom (volume sequence number). Enabling \"cruft\" mount option.\n"); - inode->i_sb->u.isofs_sb.s_cruft = 'y'; + printk("Warning: defective cdrom " + "(volume sequence number %d). " + "Enabling \"cruft\" mount option.\n", volume_seq_no); + inode->i_sb->u.isofs_sb.s_cruft = 'y'; } /* Install the inode operations vector */ @@ -1228,26 +1252,34 @@ #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && (volume_seq_no != 0) && (volume_seq_no != 1)) { - printk("Multi volume CD somehow got mounted.\n"); + printk(KERN_WARNING "Multi volume CD somehow got mounted.\n"); } else #endif IGNORE_WRONG_MULTI_VOLUME_SPECS { - if (S_ISREG(inode->i_mode)) - inode->i_op = &isofs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &isofs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &isofs_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) - inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) - inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) - init_fifo(inode); + if (S_ISREG(inode->i_mode)) + inode->i_op = &isofs_file_inode_operations; + else if (S_ISDIR(inode->i_mode)) + inode->i_op = &isofs_dir_inode_operations; + else if (S_ISLNK(inode->i_mode)) + inode->i_op = &isofs_symlink_inode_operations; + else if (S_ISCHR(inode->i_mode)) + inode->i_op = &chrdev_inode_operations; + else if (S_ISBLK(inode->i_mode)) + inode->i_op = &blkdev_inode_operations; + else if (S_ISFIFO(inode->i_mode)) + init_fifo(inode); } + + out: + if (tmpde) + kfree(tmpde); + if (bh) + brelse(bh); return; - fail: + out_badread: + printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); + fail: /* With a data error we return this information */ inode->i_mtime = inode->i_atime = inode->i_ctime = 0; inode->u.isofs_i.i_first_extent = 0; @@ -1257,144 +1289,7 @@ inode->i_uid = inode->i_gid = 0; inode->i_mode = S_IFREG; /*Regular file, no one gets to read*/ inode->i_op = NULL; - return; -} - -/* There are times when we need to know the inode number of a parent of - a particular directory. When control passes through a routine that - has access to the parent information, it fills it into the inode structure, - but sometimes the inode gets flushed out of the queue, and someone - remembers the number. When they try to open up again, we have lost - the information. The '..' entry on the disc points to the data area - for a particular inode, so we can follow these links back up, but since - we do not know the inode number, we do not actually know how large the - directory is. The disc is almost always correct, and there is - enough error checking on the drive itself, but an open ended search - makes me a little nervous. - - The BSD iso filesystem uses the extent number for an inode, and this - would work really nicely for us except that the read_inode function - would not have any clean way of finding the actual directory record - that goes with the file. If we had such info, then it would pay - to change the inode numbers and eliminate this function. -*/ - -int isofs_lookup_grandparent(struct inode * parent, int extent) -{ - unsigned long bufsize = ISOFS_BUFFER_SIZE(parent); - unsigned char bufbits = ISOFS_BUFFER_BITS(parent); - unsigned int block,offset; - int parent_dir, inode_number; - int result; - int directory_size; - struct buffer_head * bh; - struct iso_directory_record * de; - - offset = 0; - block = extent << (ISOFS_ZONE_BITS(parent) - bufbits); - if (!(bh = bread(parent->i_dev, block, bufsize))) return -1; - - while (1 == 1) { - de = (struct iso_directory_record *) (bh->b_data + offset); - if (*((unsigned char *) de) == 0) - { - brelse(bh); - printk("Directory .. not found\n"); - return -1; - } - - offset += *((unsigned char *) de); - - if (offset >= bufsize) - { - printk(".. Directory not in first block" - " of directory.\n"); - brelse(bh); - return -1; - } - - if (de->name_len[0] == 1 && de->name[0] == 1) - { - parent_dir = find_rock_ridge_relocation(de, parent); - directory_size = isonum_733 (de->size); - brelse(bh); - break; - } - } -#ifdef DEBUG - printk("Parent dir:%x\n",parent_dir); -#endif - /* Now we know the extent where the parent dir starts on. */ - - result = -1; - - offset = 0; - block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits); - if (!block || !(bh = bread(parent->i_dev,block, bufsize))) - { - return -1; - } - - for(;;) - { - de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits)+(offset & (bufsize - 1)); - - /* If the length byte is zero, we should move on to the next - CDROM sector. If we are at the end of the directory, we - kick out of the while loop. */ - - if ((*((unsigned char *) de) == 0) || (offset == bufsize) ) - { - brelse(bh); - offset = 0; - block++; - directory_size -= bufsize; - if(directory_size < 0) return -1; - if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1) - { - return -1; - } - if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2) - { - return -1; - } - if (!block - || !(bh = bread(parent->i_dev,block, bufsize))) - { - return -1; - } - continue; - } - - /* Make sure that the entire directory record is in the current - bh block. If not, we malloc a buffer, and put the two - halves together, so that we can cleanly read the block. */ - - offset += *((unsigned char *) de); - - if (offset > bufsize) - { - printk("Directory overrun\n"); - goto out; - } - - if (find_rock_ridge_relocation(de, parent) == extent){ - result = inode_number; - goto out; - } - - } - - /* We go here for any condition we cannot handle. - We also drop through to here at the end of the directory. */ - - out: - brelse(bh); -#ifdef DEBUG - printk("Resultant Inode %d\n",result); -#endif - return result; + goto out; } #ifdef LEAK_CHECK diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/joliet.c ./linux/fs/isofs/joliet.c --- ../linux-2.2.18pre23/linux/fs/isofs/joliet.c Wed Jun 7 23:26:43 2000 +++ ./linux/fs/isofs/joliet.c Mon Nov 27 00:58:55 2000 @@ -19,8 +19,6 @@ struct nls_table *nls) { unsigned char *ip, *op; - unsigned char ch, cl; - unsigned char *uni_page; ip = uni; op = ascii; @@ -68,8 +66,8 @@ } int -get_joliet_filename(struct iso_directory_record * de, struct inode * inode, - unsigned char *outname) +get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, + struct inode * inode) { unsigned char utf8; struct nls_table *nls; diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/namei.c ./linux/fs/isofs/namei.c --- ../linux-2.2.18pre23/linux/fs/isofs/namei.c Mon Aug 9 21:04:41 1999 +++ ./linux/fs/isofs/namei.c Mon Nov 27 00:55:40 2000 @@ -53,200 +53,130 @@ * isofs_find_entry() * * finds an entry in the specified directory with the wanted name. It - * returns the cache buffer in which the entry was found, and the entry - * itself (as an inode number). It does NOT read the inode of the - * entry - you'll have to do that yourself if you want to. + * returns the inode number of the found entry, or 0 on error. */ -static struct buffer_head * -isofs_find_entry(struct inode *dir, struct dentry *dentry, unsigned long *ino) +static unsigned long +isofs_find_entry(struct inode *dir, struct dentry *dentry, + char *tmpname, struct iso_directory_record *tmpde) { + unsigned long inode_number; unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); unsigned char bufbits = ISOFS_BUFFER_BITS(dir); - unsigned int block, i, f_pos, offset, - inode_number = 0; /* shut gcc up */ - struct buffer_head * bh , * retval = NULL; - unsigned int old_offset; - int dlen, match; - char * dpnt; - unsigned char *page = NULL; - struct iso_directory_record * de = NULL; /* shut gcc up */ - char de_not_in_buf = 0; /* true if de is in kmalloc'd memory */ - char c; - - *ino = 0; - - if (!(block = dir->u.isofs_i.i_first_extent)) return NULL; + unsigned int block, f_pos, offset; + struct buffer_head * bh = NULL; + + if (!dir->u.isofs_i.i_first_extent) + return 0; f_pos = 0; + offset = 0; + block = 0; - offset = f_pos & (bufsize - 1); - block = isofs_bmap(dir,f_pos >> bufbits); + while (f_pos < dir->i_size) { + struct iso_directory_record * de; + int de_len, match, i, dlen; + char *dpnt; - if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL; + if (!bh) { + bh = isofs_bread(dir, bufsize, block); + if (!bh) + return 0; + } - while (f_pos < dir->i_size) { + de = (struct iso_directory_record *) (bh->b_data + offset); + inode_number = (bh->b_blocknr << bufbits) + offset; - /* if de is in kmalloc'd memory, do not point to the - next de, instead we will move to the next sector */ - if(!de_not_in_buf) { - de = (struct iso_directory_record *) - (bh->b_data + offset); - } - inode_number = (block << bufbits) + (offset & (bufsize - 1)); - - /* If byte is zero, or we had to fetch this de past - the end of the buffer, this is the end of file, or - time to move to the next sector. Usually 2048 byte - boundaries. */ - - if (*((unsigned char *) de) == 0 || de_not_in_buf) { - if(de_not_in_buf) { - /* james@bpgc.com: Since we slopped - past the end of the last buffer, we - must start some way into the new - one */ - de_not_in_buf = 0; - kfree(de); - f_pos += offset; - } - else { - offset = 0; - f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); - } + de_len = *(unsigned char *) de; + if (!de_len) { brelse(bh); bh = NULL; - - if (f_pos >= dir->i_size) - break; - - block = isofs_bmap(dir,f_pos>>bufbits); - if (!block || !(bh = bread(dir->i_dev,block,bufsize))) - break; - - continue; /* Will kick out if past end of directory */ + f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); + block = f_pos >> bufbits; + offset = 0; + continue; } - old_offset = offset; - offset += *((unsigned char *) de); - f_pos += *((unsigned char *) de); + offset += de_len; + f_pos += de_len; - /* james@bpgc.com: new code to handle case where the - directory entry spans two blocks. Usually 1024 - byte boundaries */ + /* Make sure we have a full directory entry */ if (offset >= bufsize) { - struct buffer_head *bh_next; - - /* james@bpgc.com: read the next block, and - copy the split de into a newly kmalloc'd - buffer */ - block = isofs_bmap(dir,f_pos>>bufbits); - if (!block || - !(bh_next = bread(dir->i_dev,block,bufsize))) - break; - - de = (struct iso_directory_record *) - kmalloc(offset - old_offset, GFP_KERNEL); - if(de==NULL) - break; - memcpy((char *)de, bh->b_data + old_offset, - bufsize - old_offset); - memcpy((char *)de + bufsize - old_offset, - bh_next->b_data, offset - bufsize); - brelse(bh_next); - de_not_in_buf = 1; - offset -= bufsize; + int slop = bufsize - offset + de_len; + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; + brelse(bh); + bh = NULL; + if (offset) { + bh = isofs_bread(dir, bufsize, block); + if (!bh) + return 0; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } + dlen = de->name_len[0]; dpnt = de->name; - if (dir->i_sb->u.isofs_sb.s_rock || - dir->i_sb->u.isofs_sb.s_joliet_level || - dir->i_sb->u.isofs_sb.s_mapping == 'n' || - dir->i_sb->u.isofs_sb.s_mapping == 'a') { - if (! page) { - page = (unsigned char *) - __get_free_page(GFP_KERNEL); - if (!page) break; - } - } if (dir->i_sb->u.isofs_sb.s_rock && - ((i = get_rock_ridge_filename(de, page, dir)))) { - dlen = i; - dpnt = page; + ((i = get_rock_ridge_filename(de, tmpname, dir)))) { + dlen = i; /* possibly -1 */ + dpnt = tmpname; #ifdef CONFIG_JOLIET } else if (dir->i_sb->u.isofs_sb.s_joliet_level) { - dlen = get_joliet_filename(de, dir, page); - dpnt = page; + dlen = get_joliet_filename(de, tmpname, dir); + dpnt = tmpname; #endif } else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') { - dlen = get_acorn_filename(de, page, dir); - dpnt = page; + dlen = get_acorn_filename(de, tmpname, dir); + dpnt = tmpname; } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') { - for (i = 0; i < dlen; i++) { - c = dpnt[i]; - /* lower case */ - if (c >= 'A' && c <= 'Z') c |= 0x20; - if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') { - dlen -= 2; - break; - } - if (c == ';') c = '.'; - page[i] = c; - } - /* This allows us to match with and without - * a trailing period. */ - if(page[dlen-1] == '.' && dentry->d_name.len == dlen-1) - dlen--; - dpnt = page; + dlen = isofs_name_translate(de, tmpname, dir); + dpnt = tmpname; } + /* * Skip hidden or associated files unless unhide is set */ match = 0; - if ((!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5) - || dir->i_sb->u.isofs_sb.s_unhide == 'y') && dlen) + if (dlen > 0 && + (!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5) + || dir->i_sb->u.isofs_sb.s_unhide == 'y')) { match = (isofs_cmp(dentry,dpnt,dlen) == 0); } if (match) { - if(inode_number == -1) { - /* Should only happen for the '..' entry */ - inode_number = - isofs_lookup_grandparent(dir, - find_rock_ridge_relocation(de,dir)); - } - *ino = inode_number; - retval = bh; - bh = NULL; - break; + if (bh) + brelse(bh); + return inode_number; } } - if (page) free_page((unsigned long) page); - if (bh) brelse(bh); - if(de_not_in_buf) - kfree(de); - return retval; + if (bh) + brelse(bh); + return 0; } struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry) { unsigned long ino; - struct buffer_head * bh; struct inode *inode; + char *page; + struct iso_directory_record * tmpde; -#ifdef DEBUG - printk("lookup: %x %s\n",dir->i_ino, dentry->d_name.name); -#endif dentry->d_op = dir->i_sb->s_root->d_op; - bh = isofs_find_entry(dir, dentry, &ino); + page = (char *) __get_free_page(GFP_USER); + if (!page) + return ERR_PTR(-ENOMEM); + tmpde = (struct iso_directory_record *) (page+1024); - inode = NULL; - if (bh) { - brelse(bh); + ino = isofs_find_entry(dir, dentry, page, tmpde); + free_page((unsigned long) page); - inode = iget(dir->i_sb,ino); + inode = NULL; + if (ino) { + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); } diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/rock.c ./linux/fs/isofs/rock.c --- ../linux-2.2.18pre23/linux/fs/isofs/rock.c Tue Jan 4 19:12:23 2000 +++ ./linux/fs/isofs/rock.c Sun Nov 26 23:20:34 2000 @@ -70,7 +70,7 @@ cont_size = 0; \ cont_offset = 0; \ goto LABEL; \ - }; \ + } \ printk("Unable to read rock-ridge attributes\n"); \ }} @@ -118,22 +118,16 @@ CHECK_SP(goto out); break; case SIG('C','L'): -#ifdef DEBUG - printk("RR: CL\n"); -#endif if (flag == 0) { retval = isonum_733(rr->u.CL.location); goto out; - }; + } break; case SIG('P','L'): -#ifdef DEBUG - printk("RR: PL\n"); -#endif if (flag != 0) { retval = isonum_733(rr->u.PL.location); goto out; - }; + } break; case SIG('C','E'): CHECK_CE; /* This tells is if there is a continuation record */ @@ -141,8 +135,8 @@ default: break; } - }; - }; + } + } MAYBE_CONTINUE(repeat, inode); return retval; out: @@ -150,6 +144,7 @@ return retval; } +/* return length of name field; 0: not found, -1: to be ignored */ int get_rock_ridge_filename(struct iso_directory_record * de, char * retname, struct inode * inode) { @@ -200,24 +195,21 @@ if (rr->u.NM.flags & ~1) { printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags); break; - }; + } if((strlen(retname) + rr->len - 5) >= 254) { truncate = 1; break; - }; + } strncat(retname, rr->u.NM.name, rr->len - 5); retnamlen += rr->len - 5; break; case SIG('R','E'): -#ifdef DEBUG - printk("RR: RE (%x)\n", inode->i_ino); -#endif if (buffer) kfree(buffer); return -1; default: break; } - }; + } } MAYBE_CONTINUE(repeat,inode); return retnamlen; /* If 0, this file did not have a NM field */ @@ -263,10 +255,10 @@ break; case SIG('E','R'): inode->i_sb->u.isofs_sb.s_rock = 1; - printk(KERN_DEBUG"ISO 9660 Extensions: "); + printk(KERN_DEBUG "ISO 9660 Extensions: "); { int p; for(p=0;pu.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); - }; + } printk("\n"); break; case SIG('P','X'): @@ -337,27 +329,24 @@ slp = (struct SL_component *) (((char *) slp) + slp->len + 2); if(slen < 2) { - if( ((rr->u.SL.flags & 1) != 0) - && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; + if((rr->u.SL.flags & 1) != 0 && (oldslp->flags & 1) == 0) + inode->i_size += 1; break; } /* * If this component record isn't continued, then append a '/'. */ - if( (!rootflag) - && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; + if(!rootflag && (oldslp->flags & 1) == 0) + inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R','E'): - printk("Attempt to read inode for relocated directory\n"); + printk(KERN_WARNING "Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): -#ifdef DEBUG - printk("RR CL (%x)\n",inode->i_ino); -#endif inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); reloc = iget(inode->i_sb, (inode->u.isofs_i.i_first_extent << @@ -378,7 +367,7 @@ default: break; } - }; + } } MAYBE_CONTINUE(repeat,inode); return 0; diff -u --recursive --new-file ../linux-2.2.18pre23/linux/fs/isofs/util.c ./linux/fs/isofs/util.c --- ../linux-2.2.18pre23/linux/fs/isofs/util.c Wed Jun 24 23:30:10 1998 +++ ./linux/fs/isofs/util.c Sun Nov 26 23:12:58 2000 @@ -98,7 +98,7 @@ int iso_date(char * p, int flag) { - int year, month, day, hour ,minute, second, tz; + int year, month, day, hour, minute, second, tz; int crtime, days, i; year = p[0] - 70; @@ -114,7 +114,6 @@ crtime = 0; } else { int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; - extern struct timezone sys_tz; days = year * 365; if (year > 2) @@ -126,8 +125,6 @@ days += day - 1; crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; - if (sys_tz.tz_dsttime) - crtime -= 3600; /* sign extend */ if (tz & 0x80) @@ -149,7 +146,7 @@ * NOTE: mkisofs in versions prior to mkisofs-1.10 had * the sign wrong on the timezone offset. This has now * been corrected there too, but if you are getting screwy - * results this may be the explaination. If enough people + * results this may be the explanation. If enough people * complain, a user configuration option could be added * to add the timezone offset in with the wrong sign * for 'compatibility' with older discs, but I cannot see how diff -u --recursive --new-file ../linux-2.2.18pre23/linux/include/linux/iso_fs.h ./linux/include/linux/iso_fs.h --- ../linux-2.2.18pre23/linux/include/linux/iso_fs.h Sat Apr 24 06:20:38 1999 +++ ./linux/include/linux/iso_fs.h Mon Nov 27 00:47:12 2000 @@ -177,41 +177,22 @@ extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); +extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); extern char * get_rock_ridge_symlink(struct inode *); -extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *); -int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *); +extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *); +int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); -/* The stuff that follows may be totally unneeded. I have not checked to see - which prototypes we are still using. */ - -extern int isofs_open(struct inode * inode, struct file * filp); -extern void isofs_release(struct inode * inode, struct file * filp); extern struct dentry *isofs_lookup(struct inode * dir, struct dentry *); -extern unsigned long isofs_count_free_inodes(struct super_block *sb); -extern int isofs_new_block(int dev); -extern int isofs_free_block(int dev, int block); extern int isofs_bmap(struct inode *,int); - -extern void isofs_put_super(struct super_block *); -extern struct super_block *isofs_read_super(struct super_block *,void *,int); +extern struct buffer_head *isofs_bread(struct inode *, unsigned int, unsigned int); extern int init_iso9660_fs(void); -extern void isofs_read_inode(struct inode *); -extern void isofs_put_inode(struct inode *); -extern int isofs_statfs(struct super_block *, struct statfs *, int); - -extern int isofs_lseek(struct inode *, struct file *, off_t, int); -extern int isofs_read(struct inode *, struct file *, char *, int); -extern int isofs_lookup_grandparent(struct inode *, int); extern struct inode_operations isofs_file_inode_operations; extern struct inode_operations isofs_dir_inode_operations; extern struct inode_operations isofs_symlink_inode_operations; -extern struct inode_operations isofs_chrdev_inode_operations; -extern struct inode_operations isofs_blkdev_inode_operations; -extern struct inode_operations isofs_fifo_inode_operations; /* The following macros are used to check for memory leaks. */ #ifdef LEAK_CHECK