b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/affs/namei.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * (c) 1996 Hans-Joachim Widmaier - Rewritten
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * (C) 1991 Linus Torvalds - minix filesystem
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include "affs.h"
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 13) #include <linux/exportfs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) typedef int (*toupper_t)(int);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) /* Simple toupper() for DOS\1 */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) affs_toupper(int ch)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) /* International toupper() for DOS\3 ("international") */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) affs_intl_toupper(int ch)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) && ch <= 0xFE && ch != 0xF7) ?
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) ch - ('a' - 'A') : ch;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) static inline toupper_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) affs_get_toupper(struct super_block *sb)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) {
79bda4d510f80 (Fabian Frederick 2015-04-16 12:48:24 -0700 38) return affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL) ?
79bda4d510f80 (Fabian Frederick 2015-04-16 12:48:24 -0700 39) affs_intl_toupper : affs_toupper;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) * Note: the dentry argument is the parent dentry.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) static inline int
8387ff2577eb9 (Linus Torvalds 2016-06-10 07:51:30 -0700 46) __affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr, toupper_t toupper, bool notruncate)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) const u8 *name = qstr->name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) unsigned long hash;
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 50) int retval;
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 51) u32 len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52)
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 53) retval = affs_check_name(qstr->name, qstr->len, notruncate);
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 54) if (retval)
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 55) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56)
8387ff2577eb9 (Linus Torvalds 2016-06-10 07:51:30 -0700 57) hash = init_name_hash(dentry);
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 58) len = min(qstr->len, AFFSNAMEMAX);
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 59) for (; len > 0; name++, len--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) hash = partial_name_hash(toupper(*name), hash);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) qstr->hash = end_name_hash(hash);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) static int
da53be12bbb4f (Linus Torvalds 2013-05-21 15:22:44 -0700 67) affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) {
8387ff2577eb9 (Linus Torvalds 2016-06-10 07:51:30 -0700 69) return __affs_hash_dentry(dentry, qstr, affs_toupper,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 70) affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 71)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) }
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 73)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) static int
da53be12bbb4f (Linus Torvalds 2013-05-21 15:22:44 -0700 75) affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) {
8387ff2577eb9 (Linus Torvalds 2016-06-10 07:51:30 -0700 77) return __affs_hash_dentry(dentry, qstr, affs_intl_toupper,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 78) affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 79)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 81)
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 82) static inline int __affs_compare_dentry(unsigned int len,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 83) const char *str, const struct qstr *name, toupper_t toupper,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 84) bool notruncate)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) {
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 86) const u8 *aname = str;
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 87) const u8 *bname = name->name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88)
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 89) /*
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 90) * 'str' is the name of an already existing dentry, so the name
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 91) * must be valid. 'name' must be validated first.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93)
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 94) if (affs_check_name(name->name, name->len, notruncate))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 96)
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 97) /*
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 98) * If the names are longer than the allowed 30 chars,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) * the excess is ignored, so their length may differ.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) */
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 101) if (len >= AFFSNAMEMAX) {
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 102) if (name->len < AFFSNAMEMAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 103) return 1;
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 104) len = AFFSNAMEMAX;
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 105) } else if (len != name->len)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 106) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 108) for (; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) if (toupper(*aname++) != toupper(*bname++))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) static int
6fa67e7075593 (Al Viro 2016-07-31 16:37:25 -0400 116) affs_compare_dentry(const struct dentry *dentry,
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 117) unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) {
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 119)
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 120) return __affs_compare_dentry(len, str, name, affs_toupper,
e0b3f595d13b3 (Al Viro 2016-07-29 18:22:49 -0400 121) affs_nofilenametruncate(dentry));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) }
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 123)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) static int
6fa67e7075593 (Al Viro 2016-07-31 16:37:25 -0400 125) affs_intl_compare_dentry(const struct dentry *dentry,
621e155a35919 (Nicholas Piggin 2011-01-07 17:49:27 +1100 126) unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) {
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 128) return __affs_compare_dentry(len, str, name, affs_intl_toupper,
e0b3f595d13b3 (Al Viro 2016-07-29 18:22:49 -0400 129) affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 130)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134) * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 136)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) static inline int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138) affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) const u8 *name = dentry->d_name.name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) int len = dentry->d_name.len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142)
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 143) if (len >= AFFSNAMEMAX) {
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 144) if (*name2 < AFFSNAMEMAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145) return 0;
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 146) len = AFFSNAMEMAX;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147) } else if (len != *name2)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150) for (name2++; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) if (toupper(*name++) != toupper(*name2++))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 152) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156) int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) toupper_t toupper = affs_get_toupper(sb);
eeb36f8e938d1 (Fabian Frederick 2015-02-17 13:46:20 -0800 160) u32 hash;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 161)
f157853e407c0 (Fabian Frederick 2015-02-17 13:46:23 -0800 162) hash = len = min(len, AFFSNAMEMAX);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) for (; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) hash = (hash * 13 + toupper(*name++)) & 0x7ff;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 165)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) return hash % AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) static struct buffer_head *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) affs_find_entry(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) toupper_t toupper = affs_get_toupper(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175) u32 key;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176)
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 177) pr_debug("%s(\"%pd\")\n", __func__, dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) bh = affs_bread(sb, dir->i_ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) if (!bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181) return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) for (;;) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186) affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187) if (key == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) bh = affs_bread(sb, key);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) if (!bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 191) return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 192) if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) return bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 194) key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 196) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) struct dentry *
00cd8dd3bf95f (Al Viro 2012-06-10 17:13:09 -0400 199) affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) struct inode *inode = NULL;
87fbd639c02ec (Al Viro 2018-05-06 12:20:40 -0400 204) struct dentry *res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205)
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 206) pr_debug("%s(\"%pd\")\n", __func__, dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) affs_lock_dir(dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) bh = affs_find_entry(dir, dentry);
30da870ce4a4e (Al Viro 2018-05-06 12:15:20 -0400 210) if (IS_ERR(bh)) {
30da870ce4a4e (Al Viro 2018-05-06 12:15:20 -0400 211) affs_unlock_dir(dir);
e231c2ee64eb1 (David Howells 2008-02-07 00:15:26 -0800 212) return ERR_CAST(bh);
30da870ce4a4e (Al Viro 2018-05-06 12:15:20 -0400 213) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) if (bh) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215) u32 ino = bh->b_blocknr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) /* store the real header ino in d_fsdata for faster lookups */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) dentry->d_fsdata = (void *)(long)ino;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) //link to dirs disabled
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) //case ST_LINKDIR:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) case ST_LINKFILE:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) affs_brelse(bh);
210f855963ba5 (David Howells 2008-02-07 00:15:29 -0800 226) inode = affs_iget(sb, ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) }
87fbd639c02ec (Al Viro 2018-05-06 12:20:40 -0400 228) res = d_splice_alias(inode, dentry);
87fbd639c02ec (Al Viro 2018-05-06 12:20:40 -0400 229) if (!IS_ERR_OR_NULL(res))
87fbd639c02ec (Al Viro 2018-05-06 12:20:40 -0400 230) res->d_fsdata = dentry->d_fsdata;
30da870ce4a4e (Al Viro 2018-05-06 12:15:20 -0400 231) affs_unlock_dir(dir);
87fbd639c02ec (Al Viro 2018-05-06 12:20:40 -0400 232) return res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) affs_unlink(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) {
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 238) pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 239) d_inode(dentry)->i_ino, dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) return affs_remove_header(dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244) int
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 245) affs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 246) struct dentry *dentry, umode_t mode, bool excl)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251)
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 252) pr_debug("%s(%lu,\"%pd\",0%ho)\n",
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 253) __func__, dir->i_ino, dentry, mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) inode = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) if (!inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259) inode->i_mode = mode;
c1618208511f0 (Fabian Frederick 2017-02-27 14:27:54 -0800 260) affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) inode->i_op = &affs_file_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) inode->i_fop = &affs_file_operations;
79bda4d510f80 (Fabian Frederick 2015-04-16 12:48:24 -0700 265) inode->i_mapping->a_ops = affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS) ?
a0016ff2867ad (Fabian Frederick 2015-04-16 12:48:15 -0700 266) &affs_aops_ofs : &affs_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) error = affs_add_entry(dir, inode, dentry, ST_FILE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) if (error) {
6d6b77f163c7e (Miklos Szeredi 2011-10-28 14:13:28 +0200 269) clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) iput(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 272) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) int
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 277) affs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 278) struct dentry *dentry, umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 279) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 282)
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 283) pr_debug("%s(%lu,\"%pd\",0%ho)\n",
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 284) __func__, dir->i_ino, dentry, mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 285)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 286) inode = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) if (!inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 289)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290) inode->i_mode = S_IFDIR | mode;
c1618208511f0 (Fabian Frederick 2017-02-27 14:27:54 -0800 291) affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) inode->i_op = &affs_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294) inode->i_fop = &affs_dir_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) error = affs_add_entry(dir, inode, dentry, ST_USERDIR);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 297) if (error) {
6d6b77f163c7e (Miklos Szeredi 2011-10-28 14:13:28 +0200 298) clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 299) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) iput(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 307) affs_rmdir(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) {
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 309) pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 310) d_inode(dentry)->i_ino, dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 312) return affs_remove_header(dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 313) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) int
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 316) affs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 317) struct dentry *dentry, const char *symname)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 319) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 322) char *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 323) int i, maxlen, error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 324) char c, lc;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 325)
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 326) pr_debug("%s(%lu,\"%pd\" -> \"%s\")\n",
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 327) __func__, dir->i_ino, dentry, symname);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 329) maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 330) inode = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 331) if (!inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 333)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) inode->i_op = &affs_symlink_inode_operations;
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 335) inode_nohighmem(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 336) inode->i_data.a_ops = &affs_symlink_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 337) inode->i_mode = S_IFLNK | 0777;
c1618208511f0 (Fabian Frederick 2017-02-27 14:27:54 -0800 338) affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 339)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 340) error = -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 341) bh = affs_bread(sb, inode->i_ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 342) if (!bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343) goto err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 344) i = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 345) p = (char *)AFFS_HEAD(bh)->table;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346) lc = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 347) if (*symname == '/') {
29333920a5a46 (Al Viro 2010-01-24 00:04:07 -0500 348) struct affs_sb_info *sbi = AFFS_SB(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) while (*symname == '/')
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350) symname++;
29333920a5a46 (Al Viro 2010-01-24 00:04:07 -0500 351) spin_lock(&sbi->symlink_lock);
29333920a5a46 (Al Viro 2010-01-24 00:04:07 -0500 352) while (sbi->s_volume[i]) /* Cannot overflow */
29333920a5a46 (Al Viro 2010-01-24 00:04:07 -0500 353) *p++ = sbi->s_volume[i++];
29333920a5a46 (Al Viro 2010-01-24 00:04:07 -0500 354) spin_unlock(&sbi->symlink_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) while (i < maxlen && (c = *symname++)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 357) if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) *p++ = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) i++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) symname += 2;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 361) lc = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 362) } else if (c == '.' && lc == '/' && *symname == '/') {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 363) symname++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 364) lc = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 365) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 366) *p++ = c;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 367) lc = c;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 368) i++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 369) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 370) if (lc == '/')
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 371) while (*symname == '/')
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 372) symname++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 373) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 374) *p = 0;
f1bf90724de65 (Fabian Frederick 2017-04-15 08:54:36 +0200 375) inode->i_size = i + 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 376) mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377) affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 378) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 380) error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 381) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 382) goto err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 383)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 384) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 385)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 386) err:
6d6b77f163c7e (Miklos Szeredi 2011-10-28 14:13:28 +0200 387) clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 388) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 389) iput(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 390) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 391) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 392)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 393) int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 394) affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 395) {
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 396) struct inode *inode = d_inode(old_dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 397)
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 398) pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino,
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 399) dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 400)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 401) return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 402) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403)
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 404) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 405) affs_rename(struct inode *old_dir, struct dentry *old_dentry,
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 406) struct inode *new_dir, struct dentry *new_dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 407) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 408) struct super_block *sb = old_dir->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409) struct buffer_head *bh = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 410) int retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 411)
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 412) retval = affs_check_name(new_dentry->d_name.name,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 413) new_dentry->d_name.len,
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 414) affs_nofilenametruncate(old_dentry));
8ca577223f752 (Fabian Frederick 2014-04-07 15:39:01 -0700 415)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 416) if (retval)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 417) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 418)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 419) /* Unlink destination if it already exists */
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 420) if (d_really_is_positive(new_dentry)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421) retval = affs_remove_header(new_dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 422) if (retval)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 424) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 425)
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 426) bh = affs_bread(sb, d_inode(old_dentry)->i_ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 427) if (!bh)
3ac8141366932 (Florin Malita 2006-05-25 18:44:23 -0700 428) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 429)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430) /* Remove header from its parent directory. */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431) affs_lock_dir(old_dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) retval = affs_remove_hash(old_dir, bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 433) affs_unlock_dir(old_dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434) if (retval)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435) goto done;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 437) /* And insert it into the new directory with the new name. */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 438) affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 439) affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 440) affs_lock_dir(new_dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 441) retval = affs_insert_hash(new_dir, bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 442) affs_unlock_dir(new_dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 443) /* TODO: move it back to old_dir, if error? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 444)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445) done:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447) affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 448) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 449) }
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 450)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 451) static int
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 452) affs_xrename(struct inode *old_dir, struct dentry *old_dentry,
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 453) struct inode *new_dir, struct dentry *new_dentry)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 454) {
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 455)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 456) struct super_block *sb = old_dir->i_sb;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 457) struct buffer_head *bh_old = NULL;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 458) struct buffer_head *bh_new = NULL;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 459) int retval;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 460)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 461) bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 462) if (!bh_old)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 463) return -EIO;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 464)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 465) bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino);
70779b897395b (Pan Bian 2021-01-20 00:51:13 -0800 466) if (!bh_new) {
70779b897395b (Pan Bian 2021-01-20 00:51:13 -0800 467) affs_brelse(bh_old);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 468) return -EIO;
70779b897395b (Pan Bian 2021-01-20 00:51:13 -0800 469) }
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 470)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 471) /* Remove old header from its parent directory. */
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 472) affs_lock_dir(old_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 473) retval = affs_remove_hash(old_dir, bh_old);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 474) affs_unlock_dir(old_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 475) if (retval)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 476) goto done;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 477)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 478) /* Remove new header from its parent directory. */
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 479) affs_lock_dir(new_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 480) retval = affs_remove_hash(new_dir, bh_new);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 481) affs_unlock_dir(new_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 482) if (retval)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 483) goto done;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 484)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 485) /* Insert old into the new directory with the new name. */
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 486) affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 487) affs_fix_checksum(sb, bh_old);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 488) affs_lock_dir(new_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 489) retval = affs_insert_hash(new_dir, bh_old);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 490) affs_unlock_dir(new_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 491)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 492) /* Insert new into the old directory with the old name. */
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 493) affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 494) affs_fix_checksum(sb, bh_new);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 495) affs_lock_dir(old_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 496) retval = affs_insert_hash(old_dir, bh_new);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 497) affs_unlock_dir(old_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 498) done:
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 499) mark_buffer_dirty_inode(bh_old, new_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 500) mark_buffer_dirty_inode(bh_new, old_dir);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 501) affs_brelse(bh_old);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 502) affs_brelse(bh_new);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 503) return retval;
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 504) }
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 505)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 506) int affs_rename2(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 507) struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 508) struct dentry *new_dentry, unsigned int flags)
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 509) {
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 510)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 511) if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 512) return -EINVAL;
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 513)
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 514) pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 515) old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 516)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 517) if (flags & RENAME_EXCHANGE)
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 518) return affs_xrename(old_dir, old_dentry, new_dir, new_dentry);
6b4657667ba06 (Fabian Frederick 2017-05-05 20:52:07 +0200 519)
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 520) return affs_rename(old_dir, old_dentry, new_dir, new_dentry);
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 521) }
c6184028a75cf (Fabian Frederick 2017-05-05 20:51:42 +0200 522)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 523) static struct dentry *affs_get_parent(struct dentry *child)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 524) {
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 525) struct inode *parent;
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 526) struct buffer_head *bh;
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 527)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 528) bh = affs_bread(child->d_sb, d_inode(child)->i_ino);
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 529) if (!bh)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 530) return ERR_PTR(-EIO);
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 531)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 532) parent = affs_iget(child->d_sb,
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 533) be32_to_cpu(AFFS_TAIL(child->d_sb, bh)->parent));
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 534) brelse(bh);
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 535) if (IS_ERR(parent))
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 536) return ERR_CAST(parent);
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 537)
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 538) return d_obtain_alias(parent);
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 539) }
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 540)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 541) static struct inode *affs_nfs_get_inode(struct super_block *sb, u64 ino,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 542) u32 generation)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 543) {
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 544) struct inode *inode;
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 545)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 546) if (!affs_validblock(sb, ino))
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 547) return ERR_PTR(-ESTALE);
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 548)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 549) inode = affs_iget(sb, ino);
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 550) if (IS_ERR(inode))
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 551) return ERR_CAST(inode);
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 552)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 553) return inode;
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 554) }
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 555)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 556) static struct dentry *affs_fh_to_dentry(struct super_block *sb, struct fid *fid,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 557) int fh_len, int fh_type)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 558) {
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 559) return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 560) affs_nfs_get_inode);
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 561) }
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 562)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 563) static struct dentry *affs_fh_to_parent(struct super_block *sb, struct fid *fid,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 564) int fh_len, int fh_type)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 565) {
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 566) return generic_fh_to_parent(sb, fid, fh_len, fh_type,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 567) affs_nfs_get_inode);
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 568) }
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 569)
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 570) const struct export_operations affs_export_ops = {
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 571) .fh_to_dentry = affs_fh_to_dentry,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 572) .fh_to_parent = affs_fh_to_parent,
b3b42c0deaa1a (Fabian Frederick 2017-02-27 14:28:00 -0800 573) .get_parent = affs_get_parent,
ed4433d723941 (Fabian Frederick 2017-02-27 14:27:49 -0800 574) };
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 575)
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 576) const struct dentry_operations affs_dentry_operations = {
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 577) .d_hash = affs_hash_dentry,
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 578) .d_compare = affs_compare_dentry,
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 579) };
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 580)
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 581) const struct dentry_operations affs_intl_dentry_operations = {
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 582) .d_hash = affs_intl_hash_dentry,
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 583) .d_compare = affs_intl_compare_dentry,
f567accb3ff4a (Fabian Frederick 2017-02-27 14:27:57 -0800 584) };