linux/fs/ntfs3/namei.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *
   4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
   5 *
   6 */
   7
   8#include <linux/fs.h>
   9#include <linux/nls.h>
  10
  11#include "debug.h"
  12#include "ntfs.h"
  13#include "ntfs_fs.h"
  14
  15/*
  16 * fill_name_de - Format NTFS_DE in @buf.
  17 */
  18int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
  19                 const struct cpu_str *uni)
  20{
  21        int err;
  22        struct NTFS_DE *e = buf;
  23        u16 data_size;
  24        struct ATTR_FILE_NAME *fname = (struct ATTR_FILE_NAME *)(e + 1);
  25
  26#ifndef CONFIG_NTFS3_64BIT_CLUSTER
  27        e->ref.high = fname->home.high = 0;
  28#endif
  29        if (uni) {
  30#ifdef __BIG_ENDIAN
  31                int ulen = uni->len;
  32                __le16 *uname = fname->name;
  33                const u16 *name_cpu = uni->name;
  34
  35                while (ulen--)
  36                        *uname++ = cpu_to_le16(*name_cpu++);
  37#else
  38                memcpy(fname->name, uni->name, uni->len * sizeof(u16));
  39#endif
  40                fname->name_len = uni->len;
  41
  42        } else {
  43                /* Convert input string to unicode. */
  44                err = ntfs_nls_to_utf16(sbi, name->name, name->len,
  45                                        (struct cpu_str *)&fname->name_len,
  46                                        NTFS_NAME_LEN, UTF16_LITTLE_ENDIAN);
  47                if (err < 0)
  48                        return err;
  49        }
  50
  51        fname->type = FILE_NAME_POSIX;
  52        data_size = fname_full_size(fname);
  53
  54        e->size = cpu_to_le16(ALIGN(data_size, 8) + sizeof(struct NTFS_DE));
  55        e->key_size = cpu_to_le16(data_size);
  56        e->flags = 0;
  57        e->res = 0;
  58
  59        return 0;
  60}
  61
  62/*
  63 * ntfs_lookup - inode_operations::lookup
  64 */
  65static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
  66                                  u32 flags)
  67{
  68        struct ntfs_inode *ni = ntfs_i(dir);
  69        struct cpu_str *uni = __getname();
  70        struct inode *inode;
  71        int err;
  72
  73        if (!uni)
  74                inode = ERR_PTR(-ENOMEM);
  75        else {
  76                err = ntfs_nls_to_utf16(ni->mi.sbi, dentry->d_name.name,
  77                                        dentry->d_name.len, uni, NTFS_NAME_LEN,
  78                                        UTF16_HOST_ENDIAN);
  79                if (err < 0)
  80                        inode = ERR_PTR(err);
  81                else {
  82                        ni_lock(ni);
  83                        inode = dir_search_u(dir, uni, NULL);
  84                        ni_unlock(ni);
  85                }
  86                __putname(uni);
  87        }
  88
  89        return d_splice_alias(inode, dentry);
  90}
  91
  92/*
  93 * ntfs_create - inode_operations::create
  94 */
  95static int ntfs_create(struct user_namespace *mnt_userns, struct inode *dir,
  96                       struct dentry *dentry, umode_t mode, bool excl)
  97{
  98        struct inode *inode;
  99
 100        inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFREG | mode,
 101                                  0, NULL, 0, NULL);
 102
 103        return IS_ERR(inode) ? PTR_ERR(inode) : 0;
 104}
 105
 106/*
 107 * ntfs_mknod
 108 *
 109 * inode_operations::mknod
 110 */
 111static int ntfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
 112                      struct dentry *dentry, umode_t mode, dev_t rdev)
 113{
 114        struct inode *inode;
 115
 116        inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, mode, rdev,
 117                                  NULL, 0, NULL);
 118
 119        return IS_ERR(inode) ? PTR_ERR(inode) : 0;
 120}
 121
 122/*
 123 * ntfs_link - inode_operations::link
 124 */
 125static int ntfs_link(struct dentry *ode, struct inode *dir, struct dentry *de)
 126{
 127        int err;
 128        struct inode *inode = d_inode(ode);
 129        struct ntfs_inode *ni = ntfs_i(inode);
 130
 131        if (S_ISDIR(inode->i_mode))
 132                return -EPERM;
 133
 134        if (inode->i_nlink >= NTFS_LINK_MAX)
 135                return -EMLINK;
 136
 137        ni_lock_dir(ntfs_i(dir));
 138        if (inode != dir)
 139                ni_lock(ni);
 140
 141        inc_nlink(inode);
 142        ihold(inode);
 143
 144        err = ntfs_link_inode(inode, de);
 145
 146        if (!err) {
 147                dir->i_ctime = dir->i_mtime = inode->i_ctime =
 148                        current_time(dir);
 149                mark_inode_dirty(inode);
 150                mark_inode_dirty(dir);
 151                d_instantiate(de, inode);
 152        } else {
 153                drop_nlink(inode);
 154                iput(inode);
 155        }
 156
 157        if (inode != dir)
 158                ni_unlock(ni);
 159        ni_unlock(ntfs_i(dir));
 160
 161        return err;
 162}
 163
 164/*
 165 * ntfs_unlink - inode_operations::unlink
 166 */
 167static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
 168{
 169        struct ntfs_inode *ni = ntfs_i(dir);
 170        int err;
 171
 172        ni_lock_dir(ni);
 173
 174        err = ntfs_unlink_inode(dir, dentry);
 175
 176        ni_unlock(ni);
 177
 178        return err;
 179}
 180
 181/*
 182 * ntfs_symlink - inode_operations::symlink
 183 */
 184static int ntfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
 185                        struct dentry *dentry, const char *symname)
 186{
 187        u32 size = strlen(symname);
 188        struct inode *inode;
 189
 190        inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFLNK | 0777,
 191                                  0, symname, size, NULL);
 192
 193        return IS_ERR(inode) ? PTR_ERR(inode) : 0;
 194}
 195
 196/*
 197 * ntfs_mkdir- inode_operations::mkdir
 198 */
 199static int ntfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 200                      struct dentry *dentry, umode_t mode)
 201{
 202        struct inode *inode;
 203
 204        inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFDIR | mode,
 205                                  0, NULL, 0, NULL);
 206
 207        return IS_ERR(inode) ? PTR_ERR(inode) : 0;
 208}
 209
 210/*
 211 * ntfs_rmdir - inode_operations::rm_dir
 212 */
 213static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
 214{
 215        struct ntfs_inode *ni = ntfs_i(dir);
 216        int err;
 217
 218        ni_lock_dir(ni);
 219
 220        err = ntfs_unlink_inode(dir, dentry);
 221
 222        ni_unlock(ni);
 223
 224        return err;
 225}
 226
 227/*
 228 * ntfs_rename - inode_operations::rename
 229 */
 230static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,
 231                       struct dentry *dentry, struct inode *new_dir,
 232                       struct dentry *new_dentry, u32 flags)
 233{
 234        int err;
 235        struct super_block *sb = dir->i_sb;
 236        struct ntfs_sb_info *sbi = sb->s_fs_info;
 237        struct ntfs_inode *dir_ni = ntfs_i(dir);
 238        struct ntfs_inode *new_dir_ni = ntfs_i(new_dir);
 239        struct inode *inode = d_inode(dentry);
 240        struct ntfs_inode *ni = ntfs_i(inode);
 241        struct inode *new_inode = d_inode(new_dentry);
 242        struct NTFS_DE *de, *new_de;
 243        bool is_same, is_bad;
 244        /*
 245         * de           - memory of PATH_MAX bytes:
 246         * [0-1024)     - original name (dentry->d_name)
 247         * [1024-2048)  - paired to original name, usually DOS variant of dentry->d_name
 248         * [2048-3072)  - new name (new_dentry->d_name)
 249         */
 250        static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024);
 251        static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) <
 252                      1024);
 253        static_assert(PATH_MAX >= 4 * 1024);
 254
 255        if (flags & ~RENAME_NOREPLACE)
 256                return -EINVAL;
 257
 258        is_same = dentry->d_name.len == new_dentry->d_name.len &&
 259                  !memcmp(dentry->d_name.name, new_dentry->d_name.name,
 260                          dentry->d_name.len);
 261
 262        if (is_same && dir == new_dir) {
 263                /* Nothing to do. */
 264                return 0;
 265        }
 266
 267        if (ntfs_is_meta_file(sbi, inode->i_ino)) {
 268                /* Should we print an error? */
 269                return -EINVAL;
 270        }
 271
 272        if (new_inode) {
 273                /* Target name exists. Unlink it. */
 274                dget(new_dentry);
 275                ni_lock_dir(new_dir_ni);
 276                err = ntfs_unlink_inode(new_dir, new_dentry);
 277                ni_unlock(new_dir_ni);
 278                dput(new_dentry);
 279                if (err)
 280                        return err;
 281        }
 282
 283        /* Allocate PATH_MAX bytes. */
 284        de = __getname();
 285        if (!de)
 286                return -ENOMEM;
 287
 288        /* Translate dentry->d_name into unicode form. */
 289        err = fill_name_de(sbi, de, &dentry->d_name, NULL);
 290        if (err < 0)
 291                goto out;
 292
 293        if (is_same) {
 294                /* Reuse 'de'. */
 295                new_de = de;
 296        } else {
 297                /* Translate new_dentry->d_name into unicode form. */
 298                new_de = Add2Ptr(de, 2048);
 299                err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL);
 300                if (err < 0)
 301                        goto out;
 302        }
 303
 304        ni_lock_dir(dir_ni);
 305        ni_lock(ni);
 306
 307        is_bad = false;
 308        err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad);
 309        if (is_bad) {
 310                /* Restore after failed rename failed too. */
 311                make_bad_inode(inode);
 312                ntfs_inode_err(inode, "failed to undo rename");
 313                ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
 314        } else if (!err) {
 315                inode->i_ctime = dir->i_ctime = dir->i_mtime =
 316                        current_time(dir);
 317                mark_inode_dirty(inode);
 318                mark_inode_dirty(dir);
 319                if (dir != new_dir) {
 320                        new_dir->i_mtime = new_dir->i_ctime = dir->i_ctime;
 321                        mark_inode_dirty(new_dir);
 322                }
 323
 324                if (IS_DIRSYNC(dir))
 325                        ntfs_sync_inode(dir);
 326
 327                if (IS_DIRSYNC(new_dir))
 328                        ntfs_sync_inode(inode);
 329        }
 330
 331        ni_unlock(ni);
 332        ni_unlock(dir_ni);
 333out:
 334        __putname(de);
 335        return err;
 336}
 337
 338struct dentry *ntfs3_get_parent(struct dentry *child)
 339{
 340        struct inode *inode = d_inode(child);
 341        struct ntfs_inode *ni = ntfs_i(inode);
 342
 343        struct ATTR_LIST_ENTRY *le = NULL;
 344        struct ATTRIB *attr = NULL;
 345        struct ATTR_FILE_NAME *fname;
 346
 347        while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
 348                                    NULL))) {
 349                fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
 350                if (!fname)
 351                        continue;
 352
 353                return d_obtain_alias(
 354                        ntfs_iget5(inode->i_sb, &fname->home, NULL));
 355        }
 356
 357        return ERR_PTR(-ENOENT);
 358}
 359
 360// clang-format off
 361const struct inode_operations ntfs_dir_inode_operations = {
 362        .lookup         = ntfs_lookup,
 363        .create         = ntfs_create,
 364        .link           = ntfs_link,
 365        .unlink         = ntfs_unlink,
 366        .symlink        = ntfs_symlink,
 367        .mkdir          = ntfs_mkdir,
 368        .rmdir          = ntfs_rmdir,
 369        .mknod          = ntfs_mknod,
 370        .rename         = ntfs_rename,
 371        .permission     = ntfs_permission,
 372        .get_acl        = ntfs_get_acl,
 373        .set_acl        = ntfs_set_acl,
 374        .setattr        = ntfs3_setattr,
 375        .getattr        = ntfs_getattr,
 376        .listxattr      = ntfs_listxattr,
 377        .fiemap         = ntfs_fiemap,
 378};
 379
 380const struct inode_operations ntfs_special_inode_operations = {
 381        .setattr        = ntfs3_setattr,
 382        .getattr        = ntfs_getattr,
 383        .listxattr      = ntfs_listxattr,
 384        .get_acl        = ntfs_get_acl,
 385        .set_acl        = ntfs_set_acl,
 386};
 387// clang-format on
 388