4 * Copyright (C) 1999-2000 Russell King
6 * Common directory handling for ADFS
8 #include <linux/config.h>
9 #include <linux/version.h>
10 #include <linux/errno.h>
12 #include <linux/adfs_fs.h>
13 #include <linux/sched.h>
14 #include <linux/stat.h>
15 #include <linux/spinlock.h>
20 * For future. This should probably be per-directory.
22 static rwlock_t adfs_dir_lock
;
25 adfs_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
27 struct inode
*inode
= filp
->f_dentry
->d_inode
;
28 struct super_block
*sb
= inode
->i_sb
;
29 struct adfs_dir_ops
*ops
= sb
->u
.adfs_sb
.s_dir
;
30 struct object_info obj
;
34 if (filp
->f_pos
>> 32)
37 ret
= ops
->read(sb
, inode
->i_ino
, inode
->i_size
, &dir
);
41 switch ((unsigned long)filp
->f_pos
) {
43 if (filldir(dirent
, ".", 1, 0, inode
->i_ino
) < 0)
48 if (filldir(dirent
, "..", 2, 1, dir
.parent_id
) < 0)
56 read_lock(&adfs_dir_lock
);
58 ret
= ops
->setpos(&dir
, filp
->f_pos
- 2);
61 while (ops
->getnext(&dir
, &obj
) == 0) {
62 if (filldir(dirent
, obj
.name
, obj
.name_len
,
63 filp
->f_pos
, obj
.file_id
) < 0)
69 read_unlock(&adfs_dir_lock
);
79 adfs_dir_update(struct super_block
*sb
, struct object_info
*obj
)
82 #ifdef CONFIG_ADFS_FS_RW
83 struct adfs_dir_ops
*ops
= sb
->u
.adfs_sb
.s_dir
;
86 printk(KERN_INFO
"adfs_dir_update: object %06X in dir %06X\n",
87 obj
->file_id
, obj
->parent_id
);
94 ret
= ops
->read(sb
, obj
->parent_id
, 0, &dir
);
98 write_lock(&adfs_dir_lock
);
99 ret
= ops
->update(&dir
, obj
);
100 write_unlock(&adfs_dir_lock
);
109 adfs_match(struct qstr
*name
, struct object_info
*obj
)
113 if (name
->len
!= obj
->name_len
)
116 for (i
= 0; i
< name
->len
; i
++) {
122 if (c1
>= 'A' && c1
<= 'Z')
124 if (c2
>= 'A' && c2
<= 'Z')
134 adfs_dir_lookup_byname(struct inode
*inode
, struct qstr
*name
, struct object_info
*obj
)
136 struct super_block
*sb
= inode
->i_sb
;
137 struct adfs_dir_ops
*ops
= sb
->u
.adfs_sb
.s_dir
;
141 ret
= ops
->read(sb
, inode
->i_ino
, inode
->i_size
, &dir
);
145 if (inode
->u
.adfs_i
.parent_id
!= dir
.parent_id
) {
146 adfs_error(sb
, "parent directory changed under me! (%lx but got %lx)\n",
147 inode
->u
.adfs_i
.parent_id
, dir
.parent_id
);
152 obj
->parent_id
= inode
->i_ino
;
155 * '.' is handled by reserved_lookup() in fs/namei.c
157 if (name
->len
== 2 && name
->name
[0] == '.' && name
->name
[1] == '.') {
159 * Currently unable to fill in the rest of 'obj',
160 * but this is better than nothing. We need to
161 * ascend one level to find it's parent.
164 obj
->file_id
= obj
->parent_id
;
168 read_lock(&adfs_dir_lock
);
170 ret
= ops
->setpos(&dir
, 0);
175 while (ops
->getnext(&dir
, obj
) == 0) {
176 if (adfs_match(name
, obj
)) {
183 read_unlock(&adfs_dir_lock
);
191 struct file_operations adfs_dir_operations
= {
192 read
: generic_read_dir
,
193 readdir
: adfs_readdir
,
198 adfs_hash(struct dentry
*parent
, struct qstr
*qstr
)
200 const unsigned int name_len
= parent
->d_sb
->u
.adfs_sb
.s_namelen
;
201 const unsigned char *name
;
205 if (qstr
->len
< name_len
)
209 * Truncate the name in place, avoids
210 * having to define a compare function.
212 qstr
->len
= i
= name_len
;
214 hash
= init_name_hash();
219 if (c
>= 'A' && c
<= 'Z')
222 hash
= partial_name_hash(c
, hash
);
224 qstr
->hash
= end_name_hash(hash
);
230 * Compare two names, taking note of the name length
231 * requirements of the underlying filesystem.
234 adfs_compare(struct dentry
*parent
, struct qstr
*entry
, struct qstr
*name
)
238 if (entry
->len
!= name
->len
)
241 for (i
= 0; i
< name
->len
; i
++) {
247 if (a
>= 'A' && a
<= 'Z')
249 if (b
>= 'A' && b
<= 'Z')
258 struct dentry_operations adfs_dentry_operations
= {
260 d_compare
: adfs_compare
,
263 struct dentry
*adfs_lookup(struct inode
*dir
, struct dentry
*dentry
)
265 struct inode
*inode
= NULL
;
266 struct object_info obj
;
269 dentry
->d_op
= &adfs_dentry_operations
;
270 error
= adfs_dir_lookup_byname(dir
, &dentry
->d_name
, &obj
);
274 * This only returns NULL if get_empty_inode
277 inode
= adfs_iget(dir
->i_sb
, &obj
);
281 d_add(dentry
, inode
);
282 return ERR_PTR(error
);
286 * directories can handle most operations...
288 struct inode_operations adfs_dir_inode_operations
= {
290 setattr
: adfs_notify_change
,