Messages in this thread Patch in this message | | | Date | Thu, 28 Oct 1999 16:00:52 +0100 (BST) | From | Richard A Frewin - QMW <> | Subject | Change to fs/isofs/dir.c |
| |
Hi,
I'll lay my cards on the table right away - a) I'm not a kernel hacker (so I really don't understand what I'm doing), b) this patch has not been tested widely and c) it's not really all that important anyway, however ....
I have a set of Voyager data CDs from NASA which, I think, were burned on a VAX (they claim to conform to the ISO 9660 standard; some of the files are "record structured" which Linux sees OK [Solaris still breaks over these]). Under the 2.0 kernels all was fine but after upgrading to Red Hat 6.0 some of the directory entries on the CDs vanished. All the files can still be accessed (if you know the names) it's just that long directory listings are truncated and errors of the form
kernel: next_offset (20c) > bufsize (200)
appear in syslog.
Hunting about in fs/isofs/dir.c I think I've found the relevant bit of code that changed between 2.0 and 2.2 (in fact in 2.1.32) - the 2.0 code has a comment
/* Make sure that the entire directory record is in the current bh block. If not, put the two halves together in "tmpde" */
which has changed to
* 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.
Knowing NASA, I would not be surprised if they were producing "buggy cdrom image"s but .....
Anyway, I've generated a small patch to fs/isofs/dir.c that reverses this which applies cleanly to 2.2.5 and 2.2.12 (it should also apply to 2.3.X as it looks like fs/isofs/dir.c has remained mostly unchanged).
I have no idea if this is the correct way to do this directory record "reassembly" in 2.2 it just "Works For Me"[tm] (as I said, I'm not a kernel hacker and the patch has not been extensively tested).
I'd be pleased to hear your comments. (I'm no longer subscribed to linux-kernel as may mailbox can't take the strain and I don't have time to read it all anymore - so could you please send comments to star@qmw.ac.uk).
Many thanks for your time,
Richard.
_______________________________________________________________ Richard A. Frewin Email: star@qmw.ac.uk QMW Starlink Site Manager Tel: 0171 975 5053 Physics Department Fax: 0181 981 9465 Queen Mary and Westfield College http://www-star.qmw.ac.uk/ Mile End Road London E1 4NS [JoaT(MoN)]
--- fs/isofs/dir.c-2.2.5 Wed Oct 6 16:16:17 1999 +++ fs/isofs/dir.c Wed Oct 6 15:33:18 1999 @@ -151,7 +151,7 @@ return 0; while (filp->f_pos < inode->i_size) { - int de_len; + int de_len, next_offset; #ifdef DEBUG printk("Block, offset, f_pos: %x %x %x\n", block, offset, filp->f_pos); @@ -193,18 +193,40 @@ 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; + /* Make sure that the entire directory record is in the + current bh block. + If not, put the two halves together in "tmpde" */ + next_offset = offset + de_len; + if (next_offset > bufsize) { +#ifdef DEBUG + printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize); +#endif + next_offset &= (bufsize - 1); + memcpy(tmpde, de, bufsize - offset); + brelse(bh); + block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits); + if (!block) + { + return 0; + } + + bh = breada(inode->i_dev, block, bufsize, + filp->f_pos, + inode->i_size); + if (!bh) + { +#ifdef DEBUG + printk("!bh block=%ld, bufsize=%ld\n",block,bufsize); + printk("filp->f_pos = %ld\n",filp->f_pos); + printk("inode->i_size = %ld\n", inode->i_size); +#endif + return 0; + } + + memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset); + de = tmpde; } + offset = next_offset; if(de->flags[-high_sierra] & 0x80) { first_de = 0; | |