summaryrefslogtreecommitdiffstats
path: root/fs/efs/dir.c
diff options
context:
space:
mode:
authorMike Shaver <shaver@ingenia.com>1999-01-18 04:16:25 +0000
committerMike Shaver <shaver@ingenia.com>1999-01-18 04:16:25 +0000
commit6bafd683c6bd78f19df9a42aea24037137f913ce (patch)
tree7580dc3040c32da4048009721d60a7ac442962ca /fs/efs/dir.c
parent317b660279d583d4db3fc112e3ef2e56b20bec87 (diff)
EFS mark II. Incomplete, but much cleaner.
Diffstat (limited to 'fs/efs/dir.c')
-rw-r--r--fs/efs/dir.c239
1 files changed, 124 insertions, 115 deletions
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index a89dd304e..a31f6784a 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -1,137 +1,146 @@
-/* dir.c
-
- directory inode operations for EFS filesystem
-
- (C)95,96 Christian Vogelgsang
-*/
+/*
+ * linux/fs/efs/dir.c
+ *
+ * Copyright (C) 1998 Mike Shaver
+ *
+ * Portions derived from work (C) 1995,1996 Christian Vogelgsang.
+ * ``Inspired by'' fs/minix/dir.c.
+ */
#include <linux/string.h>
#include <linux/errno.h>
-#include <linux/fs.h>
#include <linux/efs_fs.h>
-#include <linux/efs_fs_i.h>
-#include <linux/stat.h>
#include <asm/uaccess.h>
-static int efs_readdir(struct file *,void *,filldir_t);
-extern int efs_lookup(struct inode *, struct dentry *);
+static int efs_readdir(struct file *, void *, filldir_t);
+int efs_lookup(struct inode *, struct dentry *);
+
+static ssize_t
+efs_dir_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ return -EISDIR;
+}
static struct file_operations efs_dir_ops = {
- NULL,
- NULL,
- NULL,
- efs_readdir,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ NULL, /* lseek */
+ efs_dir_read,
+ NULL, /* write */
+ efs_readdir,
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* flush */
+ NULL, /* release */
+ NULL /* fsync */
};
-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
+struct inode_operations efs_dir_inode_operations = {
+ &efs_dir_ops,
+ NULL, /* create */
+ efs_lookup,
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ efs_bmap,
+ NULL, /* truncate */
+ NULL /* permission */
};
+static int
+efs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *in = filp->f_dentry->d_inode;
+ struct efs_inode_info *ini = &in->u.efs_i;
+ struct buffer_head *bh;
+ __u16 item;
+ __u32 block;
+ __u16 offset;
+ struct efs_dirblk *dirblk;
+ struct efs_dir_entry *entry;
+
+ if (!in || !in->i_sb || !S_ISDIR(in->i_mode) || !ini->tot)
+ return -EBADF;
+
+ if (ini->tot > 1) {
+ printk("EFS: ERROR: directory %s has %d extents\n",
+ filp->f_dentry->d_name.name, ini->tot);
+ printk("EFS: ERROR: Mike is lazy, so this is NYI.\n");
+ return 0;
+ };
+
+ if (in->i_size & (EFS_BLOCK_SIZE - 1))
+ printk("EFS: readdir: dirsize %#lx not block multiple\n", in->i_size);
+
+ /* filp->f_pos is (block << BLOCK_SIZE | item) */
+ block = filp->f_pos >> EFS_BLOCK_SIZE_BITS;
+ item = filp->f_pos & 0xFF;
+
+ start_block:
+ if (block == (in->i_size >> EFS_BLOCK_SIZE_BITS))
+ return 0; /* all done! */
+
+ bh = bread(in->i_dev, efs_bmap(in, block), EFS_BLOCK_SIZE);
+ if (!bh) {
+ printk("EFS: ERROR: readdir: bread of %#lx/%#x\n",
+ in->i_ino, efs_bmap(in, block));
+ return 0;
+ }
-/* ----- efs_readdir -----
- readdir inode operation:
- read the next directory entry of a given dir file
-
- inode - pointer to inode struct of directory
- filp - pointer to file struct of directory inode
- dirent - pointer to dirent struct that has to be filled
- filldir - function to store values in the directory
+ dirblk = (struct efs_dirblk *)bh->b_data;
- return - 0 ok, <0 error
-*/
-static int efs_readdir(struct file *filp,
- 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;
-
- /* 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;
+ /* skip empty slots */
+ do {
+ offset = EFS_SLOT2OFF(dirblk, item);
+ if (!offset) {
+ DB(("EFS: skipping empty slot %d\n", item));
+ }
+ item++;
+ if (item == dirblk->db_slots) {
+ item = 0;
+ block++;
+ if (!offset) {
+ brelse(bh);
+ goto start_block;
+ }
}
- 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;
+ } while(!offset);
+ entry = EFS_DENT4OFF(dirblk, offset);
+ /*
+ DB(("EFS_SLOT2OFF(%d) -> %d, EFS_DENT4OFF(%p, %d) -> %p) || ",
+ item-1, offset, dirblk, offset, entry));
#ifdef DEBUG_EFS
- printk("efs: dir #%d @ %0#3x - inode %lx %s namelen %u\n",
- itemnum,rawdepos,iteminode,nameptr,namelen);
+ {
+ __u8 *rawdirblk, nameptr;
+ __u32 iteminode;
+ __u16 namelen, rawdepos;
+ rawdirblk = (__u8*)bh->b_data;
+ rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+item-1] << 1;
+ DB(("OLD_WAY: offset = %d, dent = %p ||", rawdepos,
+ (struct efs_dir_entry *)(rawdirblk + rawdepos)));
+ }
#endif
- /* copy filename and data in direntry */
- filldir(dirent,nameptr,namelen,filp->f_pos,iteminode);
+ DB(("EFS: filldir(dirent, \"%.*s\", %d, %d, %d)\n",
+ entry->d_namelen, entry->d_name, entry->d_namelen,
+ filp->f_pos, efs_swab32(entry->ud_inum.l)));
+ */
+ filldir(dirent, entry->d_name, entry->d_namelen, filp->f_pos,
+ efs_swab32(entry->ud_inum.l));
+
+ brelse(bh);
- brelse(bh);
+ filp->f_pos = (block << EFS_BLOCK_SIZE_BITS) | item;
+ UPDATE_ATIME(in);
- /* store pos of next item */
- itemnum++;
- if(itemnum==numitems) {
- itemnum = 0;
- block++;
- }
- filp->f_pos = (block<<EFS_BLOCK_SIZE_BITS) | itemnum;
- UPDATE_ATIME(inode);
-
- return 0;
+ return 0;
}
-