summaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /fs/isofs
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/.cvsignore1
-rw-r--r--fs/isofs/dir.c16
-rw-r--r--fs/isofs/inode.c175
-rw-r--r--fs/isofs/symlink.c14
4 files changed, 162 insertions, 44 deletions
diff --git a/fs/isofs/.cvsignore b/fs/isofs/.cvsignore
index 4671378ae..857dd22e9 100644
--- a/fs/isofs/.cvsignore
+++ b/fs/isofs/.cvsignore
@@ -1 +1,2 @@
.depend
+.*.flags
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 79d49a858..bddbe4ba6 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -101,11 +101,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
unsigned int block, offset;
- int inode_number;
+ int inode_number = 0; /* Quiet GCC */
struct buffer_head *bh;
int len;
int map;
- int high_sierra = 0;
+ int high_sierra;
+ int first_de = 1;
char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de;
@@ -114,6 +115,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
offset = filp->f_pos & (bufsize - 1);
block = isofs_bmap(inode, filp->f_pos >> bufbits);
+ high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
if (!block)
return 0;
@@ -129,7 +131,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
printk("inode->i_size = %x\n",inode->i_size);
#endif
de = (struct iso_directory_record *) (bh->b_data + offset);
- inode_number = (block << bufbits) + (offset & (bufsize - 1));
+ if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
de_len = *(unsigned char *) de;
#ifdef DEBUG
@@ -177,6 +179,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
break;
}
+ if(de->flags[-high_sierra] & 0x80) {
+ first_de = 0;
+ filp->f_pos += de_len;
+ continue;
+ }
+ first_de = 1;
+
/* Handle the case of the '.' directory */
if (de->name_len[0] == 1 && de->name[0] == 0) {
if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
@@ -200,7 +209,6 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
is no Rock Ridge NM field. */
if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
/* Do not report hidden or associated files */
- high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
if (de->flags[-high_sierra] & 5) {
filp->f_pos += de_len;
continue;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 9445b921e..5e2802365 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -5,7 +5,8 @@
* 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem.
* 1994 Eberhard Moenkeberg - multi session handling.
* 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
- *
+ * 1997 Gordon Chaffee - Joliet CDs
+ * 1998 Eric Lammerts - ISO9660 Level 3
*/
#include <linux/config.h>
@@ -79,7 +80,6 @@ struct iso9660_options{
char cruft;
char unhide;
unsigned char check;
- unsigned char conversion;
unsigned int blocksize;
mode_t mode;
gid_t gid;
@@ -98,7 +98,6 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt->cruft = 'n';
popt->unhide = 'n';
popt->check = 's'; /* default: strict */
- popt->conversion = 'b'; /* default: no conversion */
popt->blocksize = 1024;
popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could
be shared with DOS machines so
@@ -166,12 +165,14 @@ static int parse_options(char *options, struct iso9660_options * popt)
else return 0;
}
else if (!strcmp(this_char,"conv") && value) {
- if (value[0] && !value[1] && strchr("btma",*value))
- popt->conversion = *value;
- else if (!strcmp(value,"binary")) popt->conversion = 'b';
- else if (!strcmp(value,"text")) popt->conversion = 't';
- else if (!strcmp(value,"mtext")) popt->conversion = 'm';
- else if (!strcmp(value,"auto")) popt->conversion = 'a';
+ /* no conversion is done anymore;
+ we still accept the same mount options,
+ but ignore them */
+ if (value[0] && !value[1] && strchr("btma",*value)) ;
+ else if (!strcmp(value,"binary")) ;
+ else if (!strcmp(value,"text")) ;
+ else if (!strcmp(value,"mtext")) ;
+ else if (!strcmp(value,"auto")) ;
else return 0;
}
else if (value &&
@@ -254,17 +255,17 @@ static unsigned int isofs_get_last_session(kdev_t dev)
printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
}
-#endif 0
+#endif
if (i==0)
#if WE_OBEY_THE_WRITTEN_STANDARDS
if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
-#endif WE_OBEY_THE_WRITTEN_STANDARDS
+#endif
vol_desc_start=ms_info.addr.lba;
}
return vol_desc_start;
}
-struct super_block *isofs_read_super(struct super_block *s,void *data,
+struct super_block *isofs_read_super(struct super_block *s, void *data,
int silent)
{
struct buffer_head * bh = NULL;
@@ -301,7 +302,6 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
printk("check = %c\n", opt.check);
printk("cruft = %c\n", opt.cruft);
printk("unhide = %c\n", opt.unhide);
- printk("conversion = %c\n", opt.conversion);
printk("blocksize = %d\n", opt.blocksize);
printk("gid = %d\n", opt.gid);
printk("uid = %d\n", opt.uid);
@@ -571,7 +571,6 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->u.isofs_sb.s_mapping = opt.map;
s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0);
s->u.isofs_sb.s_name_check = opt.check;
- s->u.isofs_sb.s_conversion = opt.conversion;
s->u.isofs_sb.s_cruft = opt.cruft;
s->u.isofs_sb.s_unhide = opt.unhide;
s->u.isofs_sb.s_uid = opt.uid;
@@ -657,17 +656,24 @@ int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
int isofs_bmap(struct inode * inode,int block)
{
+ off_t b_off, offset, size;
+ struct inode *ino;
+ unsigned int firstext;
+ unsigned long nextino;
+ int i;
if (block<0) {
printk("_isofs_bmap: block<0");
return 0;
}
+ b_off = block << ISOFS_BUFFER_BITS(inode);
+
/*
* If we are beyond the end of this file, don't give out any
* blocks.
*/
- if( (block << ISOFS_BUFFER_BITS(inode)) >= inode->i_size )
+ if( b_off > inode->i_size )
{
off_t max_legal_read_offset;
@@ -681,7 +687,7 @@ int isofs_bmap(struct inode * inode,int block)
*/
max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
& ~(PAGE_SIZE - 1);
- if( (block << ISOFS_BUFFER_BITS(inode)) >= max_legal_read_offset )
+ if( b_off >= max_legal_read_offset )
{
printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block,
@@ -690,7 +696,42 @@ int isofs_bmap(struct inode * inode,int block)
return 0;
}
- return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
+ offset = 0;
+ 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=%lu nextino=%lu firstext=%u size=%lu\n",
+ inode->i_ino, nextino, firstext, size);
+#endif
+ i = 0;
+ while(b_off >= offset + size) {
+ offset += size;
+
+ if(nextino == 0) return 0;
+ ino = iget(inode->i_sb, nextino);
+ 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);
+
+ if(++i > 100) {
+ printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n");
+ printk("isofs_bmap: ino=%lu block=%d firstext=%u size=%u nextino=%lu\n",
+ inode->i_ino, block, firstext, (unsigned)size, nextino);
+ return 0;
+ }
+ }
+#ifdef DEBUG
+ printk("isofs_bmap: mapped inode:block %lu:%d to block %lu\n",
+ inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode));
+#endif
+ return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
}
@@ -704,6 +745,82 @@ static void test_and_set_uid(uid_t *p, uid_t value)
}
}
+static int isofs_read_level3_size(struct inode * inode)
+{
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ struct buffer_head * bh = NULL;
+ struct iso_directory_record * raw_inode = NULL; /* quiet gcc */
+ unsigned char *pnt = NULL;
+ void *cpnt = NULL;
+ int block = 0; /* Quiet GCC */
+ unsigned long ino;
+ int i;
+
+ inode->i_size = 0;
+ inode->u.isofs_i.i_next_section_ino = 0;
+ ino = inode->i_ino;
+ i = 0;
+ do {
+ if(i > 100) {
+ printk("isofs_read_level3_size: More than 100 file sections ?!?, aborting...\n"
+ "isofs_read_level3_size: inode=%lu ino=%lu\n", inode->i_ino, ino);
+ return 0;
+ }
+
+ if(bh == NULL || block != ino >> ISOFS_BUFFER_BITS(inode)) {
+ if(bh) brelse(bh);
+ block = ino >> ISOFS_BUFFER_BITS(inode);
+ if (!(bh=bread(inode->i_dev,block, bufsize))) {
+ printk("unable to read i-node block");
+ return 1;
+ }
+ }
+ pnt = ((unsigned char *) bh->b_data
+ + (ino & (bufsize - 1)));
+
+ if ((ino & (bufsize - 1)) + *pnt > bufsize){
+ int frag1, offset;
+
+ offset = (ino & (bufsize - 1));
+ frag1 = bufsize - offset;
+ cpnt = kmalloc(*pnt,GFP_KERNEL);
+ if (cpnt == NULL) {
+ printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
+ brelse(bh);
+ return 1;
+ }
+ memcpy(cpnt, bh->b_data + offset, frag1);
+ brelse(bh);
+ if (!(bh = bread(inode->i_dev,++block, bufsize))) {
+ kfree(cpnt);
+ printk("unable to read i-node block");
+ return 1;
+ }
+ offset += *pnt - bufsize;
+ memcpy((char *)cpnt+frag1, bh->b_data, offset);
+ pnt = ((unsigned char *) cpnt);
+ }
+
+ if(*pnt == 0) {
+ ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE;
+ continue;
+ }
+ raw_inode = ((struct iso_directory_record *) pnt);
+
+ inode->i_size += isonum_733 (raw_inode->size);
+ if(i == 1) inode->u.isofs_i.i_next_section_ino = ino;
+
+ ino += *pnt;
+ if (cpnt) {
+ kfree (cpnt);
+ cpnt = NULL;
+ }
+ i++;
+ } while(raw_inode->flags[-inode->i_sb->u.isofs_sb.s_high_sierra] & 0x80);
+ brelse(bh);
+ return 0;
+}
+
void isofs_read_inode(struct inode * inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
@@ -746,9 +863,16 @@ void isofs_read_inode(struct inode * inode)
}
inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
- inode->i_size = isonum_733 (raw_inode->size);
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) {
+ if(isofs_read_level3_size(inode)) goto fail;
+ } else {
+ inode->i_size = isonum_733 (raw_inode->size);
+ }
+
/* There are defective discs out there - we do this to protect
ourselves. A cdrom will never contain more than 800Mb */
if((inode->i_size < 0 || inode->i_size > 800000000) &&
@@ -799,21 +923,6 @@ void isofs_read_inode(struct inode * inode)
isonum_711 (raw_inode->ext_attr_length))
<< inode -> i_sb -> u.isofs_sb.s_log_zone_size;
- switch (inode->i_sb->u.isofs_sb.s_conversion){
- case 'a':
- inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
- break;
- case 'b':
- inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
- break;
- case 't':
- inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
- break;
- case 'm':
- inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
- break;
- }
-
/* Now test for possible Rock Ridge extensions which will override some of
these numbers in the inode structure. */
diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c
index 5321e011a..fe4abb987 100644
--- a/fs/isofs/symlink.c
+++ b/fs/isofs/symlink.c
@@ -18,8 +18,8 @@
#include <asm/uaccess.h>
-static int isofs_readlink(struct inode *, char *, int);
-static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base);
+static int isofs_readlink(struct dentry *, char *, int);
+static struct dentry * isofs_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
@@ -44,14 +44,14 @@ struct inode_operations isofs_symlink_inode_operations = {
NULL /* permission */
};
-static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
+static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
char * pnt;
int i;
if (buflen > 1023)
buflen = 1023;
- pnt = get_rock_ridge_symlink(inode);
+ pnt = get_rock_ridge_symlink(dentry->d_inode);
if (!pnt)
return 0;
@@ -65,12 +65,12 @@ static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
return i;
}
-static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base)
+static struct dentry * isofs_follow_link(struct dentry * dentry,
+ struct dentry *base)
{
char * pnt;
- pnt = get_rock_ridge_symlink(inode);
-
+ pnt = get_rock_ridge_symlink(dentry->d_inode);
if(!pnt) {
dput(base);
return ERR_PTR(-ELOOP);