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
);
28 static ssize_t
affs_dir_read(struct file
*, char *, size_t, loff_t
*);
30 static struct file_operations affs_dir_operations
= {
31 NULL
, /* lseek - default */
32 affs_dir_read
, /* read */
33 NULL
, /* write - bad */
34 affs_readdir
, /* readdir */
35 NULL
, /* poll - default */
36 NULL
, /* ioctl - default */
38 NULL
, /* no special open code */
40 NULL
, /* no special release code */
41 file_fsync
/* default fsync */
45 * directories can handle most operations...
47 struct inode_operations affs_dir_inode_operations
= {
48 &affs_dir_operations
, /* default directory file-ops */
49 affs_create
, /* create */
50 affs_lookup
, /* lookup */
52 affs_unlink
, /* unlink */
53 affs_symlink
, /* symlink */
54 affs_mkdir
, /* mkdir */
55 affs_rmdir
, /* rmdir */
57 affs_rename
, /* rename */
59 NULL
, /* follow_link */
64 NULL
, /* permissions */
69 affs_dir_read(struct file
*filp
, char *buf
, size_t count
, loff_t
*ppos
)
75 affs_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
84 struct buffer_head
*dir_bh
;
85 struct buffer_head
*fh_bh
;
87 struct inode
*inode
= filp
->f_dentry
->d_inode
;
89 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lu)\n",inode
->i_ino
,(unsigned long)filp
->f_pos
);
97 if (filp
->f_pos
== 0) {
98 filp
->private_data
= (void *)0;
99 if (filldir(dirent
,".",1,filp
->f_pos
,inode
->i_ino
) < 0) {
105 if (filp
->f_pos
== 1) {
106 if (filldir(dirent
,"..",2,filp
->f_pos
,affs_parent_ino(inode
)) < 0) {
112 chain_pos
= (filp
->f_pos
- 2) & 0xffff;
113 hash_pos
= (filp
->f_pos
- 2) >> 16;
114 if (chain_pos
== 0xffff) {
115 affs_warning(inode
->i_sb
,"readdir","More than 65535 entries in chain");
118 filp
->f_pos
= ((hash_pos
<< 16) | chain_pos
) + 2;
120 if (!(dir_bh
= affs_bread(inode
->i_dev
,inode
->i_ino
,
121 AFFS_I2BSIZE(inode
))))
125 while (hash_pos
< AFFS_I2HSIZE(inode
) &&
126 !((struct dir_front
*)dir_bh
->b_data
)->hashtable
[hash_pos
])
128 if (hash_pos
>= AFFS_I2HSIZE(inode
))
131 i
= be32_to_cpu(((struct dir_front
*)dir_bh
->b_data
)->hashtable
[hash_pos
]);
134 /* If the directory hasn't changed since the last call to readdir(),
135 * we can jump directly to where we left off.
137 if (filp
->private_data
&& filp
->f_version
== inode
->i_version
) {
138 i
= (s32
)filp
->private_data
;
140 pr_debug("AFFS: readdir() left off=%d\n",i
);
142 filp
->f_version
= inode
->i_version
;
143 pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos
,chain_pos
);
145 if (!(fh_bh
= affs_bread(inode
->i_dev
,i
,AFFS_I2BSIZE(inode
)))) {
146 affs_error(inode
->i_sb
,"readdir","Cannot read block %d",i
);
150 i
= be32_to_cpu(FILE_END(fh_bh
->b_data
,inode
)->hash_chain
);
158 namelen
= affs_get_file_name(AFFS_I2BSIZE(inode
),fh_bh
->b_data
,&name
);
159 pr_debug("AFFS: readdir(): filldir(\"%.*s\",ino=%lu), i=%d\n",
161 filp
->private_data
= (void *)ino
;
162 if (filldir(dirent
,name
,namelen
,filp
->f_pos
,ino
) < 0)
164 filp
->private_data
= (void *)i
;
174 filp
->f_pos
= ((hash_pos
<< 16) | chain_pos
) + 2;
180 pr_debug("AFFS: readdir()=%d\n",stored
);