From 07e8059de69d387ee281ed8b8d66b66810244b50 Mon Sep 17 00:00:00 2001 From: Mike Shaver Date: Tue, 16 Sep 1997 20:51:16 +0000 Subject: 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. --- fs/efs/Makefile | 2 +- fs/efs/dir.c | 173 ++++++++++++++++++++++++++++--------------------------- fs/efs/inode.c | 6 +- fs/efs/namei.c | 10 ++-- fs/efs/symlink.c | 138 +++++++++++++++++++++++--------------------- 5 files changed, 169 insertions(+), 160 deletions(-) (limited to 'fs') 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<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<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<f_pos = (block<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;iextents[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 (ib_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 (ib_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; } + -- cgit v1.2.3