2 * linux/fs/affs/namei.c
4 * (c) 1996 Hans-Joachim Widmaier - Rewritten
6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
8 * (C) 1991 Linus Torvalds - minix filesystem
13 typedef int (*toupper_t
)(int);
15 static int affs_toupper(int ch
);
16 static int affs_hash_dentry(struct dentry
*, struct qstr
*);
17 static int affs_compare_dentry(struct dentry
*, struct qstr
*, struct qstr
*);
18 static int affs_intl_toupper(int ch
);
19 static int affs_intl_hash_dentry(struct dentry
*, struct qstr
*);
20 static int affs_intl_compare_dentry(struct dentry
*, struct qstr
*, struct qstr
*);
22 struct dentry_operations affs_dentry_operations
= {
23 .d_hash
= affs_hash_dentry
,
24 .d_compare
= affs_compare_dentry
,
27 static struct dentry_operations affs_intl_dentry_operations
= {
28 .d_hash
= affs_intl_hash_dentry
,
29 .d_compare
= affs_intl_compare_dentry
,
33 /* Simple toupper() for DOS\1 */
38 return ch
>= 'a' && ch
<= 'z' ? ch
-= ('a' - 'A') : ch
;
41 /* International toupper() for DOS\3 ("international") */
44 affs_intl_toupper(int ch
)
46 return (ch
>= 'a' && ch
<= 'z') || (ch
>= 0xE0
47 && ch
<= 0xFE && ch
!= 0xF7) ?
48 ch
- ('a' - 'A') : ch
;
51 static inline toupper_t
52 affs_get_toupper(struct super_block
*sb
)
54 return AFFS_SB(sb
)->s_flags
& SF_INTL
? affs_intl_toupper
: affs_toupper
;
58 * Note: the dentry argument is the parent dentry.
61 __affs_hash_dentry(struct dentry
*dentry
, struct qstr
*qstr
, toupper_t toupper
)
63 const u8
*name
= qstr
->name
;
67 i
= affs_check_name(qstr
->name
,qstr
->len
);
71 hash
= init_name_hash();
72 i
= min(qstr
->len
, 30u);
73 for (; i
> 0; name
++, i
--)
74 hash
= partial_name_hash(toupper(*name
), hash
);
75 qstr
->hash
= end_name_hash(hash
);
81 affs_hash_dentry(struct dentry
*dentry
, struct qstr
*qstr
)
83 return __affs_hash_dentry(dentry
, qstr
, affs_toupper
);
86 affs_intl_hash_dentry(struct dentry
*dentry
, struct qstr
*qstr
)
88 return __affs_hash_dentry(dentry
, qstr
, affs_intl_toupper
);
92 __affs_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
, toupper_t toupper
)
94 const u8
*aname
= a
->name
;
95 const u8
*bname
= b
->name
;
98 /* 'a' is the qstr of an already existing dentry, so the name
99 * must be valid. 'b' must be validated first.
102 if (affs_check_name(b
->name
,b
->len
))
105 /* If the names are longer than the allowed 30 chars,
106 * the excess is ignored, so their length may differ.
113 } else if (len
!= b
->len
)
116 for (; len
> 0; len
--)
117 if (toupper(*aname
++) != toupper(*bname
++))
124 affs_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
126 return __affs_compare_dentry(dentry
, a
, b
, affs_toupper
);
129 affs_intl_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
131 return __affs_compare_dentry(dentry
, a
, b
, affs_intl_toupper
);
135 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
139 affs_match(struct dentry
*dentry
, const u8
*name2
, toupper_t toupper
)
141 const u8
*name
= dentry
->d_name
.name
;
142 int len
= dentry
->d_name
.len
;
148 } else if (len
!= *name2
)
151 for (name2
++; len
> 0; len
--)
152 if (toupper(*name
++) != toupper(*name2
++))
158 affs_hash_name(struct super_block
*sb
, const u8
*name
, unsigned int len
)
160 toupper_t toupper
= affs_get_toupper(sb
);
163 hash
= len
= min(len
, 30u);
164 for (; len
> 0; len
--)
165 hash
= (hash
* 13 + toupper(*name
++)) & 0x7ff;
167 return hash
% AFFS_SB(sb
)->s_hashsize
;
170 static struct buffer_head
*
171 affs_find_entry(struct inode
*dir
, struct dentry
*dentry
)
173 struct super_block
*sb
= dir
->i_sb
;
174 struct buffer_head
*bh
;
175 toupper_t toupper
= affs_get_toupper(sb
);
178 pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
180 bh
= affs_bread(sb
, dir
->i_ino
);
182 return ERR_PTR(-EIO
);
184 key
= be32_to_cpu(AFFS_HEAD(bh
)->table
[affs_hash_name(sb
, dentry
->d_name
.name
, dentry
->d_name
.len
)]);
190 bh
= affs_bread(sb
, key
);
192 return ERR_PTR(-EIO
);
193 if (affs_match(dentry
, AFFS_TAIL(sb
, bh
)->name
, toupper
))
195 key
= be32_to_cpu(AFFS_TAIL(sb
, bh
)->hash_chain
);
200 affs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
202 struct super_block
*sb
= dir
->i_sb
;
203 struct buffer_head
*bh
;
204 struct inode
*inode
= NULL
;
206 pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry
->d_name
.len
,dentry
->d_name
.name
);
209 bh
= affs_find_entry(dir
, dentry
);
210 affs_unlock_dir(dir
);
212 return ERR_PTR(PTR_ERR(bh
));
215 u32 ino
= bh
->b_blocknr
;
217 /* store the real header ino in d_fsdata for faster lookups */
218 dentry
->d_fsdata
= (void *)(long)ino
;
219 switch (be32_to_cpu(AFFS_TAIL(sb
, bh
)->stype
)) {
220 //link to dirs disabled
223 ino
= be32_to_cpu(AFFS_TAIL(sb
, bh
)->original
);
226 inode
= iget(sb
, ino
);
228 return ERR_PTR(-EACCES
);
231 dentry
->d_op
= AFFS_SB(sb
)->s_flags
& SF_INTL
? &affs_intl_dentry_operations
: &affs_dentry_operations
;
232 d_add(dentry
, inode
);
237 affs_unlink(struct inode
*dir
, struct dentry
*dentry
)
239 pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32
)dir
->i_ino
,
240 (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
242 return affs_remove_header(dentry
);
246 affs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
, struct nameidata
*nd
)
248 struct super_block
*sb
= dir
->i_sb
;
252 pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir
->i_ino
,(int)dentry
->d_name
.len
,
253 dentry
->d_name
.name
,mode
);
255 inode
= affs_new_inode(dir
);
259 inode
->i_mode
= mode
;
261 mark_inode_dirty(inode
);
263 inode
->i_op
= &affs_file_inode_operations
;
264 inode
->i_fop
= &affs_file_operations
;
265 inode
->i_mapping
->a_ops
= (AFFS_SB(sb
)->s_flags
& SF_OFS
) ? &affs_aops_ofs
: &affs_aops
;
266 error
= affs_add_entry(dir
, inode
, dentry
, ST_FILE
);
276 affs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
281 pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir
->i_ino
,
282 (int)dentry
->d_name
.len
,dentry
->d_name
.name
,mode
);
284 inode
= affs_new_inode(dir
);
288 inode
->i_mode
= S_IFDIR
| mode
;
291 inode
->i_op
= &affs_dir_inode_operations
;
292 inode
->i_fop
= &affs_dir_operations
;
294 error
= affs_add_entry(dir
, inode
, dentry
, ST_USERDIR
);
297 mark_inode_dirty(inode
);
305 affs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
307 pr_debug("AFFS: rmdir(dir=%u, \"%.*s\")\n", (u32
)dir
->i_ino
,
308 (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
310 return affs_remove_header(dentry
);
314 affs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
316 struct super_block
*sb
= dir
->i_sb
;
317 struct buffer_head
*bh
;
320 int i
, maxlen
, error
;
323 pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir
->i_ino
,
324 (int)dentry
->d_name
.len
,dentry
->d_name
.name
,symname
);
326 maxlen
= AFFS_SB(sb
)->s_hashsize
* sizeof(u32
) - 1;
327 inode
= affs_new_inode(dir
);
331 inode
->i_op
= &affs_symlink_inode_operations
;
332 inode
->i_data
.a_ops
= &affs_symlink_aops
;
333 inode
->i_mode
= S_IFLNK
| 0777;
337 bh
= affs_bread(sb
, inode
->i_ino
);
341 p
= (char *)AFFS_HEAD(bh
)->table
;
343 if (*symname
== '/') {
344 while (*symname
== '/')
346 while (AFFS_SB(sb
)->s_volume
[i
]) /* Cannot overflow */
347 *p
++ = AFFS_SB(sb
)->s_volume
[i
++];
349 while (i
< maxlen
&& (c
= *symname
++)) {
350 if (c
== '.' && lc
== '/' && *symname
== '.' && symname
[1] == '/') {
355 } else if (c
== '.' && lc
== '/' && *symname
== '/') {
364 while (*symname
== '/')
368 mark_buffer_dirty_inode(bh
, inode
);
370 mark_inode_dirty(inode
);
372 error
= affs_add_entry(dir
, inode
, dentry
, ST_SOFTLINK
);
380 mark_inode_dirty(inode
);
386 affs_link(struct dentry
*old_dentry
, struct inode
*dir
, struct dentry
*dentry
)
388 struct inode
*inode
= old_dentry
->d_inode
;
390 pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32
)inode
->i_ino
, (u32
)dir
->i_ino
,
391 (int)dentry
->d_name
.len
,dentry
->d_name
.name
);
393 return affs_add_entry(dir
, inode
, dentry
, ST_LINKFILE
);
397 affs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
398 struct inode
*new_dir
, struct dentry
*new_dentry
)
400 struct super_block
*sb
= old_dir
->i_sb
;
401 struct buffer_head
*bh
= NULL
;
404 pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
405 (u32
)old_dir
->i_ino
, (int)old_dentry
->d_name
.len
, old_dentry
->d_name
.name
,
406 (u32
)new_dir
->i_ino
, (int)new_dentry
->d_name
.len
, new_dentry
->d_name
.name
);
408 retval
= affs_check_name(new_dentry
->d_name
.name
,new_dentry
->d_name
.len
);
412 /* Unlink destination if it already exists */
413 if (new_dentry
->d_inode
) {
414 retval
= affs_remove_header(new_dentry
);
420 bh
= affs_bread(sb
, old_dentry
->d_inode
->i_ino
);
424 /* Remove header from its parent directory. */
425 affs_lock_dir(old_dir
);
426 retval
= affs_remove_hash(old_dir
, bh
);
427 affs_unlock_dir(old_dir
);
431 /* And insert it into the new directory with the new name. */
432 affs_copy_name(AFFS_TAIL(sb
, bh
)->name
, new_dentry
);
433 affs_fix_checksum(sb
, bh
);
434 affs_lock_dir(new_dir
);
435 retval
= affs_insert_hash(new_dir
, bh
);
436 affs_unlock_dir(new_dir
);
437 /* TODO: move it back to old_dir, if error? */
440 mark_buffer_dirty_inode(bh
, retval
? old_dir
: new_dir
);