4 * (c) 1996 Hans-Joachim Widmaier - Rewritten
6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
8 * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
10 * (C) 1991 Linus Torvalds - minix filesystem
12 * affs directory handling functions
16 #include <asm/uaccess.h>
17 #include <linux/errno.h>
19 #include <linux/kernel.h>
20 #include <linux/affs_fs.h>
21 #include <linux/stat.h>
22 #include <linux/string.h>
24 #include <linux/amigaffs.h>
26 static int affs_readdir(struct file *, void *, filldir_t);
28 struct file_operations affs_dir_operations = {
29 read: generic_read_dir,
30 readdir: affs_readdir,
35 * directories can handle most operations...
37 struct inode_operations affs_dir_inode_operations = {
42 symlink: affs_symlink,
46 setattr: affs_notify_change,
50 affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
52 struct inode *inode = filp->f_dentry->d_inode;
53 struct super_block *sb = inode->i_sb;
54 struct buffer_head *dir_bh;
55 struct buffer_head *fh_bh;
66 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos);
75 filp->private_data = (void *)0;
76 if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0)
78 filp->f_pos = f_pos = 1;
82 if (filldir(dirent, "..", 2, f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
84 filp->f_pos = f_pos = 2;
89 chain_pos = (f_pos - 2) & 0xffff;
90 hash_pos = (f_pos - 2) >> 16;
91 if (chain_pos == 0xffff) {
92 affs_warning(sb, "readdir", "More than 65535 entries in chain");
95 filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
97 dir_bh = affs_bread(sb, inode->i_ino);
101 /* If the directory hasn't changed since the last call to readdir(),
102 * we can jump directly to where we left off.
104 ino = (u32)(long)filp->private_data;
105 if (ino && filp->f_version == inode->i_version) {
106 pr_debug("AFFS: readdir() left off=%d\n", ino);
110 ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
111 for (i = 0; ino && i < chain_pos; i++) {
112 fh_bh = affs_bread(sb, ino);
114 affs_error(sb, "readdir","Cannot read block %d", i);
117 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
125 for (; hash_pos < AFFS_SB->s_hashsize; hash_pos++) {
126 ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
129 f_pos = (hash_pos << 16) + 2;
132 fh_bh = affs_bread(sb, ino);
134 affs_error(sb, "readdir","Cannot read block %d", ino);
138 namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
139 name = AFFS_TAIL(sb, fh_bh)->name + 1;
140 pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
141 namelen, name, ino, hash_pos, f_pos);
142 if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0)
146 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
153 filp->f_version = inode->i_version;
154 filp->private_data = (void *)(long)ino;
160 affs_unlock_dir(inode);
161 pr_debug("AFFS: readdir()=%d\n", stored);