diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
commit | 545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch) | |
tree | e9ce4bc598d06374bda906f18365984bf22a526a /fs/isofs | |
parent | 4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (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.c | 5 | ||||
-rw-r--r-- | fs/isofs/inode.c | 2 | ||||
-rw-r--r-- | fs/isofs/namei.c | 68 | ||||
-rw-r--r-- | fs/isofs/symlink.c | 20 |
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; +} |