]> Git Repo - linux.git/blob - fs/ntfs3/namei.c
fs/ntfs3: Change new sparse cluster processing
[linux.git] / fs / ntfs3 / namei.c
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 #include <linux/ctype.h>
11
12 #include "debug.h"
13 #include "ntfs.h"
14 #include "ntfs_fs.h"
15
16 /*
17  * fill_name_de - Format NTFS_DE in @buf.
18  */
19 int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
20                  const struct cpu_str *uni)
21 {
22         int err;
23         struct NTFS_DE *e = buf;
24         u16 data_size;
25         struct ATTR_FILE_NAME *fname = (struct ATTR_FILE_NAME *)(e + 1);
26
27 #ifndef CONFIG_NTFS3_64BIT_CLUSTER
28         e->ref.high = fname->home.high = 0;
29 #endif
30         if (uni) {
31 #ifdef __BIG_ENDIAN
32                 int ulen = uni->len;
33                 __le16 *uname = fname->name;
34                 const u16 *name_cpu = uni->name;
35
36                 while (ulen--)
37                         *uname++ = cpu_to_le16(*name_cpu++);
38 #else
39                 memcpy(fname->name, uni->name, uni->len * sizeof(u16));
40 #endif
41                 fname->name_len = uni->len;
42
43         } else {
44                 /* Convert input string to unicode. */
45                 err = ntfs_nls_to_utf16(sbi, name->name, name->len,
46                                         (struct cpu_str *)&fname->name_len,
47                                         NTFS_NAME_LEN, UTF16_LITTLE_ENDIAN);
48                 if (err < 0)
49                         return err;
50         }
51
52         fname->type = FILE_NAME_POSIX;
53         data_size = fname_full_size(fname);
54
55         e->size = cpu_to_le16(ALIGN(data_size, 8) + sizeof(struct NTFS_DE));
56         e->key_size = cpu_to_le16(data_size);
57         e->flags = 0;
58         e->res = 0;
59
60         return 0;
61 }
62
63 /*
64  * ntfs_lookup - inode_operations::lookup
65  */
66 static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
67                                   u32 flags)
68 {
69         struct ntfs_inode *ni = ntfs_i(dir);
70         struct cpu_str *uni = __getname();
71         struct inode *inode;
72         int err;
73
74         if (!uni)
75                 inode = ERR_PTR(-ENOMEM);
76         else {
77                 err = ntfs_nls_to_utf16(ni->mi.sbi, dentry->d_name.name,
78                                         dentry->d_name.len, uni, NTFS_NAME_LEN,
79                                         UTF16_HOST_ENDIAN);
80                 if (err < 0)
81                         inode = ERR_PTR(err);
82                 else {
83                         ni_lock(ni);
84                         inode = dir_search_u(dir, uni, NULL);
85                         ni_unlock(ni);
86                 }
87                 __putname(uni);
88         }
89
90         return d_splice_alias(inode, dentry);
91 }
92
93 /*
94  * ntfs_create - inode_operations::create
95  */
96 static int ntfs_create(struct user_namespace *mnt_userns, struct inode *dir,
97                        struct dentry *dentry, umode_t mode, bool excl)
98 {
99         struct inode *inode;
100
101         inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFREG | mode,
102                                   0, NULL, 0, NULL);
103
104         return IS_ERR(inode) ? PTR_ERR(inode) : 0;
105 }
106
107 /*
108  * ntfs_mknod
109  *
110  * inode_operations::mknod
111  */
112 static int ntfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
113                       struct dentry *dentry, umode_t mode, dev_t rdev)
114 {
115         struct inode *inode;
116
117         inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, mode, rdev,
118                                   NULL, 0, NULL);
119
120         return IS_ERR(inode) ? PTR_ERR(inode) : 0;
121 }
122
123 /*
124  * ntfs_link - inode_operations::link
125  */
126 static int ntfs_link(struct dentry *ode, struct inode *dir, struct dentry *de)
127 {
128         int err;
129         struct inode *inode = d_inode(ode);
130         struct ntfs_inode *ni = ntfs_i(inode);
131
132         if (S_ISDIR(inode->i_mode))
133                 return -EPERM;
134
135         if (inode->i_nlink >= NTFS_LINK_MAX)
136                 return -EMLINK;
137
138         ni_lock_dir(ntfs_i(dir));
139         if (inode != dir)
140                 ni_lock(ni);
141
142         inc_nlink(inode);
143         ihold(inode);
144
145         err = ntfs_link_inode(inode, de);
146
147         if (!err) {
148                 dir->i_ctime = dir->i_mtime = inode->i_ctime =
149                         current_time(dir);
150                 mark_inode_dirty(inode);
151                 mark_inode_dirty(dir);
152                 d_instantiate(de, inode);
153         } else {
154                 drop_nlink(inode);
155                 iput(inode);
156         }
157
158         if (inode != dir)
159                 ni_unlock(ni);
160         ni_unlock(ntfs_i(dir));
161
162         return err;
163 }
164
165 /*
166  * ntfs_unlink - inode_operations::unlink
167  */
168 static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
169 {
170         struct ntfs_inode *ni = ntfs_i(dir);
171         int err;
172
173         ni_lock_dir(ni);
174
175         err = ntfs_unlink_inode(dir, dentry);
176
177         ni_unlock(ni);
178
179         return err;
180 }
181
182 /*
183  * ntfs_symlink - inode_operations::symlink
184  */
185 static int ntfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
186                         struct dentry *dentry, const char *symname)
187 {
188         u32 size = strlen(symname);
189         struct inode *inode;
190
191         inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFLNK | 0777,
192                                   0, symname, size, NULL);
193
194         return IS_ERR(inode) ? PTR_ERR(inode) : 0;
195 }
196
197 /*
198  * ntfs_mkdir- inode_operations::mkdir
199  */
200 static int ntfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
201                       struct dentry *dentry, umode_t mode)
202 {
203         struct inode *inode;
204
205         inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFDIR | mode,
206                                   0, NULL, 0, NULL);
207
208         return IS_ERR(inode) ? PTR_ERR(inode) : 0;
209 }
210
211 /*
212  * ntfs_rmdir - inode_operations::rmdir
213  */
214 static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
215 {
216         struct ntfs_inode *ni = ntfs_i(dir);
217         int err;
218
219         ni_lock_dir(ni);
220
221         err = ntfs_unlink_inode(dir, dentry);
222
223         ni_unlock(ni);
224
225         return err;
226 }
227
228 /*
229  * ntfs_rename - inode_operations::rename
230  */
231 static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,
232                        struct dentry *dentry, struct inode *new_dir,
233                        struct dentry *new_dentry, u32 flags)
234 {
235         int err;
236         struct super_block *sb = dir->i_sb;
237         struct ntfs_sb_info *sbi = sb->s_fs_info;
238         struct ntfs_inode *dir_ni = ntfs_i(dir);
239         struct ntfs_inode *new_dir_ni = ntfs_i(new_dir);
240         struct inode *inode = d_inode(dentry);
241         struct ntfs_inode *ni = ntfs_i(inode);
242         struct inode *new_inode = d_inode(new_dentry);
243         struct NTFS_DE *de, *new_de;
244         bool is_same, is_bad;
245         /*
246          * de           - memory of PATH_MAX bytes:
247          * [0-1024)     - original name (dentry->d_name)
248          * [1024-2048)  - paired to original name, usually DOS variant of dentry->d_name
249          * [2048-3072)  - new name (new_dentry->d_name)
250          */
251         static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024);
252         static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) <
253                       1024);
254         static_assert(PATH_MAX >= 4 * 1024);
255
256         if (flags & ~RENAME_NOREPLACE)
257                 return -EINVAL;
258
259         is_same = dentry->d_name.len == new_dentry->d_name.len &&
260                   !memcmp(dentry->d_name.name, new_dentry->d_name.name,
261                           dentry->d_name.len);
262
263         if (is_same && dir == new_dir) {
264                 /* Nothing to do. */
265                 return 0;
266         }
267
268         if (ntfs_is_meta_file(sbi, inode->i_ino)) {
269                 /* Should we print an error? */
270                 return -EINVAL;
271         }
272
273         if (new_inode) {
274                 /* Target name exists. Unlink it. */
275                 dget(new_dentry);
276                 ni_lock_dir(new_dir_ni);
277                 err = ntfs_unlink_inode(new_dir, new_dentry);
278                 ni_unlock(new_dir_ni);
279                 dput(new_dentry);
280                 if (err)
281                         return err;
282         }
283
284         /* Allocate PATH_MAX bytes. */
285         de = __getname();
286         if (!de)
287                 return -ENOMEM;
288
289         /* Translate dentry->d_name into unicode form. */
290         err = fill_name_de(sbi, de, &dentry->d_name, NULL);
291         if (err < 0)
292                 goto out;
293
294         if (is_same) {
295                 /* Reuse 'de'. */
296                 new_de = de;
297         } else {
298                 /* Translate new_dentry->d_name into unicode form. */
299                 new_de = Add2Ptr(de, 2048);
300                 err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL);
301                 if (err < 0)
302                         goto out;
303         }
304
305         ni_lock_dir(dir_ni);
306         ni_lock(ni);
307
308         is_bad = false;
309         err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad);
310         if (is_bad) {
311                 /* Restore after failed rename failed too. */
312                 _ntfs_bad_inode(inode);
313         } else if (!err) {
314                 inode->i_ctime = dir->i_ctime = dir->i_mtime =
315                         current_time(dir);
316                 mark_inode_dirty(inode);
317                 mark_inode_dirty(dir);
318                 if (dir != new_dir) {
319                         new_dir->i_mtime = new_dir->i_ctime = dir->i_ctime;
320                         mark_inode_dirty(new_dir);
321                 }
322
323                 if (IS_DIRSYNC(dir))
324                         ntfs_sync_inode(dir);
325
326                 if (IS_DIRSYNC(new_dir))
327                         ntfs_sync_inode(inode);
328         }
329
330         ni_unlock(ni);
331         ni_unlock(dir_ni);
332 out:
333         __putname(de);
334         return err;
335 }
336
337 struct dentry *ntfs3_get_parent(struct dentry *child)
338 {
339         struct inode *inode = d_inode(child);
340         struct ntfs_inode *ni = ntfs_i(inode);
341
342         struct ATTR_LIST_ENTRY *le = NULL;
343         struct ATTRIB *attr = NULL;
344         struct ATTR_FILE_NAME *fname;
345
346         while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
347                                     NULL))) {
348                 fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
349                 if (!fname)
350                         continue;
351
352                 return d_obtain_alias(
353                         ntfs_iget5(inode->i_sb, &fname->home, NULL));
354         }
355
356         return ERR_PTR(-ENOENT);
357 }
358
359 /*
360  * dentry_operations::d_hash
361  */
362 static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name)
363 {
364         struct ntfs_sb_info *sbi;
365         const char *n = name->name;
366         unsigned int len = name->len;
367         unsigned long hash;
368         struct cpu_str *uni;
369         unsigned int c;
370         int err;
371
372         /* First try fast implementation. */
373         hash = init_name_hash(dentry);
374
375         for (;;) {
376                 if (!len--) {
377                         name->hash = end_name_hash(hash);
378                         return 0;
379                 }
380
381                 c = *n++;
382                 if (c >= 0x80)
383                         break;
384
385                 hash = partial_name_hash(toupper(c), hash);
386         }
387
388         /*
389          * Try slow way with current upcase table
390          */
391         uni = __getname();
392         if (!uni)
393                 return -ENOMEM;
394
395         sbi = dentry->d_sb->s_fs_info;
396
397         err = ntfs_nls_to_utf16(sbi, name->name, name->len, uni, NTFS_NAME_LEN,
398                                 UTF16_HOST_ENDIAN);
399         if (err < 0)
400                 goto out;
401
402         if (!err) {
403                 err = -EINVAL;
404                 goto out;
405         }
406
407         hash = ntfs_names_hash(uni->name, uni->len, sbi->upcase,
408                                init_name_hash(dentry));
409         name->hash = end_name_hash(hash);
410         err = 0;
411
412 out:
413         __putname(uni);
414         return err;
415 }
416
417 /*
418  * dentry_operations::d_compare
419  */
420 static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1,
421                           const char *str, const struct qstr *name)
422 {
423         struct ntfs_sb_info *sbi;
424         int ret;
425         const char *n1 = str;
426         const char *n2 = name->name;
427         unsigned int len2 = name->len;
428         unsigned int lm = min(len1, len2);
429         unsigned char c1, c2;
430         struct cpu_str *uni1;
431         struct le_str *uni2;
432
433         /* First try fast implementation. */
434         for (;;) {
435                 if (!lm--)
436                         return len1 != len2;
437
438                 if ((c1 = *n1++) == (c2 = *n2++))
439                         continue;
440
441                 if (c1 >= 0x80 || c2 >= 0x80)
442                         break;
443
444                 if (toupper(c1) != toupper(c2))
445                         return 1;
446         }
447
448         /*
449          * Try slow way with current upcase table
450          */
451         sbi = dentry->d_sb->s_fs_info;
452         uni1 = __getname();
453         if (!uni1)
454                 return -ENOMEM;
455
456         ret = ntfs_nls_to_utf16(sbi, str, len1, uni1, NTFS_NAME_LEN,
457                                 UTF16_HOST_ENDIAN);
458         if (ret < 0)
459                 goto out;
460
461         if (!ret) {
462                 ret = -EINVAL;
463                 goto out;
464         }
465
466         uni2 = Add2Ptr(uni1, 2048);
467
468         ret = ntfs_nls_to_utf16(sbi, name->name, name->len,
469                                 (struct cpu_str *)uni2, NTFS_NAME_LEN,
470                                 UTF16_LITTLE_ENDIAN);
471         if (ret < 0)
472                 goto out;
473
474         if (!ret) {
475                 ret = -EINVAL;
476                 goto out;
477         }
478
479         ret = !ntfs_cmp_names_cpu(uni1, uni2, sbi->upcase, false) ? 0 : 1;
480
481 out:
482         __putname(uni1);
483         return ret;
484 }
485
486 // clang-format off
487 const struct inode_operations ntfs_dir_inode_operations = {
488         .lookup         = ntfs_lookup,
489         .create         = ntfs_create,
490         .link           = ntfs_link,
491         .unlink         = ntfs_unlink,
492         .symlink        = ntfs_symlink,
493         .mkdir          = ntfs_mkdir,
494         .rmdir          = ntfs_rmdir,
495         .mknod          = ntfs_mknod,
496         .rename         = ntfs_rename,
497         .permission     = ntfs_permission,
498         .get_acl        = ntfs_get_acl,
499         .set_acl        = ntfs_set_acl,
500         .setattr        = ntfs3_setattr,
501         .getattr        = ntfs_getattr,
502         .listxattr      = ntfs_listxattr,
503         .fiemap         = ntfs_fiemap,
504 };
505
506 const struct inode_operations ntfs_special_inode_operations = {
507         .setattr        = ntfs3_setattr,
508         .getattr        = ntfs_getattr,
509         .listxattr      = ntfs_listxattr,
510         .get_acl        = ntfs_get_acl,
511         .set_acl        = ntfs_set_acl,
512 };
513
514 const struct dentry_operations ntfs_dentry_ops = {
515         .d_hash         = ntfs_d_hash,
516         .d_compare      = ntfs_d_compare,
517 };
518
519 // clang-format on
This page took 0.064472 seconds and 4 git commands to generate.