summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMike Shaver <shaver@ingenia.com>1997-09-16 20:51:16 +0000
committerMike Shaver <shaver@ingenia.com>1997-09-16 20:51:16 +0000
commit07e8059de69d387ee281ed8b8d66b66810244b50 (patch)
tree9123ada8119208544537a8019c2197dc4d80b81c /fs
parent4344cfb77cdc787c82a7076a50172240f82d6d38 (diff)
namei.c: - Support symlinks correctly.
inode.c: - Formatting, minor change to start supporting indirect extents. dir.c: - Prevent access to an indirect directory from hosing the system. *.h: - Add forgotten include files.
Diffstat (limited to 'fs')
-rw-r--r--fs/efs/Makefile2
-rw-r--r--fs/efs/dir.c173
-rw-r--r--fs/efs/inode.c6
-rw-r--r--fs/efs/namei.c10
-rw-r--r--fs/efs/symlink.c138
5 files changed, 169 insertions, 160 deletions
diff --git a/fs/efs/Makefile b/fs/efs/Makefile
index 049456899..5a8556795 100644
--- a/fs/efs/Makefile
+++ b/fs/efs/Makefile
@@ -7,7 +7,7 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-# CFLAGS+=-g -DDEBUG_EFS
+#CFLAGS+=-g -DDEBUG_EFS
O_TARGET := efs.o
O_OBJS := dir.o file.o inode.o namei.o \
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index fa07a298f..a89dd304e 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -17,35 +17,35 @@ static int efs_readdir(struct file *,void *,filldir_t);
extern int efs_lookup(struct inode *, struct dentry *);
static struct file_operations efs_dir_ops = {
- NULL,
- NULL,
- NULL,
- efs_readdir,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ NULL,
+ NULL,
+ NULL,
+ efs_readdir,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
struct inode_operations efs_dir_in_ops = {
- &efs_dir_ops,
- NULL,
- efs_lookup,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- efs_bmap,
- NULL,
- NULL
+ &efs_dir_ops,
+ NULL,
+ efs_lookup,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ efs_bmap,
+ NULL,
+ NULL
};
@@ -61,72 +61,77 @@ struct inode_operations efs_dir_in_ops = {
return - 0 ok, <0 error
*/
static int efs_readdir(struct file *filp,
- void *dirent, filldir_t filldir)
+ void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
- struct efs_inode_info *ini = (struct efs_inode_info *)&inode->u.efs_i;
- struct buffer_head *bh;
- __u8 *rawdirblk;
- __u32 iteminode;
- __u16 namelen;
- __u8 *nameptr;
- __u32 numitems;
- __u16 itemnum;
- __u32 block;
- __u16 rawdepos;
-
- /* some checks */
- if(!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
- return -EBADF;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct efs_inode_info *ini = (struct efs_inode_info *)&inode->u.efs_i;
+ struct buffer_head *bh;
+ __u8 *rawdirblk;
+ __u32 iteminode;
+ __u16 namelen;
+ __u8 *nameptr;
+ __u32 numitems;
+ __u16 itemnum;
+ __u32 block;
+ __u16 rawdepos;
+
+ /* some checks */
+ if(!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
+ return -EBADF;
- /* Warnings */
- if(ini->tot!=1)
- printk("efs_readdir: More than one extent!\n");
- if(inode->i_size & (EFS_BLOCK_SIZE-1))
- printk("efs_readdir: dirsize != blocksize*n\n");
-
- /* f_pos contains: dirblock<<BLOCK_SIZE | # of item in dirblock */
- block = filp->f_pos >> EFS_BLOCK_SIZE_BITS;
- itemnum = filp->f_pos & 0xff;
+ /* Warnings */
+ if(ini->tot!=1) {
+ printk("EFS: directory %s has more than one extent.\n",
+ filp->f_dentry->d_name.name);
+ printk("EFS: Mike is lazy, so we can't handle this yet. Sorry =(\n");
+ return 0;
+ }
+ if(inode->i_size & (EFS_BLOCK_SIZE-1))
+ printk("efs_readdir: dirsize != blocksize*n\n");
+
+ /* f_pos contains: dirblock<<BLOCK_SIZE | # of item in dirblock */
+ block = filp->f_pos >> EFS_BLOCK_SIZE_BITS;
+ itemnum = filp->f_pos & 0xff;
- /* We found the last entry -> ready */
- if(block == (inode->i_size>>EFS_BLOCK_SIZE_BITS))
- return 0;
-
- /* get disc block number from dir block num: 0..i_size/BLOCK_SIZE */
- bh = bread(inode->i_dev,efs_bmap(inode,block),EFS_BLOCK_SIZE);
- if(!bh) return 0;
-
- /* dirblock */
- rawdirblk = (__u8 *)bh->b_data;
- /* number of entries stored in this dirblock */
- numitems = rawdirblk[EFS_DB_ENTRIES];
- /* offset in block of #off diritem */
- rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+itemnum]<<1;
-
- /* diritem first contains the inode number, the namelen and the name */
- iteminode = ConvertLong(rawdirblk,rawdepos);
- namelen = (__u16)rawdirblk[rawdepos+EFS_DI_NAMELEN];
- nameptr = rawdirblk + rawdepos + EFS_DI_NAME;
-
-#ifdef DEBUG
- printk("efs: dir #%d @ %0#3x - inode %lx %s namelen %u\n",itemnum,rawdepos,iteminode,nameptr,namelen);
+ /* We found the last entry -> ready */
+ if(block == (inode->i_size>>EFS_BLOCK_SIZE_BITS))
+ return 0;
+
+ /* get disc block number from dir block num: 0..i_size/BLOCK_SIZE */
+ bh = bread(inode->i_dev,efs_bmap(inode,block),EFS_BLOCK_SIZE);
+ if(!bh) return 0;
+
+ /* dirblock */
+ rawdirblk = (__u8 *)bh->b_data;
+ /* number of entries stored in this dirblock */
+ numitems = rawdirblk[EFS_DB_ENTRIES];
+ /* offset in block of #off diritem */
+ rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+itemnum]<<1;
+
+ /* diritem first contains the inode number, the namelen and the name */
+ iteminode = ConvertLong(rawdirblk,rawdepos);
+ namelen = (__u16)rawdirblk[rawdepos+EFS_DI_NAMELEN];
+ nameptr = rawdirblk + rawdepos + EFS_DI_NAME;
+
+#ifdef DEBUG_EFS
+ printk("efs: dir #%d @ %0#3x - inode %lx %s namelen %u\n",
+ itemnum,rawdepos,iteminode,nameptr,namelen);
#endif
- /* copy filename and data in direntry */
- filldir(dirent,nameptr,namelen,filp->f_pos,iteminode);
+ /* copy filename and data in direntry */
+ filldir(dirent,nameptr,namelen,filp->f_pos,iteminode);
- brelse(bh);
+ brelse(bh);
/* store pos of next item */
- itemnum++;
- if(itemnum==numitems) {
- itemnum = 0;
- block++;
- }
- filp->f_pos = (block<<EFS_BLOCK_SIZE_BITS) | itemnum;
- UPDATE_ATIME(inode);
+ itemnum++;
+ if(itemnum==numitems) {
+ itemnum = 0;
+ block++;
+ }
+ filp->f_pos = (block<<EFS_BLOCK_SIZE_BITS) | itemnum;
+ UPDATE_ATIME(inode);
- return 0;
+ return 0;
}
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index b84231cd5..e8f38294d 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -415,16 +415,18 @@ void efs_read_inode(struct inode *in)
ini->extblk = sbi->fs_start + efs_swab32((__u32)(di->di_u.di_extents));
/* read INI_MAX_EXT extents from the indirect block */
+ printk("EFS: ");
bh2 = bread(in->i_dev,ini->extblk,EFS_BLOCK_SIZE);
if(bh2) {
- union efs_extent *ptr = (union efs_extent *)bh2->b_data;
+ union efs_extent *ptr =
+ (union efs_extent *)bh2->b_data;
for(i=0;i<EFS_MAX_EXTENTS;i++) {
ini->extents[i].ex_bytes[0] = efs_swab32(ptr[i].ex_bytes[0]);
ini->extents[i].ex_bytes[1] = efs_swab32(ptr[i].ex_bytes[1]);
}
brelse(bh2);
} else
- printk("efs: failed reading indirect extends!\n");
+ printk("efs: failed reading indirect extents!\n");
} else {
#ifdef DEBUG_EFS
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index 82086accd..752aa5fe1 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -84,7 +84,7 @@ static struct buffer_head * efs_find_entry(struct inode *dir,
entry_inode = efs_swab32(de->ud_inum.l);
namelen = de->d_namelen;
name = de->d_name;
-#ifdef DEBUG_EFS
+#ifdef 0
printk("EFS: entry %d @ %#x has inode %#x, %s/%d\n",
i, db_offset, entry_inode, name, namelen);
#endif
@@ -99,13 +99,11 @@ static struct buffer_head * efs_find_entry(struct inode *dir,
return bh;
}
}
+ }
#ifdef DEBUG_EFS
- printk("EFS: efs_find_entry didn't find inode for \"%s\"!\n",
- oname);
+ printk("EFS: efs_find_entry didn't find inode for \"%s\"/%d!\n",
+ oname, onamelen);
#endif
- return NULL;
- }
- printk("EFS: Falling off the end of efs_find_entry! Bogus!\n");
return NULL;
/* not reached */
}
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index 6197bb6f3..05e3c082d 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -45,45 +45,45 @@ struct inode_operations efs_symlink_in_ops = {
*/
static char *efs_getlinktarget(struct inode *in)
{
- struct buffer_head * bh;
- char *name;
- __u32 size = in->i_size;
- __u32 block;
+ struct buffer_head * bh;
+ char *name;
+ __u32 size = in->i_size;
+ __u32 block;
- /* link data longer than 1024 not supported */
- if(size>2*EFS_BLOCK_SIZE) {
- printk("efs_getlinktarget: name too long: %lu\n",in->i_size);
- return NULL;
- }
+ /* link data longer than 1024 not supported */
+ if(size>2*EFS_BLOCK_SIZE) {
+ printk("efs_getlinktarget: name too long: %lu\n",in->i_size);
+ return NULL;
+ }
- /* get some memory from the kernel to store the name */
- name = kmalloc(size+1,GFP_KERNEL);
- if(!name) return NULL;
+ /* get some memory from the kernel to store the name */
+ name = kmalloc(size+1,GFP_KERNEL);
+ if(!name) return NULL;
- /* read first 512 bytes of target */
- block = efs_bmap(in,0);
- bh = bread(in->i_dev,block,EFS_BLOCK_SIZE);
- if(!bh) {
- kfree(name);
- return NULL;
- }
- memcpy(name,bh->b_data,(size>EFS_BLOCK_SIZE)?EFS_BLOCK_SIZE:size);
- brelse(bh);
+ /* read first 512 bytes of target */
+ block = efs_bmap(in,0);
+ bh = bread(in->i_dev,block,EFS_BLOCK_SIZE);
+ if(!bh) {
+ kfree(name);
+ return NULL;
+ }
+ memcpy(name,bh->b_data,(size>EFS_BLOCK_SIZE)?EFS_BLOCK_SIZE:size);
+ brelse(bh);
- /* if the linktarget is long, read the next block */
- if(size>EFS_BLOCK_SIZE) {
- bh = bread(in->i_dev,block+1,EFS_BLOCK_SIZE);
- if(!bh) {
- kfree(name);
- return NULL;
- }
- memcpy(name+EFS_BLOCK_SIZE,bh->b_data,size-EFS_BLOCK_SIZE);
- brelse(bh);
- }
+ /* if the linktarget is long, read the next block */
+ if(size>EFS_BLOCK_SIZE) {
+ bh = bread(in->i_dev,block+1,EFS_BLOCK_SIZE);
+ if(!bh) {
+ kfree(name);
+ return NULL;
+ }
+ memcpy(name+EFS_BLOCK_SIZE,bh->b_data,size-EFS_BLOCK_SIZE);
+ brelse(bh);
+ }
- /* terminate string and return it */
- name[size]=0;
- return name;
+ /* terminate string and return it */
+ name[size]=0;
+ return name;
}
@@ -92,19 +92,16 @@ static char *efs_getlinktarget(struct inode *in)
*/
static struct dentry * efs_follow_link(struct inode * dir, struct dentry *base)
{
- struct buffer_head * bh;
- __u32 block;
-
- block = efs_bmap(dir,0);
- bh = bread(dir->i_dev,block,EFS_BLOCK_SIZE);
- if (!bh) {
- dput(base);
- return ERR_PTR(-EIO);
- }
- UPDATE_ATIME(dir);
- base = lookup_dentry(bh->b_data, base, 1);
- brelse(bh);
- return base;
+ char * name;
+ UPDATE_ATIME(dir);
+ name = efs_getlinktarget(dir);
+#ifdef DEBUG_EFS
+ printk("EFS: efs_getlinktarget(%d) returned \"%s\"\n",
+ dir->i_ino, name);
+#endif
+ base = lookup_dentry(name, base, 1);
+ kfree(name);
+ return base;
}
/* ----- efs_readlink -----
@@ -112,25 +109,32 @@ static struct dentry * efs_follow_link(struct inode * dir, struct dentry *base)
*/
static int efs_readlink(struct inode * dir, char * buffer, int buflen)
{
- int i;
- char c;
- struct buffer_head * bh;
- __u32 block;
-
- block = efs_bmap(dir,0);
- if (buflen > 1023)
- buflen = 1023;
- bh = bread(dir->i_dev,block,EFS_BLOCK_SIZE);
- if (!bh)
- return 0;
+ int i;
+ struct buffer_head * bh;
- /* copy the link target to the given buffer */
- i = 0;
- while (i<buflen && (c = bh->b_data[i])) {
- i++;
- put_user(c,buffer++);
- }
-
- brelse(bh);
- return i;
+ if (buflen > 1023)
+ buflen = 1023;
+ bh = bread(dir->i_dev,efs_bmap(dir,0),EFS_BLOCK_SIZE);
+ if (!bh)
+ return 0;
+ /* copy the link target to the given buffer */
+ i = 0;
+#ifdef DEBUG_EFS
+ printk("EFS: efs_readlink returning ");
+#endif
+ while (i<buflen && bh->b_data[i] && i < dir->i_size) {
+#ifdef DEBUG_EFS
+ printk("%c", bh->b_data[i]);
+#endif
+ i++;
+ }
+#ifdef DEBUG_EFS
+ printk("\n");
+#endif
+ if (copy_to_user(buffer, bh->b_data, i))
+ i = -EFAULT;
+
+ brelse(bh);
+ return i;
}
+