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