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>
25 #include <linux/smp_lock.h>
26 #include <linux/buffer_head.h>
28 static int affs_readdir(struct file
*, void *, filldir_t
);
30 struct file_operations affs_dir_operations
= {
31 .read
= generic_read_dir
,
32 .readdir
= affs_readdir
,
37 * directories can handle most operations...
39 struct inode_operations affs_dir_inode_operations
= {
40 .create
= affs_create
,
41 .lookup
= affs_lookup
,
43 .unlink
= affs_unlink
,
44 .symlink
= affs_symlink
,
47 .rename
= affs_rename
,
48 .setattr
= affs_notify_change
,
52 affs_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
54 struct inode
*inode
= filp
->f_dentry
->d_inode
;
55 struct super_block
*sb
= inode
->i_sb
;
56 struct buffer_head
*dir_bh
;
57 struct buffer_head
*fh_bh
;
68 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode
->i_ino
,(unsigned long)filp
->f_pos
);
77 filp
->private_data
= (void *)0;
78 if (filldir(dirent
, ".", 1, f_pos
, inode
->i_ino
, DT_DIR
) < 0)
80 filp
->f_pos
= f_pos
= 1;
84 if (filldir(dirent
, "..", 2, f_pos
, parent_ino(filp
->f_dentry
), DT_DIR
) < 0)
86 filp
->f_pos
= f_pos
= 2;
91 chain_pos
= (f_pos
- 2) & 0xffff;
92 hash_pos
= (f_pos
- 2) >> 16;
93 if (chain_pos
== 0xffff) {
94 affs_warning(sb
, "readdir", "More than 65535 entries in chain");
97 filp
->f_pos
= ((hash_pos
<< 16) | chain_pos
) + 2;
99 dir_bh
= affs_bread(sb
, inode
->i_ino
);
103 /* If the directory hasn't changed since the last call to readdir(),
104 * we can jump directly to where we left off.
106 ino
= (u32
)(long)filp
->private_data
;
107 if (ino
&& filp
->f_version
== inode
->i_version
) {
108 pr_debug("AFFS: readdir() left off=%d\n", ino
);
112 ino
= be32_to_cpu(AFFS_HEAD(dir_bh
)->table
[hash_pos
]);
113 for (i
= 0; ino
&& i
< chain_pos
; i
++) {
114 fh_bh
= affs_bread(sb
, ino
);
116 affs_error(sb
, "readdir","Cannot read block %d", i
);
119 ino
= be32_to_cpu(AFFS_TAIL(sb
, fh_bh
)->hash_chain
);
127 for (; hash_pos
< AFFS_SB(sb
)->s_hashsize
; hash_pos
++) {
128 ino
= be32_to_cpu(AFFS_HEAD(dir_bh
)->table
[hash_pos
]);
131 f_pos
= (hash_pos
<< 16) + 2;
134 fh_bh
= affs_bread(sb
, ino
);
136 affs_error(sb
, "readdir","Cannot read block %d", ino
);
140 namelen
= min(AFFS_TAIL(sb
, fh_bh
)->name
[0], (u8
)30);
141 name
= AFFS_TAIL(sb
, fh_bh
)->name
+ 1;
142 pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
143 namelen
, name
, ino
, hash_pos
, f_pos
);
144 if (filldir(dirent
, name
, namelen
, f_pos
, ino
, DT_UNKNOWN
) < 0)
148 ino
= be32_to_cpu(AFFS_TAIL(sb
, fh_bh
)->hash_chain
);
155 filp
->f_version
= inode
->i_version
;
156 filp
->private_data
= (void *)(long)ino
;
162 affs_unlock_dir(inode
);
163 pr_debug("AFFS: readdir()=%d\n", stored
);