summaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
commit545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch)
treee9ce4bc598d06374bda906f18365984bf22a526a /fs/isofs
parent4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff)
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/dir.c5
-rw-r--r--fs/isofs/inode.c2
-rw-r--r--fs/isofs/namei.c68
-rw-r--r--fs/isofs/symlink.c20
4 files changed, 79 insertions, 16 deletions
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 48321d356..a198141d8 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -23,7 +23,7 @@
#include <asm/uaccess.h>
-static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
+static int isofs_readdir(struct file *, void *, filldir_t);
static struct file_operations isofs_dir_operations =
{
@@ -241,12 +241,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
* handling split directory entries.. The real work is done by
* "do_isofs_readdir()".
*/
-static int isofs_readdir(struct inode *inode, struct file *filp,
+static int isofs_readdir(struct file *filp,
void *dirent, filldir_t filldir)
{
int result;
char * tmpname;
struct iso_directory_record * tmpde;
+ struct inode *inode = filp->f_dentry->d_inode;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 436c22140..a925159bf 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -613,6 +613,7 @@ 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;
/* There are defective discs out there - we do this to protect
ourselves. A cdrom will never contain more than 800Mb */
@@ -736,6 +737,7 @@ void isofs_read_inode(struct inode * inode)
inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
inode->u.isofs_i.i_first_extent = 0;
inode->i_size = 0;
+ inode->i_blocks = inode->i_blksize = 0;
inode->i_nlink = 1;
inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFREG; /*Regular file, no one gets to read*/
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 1c0be7fde..99555835b 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -63,12 +63,14 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
- unsigned int block, i, f_pos, offset, inode_number;
+ unsigned int block, i, f_pos, offset,
+ inode_number = 0; /* shut gcc up */
struct buffer_head * bh;
unsigned int old_offset;
int dlen, rrflag, match;
char * dpnt;
- struct iso_directory_record * de;
+ 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;
@@ -84,17 +86,36 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL;
while (f_pos < dir->i_size) {
- de = (struct iso_directory_record *) (bh->b_data + offset);
- inode_number = (block << bufbits) + (offset & (bufsize - 1));
- /* If byte is zero, this is the end of file, or time to move to
- the next sector. Usually 2048 byte boundaries. */
+ /* 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) {
+ 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);
+ offset -= bufsize;
+ }
+ else
+ offset = 0;
brelse(bh);
- offset = 0;
f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
- + ISOFS_BLOCK_SIZE);
+ + ISOFS_BLOCK_SIZE) + offset;
if( f_pos >= dir->i_size )
{
@@ -111,11 +132,28 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
offset += *((unsigned char *) de);
f_pos += *((unsigned char *) de);
- /* Handle case where the directory entry spans two blocks.
- Usually 1024 byte boundaries */
+ /* james@bpgc.com: new code to handle case where the
+ directory entry spans two blocks. Usually 1024
+ byte boundaries */
if (offset >= bufsize) {
- printk("Directory entry extends past end of iso9660 block\n");
- return 0;
+ 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)))
+ return NULL;
+
+ de = (struct iso_directory_record *)
+ kmalloc(offset - old_offset, GFP_KERNEL);
+ 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;
}
dlen = de->name_len[0];
@@ -161,11 +199,15 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
find_rock_ridge_relocation(de,dir));
}
*ino = inode_number;
+ if(de_not_in_buf)
+ kfree(de);
return bh;
}
}
out:
brelse(bh);
+ if(de_not_in_buf)
+ kfree(de);
return NULL;
}
diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c
index f49bc3ee3..c88c56760 100644
--- a/fs/isofs/symlink.c
+++ b/fs/isofs/symlink.c
@@ -19,6 +19,7 @@
#include <asm/uaccess.h>
static int isofs_readlink(struct inode *, char *, int);
+static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base);
/*
* symlinks can't do much...
@@ -35,6 +36,7 @@ struct inode_operations isofs_symlink_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
isofs_readlink, /* readlink */
+ isofs_follow_link, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
@@ -51,7 +53,6 @@ static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
buflen = 1023;
pnt = get_rock_ridge_symlink(inode);
- iput(inode);
if (!pnt)
return 0;
@@ -63,3 +64,20 @@ static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
kfree(pnt);
return i;
}
+
+static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base)
+{
+ char * pnt;
+
+ pnt = get_rock_ridge_symlink(inode);
+
+ if(!pnt) {
+ dput(base);
+ return ERR_PTR(-ELOOP);
+ }
+
+ base = lookup_dentry(pnt, base, 1);
+
+ kfree(pnt);
+ return base;
+}