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(const struct dentry
*, struct qstr
*);
17 static int affs_compare_dentry(const struct dentry
*parent
, const struct dentry
*dentry
,
18 unsigned int len
, const char *str
, const struct qstr
*name
);
19 static int affs_intl_toupper(int ch
);
20 static int affs_intl_hash_dentry(const struct dentry
*, struct qstr
*);
21 static int affs_intl_compare_dentry(const struct dentry
*parent
, const struct dentry
*dentry
,
22 unsigned int len
, const char *str
, const struct qstr
*name
);
24 const struct dentry_operations affs_dentry_operations
= {
25 .d_hash
= affs_hash_dentry
,
26 .d_compare
= affs_compare_dentry
,
29 const struct dentry_operations affs_intl_dentry_operations
= {
30 .d_hash
= affs_intl_hash_dentry
,
31 .d_compare
= affs_intl_compare_dentry
,
35 /* Simple toupper() for DOS\1 */
40 return ch
>= 'a' && ch
<= 'z' ? ch
-= ('a' - 'A') : ch
;
43 /* International toupper() for DOS\3 ("international") */
46 affs_intl_toupper(int ch
)
48 return (ch
>= 'a' && ch
<= 'z') || (ch
>= 0xE0
49 && ch
<= 0xFE && ch
!= 0xF7) ?
50 ch
- ('a' - 'A') : ch
;
53 static inline toupper_t
54 affs_get_toupper(struct super_block
*sb
)
56 return AFFS_SB(sb
)->s_flags
& SF_INTL
? affs_intl_toupper
: affs_toupper
;
60 * Note: the dentry argument is the parent dentry.
63 __affs_hash_dentry(struct qstr
*qstr
, toupper_t toupper
, bool notruncate
)
65 const u8
*name
= qstr
->name
;
69 i
= affs_check_name(qstr
->name
, qstr
->len
, notruncate
);
73 hash
= init_name_hash();
74 i
= min(qstr
->len
, 30u);
75 for (; i
> 0; name
++, i
--)
76 hash
= partial_name_hash(toupper(*name
), hash
);
77 qstr
->hash
= end_name_hash(hash
);
83 affs_hash_dentry(const struct dentry
*dentry
, struct qstr
*qstr
)
85 return __affs_hash_dentry(qstr
, affs_toupper
,
86 affs_nofilenametruncate(dentry
));
91 affs_intl_hash_dentry(const struct dentry
*dentry
, struct qstr
*qstr
)
93 return __affs_hash_dentry(qstr
, affs_intl_toupper
,
94 affs_nofilenametruncate(dentry
));
98 static inline int __affs_compare_dentry(unsigned int len
,
99 const char *str
, const struct qstr
*name
, toupper_t toupper
,
102 const u8
*aname
= str
;
103 const u8
*bname
= name
->name
;
106 * 'str' is the name of an already existing dentry, so the name
107 * must be valid. 'name' must be validated first.
110 if (affs_check_name(name
->name
, name
->len
, notruncate
))
114 * If the names are longer than the allowed 30 chars,
115 * the excess is ignored, so their length may differ.
121 } else if (len
!= name
->len
)
124 for (; len
> 0; len
--)
125 if (toupper(*aname
++) != toupper(*bname
++))
132 affs_compare_dentry(const struct dentry
*parent
, const struct dentry
*dentry
,
133 unsigned int len
, const char *str
, const struct qstr
*name
)
136 return __affs_compare_dentry(len
, str
, name
, affs_toupper
,
137 affs_nofilenametruncate(parent
));
141 affs_intl_compare_dentry(const struct dentry
*parent
, const struct dentry
*dentry
,
142 unsigned int len
, const char *str
, const struct qstr
*name
)
144 return __affs_compare_dentry(len
, str
, name
, affs_intl_toupper
,
145 affs_nofilenametruncate(parent
));
150 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
154 affs_match(struct dentry
*dentry
, const u8
*name2
, toupper_t toupper
)
156 const u8
*name
= dentry
->d_name
.name
;
157 int len
= dentry
->d_name
.len
;
163 } else if (len
!= *name2
)
166 for (name2
++; len
> 0; len
--)
167 if (toupper(*name
++) != toupper(*name2
++))
173 affs_hash_name(struct super_block
*sb
, const u8
*name
, unsigned int len
)
175 toupper_t toupper
= affs_get_toupper(sb
);
178 hash
= len
= min(len
, 30u);
179 for (; len
> 0; len
--)
180 hash
= (hash
* 13 + toupper(*name
++)) & 0x7ff;
182 return hash
% AFFS_SB(sb
)->s_hashsize
;
185 static struct buffer_head
*
186 affs_find_entry(struct inode
*dir
, struct dentry
*dentry
)
188 struct super_block
*sb
= dir
->i_sb
;
189 struct buffer_head
*bh
;
190 toupper_t toupper
= affs_get_toupper(sb
);
193 pr_debug("%s(\"%.*s\")\n",
194 __func__
, (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
196 bh
= affs_bread(sb
, dir
->i_ino
);
198 return ERR_PTR(-EIO
);
200 key
= be32_to_cpu(AFFS_HEAD(bh
)->table
[affs_hash_name(sb
, dentry
->d_name
.name
, dentry
->d_name
.len
)]);
206 bh
= affs_bread(sb
, key
);
208 return ERR_PTR(-EIO
);
209 if (affs_match(dentry
, AFFS_TAIL(sb
, bh
)->name
, toupper
))
211 key
= be32_to_cpu(AFFS_TAIL(sb
, bh
)->hash_chain
);
216 affs_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
218 struct super_block
*sb
= dir
->i_sb
;
219 struct buffer_head
*bh
;
220 struct inode
*inode
= NULL
;
222 pr_debug("%s(\"%.*s\")\n",
223 __func__
, (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
226 bh
= affs_find_entry(dir
, dentry
);
227 affs_unlock_dir(dir
);
231 u32 ino
= bh
->b_blocknr
;
233 /* store the real header ino in d_fsdata for faster lookups */
234 dentry
->d_fsdata
= (void *)(long)ino
;
235 switch (be32_to_cpu(AFFS_TAIL(sb
, bh
)->stype
)) {
236 //link to dirs disabled
239 ino
= be32_to_cpu(AFFS_TAIL(sb
, bh
)->original
);
242 inode
= affs_iget(sb
, ino
);
244 return ERR_CAST(inode
);
246 d_add(dentry
, inode
);
251 affs_unlink(struct inode
*dir
, struct dentry
*dentry
)
253 pr_debug("%s(dir=%d, %lu \"%.*s\")\n",
254 __func__
, (u32
)dir
->i_ino
, dentry
->d_inode
->i_ino
,
255 (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
257 return affs_remove_header(dentry
);
261 affs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
, bool excl
)
263 struct super_block
*sb
= dir
->i_sb
;
267 pr_debug("%s(%lu,\"%.*s\",0%ho)\n",
268 __func__
, dir
->i_ino
, (int)dentry
->d_name
.len
,
269 dentry
->d_name
.name
,mode
);
271 inode
= affs_new_inode(dir
);
275 inode
->i_mode
= mode
;
277 mark_inode_dirty(inode
);
279 inode
->i_op
= &affs_file_inode_operations
;
280 inode
->i_fop
= &affs_file_operations
;
281 inode
->i_mapping
->a_ops
= (AFFS_SB(sb
)->s_flags
& SF_OFS
) ? &affs_aops_ofs
: &affs_aops
;
282 error
= affs_add_entry(dir
, inode
, dentry
, ST_FILE
);
292 affs_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
297 pr_debug("%s(%lu,\"%.*s\",0%ho)\n",
298 __func__
, dir
->i_ino
, (int)dentry
->d_name
.len
,
299 dentry
->d_name
.name
, mode
);
301 inode
= affs_new_inode(dir
);
305 inode
->i_mode
= S_IFDIR
| mode
;
308 inode
->i_op
= &affs_dir_inode_operations
;
309 inode
->i_fop
= &affs_dir_operations
;
311 error
= affs_add_entry(dir
, inode
, dentry
, ST_USERDIR
);
314 mark_inode_dirty(inode
);
322 affs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
324 pr_debug("%s(dir=%u, %lu \"%.*s\")\n",
325 __func__
, (u32
)dir
->i_ino
, dentry
->d_inode
->i_ino
,
326 (int)dentry
->d_name
.len
, dentry
->d_name
.name
);
328 return affs_remove_header(dentry
);
332 affs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
334 struct super_block
*sb
= dir
->i_sb
;
335 struct buffer_head
*bh
;
338 int i
, maxlen
, error
;
341 pr_debug("%s(%lu,\"%.*s\" -> \"%s\")\n",
342 __func__
, dir
->i_ino
, (int)dentry
->d_name
.len
,
343 dentry
->d_name
.name
, symname
);
345 maxlen
= AFFS_SB(sb
)->s_hashsize
* sizeof(u32
) - 1;
346 inode
= affs_new_inode(dir
);
350 inode
->i_op
= &affs_symlink_inode_operations
;
351 inode
->i_data
.a_ops
= &affs_symlink_aops
;
352 inode
->i_mode
= S_IFLNK
| 0777;
356 bh
= affs_bread(sb
, inode
->i_ino
);
360 p
= (char *)AFFS_HEAD(bh
)->table
;
362 if (*symname
== '/') {
363 struct affs_sb_info
*sbi
= AFFS_SB(sb
);
364 while (*symname
== '/')
366 spin_lock(&sbi
->symlink_lock
);
367 while (sbi
->s_volume
[i
]) /* Cannot overflow */
368 *p
++ = sbi
->s_volume
[i
++];
369 spin_unlock(&sbi
->symlink_lock
);
371 while (i
< maxlen
&& (c
= *symname
++)) {
372 if (c
== '.' && lc
== '/' && *symname
== '.' && symname
[1] == '/') {
377 } else if (c
== '.' && lc
== '/' && *symname
== '/') {
386 while (*symname
== '/')
390 mark_buffer_dirty_inode(bh
, inode
);
392 mark_inode_dirty(inode
);
394 error
= affs_add_entry(dir
, inode
, dentry
, ST_SOFTLINK
);
402 mark_inode_dirty(inode
);
408 affs_link(struct dentry
*old_dentry
, struct inode
*dir
, struct dentry
*dentry
)
410 struct inode
*inode
= old_dentry
->d_inode
;
412 pr_debug("%s(%u, %u, \"%.*s\")\n",
413 __func__
, (u32
)inode
->i_ino
, (u32
)dir
->i_ino
,
414 (int)dentry
->d_name
.len
,dentry
->d_name
.name
);
416 return affs_add_entry(dir
, inode
, dentry
, ST_LINKFILE
);
420 affs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
421 struct inode
*new_dir
, struct dentry
*new_dentry
)
423 struct super_block
*sb
= old_dir
->i_sb
;
424 struct buffer_head
*bh
= NULL
;
427 pr_debug("%s(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
428 __func__
, (u32
)old_dir
->i_ino
, (int)old_dentry
->d_name
.len
,
429 old_dentry
->d_name
.name
, (u32
)new_dir
->i_ino
,
430 (int)new_dentry
->d_name
.len
, new_dentry
->d_name
.name
);
432 retval
= affs_check_name(new_dentry
->d_name
.name
,
433 new_dentry
->d_name
.len
,
434 affs_nofilenametruncate(old_dentry
));
439 /* Unlink destination if it already exists */
440 if (new_dentry
->d_inode
) {
441 retval
= affs_remove_header(new_dentry
);
446 bh
= affs_bread(sb
, old_dentry
->d_inode
->i_ino
);
450 /* Remove header from its parent directory. */
451 affs_lock_dir(old_dir
);
452 retval
= affs_remove_hash(old_dir
, bh
);
453 affs_unlock_dir(old_dir
);
457 /* And insert it into the new directory with the new name. */
458 affs_copy_name(AFFS_TAIL(sb
, bh
)->name
, new_dentry
);
459 affs_fix_checksum(sb
, bh
);
460 affs_lock_dir(new_dir
);
461 retval
= affs_insert_hash(new_dir
, bh
);
462 affs_unlock_dir(new_dir
);
463 /* TODO: move it back to old_dir, if error? */
466 mark_buffer_dirty_inode(bh
, retval
? old_dir
: new_dir
);