fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO list)
[linux-2.6-microblaze.git] / fs / ntfs3 / dir.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *
4  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
5  *
6  *  Directory handling functions for NTFS-based filesystems.
7  *
8  */
9
10 #include <linux/blkdev.h>
11 #include <linux/buffer_head.h>
12 #include <linux/fs.h>
13 #include <linux/iversion.h>
14 #include <linux/nls.h>
15
16 #include "debug.h"
17 #include "ntfs.h"
18 #include "ntfs_fs.h"
19
20 /* Convert little endian UTF-16 to NLS string. */
21 int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni,
22                       u8 *buf, int buf_len)
23 {
24         int ret, uni_len, warn;
25         const __le16 *ip;
26         u8 *op;
27         struct nls_table *nls = sbi->options.nls;
28
29         static_assert(sizeof(wchar_t) == sizeof(__le16));
30
31         if (!nls) {
32                 /* UTF-16 -> UTF-8 */
33                 ret = utf16s_to_utf8s((wchar_t *)uni->name, uni->len,
34                                       UTF16_LITTLE_ENDIAN, buf, buf_len);
35                 buf[ret] = '\0';
36                 return ret;
37         }
38
39         ip = uni->name;
40         op = buf;
41         uni_len = uni->len;
42         warn = 0;
43
44         while (uni_len--) {
45                 u16 ec;
46                 int charlen;
47                 char dump[5];
48
49                 if (buf_len < NLS_MAX_CHARSET_SIZE) {
50                         ntfs_warn(sbi->sb,
51                                   "filename was truncated while converting.");
52                         break;
53                 }
54
55                 ec = le16_to_cpu(*ip++);
56                 charlen = nls->uni2char(ec, op, buf_len);
57
58                 if (charlen > 0) {
59                         op += charlen;
60                         buf_len -= charlen;
61                         continue;
62                 }
63
64                 *op++ = '_';
65                 buf_len -= 1;
66                 if (warn)
67                         continue;
68
69                 warn = 1;
70                 hex_byte_pack(&dump[0], ec >> 8);
71                 hex_byte_pack(&dump[2], ec);
72                 dump[4] = 0;
73
74                 ntfs_err(sbi->sb, "failed to convert \"%s\" to %s", dump,
75                          nls->charset);
76         }
77
78         *op = '\0';
79         return op - buf;
80 }
81
82 // clang-format off
83 #define PLANE_SIZE      0x00010000
84
85 #define SURROGATE_PAIR  0x0000d800
86 #define SURROGATE_LOW   0x00000400
87 #define SURROGATE_BITS  0x000003ff
88 // clang-format on
89
90 /*
91  * put_utf16 - Modified version of put_utf16 from fs/nls/nls_base.c
92  *
93  * Function is sparse warnings free.
94  */
95 static inline void put_utf16(wchar_t *s, unsigned int c,
96                              enum utf16_endian endian)
97 {
98         static_assert(sizeof(wchar_t) == sizeof(__le16));
99         static_assert(sizeof(wchar_t) == sizeof(__be16));
100
101         switch (endian) {
102         default:
103                 *s = (wchar_t)c;
104                 break;
105         case UTF16_LITTLE_ENDIAN:
106                 *(__le16 *)s = __cpu_to_le16(c);
107                 break;
108         case UTF16_BIG_ENDIAN:
109                 *(__be16 *)s = __cpu_to_be16(c);
110                 break;
111         }
112 }
113
114 /*
115  * _utf8s_to_utf16s
116  *
117  * Modified version of 'utf8s_to_utf16s' allows to
118  * detect -ENAMETOOLONG without writing out of expected maximum.
119  */
120 static int _utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
121                             wchar_t *pwcs, int maxout)
122 {
123         u16 *op;
124         int size;
125         unicode_t u;
126
127         op = pwcs;
128         while (inlen > 0 && *s) {
129                 if (*s & 0x80) {
130                         size = utf8_to_utf32(s, inlen, &u);
131                         if (size < 0)
132                                 return -EINVAL;
133                         s += size;
134                         inlen -= size;
135
136                         if (u >= PLANE_SIZE) {
137                                 if (maxout < 2)
138                                         return -ENAMETOOLONG;
139
140                                 u -= PLANE_SIZE;
141                                 put_utf16(op++,
142                                           SURROGATE_PAIR |
143                                                   ((u >> 10) & SURROGATE_BITS),
144                                           endian);
145                                 put_utf16(op++,
146                                           SURROGATE_PAIR | SURROGATE_LOW |
147                                                   (u & SURROGATE_BITS),
148                                           endian);
149                                 maxout -= 2;
150                         } else {
151                                 if (maxout < 1)
152                                         return -ENAMETOOLONG;
153
154                                 put_utf16(op++, u, endian);
155                                 maxout--;
156                         }
157                 } else {
158                         if (maxout < 1)
159                                 return -ENAMETOOLONG;
160
161                         put_utf16(op++, *s++, endian);
162                         inlen--;
163                         maxout--;
164                 }
165         }
166         return op - pwcs;
167 }
168
169 /*
170  * ntfs_nls_to_utf16 - Convert input string to UTF-16.
171  * @name:       Input name.
172  * @name_len:   Input name length.
173  * @uni:        Destination memory.
174  * @max_ulen:   Destination memory.
175  * @endian:     Endian of target UTF-16 string.
176  *
177  * This function is called:
178  * - to create NTFS name
179  * - to create symlink
180  *
181  * Return: UTF-16 string length or error (if negative).
182  */
183 int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len,
184                       struct cpu_str *uni, u32 max_ulen,
185                       enum utf16_endian endian)
186 {
187         int ret, slen;
188         const u8 *end;
189         struct nls_table *nls = sbi->options.nls;
190         u16 *uname = uni->name;
191
192         static_assert(sizeof(wchar_t) == sizeof(u16));
193
194         if (!nls) {
195                 /* utf8 -> utf16 */
196                 ret = _utf8s_to_utf16s(name, name_len, endian, uname, max_ulen);
197                 uni->len = ret;
198                 return ret;
199         }
200
201         for (ret = 0, end = name + name_len; name < end; ret++, name += slen) {
202                 if (ret >= max_ulen)
203                         return -ENAMETOOLONG;
204
205                 slen = nls->char2uni(name, end - name, uname + ret);
206                 if (!slen)
207                         return -EINVAL;
208                 if (slen < 0)
209                         return slen;
210         }
211
212 #ifdef __BIG_ENDIAN
213         if (endian == UTF16_LITTLE_ENDIAN) {
214                 int i = ret;
215
216                 while (i--) {
217                         __cpu_to_le16s(uname);
218                         uname++;
219                 }
220         }
221 #else
222         if (endian == UTF16_BIG_ENDIAN) {
223                 int i = ret;
224
225                 while (i--) {
226                         __cpu_to_be16s(uname);
227                         uname++;
228                 }
229         }
230 #endif
231
232         uni->len = ret;
233         return ret;
234 }
235
236 /*
237  * dir_search_u - Helper function.
238  */
239 struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
240                            struct ntfs_fnd *fnd)
241 {
242         int err = 0;
243         struct super_block *sb = dir->i_sb;
244         struct ntfs_sb_info *sbi = sb->s_fs_info;
245         struct ntfs_inode *ni = ntfs_i(dir);
246         struct NTFS_DE *e;
247         int diff;
248         struct inode *inode = NULL;
249         struct ntfs_fnd *fnd_a = NULL;
250
251         if (!fnd) {
252                 fnd_a = fnd_get();
253                 if (!fnd_a) {
254                         err = -ENOMEM;
255                         goto out;
256                 }
257                 fnd = fnd_a;
258         }
259
260         err = indx_find(&ni->dir, ni, NULL, uni, 0, sbi, &diff, &e, fnd);
261
262         if (err)
263                 goto out;
264
265         if (diff) {
266                 err = -ENOENT;
267                 goto out;
268         }
269
270         inode = ntfs_iget5(sb, &e->ref, uni);
271         if (!IS_ERR(inode) && is_bad_inode(inode)) {
272                 iput(inode);
273                 err = -EINVAL;
274         }
275 out:
276         fnd_put(fnd_a);
277
278         return err == -ENOENT ? NULL : err ? ERR_PTR(err) : inode;
279 }
280
281 static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
282                                const struct NTFS_DE *e, u8 *name,
283                                struct dir_context *ctx)
284 {
285         const struct ATTR_FILE_NAME *fname;
286         unsigned long ino;
287         int name_len;
288         u32 dt_type;
289
290         fname = Add2Ptr(e, sizeof(struct NTFS_DE));
291
292         if (fname->type == FILE_NAME_DOS)
293                 return 0;
294
295         if (!mi_is_ref(&ni->mi, &fname->home))
296                 return 0;
297
298         ino = ino_get(&e->ref);
299
300         if (ino == MFT_REC_ROOT)
301                 return 0;
302
303         /* Skip meta files. Unless option to show metafiles is set. */
304         if (!sbi->options.showmeta && ntfs_is_meta_file(sbi, ino))
305                 return 0;
306
307         if (sbi->options.nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN))
308                 return 0;
309
310         name_len = ntfs_utf16_to_nls(sbi, (struct le_str *)&fname->name_len,
311                                      name, PATH_MAX);
312         if (name_len <= 0) {
313                 ntfs_warn(sbi->sb, "failed to convert name for inode %lx.",
314                           ino);
315                 return 0;
316         }
317
318         dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
319
320         return !dir_emit(ctx, (s8 *)name, name_len, ino, dt_type);
321 }
322
323 /*
324  * ntfs_read_hdr - Helper function for ntfs_readdir().
325  */
326 static int ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
327                          const struct INDEX_HDR *hdr, u64 vbo, u64 pos,
328                          u8 *name, struct dir_context *ctx)
329 {
330         int err;
331         const struct NTFS_DE *e;
332         u32 e_size;
333         u32 end = le32_to_cpu(hdr->used);
334         u32 off = le32_to_cpu(hdr->de_off);
335
336         for (;; off += e_size) {
337                 if (off + sizeof(struct NTFS_DE) > end)
338                         return -1;
339
340                 e = Add2Ptr(hdr, off);
341                 e_size = le16_to_cpu(e->size);
342                 if (e_size < sizeof(struct NTFS_DE) || off + e_size > end)
343                         return -1;
344
345                 if (de_is_last(e))
346                         return 0;
347
348                 /* Skip already enumerated. */
349                 if (vbo + off < pos)
350                         continue;
351
352                 if (le16_to_cpu(e->key_size) < SIZEOF_ATTRIBUTE_FILENAME)
353                         return -1;
354
355                 ctx->pos = vbo + off;
356
357                 /* Submit the name to the filldir callback. */
358                 err = ntfs_filldir(sbi, ni, e, name, ctx);
359                 if (err)
360                         return err;
361         }
362 }
363
364 /*
365  * ntfs_readdir - file_operations::iterate_shared
366  *
367  * Use non sorted enumeration.
368  * We have an example of broken volume where sorted enumeration
369  * counts each name twice.
370  */
371 static int ntfs_readdir(struct file *file, struct dir_context *ctx)
372 {
373         const struct INDEX_ROOT *root;
374         u64 vbo;
375         size_t bit;
376         loff_t eod;
377         int err = 0;
378         struct inode *dir = file_inode(file);
379         struct ntfs_inode *ni = ntfs_i(dir);
380         struct super_block *sb = dir->i_sb;
381         struct ntfs_sb_info *sbi = sb->s_fs_info;
382         loff_t i_size = i_size_read(dir);
383         u32 pos = ctx->pos;
384         u8 *name = NULL;
385         struct indx_node *node = NULL;
386         u8 index_bits = ni->dir.index_bits;
387
388         /* Name is a buffer of PATH_MAX length. */
389         static_assert(NTFS_NAME_LEN * 4 < PATH_MAX);
390
391         eod = i_size + sbi->record_size;
392
393         if (pos >= eod)
394                 return 0;
395
396         if (!dir_emit_dots(file, ctx))
397                 return 0;
398
399         /* Allocate PATH_MAX bytes. */
400         name = __getname();
401         if (!name)
402                 return -ENOMEM;
403
404         if (!ni->mi_loaded && ni->attr_list.size) {
405                 /*
406                  * Directory inode is locked for read.
407                  * Load all subrecords to avoid 'write' access to 'ni' during
408                  * directory reading.
409                  */
410                 ni_lock(ni);
411                 if (!ni->mi_loaded && ni->attr_list.size) {
412                         err = ni_load_all_mi(ni);
413                         if (!err)
414                                 ni->mi_loaded = true;
415                 }
416                 ni_unlock(ni);
417                 if (err)
418                         goto out;
419         }
420
421         root = indx_get_root(&ni->dir, ni, NULL, NULL);
422         if (!root) {
423                 err = -EINVAL;
424                 goto out;
425         }
426
427         if (pos >= sbi->record_size) {
428                 bit = (pos - sbi->record_size) >> index_bits;
429         } else {
430                 err = ntfs_read_hdr(sbi, ni, &root->ihdr, 0, pos, name, ctx);
431                 if (err)
432                         goto out;
433                 bit = 0;
434         }
435
436         if (!i_size) {
437                 ctx->pos = eod;
438                 goto out;
439         }
440
441         for (;;) {
442                 vbo = (u64)bit << index_bits;
443                 if (vbo >= i_size) {
444                         ctx->pos = eod;
445                         goto out;
446                 }
447
448                 err = indx_used_bit(&ni->dir, ni, &bit);
449                 if (err)
450                         goto out;
451
452                 if (bit == MINUS_ONE_T) {
453                         ctx->pos = eod;
454                         goto out;
455                 }
456
457                 vbo = (u64)bit << index_bits;
458                 if (vbo >= i_size) {
459                         ntfs_inode_err(dir, "Looks like your dir is corrupt");
460                         err = -EINVAL;
461                         goto out;
462                 }
463
464                 err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
465                                 &node);
466                 if (err)
467                         goto out;
468
469                 err = ntfs_read_hdr(sbi, ni, &node->index->ihdr,
470                                     vbo + sbi->record_size, pos, name, ctx);
471                 if (err)
472                         goto out;
473
474                 bit += 1;
475         }
476
477 out:
478
479         __putname(name);
480         put_indx_node(node);
481
482         if (err == -ENOENT) {
483                 err = 0;
484                 ctx->pos = pos;
485         }
486
487         return err;
488 }
489
490 static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
491                           size_t *files)
492 {
493         int err = 0;
494         struct ntfs_inode *ni = ntfs_i(dir);
495         struct NTFS_DE *e = NULL;
496         struct INDEX_ROOT *root;
497         struct INDEX_HDR *hdr;
498         const struct ATTR_FILE_NAME *fname;
499         u32 e_size, off, end;
500         u64 vbo = 0;
501         size_t drs = 0, fles = 0, bit = 0;
502         loff_t i_size = ni->vfs_inode.i_size;
503         struct indx_node *node = NULL;
504         u8 index_bits = ni->dir.index_bits;
505
506         if (is_empty)
507                 *is_empty = true;
508
509         root = indx_get_root(&ni->dir, ni, NULL, NULL);
510         if (!root)
511                 return -EINVAL;
512
513         hdr = &root->ihdr;
514
515         for (;;) {
516                 end = le32_to_cpu(hdr->used);
517                 off = le32_to_cpu(hdr->de_off);
518
519                 for (; off + sizeof(struct NTFS_DE) <= end; off += e_size) {
520                         e = Add2Ptr(hdr, off);
521                         e_size = le16_to_cpu(e->size);
522                         if (e_size < sizeof(struct NTFS_DE) ||
523                             off + e_size > end)
524                                 break;
525
526                         if (de_is_last(e))
527                                 break;
528
529                         fname = de_get_fname(e);
530                         if (!fname)
531                                 continue;
532
533                         if (fname->type == FILE_NAME_DOS)
534                                 continue;
535
536                         if (is_empty) {
537                                 *is_empty = false;
538                                 if (!dirs && !files)
539                                         goto out;
540                         }
541
542                         if (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY)
543                                 drs += 1;
544                         else
545                                 fles += 1;
546                 }
547
548                 if (vbo >= i_size)
549                         goto out;
550
551                 err = indx_used_bit(&ni->dir, ni, &bit);
552                 if (err)
553                         goto out;
554
555                 if (bit == MINUS_ONE_T)
556                         goto out;
557
558                 vbo = (u64)bit << index_bits;
559                 if (vbo >= i_size)
560                         goto out;
561
562                 err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
563                                 &node);
564                 if (err)
565                         goto out;
566
567                 hdr = &node->index->ihdr;
568                 bit += 1;
569                 vbo = (u64)bit << ni->dir.idx2vbn_bits;
570         }
571
572 out:
573         put_indx_node(node);
574         if (dirs)
575                 *dirs = drs;
576         if (files)
577                 *files = fles;
578
579         return err;
580 }
581
582 bool dir_is_empty(struct inode *dir)
583 {
584         bool is_empty = false;
585
586         ntfs_dir_count(dir, &is_empty, NULL, NULL);
587
588         return is_empty;
589 }
590
591 // clang-format off
592 const struct file_operations ntfs_dir_operations = {
593         .llseek         = generic_file_llseek,
594         .read           = generic_read_dir,
595         .iterate_shared = ntfs_readdir,
596         .fsync          = generic_file_fsync,
597         .open           = ntfs_file_open,
598 };
599 // clang-format on