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
17 #include <asm/uaccess.h>
18 #include <linux/errno.h>
20 #include <linux/kernel.h>
21 #include <linux/affs_fs.h>
22 #include <linux/stat.h>
23 #include <linux/string.h>
25 #include <linux/amigaffs.h>
27 static int affs_readdir(struct file
*, void *, filldir_t
);
29 struct file_operations affs_dir_operations
= {
30 read
: generic_read_dir
,
31 readdir
: affs_readdir
,
36 * directories can handle most operations...
38 struct inode_operations affs_dir_inode_operations
= {
43 symlink
: affs_symlink
,
47 setattr
: affs_notify_change
,
51 affs_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
60 struct buffer_head
*dir_bh
;
61 struct buffer_head
*fh_bh
;
63 struct inode
*inode
= filp
->f_dentry
->d_inode
;
65 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lu)\n",inode
->i_ino
,(unsigned long)filp
->f_pos
);
73 if (filp
->f_pos
== 0) {
74 filp
->private_data
= (void *)0;
75 if (filldir(dirent
,".",1,filp
->f_pos
,inode
->i_ino
) < 0) {
81 if (filp
->f_pos
== 1) {
82 if (filldir(dirent
,"..",2,filp
->f_pos
,affs_parent_ino(inode
)) < 0) {
88 chain_pos
= (filp
->f_pos
- 2) & 0xffff;
89 hash_pos
= (filp
->f_pos
- 2) >> 16;
90 if (chain_pos
== 0xffff) {
91 affs_warning(inode
->i_sb
,"readdir","More than 65535 entries in chain");
94 filp
->f_pos
= ((hash_pos
<< 16) | chain_pos
) + 2;
96 if (!(dir_bh
= affs_bread(inode
->i_dev
,inode
->i_ino
,
97 AFFS_I2BSIZE(inode
))))
101 while (hash_pos
< AFFS_I2HSIZE(inode
) &&
102 !((struct dir_front
*)dir_bh
->b_data
)->hashtable
[hash_pos
])
104 if (hash_pos
>= AFFS_I2HSIZE(inode
))
107 i
= be32_to_cpu(((struct dir_front
*)dir_bh
->b_data
)->hashtable
[hash_pos
]);
110 /* If the directory hasn't changed since the last call to readdir(),
111 * we can jump directly to where we left off.
113 if (filp
->private_data
&& filp
->f_version
== inode
->i_version
) {
114 i
= (s32
)filp
->private_data
;
116 pr_debug("AFFS: readdir() left off=%d\n",i
);
118 filp
->f_version
= inode
->i_version
;
119 pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos
,chain_pos
);
121 if (!(fh_bh
= affs_bread(inode
->i_dev
,i
,AFFS_I2BSIZE(inode
)))) {
122 affs_error(inode
->i_sb
,"readdir","Cannot read block %d",i
);
126 i
= be32_to_cpu(FILE_END(fh_bh
->b_data
,inode
)->hash_chain
);
134 namelen
= affs_get_file_name(AFFS_I2BSIZE(inode
),fh_bh
->b_data
,&name
);
135 pr_debug("AFFS: readdir(): filldir(\"%.*s\",ino=%lu), i=%d\n",
137 filp
->private_data
= (void *)ino
;
138 if (filldir(dirent
,name
,namelen
,filp
->f_pos
,ino
) < 0)
140 filp
->private_data
= (void *)i
;
150 filp
->f_pos
= ((hash_pos
<< 16) | chain_pos
) + 2;
156 pr_debug("AFFS: readdir()=%d\n",stored
);