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