1 // SPDX-License-Identifier: GPL-2.0
3 * linux/fs/affs/namei.c
5 * (c) 1996 Hans-Joachim Widmaier - Rewritten
7 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
9 * (C) 1991 Linus Torvalds - minix filesystem
13 #include <linux/exportfs.h>
15 typedef int (*toupper_t
)(int);
17 /* Simple toupper() for DOS\1 */
22 return ch
>= 'a' && ch
<= 'z' ? ch
-= ('a' - 'A') : ch
;
25 /* International toupper() for DOS\3 ("international") */
28 affs_intl_toupper(int ch
)
30 return (ch
>= 'a' && ch
<= 'z') || (ch
>= 0xE0
31 && ch
<= 0xFE && ch
!= 0xF7) ?
32 ch
- ('a' - 'A') : ch
;
35 static inline toupper_t
36 affs_get_toupper(struct super_block
*sb
)
38 return affs_test_opt(AFFS_SB(sb
)->s_flags
, SF_INTL
) ?
39 affs_intl_toupper
: affs_toupper
;
43 * Note: the dentry argument is the parent dentry.
46 __affs_hash_dentry(const struct dentry
*dentry
, struct qstr
*qstr
, toupper_t toupper
, bool notruncate
)
48 const u8
*name
= qstr
->name
;
53 retval
= affs_check_name(qstr
->name
, qstr
->len
, notruncate
);
57 hash
= init_name_hash(dentry
);
58 len
= min(qstr
->len
, AFFSNAMEMAX
);
59 for (; len
> 0; name
++, len
--)
60 hash
= partial_name_hash(toupper(*name
), hash
);
61 qstr
->hash
= end_name_hash(hash
);
67 affs_hash_dentry(const struct dentry
*dentry
, struct qstr
*qstr
)
69 return __affs_hash_dentry(dentry
, qstr
, affs_toupper
,
70 affs_nofilenametruncate(dentry
));
75 affs_intl_hash_dentry(const struct dentry
*dentry
, struct qstr
*qstr
)
77 return __affs_hash_dentry(dentry
, qstr
, affs_intl_toupper
,
78 affs_nofilenametruncate(dentry
));
82 static inline int __affs_compare_dentry(unsigned int len
,
83 const char *str
, const struct qstr
*name
, toupper_t toupper
,
86 const u8
*aname
= str
;
87 const u8
*bname
= name
->name
;
90 * 'str' is the name of an already existing dentry, so the name
91 * must be valid. 'name' must be validated first.
94 if (affs_check_name(name
->name
, name
->len
, notruncate
))
98 * If the names are longer than the allowed 30 chars,
99 * the excess is ignored, so their length may differ.
101 if (len
>= AFFSNAMEMAX
) {
102 if (name
->len
< AFFSNAMEMAX
)
105 } else if (len
!= name
->len
)
108 for (; len
> 0; len
--)
109 if (toupper(*aname
++) != toupper(*bname
++))
116 affs_compare_dentry(const struct dentry
*dentry
,
117 unsigned int len
, const char *str
, const struct qstr
*name
)
120 return __affs_compare_dentry(len
, str
, name
, affs_toupper
,
121 affs_nofilenametruncate(dentry
));
125 affs_intl_compare_dentry(const struct dentry
*dentry
,
126 unsigned int len
, const char *str
, const struct qstr
*name
)
128 return __affs_compare_dentry(len
, str
, name
, affs_intl_toupper
,
129 affs_nofilenametruncate(dentry
));
134 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
138 affs_match(struct dentry
*dentry
, const u8
*name2
, toupper_t toupper
)
140 const u8
*name
= dentry
->d_name
.name
;
141 int len
= dentry
->d_name
.len
;
143 if (len
>= AFFSNAMEMAX
) {
144 if (*name2
< AFFSNAMEMAX
)
147 } else if (len
!= *name2
)
150 for (name2
++; len
> 0; len
--)
151 if (toupper(*name
++) != toupper(*name2
++))
157 affs_hash_name(struct super_block
*sb
, const u8
*name
, unsigned int len
)
159 toupper_t toupper
= affs_get_toupper(sb
);
162 hash
= len
= min(len
, AFFSNAMEMAX
);
163 for (; len
> 0; len
--)
164 hash
= (hash
* 13 + toupper(*name
++)) & 0x7ff;
166 return hash
% AFFS_SB(sb
)->s_hashsize
;
169 static struct buffer_head
*
170 affs_find_entry(struct inode
*dir
, struct dentry
*dentry
)
172 struct super_block
*sb
= dir
->i_sb
;
173 struct buffer_head
*bh
;
174 toupper_t toupper
= affs_get_toupper(sb
);
177 pr_debug("%s(\"%pd\")\n", __func__
, dentry
);
179 bh
= affs_bread(sb
, dir
->i_ino
);
181 return ERR_PTR(-EIO
);
183 key
= be32_to_cpu(AFFS_HEAD(bh
)->table
[affs_hash_name(sb
, dentry
->d_name
.name
, dentry
->d_name
.len
)]);
189 bh
= affs_bread(sb
, key
);
191 return ERR_PTR(-EIO
);
192 if (affs_match(dentry
, AFFS_TAIL(sb
, bh
)->name
, toupper
))
194 key
= be32_to_cpu(AFFS_TAIL(sb
, bh
)->hash_chain
);
199 affs_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
201 struct super_block
*sb
= dir
->i_sb
;
202 struct buffer_head
*bh
;
203 struct inode
*inode
= NULL
;
206 pr_debug("%s(\"%pd\")\n", __func__
, dentry
);
209 bh
= affs_find_entry(dir
, dentry
);
211 affs_unlock_dir(dir
);
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
= affs_iget(sb
, ino
);
228 res
= d_splice_alias(inode
, dentry
);
229 if (!IS_ERR_OR_NULL(res
))
230 res
->d_fsdata
= dentry
->d_fsdata
;
231 affs_unlock_dir(dir
);
236 affs_unlink(struct inode
*dir
, struct dentry
*dentry
)
238 pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__
, dir
->i_ino
,
239 d_inode(dentry
)->i_ino
, dentry
);
241 return affs_remove_header(dentry
);
245 affs_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
, bool excl
)
247 struct super_block
*sb
= dir
->i_sb
;
251 pr_debug("%s(%lu,\"%pd\",0%ho)\n",
252 __func__
, dir
->i_ino
, dentry
, mode
);
254 inode
= affs_new_inode(dir
);
258 inode
->i_mode
= mode
;
259 affs_mode_to_prot(inode
);
260 mark_inode_dirty(inode
);
262 inode
->i_op
= &affs_file_inode_operations
;
263 inode
->i_fop
= &affs_file_operations
;
264 inode
->i_mapping
->a_ops
= affs_test_opt(AFFS_SB(sb
)->s_flags
, SF_OFS
) ?
265 &affs_aops_ofs
: &affs_aops
;
266 error
= affs_add_entry(dir
, inode
, dentry
, ST_FILE
);
276 affs_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
281 pr_debug("%s(%lu,\"%pd\",0%ho)\n",
282 __func__
, dir
->i_ino
, dentry
, mode
);
284 inode
= affs_new_inode(dir
);
288 inode
->i_mode
= S_IFDIR
| mode
;
289 affs_mode_to_prot(inode
);
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("%s(dir=%lu, %lu \"%pd\")\n", __func__
, dir
->i_ino
,
308 d_inode(dentry
)->i_ino
, dentry
);
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("%s(%lu,\"%pd\" -> \"%s\")\n",
324 __func__
, dir
->i_ino
, dentry
, 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_nohighmem(inode
);
333 inode
->i_data
.a_ops
= &affs_symlink_aops
;
334 inode
->i_mode
= S_IFLNK
| 0777;
335 affs_mode_to_prot(inode
);
338 bh
= affs_bread(sb
, inode
->i_ino
);
342 p
= (char *)AFFS_HEAD(bh
)->table
;
344 if (*symname
== '/') {
345 struct affs_sb_info
*sbi
= AFFS_SB(sb
);
346 while (*symname
== '/')
348 spin_lock(&sbi
->symlink_lock
);
349 while (sbi
->s_volume
[i
]) /* Cannot overflow */
350 *p
++ = sbi
->s_volume
[i
++];
351 spin_unlock(&sbi
->symlink_lock
);
353 while (i
< maxlen
&& (c
= *symname
++)) {
354 if (c
== '.' && lc
== '/' && *symname
== '.' && symname
[1] == '/') {
359 } else if (c
== '.' && lc
== '/' && *symname
== '/') {
368 while (*symname
== '/')
372 inode
->i_size
= i
+ 1;
373 mark_buffer_dirty_inode(bh
, inode
);
375 mark_inode_dirty(inode
);
377 error
= affs_add_entry(dir
, inode
, dentry
, ST_SOFTLINK
);
385 mark_inode_dirty(inode
);
391 affs_link(struct dentry
*old_dentry
, struct inode
*dir
, struct dentry
*dentry
)
393 struct inode
*inode
= d_inode(old_dentry
);
395 pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__
, inode
->i_ino
, dir
->i_ino
,
398 return affs_add_entry(dir
, inode
, dentry
, ST_LINKFILE
);
402 affs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
403 struct inode
*new_dir
, struct dentry
*new_dentry
)
405 struct super_block
*sb
= old_dir
->i_sb
;
406 struct buffer_head
*bh
= NULL
;
409 retval
= affs_check_name(new_dentry
->d_name
.name
,
410 new_dentry
->d_name
.len
,
411 affs_nofilenametruncate(old_dentry
));
416 /* Unlink destination if it already exists */
417 if (d_really_is_positive(new_dentry
)) {
418 retval
= affs_remove_header(new_dentry
);
423 bh
= affs_bread(sb
, d_inode(old_dentry
)->i_ino
);
427 /* Remove header from its parent directory. */
428 affs_lock_dir(old_dir
);
429 retval
= affs_remove_hash(old_dir
, bh
);
430 affs_unlock_dir(old_dir
);
434 /* And insert it into the new directory with the new name. */
435 affs_copy_name(AFFS_TAIL(sb
, bh
)->name
, new_dentry
);
436 affs_fix_checksum(sb
, bh
);
437 affs_lock_dir(new_dir
);
438 retval
= affs_insert_hash(new_dir
, bh
);
439 affs_unlock_dir(new_dir
);
440 /* TODO: move it back to old_dir, if error? */
443 mark_buffer_dirty_inode(bh
, retval
? old_dir
: new_dir
);
449 affs_xrename(struct inode
*old_dir
, struct dentry
*old_dentry
,
450 struct inode
*new_dir
, struct dentry
*new_dentry
)
453 struct super_block
*sb
= old_dir
->i_sb
;
454 struct buffer_head
*bh_old
= NULL
;
455 struct buffer_head
*bh_new
= NULL
;
458 bh_old
= affs_bread(sb
, d_inode(old_dentry
)->i_ino
);
462 bh_new
= affs_bread(sb
, d_inode(new_dentry
)->i_ino
);
466 /* Remove old header from its parent directory. */
467 affs_lock_dir(old_dir
);
468 retval
= affs_remove_hash(old_dir
, bh_old
);
469 affs_unlock_dir(old_dir
);
473 /* Remove new header from its parent directory. */
474 affs_lock_dir(new_dir
);
475 retval
= affs_remove_hash(new_dir
, bh_new
);
476 affs_unlock_dir(new_dir
);
480 /* Insert old into the new directory with the new name. */
481 affs_copy_name(AFFS_TAIL(sb
, bh_old
)->name
, new_dentry
);
482 affs_fix_checksum(sb
, bh_old
);
483 affs_lock_dir(new_dir
);
484 retval
= affs_insert_hash(new_dir
, bh_old
);
485 affs_unlock_dir(new_dir
);
487 /* Insert new into the old directory with the old name. */
488 affs_copy_name(AFFS_TAIL(sb
, bh_new
)->name
, old_dentry
);
489 affs_fix_checksum(sb
, bh_new
);
490 affs_lock_dir(old_dir
);
491 retval
= affs_insert_hash(old_dir
, bh_new
);
492 affs_unlock_dir(old_dir
);
494 mark_buffer_dirty_inode(bh_old
, new_dir
);
495 mark_buffer_dirty_inode(bh_new
, old_dir
);
501 int affs_rename2(struct inode
*old_dir
, struct dentry
*old_dentry
,
502 struct inode
*new_dir
, struct dentry
*new_dentry
,
506 if (flags
& ~(RENAME_NOREPLACE
| RENAME_EXCHANGE
))
509 pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__
,
510 old_dir
->i_ino
, old_dentry
, new_dir
->i_ino
, new_dentry
);
512 if (flags
& RENAME_EXCHANGE
)
513 return affs_xrename(old_dir
, old_dentry
, new_dir
, new_dentry
);
515 return affs_rename(old_dir
, old_dentry
, new_dir
, new_dentry
);
518 static struct dentry
*affs_get_parent(struct dentry
*child
)
520 struct inode
*parent
;
521 struct buffer_head
*bh
;
523 bh
= affs_bread(child
->d_sb
, d_inode(child
)->i_ino
);
525 return ERR_PTR(-EIO
);
527 parent
= affs_iget(child
->d_sb
,
528 be32_to_cpu(AFFS_TAIL(child
->d_sb
, bh
)->parent
));
531 return ERR_CAST(parent
);
533 return d_obtain_alias(parent
);
536 static struct inode
*affs_nfs_get_inode(struct super_block
*sb
, u64 ino
,
541 if (!affs_validblock(sb
, ino
))
542 return ERR_PTR(-ESTALE
);
544 inode
= affs_iget(sb
, ino
);
546 return ERR_CAST(inode
);
551 static struct dentry
*affs_fh_to_dentry(struct super_block
*sb
, struct fid
*fid
,
552 int fh_len
, int fh_type
)
554 return generic_fh_to_dentry(sb
, fid
, fh_len
, fh_type
,
558 static struct dentry
*affs_fh_to_parent(struct super_block
*sb
, struct fid
*fid
,
559 int fh_len
, int fh_type
)
561 return generic_fh_to_parent(sb
, fid
, fh_len
, fh_type
,
565 const struct export_operations affs_export_ops
= {
566 .fh_to_dentry
= affs_fh_to_dentry
,
567 .fh_to_parent
= affs_fh_to_parent
,
568 .get_parent
= affs_get_parent
,
571 const struct dentry_operations affs_dentry_operations
= {
572 .d_hash
= affs_hash_dentry
,
573 .d_compare
= affs_compare_dentry
,
576 const struct dentry_operations affs_intl_dentry_operations
= {
577 .d_hash
= affs_intl_hash_dentry
,
578 .d_compare
= affs_intl_compare_dentry
,