xref: /linux/fs/ntfs3/namei.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
14342306fSKonstantin Komarov // SPDX-License-Identifier: GPL-2.0
24342306fSKonstantin Komarov /*
34342306fSKonstantin Komarov  *
44342306fSKonstantin Komarov  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
54342306fSKonstantin Komarov  *
64342306fSKonstantin Komarov  */
74342306fSKonstantin Komarov 
84342306fSKonstantin Komarov #include <linux/fs.h>
94342306fSKonstantin Komarov #include <linux/nls.h>
10a3a956c7SKonstantin Komarov #include <linux/ctype.h>
112b108260SKonstantin Komarov #include <linux/posix_acl.h>
124342306fSKonstantin Komarov 
134342306fSKonstantin Komarov #include "debug.h"
144342306fSKonstantin Komarov #include "ntfs.h"
154342306fSKonstantin Komarov #include "ntfs_fs.h"
164342306fSKonstantin Komarov 
174342306fSKonstantin Komarov /*
18e8b8e97fSKari Argillander  * fill_name_de - Format NTFS_DE in @buf.
194342306fSKonstantin Komarov  */
fill_name_de(struct ntfs_sb_info * sbi,void * buf,const struct qstr * name,const struct cpu_str * uni)204342306fSKonstantin Komarov int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
214342306fSKonstantin Komarov 		 const struct cpu_str *uni)
224342306fSKonstantin Komarov {
234342306fSKonstantin Komarov 	int err;
244342306fSKonstantin Komarov 	struct NTFS_DE *e = buf;
254342306fSKonstantin Komarov 	u16 data_size;
264342306fSKonstantin Komarov 	struct ATTR_FILE_NAME *fname = (struct ATTR_FILE_NAME *)(e + 1);
274342306fSKonstantin Komarov 
284342306fSKonstantin Komarov #ifndef CONFIG_NTFS3_64BIT_CLUSTER
294342306fSKonstantin Komarov 	e->ref.high = fname->home.high = 0;
304342306fSKonstantin Komarov #endif
314342306fSKonstantin Komarov 	if (uni) {
324342306fSKonstantin Komarov #ifdef __BIG_ENDIAN
334342306fSKonstantin Komarov 		int ulen = uni->len;
344342306fSKonstantin Komarov 		__le16 *uname = fname->name;
354342306fSKonstantin Komarov 		const u16 *name_cpu = uni->name;
364342306fSKonstantin Komarov 
374342306fSKonstantin Komarov 		while (ulen--)
384342306fSKonstantin Komarov 			*uname++ = cpu_to_le16(*name_cpu++);
394342306fSKonstantin Komarov #else
404342306fSKonstantin Komarov 		memcpy(fname->name, uni->name, uni->len * sizeof(u16));
414342306fSKonstantin Komarov #endif
424342306fSKonstantin Komarov 		fname->name_len = uni->len;
434342306fSKonstantin Komarov 
444342306fSKonstantin Komarov 	} else {
45e8b8e97fSKari Argillander 		/* Convert input string to unicode. */
464342306fSKonstantin Komarov 		err = ntfs_nls_to_utf16(sbi, name->name, name->len,
474342306fSKonstantin Komarov 					(struct cpu_str *)&fname->name_len,
484342306fSKonstantin Komarov 					NTFS_NAME_LEN, UTF16_LITTLE_ENDIAN);
494342306fSKonstantin Komarov 		if (err < 0)
504342306fSKonstantin Komarov 			return err;
514342306fSKonstantin Komarov 	}
524342306fSKonstantin Komarov 
534342306fSKonstantin Komarov 	fname->type = FILE_NAME_POSIX;
544342306fSKonstantin Komarov 	data_size = fname_full_size(fname);
554342306fSKonstantin Komarov 
56fa3cacf5SKari Argillander 	e->size = cpu_to_le16(ALIGN(data_size, 8) + sizeof(struct NTFS_DE));
574342306fSKonstantin Komarov 	e->key_size = cpu_to_le16(data_size);
584342306fSKonstantin Komarov 	e->flags = 0;
594342306fSKonstantin Komarov 	e->res = 0;
604342306fSKonstantin Komarov 
614342306fSKonstantin Komarov 	return 0;
624342306fSKonstantin Komarov }
634342306fSKonstantin Komarov 
644342306fSKonstantin Komarov /*
65e8b8e97fSKari Argillander  * ntfs_lookup - inode_operations::lookup
664342306fSKonstantin Komarov  */
ntfs_lookup(struct inode * dir,struct dentry * dentry,u32 flags)674342306fSKonstantin Komarov static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
684342306fSKonstantin Komarov 				  u32 flags)
694342306fSKonstantin Komarov {
704342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(dir);
714342306fSKonstantin Komarov 	struct cpu_str *uni = __getname();
724342306fSKonstantin Komarov 	struct inode *inode;
734342306fSKonstantin Komarov 	int err;
744342306fSKonstantin Komarov 
754342306fSKonstantin Komarov 	if (!uni)
764342306fSKonstantin Komarov 		inode = ERR_PTR(-ENOMEM);
774342306fSKonstantin Komarov 	else {
784342306fSKonstantin Komarov 		err = ntfs_nls_to_utf16(ni->mi.sbi, dentry->d_name.name,
794342306fSKonstantin Komarov 					dentry->d_name.len, uni, NTFS_NAME_LEN,
804342306fSKonstantin Komarov 					UTF16_HOST_ENDIAN);
814342306fSKonstantin Komarov 		if (err < 0)
824342306fSKonstantin Komarov 			inode = ERR_PTR(err);
834342306fSKonstantin Komarov 		else {
8403b09709SKonstantin Komarov 			ni_lock_dir(ni);
854342306fSKonstantin Komarov 			inode = dir_search_u(dir, uni, NULL);
864342306fSKonstantin Komarov 			ni_unlock(ni);
874342306fSKonstantin Komarov 		}
884342306fSKonstantin Komarov 		__putname(uni);
894342306fSKonstantin Komarov 	}
904342306fSKonstantin Komarov 
91254e69f2SZhangPeng 	/*
92254e69f2SZhangPeng 	 * Check for a null pointer
93254e69f2SZhangPeng 	 * If the MFT record of ntfs inode is not a base record, inode->i_op can be NULL.
94254e69f2SZhangPeng 	 * This causes null pointer dereference in d_splice_alias().
95254e69f2SZhangPeng 	 */
966827d50bSKonstantin Komarov 	if (!IS_ERR_OR_NULL(inode) && !inode->i_op) {
97254e69f2SZhangPeng 		iput(inode);
98254e69f2SZhangPeng 		inode = ERR_PTR(-EINVAL);
99254e69f2SZhangPeng 	}
100254e69f2SZhangPeng 
1014342306fSKonstantin Komarov 	return d_splice_alias(inode, dentry);
1024342306fSKonstantin Komarov }
1034342306fSKonstantin Komarov 
1044342306fSKonstantin Komarov /*
105e8b8e97fSKari Argillander  * ntfs_create - inode_operations::create
1064342306fSKonstantin Komarov  */
ntfs_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)1076c960e68SChristian Brauner static int ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
1084342306fSKonstantin Komarov 		       struct dentry *dentry, umode_t mode, bool excl)
1094342306fSKonstantin Komarov {
110c935c668SKonstantin Komarov 	return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode, 0,
111f0377761SKonstantin Komarov 				 NULL, 0, NULL);
1124342306fSKonstantin Komarov }
1134342306fSKonstantin Komarov 
1144342306fSKonstantin Komarov /*
115911daf69SKonstantin Komarov  * ntfs_mknod - inode_operations::mknod
1164342306fSKonstantin Komarov  */
ntfs_mknod(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,dev_t rdev)1175ebb29beSChristian Brauner static int ntfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
1184342306fSKonstantin Komarov 		      struct dentry *dentry, umode_t mode, dev_t rdev)
1194342306fSKonstantin Komarov {
120c935c668SKonstantin Komarov 	return ntfs_create_inode(idmap, dir, dentry, NULL, mode, rdev, NULL, 0,
121f0377761SKonstantin Komarov 				 NULL);
1224342306fSKonstantin Komarov }
1234342306fSKonstantin Komarov 
1244342306fSKonstantin Komarov /*
125e8b8e97fSKari Argillander  * ntfs_link - inode_operations::link
1264342306fSKonstantin Komarov  */
ntfs_link(struct dentry * ode,struct inode * dir,struct dentry * de)1274342306fSKonstantin Komarov static int ntfs_link(struct dentry *ode, struct inode *dir, struct dentry *de)
1284342306fSKonstantin Komarov {
1294342306fSKonstantin Komarov 	int err;
1304342306fSKonstantin Komarov 	struct inode *inode = d_inode(ode);
1314342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(inode);
1324342306fSKonstantin Komarov 
1334342306fSKonstantin Komarov 	if (S_ISDIR(inode->i_mode))
1344342306fSKonstantin Komarov 		return -EPERM;
1354342306fSKonstantin Komarov 
1364342306fSKonstantin Komarov 	if (inode->i_nlink >= NTFS_LINK_MAX)
1374342306fSKonstantin Komarov 		return -EMLINK;
1384342306fSKonstantin Komarov 
1394342306fSKonstantin Komarov 	ni_lock_dir(ntfs_i(dir));
1404342306fSKonstantin Komarov 	if (inode != dir)
1414342306fSKonstantin Komarov 		ni_lock(ni);
1424342306fSKonstantin Komarov 
1434342306fSKonstantin Komarov 	inc_nlink(inode);
1444342306fSKonstantin Komarov 	ihold(inode);
1454342306fSKonstantin Komarov 
1464342306fSKonstantin Komarov 	err = ntfs_link_inode(inode, de);
14778ab59feSKonstantin Komarov 
1484342306fSKonstantin Komarov 	if (!err) {
1492be861faSJeff Layton 		inode_set_ctime_current(inode);
1502be861faSJeff Layton 		inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
1514342306fSKonstantin Komarov 		mark_inode_dirty(inode);
1524342306fSKonstantin Komarov 		mark_inode_dirty(dir);
1534342306fSKonstantin Komarov 		d_instantiate(de, inode);
1544342306fSKonstantin Komarov 	} else {
1554342306fSKonstantin Komarov 		drop_nlink(inode);
1564342306fSKonstantin Komarov 		iput(inode);
1574342306fSKonstantin Komarov 	}
1584342306fSKonstantin Komarov 
1594342306fSKonstantin Komarov 	if (inode != dir)
1604342306fSKonstantin Komarov 		ni_unlock(ni);
1614342306fSKonstantin Komarov 	ni_unlock(ntfs_i(dir));
1624342306fSKonstantin Komarov 
1634342306fSKonstantin Komarov 	return err;
1644342306fSKonstantin Komarov }
1654342306fSKonstantin Komarov 
1664342306fSKonstantin Komarov /*
167e8b8e97fSKari Argillander  * ntfs_unlink - inode_operations::unlink
1684342306fSKonstantin Komarov  */
ntfs_unlink(struct inode * dir,struct dentry * dentry)1694342306fSKonstantin Komarov static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
1704342306fSKonstantin Komarov {
1714342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(dir);
1724342306fSKonstantin Komarov 	int err;
1734342306fSKonstantin Komarov 
1746c3684e7SKonstantin Komarov 	/* Avoid any operation if inode is bad. */
1756c3684e7SKonstantin Komarov 	if (unlikely(is_bad_ni(ni)))
1766c3684e7SKonstantin Komarov 		return -EINVAL;
1774342306fSKonstantin Komarov 
1784342306fSKonstantin Komarov 	if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
1794342306fSKonstantin Komarov 		return -EIO;
1804342306fSKonstantin Komarov 
1814342306fSKonstantin Komarov 	ni_lock_dir(ni);
1824342306fSKonstantin Komarov 
1834342306fSKonstantin Komarov 	err = ntfs_unlink_inode(dir, dentry);
1844342306fSKonstantin Komarov 
1854342306fSKonstantin Komarov 	ni_unlock(ni);
1864342306fSKonstantin Komarov 
187e8b8e97fSKari Argillander 	return err;
1884342306fSKonstantin Komarov }
1897a77db95SChristian Brauner 
1904342306fSKonstantin Komarov /*
1914342306fSKonstantin Komarov  * ntfs_symlink - inode_operations::symlink
1924342306fSKonstantin Komarov  */
ntfs_symlink(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,const char * symname)1934342306fSKonstantin Komarov static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
1946c3684e7SKonstantin Komarov 			struct dentry *dentry, const char *symname)
1956c3684e7SKonstantin Komarov {
1966c3684e7SKonstantin Komarov 	u32 size = strlen(symname);
197c935c668SKonstantin Komarov 
198f0377761SKonstantin Komarov 	/* Avoid any operation if inode is bad. */
1994342306fSKonstantin Komarov 	if (unlikely(is_bad_ni(ntfs_i(dir))))
2004342306fSKonstantin Komarov 		return -EINVAL;
2014342306fSKonstantin Komarov 
202e8b8e97fSKari Argillander 	if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
2034342306fSKonstantin Komarov 		return -EIO;
204*88d5baf6SNeilBrown 
2054342306fSKonstantin Komarov 	return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
2064342306fSKonstantin Komarov 				 symname, size, NULL);
207*88d5baf6SNeilBrown }
208*88d5baf6SNeilBrown 
2094342306fSKonstantin Komarov /*
2104342306fSKonstantin Komarov  * ntfs_mkdir- inode_operations::mkdir
2114342306fSKonstantin Komarov  */
ntfs_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)2126700eabbSKonstantin Komarov static struct dentry *ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
2134342306fSKonstantin Komarov 				 struct dentry *dentry, umode_t mode)
2144342306fSKonstantin Komarov {
2154342306fSKonstantin Komarov 	return ERR_PTR(ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
2164342306fSKonstantin Komarov 					 NULL, 0, NULL));
2174342306fSKonstantin Komarov }
2184342306fSKonstantin Komarov 
2196c3684e7SKonstantin Komarov /*
2206c3684e7SKonstantin Komarov  * ntfs_rmdir - inode_operations::rmdir
2216c3684e7SKonstantin Komarov  */
ntfs_rmdir(struct inode * dir,struct dentry * dentry)2224342306fSKonstantin Komarov static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
2234342306fSKonstantin Komarov {
2244342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(dir);
2254342306fSKonstantin Komarov 	int err;
2264342306fSKonstantin Komarov 
2274342306fSKonstantin Komarov 	/* Avoid any operation if inode is bad. */
2284342306fSKonstantin Komarov 	if (unlikely(is_bad_ni(ni)))
2294342306fSKonstantin Komarov 		return -EINVAL;
2304342306fSKonstantin Komarov 
2314342306fSKonstantin Komarov 	if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
232e8b8e97fSKari Argillander 		return -EIO;
2334342306fSKonstantin Komarov 
234e18275aeSChristian Brauner 	ni_lock_dir(ni);
23578ab59feSKonstantin Komarov 
2364342306fSKonstantin Komarov 	err = ntfs_unlink_inode(dir, dentry);
2374342306fSKonstantin Komarov 
2384342306fSKonstantin Komarov 	ni_unlock(ni);
23978ab59feSKonstantin Komarov 
2404342306fSKonstantin Komarov 	return err;
24178ab59feSKonstantin Komarov }
2424342306fSKonstantin Komarov 
24378ab59feSKonstantin Komarov /*
24478ab59feSKonstantin Komarov  * ntfs_rename - inode_operations::rename
24578ab59feSKonstantin Komarov  */
ntfs_rename(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,struct inode * new_dir,struct dentry * new_dentry,u32 flags)24678ab59feSKonstantin Komarov static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
24778ab59feSKonstantin Komarov 		       struct dentry *dentry, struct inode *new_dir,
24878ab59feSKonstantin Komarov 		       struct dentry *new_dentry, u32 flags)
24978ab59feSKonstantin Komarov {
25078ab59feSKonstantin Komarov 	int err;
25178ab59feSKonstantin Komarov 	struct super_block *sb = dir->i_sb;
25278ab59feSKonstantin Komarov 	struct ntfs_sb_info *sbi = sb->s_fs_info;
25378ab59feSKonstantin Komarov 	struct ntfs_inode *dir_ni = ntfs_i(dir);
2544342306fSKonstantin Komarov 	struct ntfs_inode *new_dir_ni = ntfs_i(new_dir);
2554342306fSKonstantin Komarov 	struct inode *inode = d_inode(dentry);
2564342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(inode);
2574342306fSKonstantin Komarov 	struct inode *new_inode = d_inode(new_dentry);
2584342306fSKonstantin Komarov 	struct NTFS_DE *de, *new_de;
2596c3684e7SKonstantin Komarov 	bool is_same;
2606c3684e7SKonstantin Komarov 	/*
2616c3684e7SKonstantin Komarov 	 * de		- memory of PATH_MAX bytes:
2624342306fSKonstantin Komarov 	 * [0-1024)	- original name (dentry->d_name)
2634342306fSKonstantin Komarov 	 * [1024-2048)	- paired to original name, usually DOS variant of dentry->d_name
2644342306fSKonstantin Komarov 	 * [2048-3072)	- new name (new_dentry->d_name)
26578ab59feSKonstantin Komarov 	 */
26678ab59feSKonstantin Komarov 	static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024);
26778ab59feSKonstantin Komarov 	static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) <
2684342306fSKonstantin Komarov 		      1024);
26978ab59feSKonstantin Komarov 	static_assert(PATH_MAX >= 4 * 1024);
270e8b8e97fSKari Argillander 
27178ab59feSKonstantin Komarov 	/* Avoid any operation if inode is bad. */
2724342306fSKonstantin Komarov 	if (unlikely(is_bad_ni(ni)))
2734342306fSKonstantin Komarov 		return -EINVAL;
27478ab59feSKonstantin Komarov 
27578ab59feSKonstantin Komarov 	if (unlikely(ntfs3_forced_shutdown(sb)))
27678ab59feSKonstantin Komarov 		return -EIO;
2774342306fSKonstantin Komarov 
2784342306fSKonstantin Komarov 	if (flags & ~RENAME_NOREPLACE)
2794342306fSKonstantin Komarov 		return -EINVAL;
280e8b8e97fSKari Argillander 
2814342306fSKonstantin Komarov 	is_same = dentry->d_name.len == new_dentry->d_name.len &&
2824342306fSKonstantin Komarov 		  !memcmp(dentry->d_name.name, new_dentry->d_name.name,
2834342306fSKonstantin Komarov 			  dentry->d_name.len);
2844342306fSKonstantin Komarov 
2854342306fSKonstantin Komarov 	if (is_same && dir == new_dir) {
2864342306fSKonstantin Komarov 		/* Nothing to do. */
28778ab59feSKonstantin Komarov 		return 0;
2884342306fSKonstantin Komarov 	}
2894342306fSKonstantin Komarov 
290e8b8e97fSKari Argillander 	if (ntfs_is_meta_file(sbi, inode->i_ino)) {
29178ab59feSKonstantin Komarov 		/* Should we print an error? */
29278ab59feSKonstantin Komarov 		return -EINVAL;
29378ab59feSKonstantin Komarov 	}
29478ab59feSKonstantin Komarov 
29578ab59feSKonstantin Komarov 	if (new_inode) {
29678ab59feSKonstantin Komarov 		/* Target name exists. Unlink it. */
29778ab59feSKonstantin Komarov 		dget(new_dentry);
29878ab59feSKonstantin Komarov 		ni_lock_dir(new_dir_ni);
29978ab59feSKonstantin Komarov 		err = ntfs_unlink_inode(new_dir, new_dentry);
30078ab59feSKonstantin Komarov 		ni_unlock(new_dir_ni);
30178ab59feSKonstantin Komarov 		dput(new_dentry);
30278ab59feSKonstantin Komarov 		if (err)
30378ab59feSKonstantin Komarov 			return err;
30478ab59feSKonstantin Komarov 	}
30578ab59feSKonstantin Komarov 
30678ab59feSKonstantin Komarov 	/* Allocate PATH_MAX bytes. */
30778ab59feSKonstantin Komarov 	de = __getname();
3084342306fSKonstantin Komarov 	if (!de)
3094342306fSKonstantin Komarov 		return -ENOMEM;
3104342306fSKonstantin Komarov 
31178ab59feSKonstantin Komarov 	/* Translate dentry->d_name into unicode form. */
31278ab59feSKonstantin Komarov 	err = fill_name_de(sbi, de, &dentry->d_name, NULL);
3130ad9dfcbSKonstantin Komarov 	if (err < 0)
3140ad9dfcbSKonstantin Komarov 		goto out;
3154342306fSKonstantin Komarov 
31678ab59feSKonstantin Komarov 	if (is_same) {
31778ab59feSKonstantin Komarov 		/* Reuse 'de'. */
31878ab59feSKonstantin Komarov 		new_de = de;
31978ab59feSKonstantin Komarov 	} else {
320c12df45eSKonstantin Komarov 		/* Translate new_dentry->d_name into unicode form. */
32178ab59feSKonstantin Komarov 		new_de = Add2Ptr(de, 2048);
322487e34fcSJeff Layton 		err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL);
32378ab59feSKonstantin Komarov 		if (err < 0)
32478ab59feSKonstantin Komarov 			goto out;
325487e34fcSJeff Layton 	}
3264342306fSKonstantin Komarov 
3274342306fSKonstantin Komarov 	ni_lock_dir(dir_ni);
32878ab59feSKonstantin Komarov 	ni_lock(ni);
32978ab59feSKonstantin Komarov 	if (dir_ni != new_dir_ni)
33078ab59feSKonstantin Komarov 		ni_lock_dir2(new_dir_ni);
33178ab59feSKonstantin Komarov 
33278ab59feSKonstantin Komarov 	err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de);
3334342306fSKonstantin Komarov 	if (!err) {
3344342306fSKonstantin Komarov 		simple_rename_timestamp(dir, dentry, new_dir, new_dentry);
3350ad9dfcbSKonstantin Komarov 		mark_inode_dirty(inode);
3360ad9dfcbSKonstantin Komarov 		mark_inode_dirty(dir);
33778ab59feSKonstantin Komarov 		if (dir != new_dir)
33878ab59feSKonstantin Komarov 			mark_inode_dirty(new_dir);
3394342306fSKonstantin Komarov 
34078ab59feSKonstantin Komarov 		if (IS_DIRSYNC(dir))
3414342306fSKonstantin Komarov 			ntfs_sync_inode(dir);
3424342306fSKonstantin Komarov 
3434342306fSKonstantin Komarov 		if (IS_DIRSYNC(new_dir))
3444342306fSKonstantin Komarov 			ntfs_sync_inode(inode);
3454342306fSKonstantin Komarov 	}
3464342306fSKonstantin Komarov 
3474342306fSKonstantin Komarov 	if (dir_ni != new_dir_ni)
3484342306fSKonstantin Komarov 		ni_unlock(new_dir_ni);
3494342306fSKonstantin Komarov 	ni_unlock(ni);
3504342306fSKonstantin Komarov 	ni_unlock(dir_ni);
3514342306fSKonstantin Komarov out:
3524342306fSKonstantin Komarov 	__putname(de);
3534342306fSKonstantin Komarov 	return err;
3544342306fSKonstantin Komarov }
3554342306fSKonstantin Komarov 
ntfs3_get_parent(struct dentry * child)3564342306fSKonstantin Komarov struct dentry *ntfs3_get_parent(struct dentry *child)
3574342306fSKonstantin Komarov {
3584342306fSKonstantin Komarov 	struct inode *inode = d_inode(child);
3594342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(inode);
3604342306fSKonstantin Komarov 
3614342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL;
3624342306fSKonstantin Komarov 	struct ATTRIB *attr = NULL;
3634342306fSKonstantin Komarov 	struct ATTR_FILE_NAME *fname;
3644342306fSKonstantin Komarov 
3654342306fSKonstantin Komarov 	while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
366a3a956c7SKonstantin Komarov 				    NULL))) {
367a3a956c7SKonstantin Komarov 		fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
368a3a956c7SKonstantin Komarov 		if (!fname)
369a3a956c7SKonstantin Komarov 			continue;
370a3a956c7SKonstantin Komarov 
371a3a956c7SKonstantin Komarov 		return d_obtain_alias(
372a3a956c7SKonstantin Komarov 			ntfs_iget5(inode->i_sb, &fname->home, NULL));
373a3a956c7SKonstantin Komarov 	}
374a3a956c7SKonstantin Komarov 
375a3a956c7SKonstantin Komarov 	return ERR_PTR(-ENOENT);
376a3a956c7SKonstantin Komarov }
377a3a956c7SKonstantin Komarov 
378a3a956c7SKonstantin Komarov /*
379a3a956c7SKonstantin Komarov  * dentry_operations::d_hash
380a3a956c7SKonstantin Komarov  */
ntfs_d_hash(const struct dentry * dentry,struct qstr * name)381a3a956c7SKonstantin Komarov static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name)
382a3a956c7SKonstantin Komarov {
383a3a956c7SKonstantin Komarov 	struct ntfs_sb_info *sbi;
384a3a956c7SKonstantin Komarov 	const char *n = name->name;
385a3a956c7SKonstantin Komarov 	unsigned int len = name->len;
386a3a956c7SKonstantin Komarov 	unsigned long hash;
387a3a956c7SKonstantin Komarov 	struct cpu_str *uni;
388a3a956c7SKonstantin Komarov 	unsigned int c;
389a3a956c7SKonstantin Komarov 	int err;
390a3a956c7SKonstantin Komarov 
391a3a956c7SKonstantin Komarov 	/* First try fast implementation. */
392a3a956c7SKonstantin Komarov 	hash = init_name_hash(dentry);
393a3a956c7SKonstantin Komarov 
394a3a956c7SKonstantin Komarov 	for (;;) {
395a3a956c7SKonstantin Komarov 		if (!len--) {
396a3a956c7SKonstantin Komarov 			name->hash = end_name_hash(hash);
397a3a956c7SKonstantin Komarov 			return 0;
398589996bfSDiogo Jahchan Koike 		}
399a3a956c7SKonstantin Komarov 
400a3a956c7SKonstantin Komarov 		c = *n++;
401a3a956c7SKonstantin Komarov 		if (c >= 0x80)
402a3a956c7SKonstantin Komarov 			break;
403a3a956c7SKonstantin Komarov 
404a3a956c7SKonstantin Komarov 		hash = partial_name_hash(toupper(c), hash);
405a3a956c7SKonstantin Komarov 	}
406a3a956c7SKonstantin Komarov 
407a3a956c7SKonstantin Komarov 	/*
408a3a956c7SKonstantin Komarov 	 * Try slow way with current upcase table
409a3a956c7SKonstantin Komarov 	 */
410a3a956c7SKonstantin Komarov 	uni = kmem_cache_alloc(names_cachep, GFP_NOWAIT);
411a3a956c7SKonstantin Komarov 	if (!uni)
412a3a956c7SKonstantin Komarov 		return -ENOMEM;
413a3a956c7SKonstantin Komarov 
414a3a956c7SKonstantin Komarov 	sbi = dentry->d_sb->s_fs_info;
415a3a956c7SKonstantin Komarov 
416a3a956c7SKonstantin Komarov 	err = ntfs_nls_to_utf16(sbi, name->name, name->len, uni, NTFS_NAME_LEN,
417a3a956c7SKonstantin Komarov 				UTF16_HOST_ENDIAN);
418a3a956c7SKonstantin Komarov 	if (err < 0)
419a3a956c7SKonstantin Komarov 		goto out;
420589996bfSDiogo Jahchan Koike 
421a3a956c7SKonstantin Komarov 	if (!err) {
422a3a956c7SKonstantin Komarov 		err = -EINVAL;
423a3a956c7SKonstantin Komarov 		goto out;
424a3a956c7SKonstantin Komarov 	}
425a3a956c7SKonstantin Komarov 
426a3a956c7SKonstantin Komarov 	hash = ntfs_names_hash(uni->name, uni->len, sbi->upcase,
427a3a956c7SKonstantin Komarov 			       init_name_hash(dentry));
428a3a956c7SKonstantin Komarov 	name->hash = end_name_hash(hash);
429a3a956c7SKonstantin Komarov 	err = 0;
430a3a956c7SKonstantin Komarov 
431a3a956c7SKonstantin Komarov out:
432a3a956c7SKonstantin Komarov 	kmem_cache_free(names_cachep, uni);
433a3a956c7SKonstantin Komarov 	return err;
434a3a956c7SKonstantin Komarov }
435a3a956c7SKonstantin Komarov 
436a3a956c7SKonstantin Komarov /*
4379144b438SKonstantin Komarov  * dentry_operations::d_compare
4389144b438SKonstantin Komarov  */
ntfs_d_compare(const struct dentry * dentry,unsigned int len1,const char * str,const struct qstr * name)439a3a956c7SKonstantin Komarov static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1,
440a3a956c7SKonstantin Komarov 			  const char *str, const struct qstr *name)
441a3a956c7SKonstantin Komarov {
4420d6d7c61SNathan Chancellor 	struct ntfs_sb_info *sbi;
44375b5e472SNathan Chancellor 	int ret;
444a3a956c7SKonstantin Komarov 	const char *n1 = str;
445a3a956c7SKonstantin Komarov 	const char *n2 = name->name;
446a3a956c7SKonstantin Komarov 	unsigned int len2 = name->len;
447a3a956c7SKonstantin Komarov 	unsigned int lm = min(len1, len2);
448a3a956c7SKonstantin Komarov 	unsigned char c1, c2;
449a3a956c7SKonstantin Komarov 	struct cpu_str *uni1;
450a3a956c7SKonstantin Komarov 	struct le_str *uni2;
4510d6d7c61SNathan Chancellor 
4520d6d7c61SNathan Chancellor 	/* First try fast implementation. */
453a3a956c7SKonstantin Komarov 	for (;;) {
454a3a956c7SKonstantin Komarov 		if (!lm--)
455a3a956c7SKonstantin Komarov 			return len1 != len2;
456a3a956c7SKonstantin Komarov 
457a3a956c7SKonstantin Komarov 		if ((c1 = *n1++) == (c2 = *n2++))
458a3a956c7SKonstantin Komarov 			continue;
459a3a956c7SKonstantin Komarov 
460a3a956c7SKonstantin Komarov 		if (c1 >= 0x80 || c2 >= 0x80)
461a3a956c7SKonstantin Komarov 			break;
462a3a956c7SKonstantin Komarov 
463a3a956c7SKonstantin Komarov 		if (toupper(c1) != toupper(c2))
464a3a956c7SKonstantin Komarov 			return 1;
465a3a956c7SKonstantin Komarov 	}
466a3a956c7SKonstantin Komarov 
467a3a956c7SKonstantin Komarov 	/*
468a3a956c7SKonstantin Komarov 	 * Try slow way with current upcase table
469a3a956c7SKonstantin Komarov 	 */
470a3a956c7SKonstantin Komarov 	sbi = dentry->d_sb->s_fs_info;
471a3a956c7SKonstantin Komarov 	uni1 = __getname();
472a3a956c7SKonstantin Komarov 	if (!uni1)
473a3a956c7SKonstantin Komarov 		return -ENOMEM;
474a3a956c7SKonstantin Komarov 
4759144b438SKonstantin Komarov 	ret = ntfs_nls_to_utf16(sbi, str, len1, uni1, NTFS_NAME_LEN,
4769144b438SKonstantin Komarov 				UTF16_HOST_ENDIAN);
4779144b438SKonstantin Komarov 	if (ret < 0)
478a3a956c7SKonstantin Komarov 		goto out;
479a3a956c7SKonstantin Komarov 
480a3a956c7SKonstantin Komarov 	if (!ret) {
481a3a956c7SKonstantin Komarov 		ret = -EINVAL;
482a3a956c7SKonstantin Komarov 		goto out;
483a3a956c7SKonstantin Komarov 	}
484a3a956c7SKonstantin Komarov 
485a3a956c7SKonstantin Komarov 	uni2 = Add2Ptr(uni1, 2048);
4869144b438SKonstantin Komarov 
487a3a956c7SKonstantin Komarov 	ret = ntfs_nls_to_utf16(sbi, name->name, name->len,
488a3a956c7SKonstantin Komarov 				(struct cpu_str *)uni2, NTFS_NAME_LEN,
489a3a956c7SKonstantin Komarov 				UTF16_LITTLE_ENDIAN);
490a3a956c7SKonstantin Komarov 	if (ret < 0)
491a3a956c7SKonstantin Komarov 		goto out;
492a3a956c7SKonstantin Komarov 
4934342306fSKonstantin Komarov 	if (!ret) {
4944342306fSKonstantin Komarov 		ret = -EINVAL;
4954342306fSKonstantin Komarov 		goto out;
4964342306fSKonstantin Komarov 	}
4974342306fSKonstantin Komarov 
4984342306fSKonstantin Komarov 	ret = !ntfs_cmp_names_cpu(uni1, uni2, sbi->upcase, false) ? 0 : 1;
4994342306fSKonstantin Komarov 
5004342306fSKonstantin Komarov out:
5014342306fSKonstantin Komarov 	__putname(uni1);
5024342306fSKonstantin Komarov 	return ret;
5034342306fSKonstantin Komarov }
50475c5e0c9SKonstantin Komarov 
5054342306fSKonstantin Komarov // clang-format off
506689ecd06SKonstantin Komarov const struct inode_operations ntfs_dir_inode_operations = {
5074342306fSKonstantin Komarov 	.lookup		= ntfs_lookup,
5084342306fSKonstantin Komarov 	.create		= ntfs_create,
5094342306fSKonstantin Komarov 	.link		= ntfs_link,
5104342306fSKonstantin Komarov 	.unlink		= ntfs_unlink,
5114342306fSKonstantin Komarov 	.symlink	= ntfs_symlink,
5124342306fSKonstantin Komarov 	.mkdir		= ntfs_mkdir,
513689ecd06SKonstantin Komarov 	.rmdir		= ntfs_rmdir,
5144342306fSKonstantin Komarov 	.mknod		= ntfs_mknod,
5154342306fSKonstantin Komarov 	.rename		= ntfs_rename,
51675c5e0c9SKonstantin Komarov 	.get_acl	= ntfs_get_acl,
5174342306fSKonstantin Komarov 	.set_acl	= ntfs_set_acl,
5184342306fSKonstantin Komarov 	.setattr	= ntfs_setattr,
519a3a956c7SKonstantin Komarov 	.getattr	= ntfs_getattr,
520a3a956c7SKonstantin Komarov 	.listxattr	= ntfs_listxattr,
521a3a956c7SKonstantin Komarov 	.fiemap		= ntfs_fiemap,
522a3a956c7SKonstantin Komarov };
523a3a956c7SKonstantin Komarov 
524a3a956c7SKonstantin Komarov const struct inode_operations ntfs_special_inode_operations = {
5254342306fSKonstantin Komarov 	.setattr	= ntfs_setattr,
526 	.getattr	= ntfs_getattr,
527 	.listxattr	= ntfs_listxattr,
528 	.get_acl	= ntfs_get_acl,
529 	.set_acl	= ntfs_set_acl,
530 };
531 
532 const struct dentry_operations ntfs_dentry_ops = {
533 	.d_hash		= ntfs_d_hash,
534 	.d_compare	= ntfs_d_compare,
535 };
536 
537 // clang-format on
538