1 /**
2 * dir.c - Directory handling code. Originated from the Linux-NTFS project.
3 *
4 * Copyright (c) 2002-2005 Anton Altaparmakov
5 * Copyright (c) 2004-2005 Richard Russon
6 * Copyright (c) 2004-2008 Szabolcs Szakacsits
7 * Copyright (c) 2005-2007 Yura Pakhuchiy
8 * Copyright (c) 2008-2021 Jean-Pierre Andre
9 *
10 * This program/include file is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as published
12 * by the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program/include file is distributed in the hope that it will be
16 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program (in the main directory of the NTFS-3G
22 * distribution in the file COPYING); if not, write to the Free Software
23 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #ifdef HAVE_ERRNO_H
34 #include <errno.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
39 #ifdef HAVE_SYS_STAT_H
40 #include <sys/stat.h>
41 #endif
42
43 #ifdef HAVE_SYS_TYPES_H
44 #include <sys/types.h>
45 #endif
46 #ifdef MAJOR_IN_MKDEV
47 #include <sys/mkdev.h>
48 #endif
49 #ifdef MAJOR_IN_SYSMACROS
50 #include <sys/sysmacros.h>
51 #endif
52
53 #include "param.h"
54 #include "types.h"
55 #include "debug.h"
56 #include "attrib.h"
57 #include "inode.h"
58 #include "dir.h"
59 #include "volume.h"
60 #include "mft.h"
61 #include "index.h"
62 #include "ntfstime.h"
63 #include "lcnalloc.h"
64 #include "logging.h"
65 #include "cache.h"
66 #include "misc.h"
67 #include "security.h"
68 #include "reparse.h"
69 #include "object_id.h"
70 #include "xattrs.h"
71 #include "ea.h"
72
73 /*
74 * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
75 * and "$Q" as global constants.
76 */
77 ntfschar NTFS_INDEX_I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
78 const_cpu_to_le16('3'), const_cpu_to_le16('0'),
79 const_cpu_to_le16('\0') };
80 ntfschar NTFS_INDEX_SII[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'),
81 const_cpu_to_le16('I'), const_cpu_to_le16('I'),
82 const_cpu_to_le16('\0') };
83 ntfschar NTFS_INDEX_SDH[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'),
84 const_cpu_to_le16('D'), const_cpu_to_le16('H'),
85 const_cpu_to_le16('\0') };
86 ntfschar NTFS_INDEX_O[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('O'),
87 const_cpu_to_le16('\0') };
88 ntfschar NTFS_INDEX_Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'),
89 const_cpu_to_le16('\0') };
90 ntfschar NTFS_INDEX_R[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('R'),
91 const_cpu_to_le16('\0') };
92
93 #if CACHE_INODE_SIZE
94
95 /*
96 * Pathname hashing
97 *
98 * Based on first char and second char (which may be '\0')
99 */
100
ntfs_dir_inode_hash(const struct CACHED_GENERIC * cached)101 int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached)
102 {
103 const char *path;
104 const unsigned char *name;
105
106 path = (const char*)cached->variable;
107 if (!path) {
108 ntfs_log_error("Bad inode cache entry\n");
109 return (-1);
110 }
111 name = (const unsigned char*)strrchr(path,'/');
112 if (!name)
113 name = (const unsigned char*)path;
114 return (((name[0] << 1) + name[1] + strlen((const char*)name))
115 % (2*CACHE_INODE_SIZE));
116 }
117
118 /*
119 * Pathname comparing for entering/fetching from cache
120 */
121
inode_cache_compare(const struct CACHED_GENERIC * cached,const struct CACHED_GENERIC * wanted)122 static int inode_cache_compare(const struct CACHED_GENERIC *cached,
123 const struct CACHED_GENERIC *wanted)
124 {
125 return (!cached->variable
126 || strcmp(cached->variable, wanted->variable));
127 }
128
129 /*
130 * Pathname comparing for invalidating entries in cache
131 *
132 * A partial path is compared in order to invalidate all paths
133 * related to a renamed directory
134 * inode numbers are also checked, as deleting a long name may
135 * imply deleting a short name and conversely
136 *
137 * Only use associated with a CACHE_NOHASH flag
138 */
139
inode_cache_inv_compare(const struct CACHED_GENERIC * cached,const struct CACHED_GENERIC * wanted)140 static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
141 const struct CACHED_GENERIC *wanted)
142 {
143 int len;
144 BOOL different;
145 const struct CACHED_INODE *w;
146 const struct CACHED_INODE *c;
147
148 w = (const struct CACHED_INODE*)wanted;
149 c = (const struct CACHED_INODE*)cached;
150 if (w->pathname) {
151 len = strlen(w->pathname);
152 different = !cached->variable
153 || ((w->inum != MREF(c->inum))
154 && (strncmp(c->pathname, w->pathname, len)
155 || ((c->pathname[len] != '\0')
156 && (c->pathname[len] != '/'))));
157 } else
158 different = !c->pathname
159 || (w->inum != MREF(c->inum));
160 return (different);
161 }
162
163 #endif
164
165 #if CACHE_LOOKUP_SIZE
166
167 /*
168 * File name comparing for entering/fetching from lookup cache
169 */
170
lookup_cache_compare(const struct CACHED_GENERIC * cached,const struct CACHED_GENERIC * wanted)171 static int lookup_cache_compare(const struct CACHED_GENERIC *cached,
172 const struct CACHED_GENERIC *wanted)
173 {
174 const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
175 const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
176 return (!c->name
177 || (c->parent != w->parent)
178 || (c->namesize != w->namesize)
179 || memcmp(c->name, w->name, c->namesize));
180 }
181
182 /*
183 * Inode number comparing for invalidating lookup cache
184 *
185 * All entries with designated inode number are invalidated
186 *
187 * Only use associated with a CACHE_NOHASH flag
188 */
189
lookup_cache_inv_compare(const struct CACHED_GENERIC * cached,const struct CACHED_GENERIC * wanted)190 static int lookup_cache_inv_compare(const struct CACHED_GENERIC *cached,
191 const struct CACHED_GENERIC *wanted)
192 {
193 const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
194 const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
195 return (!c->name
196 || (c->parent != w->parent)
197 || (MREF(c->inum) != MREF(w->inum)));
198 }
199
200 /*
201 * Lookup hashing
202 *
203 * Based on first, second and and last char
204 */
205
ntfs_dir_lookup_hash(const struct CACHED_GENERIC * cached)206 int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached)
207 {
208 const unsigned char *name;
209 int count;
210 unsigned int val;
211
212 name = (const unsigned char*)cached->variable;
213 count = cached->varsize;
214 if (!name || !count) {
215 ntfs_log_error("Bad lookup cache entry\n");
216 return (-1);
217 }
218 val = (name[0] << 2) + (name[1] << 1) + name[count - 1] + count;
219 return (val % (2*CACHE_LOOKUP_SIZE));
220 }
221
222 #endif
223
224 /**
225 * ntfs_inode_lookup_by_name - find an inode in a directory given its name
226 * @dir_ni: ntfs inode of the directory in which to search for the name
227 * @uname: Unicode name for which to search in the directory
228 * @uname_len: length of the name @uname in Unicode characters
229 *
230 * Look for an inode with name @uname in the directory with inode @dir_ni.
231 * ntfs_inode_lookup_by_name() walks the contents of the directory looking for
232 * the Unicode name. If the name is found in the directory, the corresponding
233 * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
234 * is a 64-bit number containing the sequence number.
235 *
236 * On error, return -1 with errno set to the error code. If the inode is is not
237 * found errno is ENOENT.
238 *
239 * Note, @uname_len does not include the (optional) terminating NULL character.
240 *
241 * Note, we look for a case sensitive match first but we also look for a case
242 * insensitive match at the same time. If we find a case insensitive match, we
243 * save that for the case that we don't find an exact match, where we return
244 * the mft reference of the case insensitive match.
245 *
246 * If the volume is mounted with the case sensitive flag set, then we only
247 * allow exact matches.
248 */
ntfs_inode_lookup_by_name(ntfs_inode * dir_ni,const ntfschar * uname,const int uname_len)249 u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
250 const ntfschar *uname, const int uname_len)
251 {
252 VCN vcn;
253 u64 mref = 0;
254 s64 br;
255 ntfs_volume *vol = dir_ni->vol;
256 ntfs_attr_search_ctx *ctx;
257 INDEX_ROOT *ir;
258 INDEX_ENTRY *ie;
259 INDEX_ALLOCATION *ia;
260 IGNORE_CASE_BOOL case_sensitivity;
261 u8 *index_end;
262 ntfs_attr *ia_na;
263 int eo, rc;
264 u32 index_block_size;
265 u8 index_vcn_size_bits;
266
267 ntfs_log_trace("Entering\n");
268
269 if (!dir_ni || !dir_ni->mrec || !uname || uname_len <= 0) {
270 errno = EINVAL;
271 return -1;
272 }
273
274 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
275 if (!ctx)
276 return -1;
277
278 /* Find the index root attribute in the mft record. */
279 if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
280 0, ctx)) {
281 ntfs_log_perror("Index root attribute missing in directory inode "
282 "%lld", (unsigned long long)dir_ni->mft_no);
283 goto put_err_out;
284 }
285 case_sensitivity = (NVolCaseSensitive(vol) ? CASE_SENSITIVE : IGNORE_CASE);
286 /* Get to the index root value. */
287 ir = (INDEX_ROOT*)((u8*)ctx->attr +
288 le16_to_cpu(ctx->attr->value_offset));
289 index_block_size = le32_to_cpu(ir->index_block_size);
290 if (index_block_size < NTFS_BLOCK_SIZE ||
291 index_block_size & (index_block_size - 1)) {
292 ntfs_log_error("Index block size %u is invalid.\n",
293 (unsigned)index_block_size);
294 goto put_err_out;
295 }
296 /* Consistency check of ir done while fetching attribute */
297 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
298 /* The first index entry. */
299 ie = (INDEX_ENTRY*)((u8*)&ir->index +
300 le32_to_cpu(ir->index.entries_offset));
301 /*
302 * Loop until we exceed valid memory (corruption case) or until we
303 * reach the last entry.
304 */
305 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
306 /* Bounds checks. */
307 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
308 sizeof(INDEX_ENTRY_HEADER) > index_end ||
309 (u8*)ie + le16_to_cpu(ie->length) >
310 index_end) {
311 ntfs_log_error("Index root entry out of bounds in"
312 " inode %lld\n",
313 (unsigned long long)dir_ni->mft_no);
314 goto put_err_out;
315 }
316 /*
317 * The last entry cannot contain a name. It can however contain
318 * a pointer to a child node in the B+tree so we just break out.
319 */
320 if (ie->ie_flags & INDEX_ENTRY_END)
321 break;
322
323 /* The file name must not overflow from the entry */
324 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
325 dir_ni->mft_no)) {
326 errno = EIO;
327 goto put_err_out;
328 }
329 /*
330 * Not a perfect match, need to do full blown collation so we
331 * know which way in the B+tree we have to go.
332 */
333 rc = ntfs_names_full_collate(uname, uname_len,
334 (ntfschar*)&ie->key.file_name.file_name,
335 ie->key.file_name.file_name_length,
336 case_sensitivity, vol->upcase, vol->upcase_len);
337 /*
338 * If uname collates before the name of the current entry, there
339 * is definitely no such name in this index but we might need to
340 * descend into the B+tree so we just break out of the loop.
341 */
342 if (rc == -1)
343 break;
344 /* The names are not equal, continue the search. */
345 if (rc)
346 continue;
347 /*
348 * Perfect match, this will never happen as the
349 * ntfs_are_names_equal() call will have gotten a match but we
350 * still treat it correctly.
351 */
352 mref = le64_to_cpu(ie->indexed_file);
353 ntfs_attr_put_search_ctx(ctx);
354 return mref;
355 }
356 /*
357 * We have finished with this index without success. Check for the
358 * presence of a child node and if not present return error code
359 * ENOENT, unless we have got the mft reference of a matching name
360 * cached in mref in which case return mref.
361 */
362 if (!(ie->ie_flags & INDEX_ENTRY_NODE)) {
363 ntfs_attr_put_search_ctx(ctx);
364 if (mref)
365 return mref;
366 ntfs_log_debug("Entry not found - between root entries.\n");
367 errno = ENOENT;
368 return -1;
369 } /* Child node present, descend into it. */
370
371 /* Open the index allocation attribute. */
372 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
373 if (!ia_na) {
374 ntfs_log_perror("Failed to open index allocation (inode %lld)",
375 (unsigned long long)dir_ni->mft_no);
376 goto put_err_out;
377 }
378
379 /* Allocate a buffer for the current index block. */
380 ia = ntfs_malloc(index_block_size);
381 if (!ia) {
382 ntfs_attr_close(ia_na);
383 goto put_err_out;
384 }
385
386 /* Determine the size of a vcn in the directory index. */
387 if (vol->cluster_size <= index_block_size) {
388 index_vcn_size_bits = vol->cluster_size_bits;
389 } else {
390 index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
391 }
392
393 /* Get the starting vcn of the index_block holding the child node. */
394 vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
395
396 descend_into_child_node:
397
398 /* Read the index block starting at vcn. */
399 br = ntfs_attr_mst_pread(ia_na, vcn << index_vcn_size_bits, 1,
400 index_block_size, ia);
401 if (br != 1) {
402 if (br != -1)
403 errno = EIO;
404 ntfs_log_perror("Failed to read vcn 0x%llx from inode %lld",
405 (unsigned long long)vcn,
406 (unsigned long long)ia_na->ni->mft_no);
407 goto close_err_out;
408 }
409
410 if (ntfs_index_block_inconsistent((INDEX_BLOCK*)ia, index_block_size,
411 ia_na->ni->mft_no, vcn)) {
412 errno = EIO;
413 goto close_err_out;
414 }
415 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
416
417 /* The first index entry. */
418 ie = (INDEX_ENTRY*)((u8*)&ia->index +
419 le32_to_cpu(ia->index.entries_offset));
420 /*
421 * Iterate similar to above big loop but applied to index buffer, thus
422 * loop until we exceed valid memory (corruption case) or until we
423 * reach the last entry.
424 */
425 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
426 /* Bounds check. */
427 if ((u8*)ie < (u8*)ia || (u8*)ie +
428 sizeof(INDEX_ENTRY_HEADER) > index_end ||
429 (u8*)ie + le16_to_cpu(ie->length) >
430 index_end) {
431 ntfs_log_error("Index entry out of bounds in directory "
432 "inode %lld.\n",
433 (unsigned long long)dir_ni->mft_no);
434 errno = EIO;
435 goto close_err_out;
436 }
437 /*
438 * The last entry cannot contain a name. It can however contain
439 * a pointer to a child node in the B+tree so we just break out.
440 */
441 if (ie->ie_flags & INDEX_ENTRY_END)
442 break;
443
444 /* The file name must not overflow from the entry */
445 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
446 dir_ni->mft_no)) {
447 errno = EIO;
448 goto close_err_out;
449 }
450 /*
451 * Not a perfect match, need to do full blown collation so we
452 * know which way in the B+tree we have to go.
453 */
454 rc = ntfs_names_full_collate(uname, uname_len,
455 (ntfschar*)&ie->key.file_name.file_name,
456 ie->key.file_name.file_name_length,
457 case_sensitivity, vol->upcase, vol->upcase_len);
458 /*
459 * If uname collates before the name of the current entry, there
460 * is definitely no such name in this index but we might need to
461 * descend into the B+tree so we just break out of the loop.
462 */
463 if (rc == -1)
464 break;
465 /* The names are not equal, continue the search. */
466 if (rc)
467 continue;
468 mref = le64_to_cpu(ie->indexed_file);
469 free(ia);
470 ntfs_attr_close(ia_na);
471 ntfs_attr_put_search_ctx(ctx);
472 return mref;
473 }
474 /*
475 * We have finished with this index buffer without success. Check for
476 * the presence of a child node.
477 */
478 if (ie->ie_flags & INDEX_ENTRY_NODE) {
479 if ((ia->index.ih_flags & NODE_MASK) == LEAF_NODE) {
480 ntfs_log_error("Index entry with child node found in a leaf "
481 "node in directory inode %lld.\n",
482 (unsigned long long)dir_ni->mft_no);
483 errno = EIO;
484 goto close_err_out;
485 }
486 /* Child node present, descend into it. */
487 vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
488 if (vcn >= 0)
489 goto descend_into_child_node;
490 ntfs_log_error("Negative child node vcn in directory inode "
491 "0x%llx.\n", (unsigned long long)dir_ni->mft_no);
492 errno = EIO;
493 goto close_err_out;
494 }
495 free(ia);
496 ntfs_attr_close(ia_na);
497 ntfs_attr_put_search_ctx(ctx);
498 /*
499 * No child node present, return error code ENOENT, unless we have got
500 * the mft reference of a matching name cached in mref in which case
501 * return mref.
502 */
503 if (mref)
504 return mref;
505 ntfs_log_debug("Entry not found.\n");
506 errno = ENOENT;
507 return -1;
508 put_err_out:
509 eo = EIO;
510 ntfs_log_debug("Corrupt directory. Aborting lookup.\n");
511 eo_put_err_out:
512 ntfs_attr_put_search_ctx(ctx);
513 errno = eo;
514 return -1;
515 close_err_out:
516 eo = errno;
517 free(ia);
518 ntfs_attr_close(ia_na);
519 goto eo_put_err_out;
520 }
521
522 /*
523 * Lookup a file in a directory from its UTF-8 name
524 *
525 * The name is first fetched from cache if one is defined
526 *
527 * Returns the inode number
528 * or -1 if not possible (errno tells why)
529 */
530
ntfs_inode_lookup_by_mbsname(ntfs_inode * dir_ni,const char * name)531 u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name)
532 {
533 int uname_len;
534 ntfschar *uname = (ntfschar*)NULL;
535 u64 inum;
536 char *cached_name;
537 const char *const_name;
538
539 if (!NVolCaseSensitive(dir_ni->vol)) {
540 cached_name = ntfs_uppercase_mbs(name,
541 dir_ni->vol->upcase, dir_ni->vol->upcase_len);
542 const_name = cached_name;
543 } else {
544 cached_name = (char*)NULL;
545 const_name = name;
546 }
547 if (const_name) {
548 #if CACHE_LOOKUP_SIZE
549
550 /*
551 * fetch inode from cache
552 */
553
554 if (dir_ni->vol->lookup_cache) {
555 struct CACHED_LOOKUP item;
556 struct CACHED_LOOKUP *cached;
557
558 item.name = const_name;
559 item.namesize = strlen(const_name) + 1;
560 item.parent = dir_ni->mft_no;
561 cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache(
562 dir_ni->vol->lookup_cache,
563 GENERIC(&item), lookup_cache_compare);
564 if (cached) {
565 inum = cached->inum;
566 if (inum == (u64)-1)
567 errno = ENOENT;
568 } else {
569 /* Generate unicode name. */
570 uname_len = ntfs_mbstoucs(name, &uname);
571 if (uname_len >= 0) {
572 inum = ntfs_inode_lookup_by_name(dir_ni,
573 uname, uname_len);
574 item.inum = inum;
575 /* enter into cache, even if not found */
576 ntfs_enter_cache(dir_ni->vol->lookup_cache,
577 GENERIC(&item),
578 lookup_cache_compare);
579 free(uname);
580 } else
581 inum = (s64)-1;
582 }
583 } else
584 #endif
585 {
586 /* Generate unicode name. */
587 uname_len = ntfs_mbstoucs(cached_name, &uname);
588 if (uname_len >= 0)
589 inum = ntfs_inode_lookup_by_name(dir_ni,
590 uname, uname_len);
591 else
592 inum = (s64)-1;
593 }
594 if (cached_name)
595 free(cached_name);
596 } else
597 inum = (s64)-1;
598 return (inum);
599 }
600
601 /*
602 * Update a cache lookup record when a name has been defined
603 *
604 * The UTF-8 name is required
605 */
606
ntfs_inode_update_mbsname(ntfs_inode * dir_ni,const char * name,u64 inum)607 void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, u64 inum)
608 {
609 #if CACHE_LOOKUP_SIZE
610 struct CACHED_LOOKUP item;
611 struct CACHED_LOOKUP *cached;
612 char *cached_name;
613
614 if (dir_ni->vol->lookup_cache) {
615 if (!NVolCaseSensitive(dir_ni->vol)) {
616 cached_name = ntfs_uppercase_mbs(name,
617 dir_ni->vol->upcase, dir_ni->vol->upcase_len);
618 item.name = cached_name;
619 } else {
620 cached_name = (char*)NULL;
621 item.name = name;
622 }
623 if (item.name) {
624 item.namesize = strlen(item.name) + 1;
625 item.parent = dir_ni->mft_no;
626 item.inum = inum;
627 cached = (struct CACHED_LOOKUP*)ntfs_enter_cache(
628 dir_ni->vol->lookup_cache,
629 GENERIC(&item), lookup_cache_compare);
630 if (cached)
631 cached->inum = inum;
632 if (cached_name)
633 free(cached_name);
634 }
635 }
636 #endif
637 }
638
639 /**
640 * ntfs_pathname_to_inode - Find the inode which represents the given pathname
641 * @vol: An ntfs volume obtained from ntfs_mount
642 * @parent: A directory inode to begin the search (may be NULL)
643 * @pathname: Pathname to be located
644 *
645 * Take an ASCII pathname and find the inode that represents it. The function
646 * splits the path and then descends the directory tree. If @parent is NULL,
647 * then the root directory '.' will be used as the base for the search.
648 *
649 * Return: inode Success, the pathname was valid
650 * NULL Error, the pathname was invalid, or some other error occurred
651 */
ntfs_pathname_to_inode(ntfs_volume * vol,ntfs_inode * parent,const char * pathname)652 ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
653 const char *pathname)
654 {
655 u64 inum;
656 int len, err = 0;
657 char *p, *q;
658 ntfs_inode *ni;
659 ntfs_inode *result = NULL;
660 ntfschar *unicode = NULL;
661 char *ascii = NULL;
662 #if CACHE_INODE_SIZE
663 struct CACHED_INODE item;
664 struct CACHED_INODE *cached;
665 char *fullname;
666 #endif
667
668 if (!vol || !pathname) {
669 errno = EINVAL;
670 return NULL;
671 }
672
673 ntfs_log_trace("path: '%s'\n", pathname);
674
675 ascii = strdup(pathname);
676 if (!ascii) {
677 ntfs_log_error("Out of memory.\n");
678 err = ENOMEM;
679 goto out;
680 }
681
682 p = ascii;
683 /* Remove leading /'s. */
684 while (p && *p && *p == PATH_SEP)
685 p++;
686 #if CACHE_INODE_SIZE
687 fullname = p;
688 if (p[0] && (p[strlen(p)-1] == PATH_SEP))
689 ntfs_log_error("Unnormalized path %s\n",ascii);
690 #endif
691 if (parent) {
692 ni = parent;
693 } else {
694 #if CACHE_INODE_SIZE
695 /*
696 * fetch inode for full path from cache
697 */
698 if (*fullname) {
699 item.pathname = fullname;
700 item.varsize = strlen(fullname) + 1;
701 cached = (struct CACHED_INODE*)ntfs_fetch_cache(
702 vol->xinode_cache, GENERIC(&item),
703 inode_cache_compare);
704 } else
705 cached = (struct CACHED_INODE*)NULL;
706 if (cached) {
707 /*
708 * return opened inode if found in cache
709 */
710 inum = MREF(cached->inum);
711 ni = ntfs_inode_open(vol, inum);
712 if (!ni) {
713 ntfs_log_debug("Cannot open inode %llu: %s.\n",
714 (unsigned long long)inum, p);
715 err = EIO;
716 }
717 result = ni;
718 goto out;
719 }
720 #endif
721 ni = ntfs_inode_open(vol, FILE_root);
722 if (!ni) {
723 ntfs_log_debug("Couldn't open the inode of the root "
724 "directory.\n");
725 err = EIO;
726 result = (ntfs_inode*)NULL;
727 goto out;
728 }
729 }
730
731 while (p && *p) {
732 /* Find the end of the first token. */
733 q = strchr(p, PATH_SEP);
734 if (q != NULL) {
735 *q = '\0';
736 }
737 #if CACHE_INODE_SIZE
738 /*
739 * fetch inode for partial path from cache
740 */
741 cached = (struct CACHED_INODE*)NULL;
742 if (!parent) {
743 item.pathname = fullname;
744 item.varsize = strlen(fullname) + 1;
745 cached = (struct CACHED_INODE*)ntfs_fetch_cache(
746 vol->xinode_cache, GENERIC(&item),
747 inode_cache_compare);
748 if (cached) {
749 inum = cached->inum;
750 }
751 }
752 /*
753 * if not in cache, translate, search, then
754 * insert into cache if found
755 */
756 if (!cached) {
757 len = ntfs_mbstoucs(p, &unicode);
758 if (len < 0) {
759 ntfs_log_perror("Could not convert filename to Unicode:"
760 " '%s'", p);
761 err = errno;
762 goto close;
763 } else if (len > NTFS_MAX_NAME_LEN) {
764 err = ENAMETOOLONG;
765 goto close;
766 }
767 inum = ntfs_inode_lookup_by_name(ni, unicode, len);
768 if (!parent && (inum != (u64) -1)) {
769 item.inum = inum;
770 ntfs_enter_cache(vol->xinode_cache,
771 GENERIC(&item),
772 inode_cache_compare);
773 }
774 }
775 #else
776 len = ntfs_mbstoucs(p, &unicode);
777 if (len < 0) {
778 ntfs_log_perror("Could not convert filename to Unicode:"
779 " '%s'", p);
780 err = errno;
781 goto close;
782 } else if (len > NTFS_MAX_NAME_LEN) {
783 err = ENAMETOOLONG;
784 goto close;
785 }
786 inum = ntfs_inode_lookup_by_name(ni, unicode, len);
787 #endif
788 if (inum == (u64) -1) {
789 ntfs_log_debug("Couldn't find name '%s' in pathname "
790 "'%s'.\n", p, pathname);
791 err = ENOENT;
792 goto close;
793 }
794
795 if (ni != parent)
796 if (ntfs_inode_close(ni)) {
797 err = errno;
798 goto out;
799 }
800
801 inum = MREF(inum);
802 ni = ntfs_inode_open(vol, inum);
803 if (!ni) {
804 ntfs_log_debug("Cannot open inode %llu: %s.\n",
805 (unsigned long long)inum, p);
806 err = EIO;
807 goto close;
808 }
809
810 free(unicode);
811 unicode = NULL;
812
813 if (q) *q++ = PATH_SEP; /* JPA */
814 p = q;
815 while (p && *p && *p == PATH_SEP)
816 p++;
817 }
818
819 result = ni;
820 ni = NULL;
821 close:
822 if (ni && (ni != parent))
823 if (ntfs_inode_close(ni) && !err)
824 err = errno;
825 out:
826 free(ascii);
827 free(unicode);
828 if (err)
829 errno = err;
830 return result;
831 }
832
833 /*
834 * The little endian Unicode string ".." for ntfs_readdir().
835 */
836 static const ntfschar dotdot[3] = { const_cpu_to_le16('.'),
837 const_cpu_to_le16('.'),
838 const_cpu_to_le16('\0') };
839
840 /*
841 * union index_union -
842 * More helpers for ntfs_readdir().
843 */
844 typedef union {
845 INDEX_ROOT *ir;
846 INDEX_ALLOCATION *ia;
847 } index_union __attribute__((__transparent_union__));
848
849 /**
850 * enum INDEX_TYPE -
851 * More helpers for ntfs_readdir().
852 */
853 typedef enum {
854 INDEX_TYPE_ROOT, /* index root */
855 INDEX_TYPE_ALLOCATION, /* index allocation */
856 } INDEX_TYPE;
857
858 /*
859 * Decode Interix file types
860 *
861 * Non-Interix types are returned as plain files, because a
862 * Windows user may force patterns very similar to Interix,
863 * and most metadata files have such similar patters.
864 */
865
ntfs_interix_types(ntfs_inode * ni)866 u32 ntfs_interix_types(ntfs_inode *ni)
867 {
868 ntfs_attr *na;
869 u32 dt_type;
870 le64 magic;
871
872 dt_type = NTFS_DT_UNKNOWN;
873 na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
874 if (na) {
875 /*
876 * Unrecognized patterns (eg HID + SYST for metadata)
877 * are plain files or directories
878 */
879 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
880 dt_type = NTFS_DT_DIR;
881 else
882 dt_type = NTFS_DT_REG;
883 if (na->data_size <= 1) {
884 if (!(ni->flags & FILE_ATTR_HIDDEN))
885 dt_type = (na->data_size ?
886 NTFS_DT_SOCK : NTFS_DT_FIFO);
887 } else {
888 if ((na->data_size >= (s64)sizeof(magic))
889 && (ntfs_attr_pread(na, 0, sizeof(magic), &magic)
890 == sizeof(magic))) {
891 if (magic == INTX_SYMBOLIC_LINK)
892 dt_type = NTFS_DT_LNK;
893 else if (magic == INTX_BLOCK_DEVICE)
894 dt_type = NTFS_DT_BLK;
895 else if (magic == INTX_CHARACTER_DEVICE)
896 dt_type = NTFS_DT_CHR;
897 }
898 }
899 ntfs_attr_close(na);
900 }
901 return (dt_type);
902 }
903
904 /*
905 * Decode file types
906 *
907 * Better only use for Interix types and junctions,
908 * unneeded complexity when used for plain files or directories
909 *
910 * Error cases are logged and returned as unknown.
911 */
912
ntfs_dir_entry_type(ntfs_inode * dir_ni,MFT_REF mref,FILE_ATTR_FLAGS attributes)913 static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref,
914 FILE_ATTR_FLAGS attributes)
915 {
916 ntfs_inode *ni;
917 u32 dt_type;
918
919 dt_type = NTFS_DT_UNKNOWN;
920 ni = ntfs_inode_open(dir_ni->vol, mref);
921 if (ni) {
922 if (attributes & FILE_ATTR_REPARSE_POINT)
923 dt_type = (ntfs_possible_symlink(ni)
924 ? NTFS_DT_LNK : NTFS_DT_REPARSE);
925 else
926 if ((attributes & FILE_ATTR_SYSTEM)
927 && !(attributes & FILE_ATTR_I30_INDEX_PRESENT))
928 dt_type = ntfs_interix_types(ni);
929 else
930 dt_type = (attributes
931 & FILE_ATTR_I30_INDEX_PRESENT
932 ? NTFS_DT_DIR : NTFS_DT_REG);
933 if (ntfs_inode_close(ni)) {
934 /* anything special worth doing ? */
935 ntfs_log_error("Failed to close inode %lld\n",
936 (long long)MREF(mref));
937 }
938 }
939 if (dt_type == NTFS_DT_UNKNOWN)
940 ntfs_log_error("Could not decode the type of inode %lld\n",
941 (long long)MREF(mref));
942 return (dt_type);
943 }
944
945 /**
946 * ntfs_filldir - ntfs specific filldir method
947 * @dir_ni: ntfs inode of current directory
948 * @pos: current position in directory
949 * @ivcn_bits: log(2) of index vcn size
950 * @index_type: specifies whether @iu is an index root or an index allocation
951 * @iu: index root or index block to which @ie belongs
952 * @ie: current index entry
953 * @dirent: context for filldir callback supplied by the caller
954 * @filldir: filldir callback supplied by the caller
955 *
956 * Pass information specifying the current directory entry @ie to the @filldir
957 * callback.
958 */
ntfs_filldir(ntfs_inode * dir_ni,s64 * pos,u8 ivcn_bits,const INDEX_TYPE index_type,index_union iu,INDEX_ENTRY * ie,void * dirent,ntfs_filldir_t filldir)959 static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
960 const INDEX_TYPE index_type, index_union iu, INDEX_ENTRY *ie,
961 void *dirent, ntfs_filldir_t filldir)
962 {
963 FILE_NAME_ATTR *fn = &ie->key.file_name;
964 unsigned dt_type;
965 BOOL metadata;
966 ntfschar *loname;
967 int res;
968 MFT_REF mref;
969
970 ntfs_log_trace("Entering.\n");
971
972 /* Advance the position even if going to skip the entry. */
973 if (index_type == INDEX_TYPE_ALLOCATION)
974 *pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
975 iu.ia->index_block_vcn) << ivcn_bits) +
976 dir_ni->vol->mft_record_size;
977 else /* if (index_type == INDEX_TYPE_ROOT) */
978 *pos = (u8*)ie - (u8*)iu.ir;
979 mref = le64_to_cpu(ie->indexed_file);
980 metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user);
981 /* Skip root directory self reference entry. */
982 if (MREF_LE(ie->indexed_file) == FILE_root)
983 return 0;
984 if ((ie->key.file_name.file_attributes
985 & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM))
986 && !metadata)
987 dt_type = ntfs_dir_entry_type(dir_ni, mref,
988 ie->key.file_name.file_attributes);
989 else if (ie->key.file_name.file_attributes
990 & FILE_ATTR_I30_INDEX_PRESENT)
991 dt_type = NTFS_DT_DIR;
992 else
993 dt_type = NTFS_DT_REG;
994
995 /* return metadata files and hidden files if requested */
996 if ((!metadata && (NVolShowHidFiles(dir_ni->vol)
997 || !(fn->file_attributes & FILE_ATTR_HIDDEN)))
998 || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
999 || metadata))) {
1000 if (NVolCaseSensitive(dir_ni->vol)) {
1001 res = filldir(dirent, fn->file_name,
1002 fn->file_name_length,
1003 fn->file_name_type, *pos,
1004 mref, dt_type);
1005 } else {
1006 loname = (ntfschar*)ntfs_malloc(2*fn->file_name_length);
1007 if (loname) {
1008 memcpy(loname, fn->file_name,
1009 2*fn->file_name_length);
1010 ntfs_name_locase(loname, fn->file_name_length,
1011 dir_ni->vol->locase,
1012 dir_ni->vol->upcase_len);
1013 res = filldir(dirent, loname,
1014 fn->file_name_length,
1015 fn->file_name_type, *pos,
1016 mref, dt_type);
1017 free(loname);
1018 } else
1019 res = -1;
1020 }
1021 } else
1022 res = 0;
1023 return (res);
1024 }
1025
1026 /**
1027 * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode
1028 * @ni: ntfs inode whose parent directory to find
1029 *
1030 * Find the parent directory of the ntfs inode @ni. To do this, find the first
1031 * file name attribute in the mft record of @ni and return the parent mft
1032 * reference from that.
1033 *
1034 * Note this only makes sense for directories, since files can be hard linked
1035 * from multiple directories and there is no way for us to tell which one is
1036 * being looked for.
1037 *
1038 * Technically directories can have hard links, too, but we consider that as
1039 * illegal as Linux/UNIX do not support directory hard links.
1040 *
1041 * Return the mft reference of the parent directory on success or -1 on error
1042 * with errno set to the error code.
1043 */
1044 #ifndef __HAIKU__
1045 static
1046 #endif
ntfs_mft_get_parent_ref(ntfs_inode * ni)1047 MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
1048 {
1049 MFT_REF mref;
1050 ntfs_attr_search_ctx *ctx;
1051 FILE_NAME_ATTR *fn;
1052 int eo;
1053
1054 ntfs_log_trace("Entering.\n");
1055
1056 if (!ni) {
1057 errno = EINVAL;
1058 return ERR_MREF(-1);
1059 }
1060
1061 ctx = ntfs_attr_get_search_ctx(ni, NULL);
1062 if (!ctx)
1063 return ERR_MREF(-1);
1064 if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
1065 ntfs_log_error("No file name found in inode %lld\n",
1066 (unsigned long long)ni->mft_no);
1067 goto err_out;
1068 }
1069 if (ctx->attr->non_resident) {
1070 ntfs_log_error("File name attribute must be resident (inode "
1071 "%lld)\n", (unsigned long long)ni->mft_no);
1072 goto io_err_out;
1073 }
1074 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
1075 le16_to_cpu(ctx->attr->value_offset));
1076 mref = le64_to_cpu(fn->parent_directory);
1077 ntfs_attr_put_search_ctx(ctx);
1078 return mref;
1079 io_err_out:
1080 errno = EIO;
1081 err_out:
1082 eo = errno;
1083 ntfs_attr_put_search_ctx(ctx);
1084 errno = eo;
1085 return ERR_MREF(-1);
1086 }
1087
1088 /**
1089 * ntfs_readdir - read the contents of an ntfs directory
1090 * @dir_ni: ntfs inode of current directory
1091 * @pos: current position in directory
1092 * @dirent: context for filldir callback supplied by the caller
1093 * @filldir: filldir callback supplied by the caller
1094 *
1095 * Parse the index root and the index blocks that are marked in use in the
1096 * index bitmap and hand each found directory entry to the @filldir callback
1097 * supplied by the caller.
1098 *
1099 * Return 0 on success or -1 on error with errno set to the error code.
1100 *
1101 * Note: Index blocks are parsed in ascending vcn order, from which follows
1102 * that the directory entries are not returned sorted.
1103 */
ntfs_readdir(ntfs_inode * dir_ni,s64 * pos,void * dirent,ntfs_filldir_t filldir)1104 int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
1105 void *dirent, ntfs_filldir_t filldir)
1106 {
1107 s64 i_size, br, ia_pos, bmp_pos, ia_start;
1108 ntfs_volume *vol;
1109 ntfs_attr *ia_na, *bmp_na = NULL;
1110 ntfs_attr_search_ctx *ctx = NULL;
1111 u8 *index_end, *bmp = NULL;
1112 INDEX_ROOT *ir;
1113 INDEX_ENTRY *ie;
1114 INDEX_ALLOCATION *ia = NULL;
1115 int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
1116 u32 index_block_size;
1117 u8 index_block_size_bits, index_vcn_size_bits;
1118
1119 ntfs_log_trace("Entering.\n");
1120
1121 if (!dir_ni || !pos || !filldir) {
1122 errno = EINVAL;
1123 return -1;
1124 }
1125
1126 if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
1127 errno = ENOTDIR;
1128 return -1;
1129 }
1130
1131 vol = dir_ni->vol;
1132
1133 ntfs_log_trace("Entering for inode %lld, *pos 0x%llx.\n",
1134 (unsigned long long)dir_ni->mft_no, (long long)*pos);
1135
1136 /* Open the index allocation attribute. */
1137 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
1138 if (!ia_na) {
1139 if (errno != ENOENT) {
1140 ntfs_log_perror("Failed to open index allocation attribute. "
1141 "Directory inode %lld is corrupt or bug",
1142 (unsigned long long)dir_ni->mft_no);
1143 return -1;
1144 }
1145 i_size = 0;
1146 } else
1147 i_size = ia_na->data_size;
1148
1149 rc = 0;
1150
1151 /* Are we at end of dir yet? */
1152 if (*pos >= i_size + vol->mft_record_size)
1153 goto done;
1154
1155 /* Emulate . and .. for all directories. */
1156 if (!*pos) {
1157 rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos,
1158 MK_MREF(dir_ni->mft_no,
1159 le16_to_cpu(dir_ni->mrec->sequence_number)),
1160 NTFS_DT_DIR);
1161 if (rc)
1162 goto err_out;
1163 ++*pos;
1164 }
1165 if (*pos == 1) {
1166 MFT_REF parent_mref;
1167
1168 parent_mref = ntfs_mft_get_parent_ref(dir_ni);
1169 if (parent_mref == ERR_MREF(-1)) {
1170 ntfs_log_perror("Parent directory not found");
1171 goto dir_err_out;
1172 }
1173
1174 rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos,
1175 parent_mref, NTFS_DT_DIR);
1176 if (rc)
1177 goto err_out;
1178 ++*pos;
1179 }
1180
1181 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
1182 if (!ctx)
1183 goto err_out;
1184
1185 /* Get the offset into the index root attribute. */
1186 ir_pos = (int)*pos;
1187 /* Find the index root attribute in the mft record. */
1188 if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
1189 0, ctx)) {
1190 ntfs_log_perror("Index root attribute missing in directory inode "
1191 "%lld", (unsigned long long)dir_ni->mft_no);
1192 goto dir_err_out;
1193 }
1194 /* Get to the index root value. */
1195 ir = (INDEX_ROOT*)((u8*)ctx->attr +
1196 le16_to_cpu(ctx->attr->value_offset));
1197
1198 /* Determine the size of a vcn in the directory index. */
1199 index_block_size = le32_to_cpu(ir->index_block_size);
1200 if (index_block_size < NTFS_BLOCK_SIZE ||
1201 index_block_size & (index_block_size - 1)) {
1202 ntfs_log_error("Index block size %u is invalid.\n",
1203 (unsigned)index_block_size);
1204 goto dir_err_out;
1205 }
1206 index_block_size_bits = ffs(index_block_size) - 1;
1207 if (vol->cluster_size <= index_block_size) {
1208 index_vcn_size_bits = vol->cluster_size_bits;
1209 } else {
1210 index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
1211 }
1212
1213 /* Are we jumping straight into the index allocation attribute? */
1214 if (*pos >= vol->mft_record_size) {
1215 ntfs_attr_put_search_ctx(ctx);
1216 ctx = NULL;
1217 goto skip_index_root;
1218 }
1219
1220 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
1221 /* The first index entry. */
1222 ie = (INDEX_ENTRY*)((u8*)&ir->index +
1223 le32_to_cpu(ir->index.entries_offset));
1224 /*
1225 * Loop until we exceed valid memory (corruption case) or until we
1226 * reach the last entry or until filldir tells us it has had enough
1227 * or signals an error (both covered by the rc test).
1228 */
1229 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
1230 ntfs_log_debug("In index root, offset %d.\n", (int)((u8*)ie - (u8*)ir));
1231 /* Bounds checks. */
1232 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
1233 sizeof(INDEX_ENTRY_HEADER) > index_end ||
1234 (u8*)ie + le16_to_cpu(ie->length) >
1235 index_end) {
1236 ntfs_log_error("Index root entry out of bounds in"
1237 " inode %lld\n",
1238 (unsigned long long)dir_ni->mft_no);
1239 goto dir_err_out;
1240 }
1241 /* The last entry cannot contain a name. */
1242 if (ie->ie_flags & INDEX_ENTRY_END)
1243 break;
1244
1245 if (!le16_to_cpu(ie->length))
1246 goto dir_err_out;
1247
1248 /* Skip index root entry if continuing previous readdir. */
1249 if (ir_pos > (u8*)ie - (u8*)ir)
1250 continue;
1251
1252 /* The file name must not overflow from the entry */
1253 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
1254 dir_ni->mft_no)) {
1255 errno = EIO;
1256 goto dir_err_out;
1257 }
1258 /*
1259 * Submit the directory entry to ntfs_filldir(), which will
1260 * invoke the filldir() callback as appropriate.
1261 */
1262 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
1263 INDEX_TYPE_ROOT, ir, ie, dirent, filldir);
1264 if (rc) {
1265 ntfs_attr_put_search_ctx(ctx);
1266 ctx = NULL;
1267 goto err_out;
1268 }
1269 }
1270 ntfs_attr_put_search_ctx(ctx);
1271 ctx = NULL;
1272
1273 /* If there is no index allocation attribute we are finished. */
1274 if (!ia_na)
1275 goto EOD;
1276
1277 /* Advance *pos to the beginning of the index allocation. */
1278 *pos = vol->mft_record_size;
1279
1280 skip_index_root:
1281
1282 if (!ia_na)
1283 goto done;
1284
1285 /* Allocate a buffer for the current index block. */
1286 ia = ntfs_malloc(index_block_size);
1287 if (!ia)
1288 goto err_out;
1289
1290 bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4);
1291 if (!bmp_na) {
1292 ntfs_log_perror("Failed to open index bitmap attribute");
1293 goto dir_err_out;
1294 }
1295
1296 /* Get the offset into the index allocation attribute. */
1297 ia_pos = *pos - vol->mft_record_size;
1298
1299 bmp_pos = ia_pos >> index_block_size_bits;
1300 if (bmp_pos >> 3 >= bmp_na->data_size) {
1301 ntfs_log_error("Current index position exceeds index bitmap "
1302 "size.\n");
1303 goto dir_err_out;
1304 }
1305
1306 bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096);
1307 bmp = ntfs_malloc(bmp_buf_size);
1308 if (!bmp)
1309 goto err_out;
1310
1311 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
1312 if (br != bmp_buf_size) {
1313 if (br != -1)
1314 errno = EIO;
1315 ntfs_log_perror("Failed to read from index bitmap attribute");
1316 goto err_out;
1317 }
1318
1319 bmp_buf_pos = 0;
1320 /* If the index block is not in use find the next one that is. */
1321 while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {
1322 find_next_index_buffer:
1323 bmp_pos++;
1324 bmp_buf_pos++;
1325 /* If we have reached the end of the bitmap, we are done. */
1326 if (bmp_pos >> 3 >= bmp_na->data_size)
1327 goto EOD;
1328 ia_pos = bmp_pos << index_block_size_bits;
1329 if (bmp_buf_pos >> 3 < bmp_buf_size)
1330 continue;
1331 /* Read next chunk from the index bitmap. */
1332 bmp_buf_pos = 0;
1333 if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size)
1334 bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3);
1335 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
1336 if (br != bmp_buf_size) {
1337 if (br != -1)
1338 errno = EIO;
1339 ntfs_log_perror("Failed to read from index bitmap attribute");
1340 goto err_out;
1341 }
1342 }
1343
1344 ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos);
1345
1346 /* Read the index block starting at bmp_pos. */
1347 br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1,
1348 index_block_size, ia);
1349 if (br != 1) {
1350 if (br != -1)
1351 errno = EIO;
1352 ntfs_log_perror("Failed to read index block");
1353 goto err_out;
1354 }
1355
1356 ia_start = ia_pos & ~(s64)(index_block_size - 1);
1357 if (ntfs_index_block_inconsistent((INDEX_BLOCK*)ia, index_block_size,
1358 ia_na->ni->mft_no, ia_start >> index_vcn_size_bits)) {
1359 goto dir_err_out;
1360 }
1361 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
1362
1363 /* The first index entry. */
1364 ie = (INDEX_ENTRY*)((u8*)&ia->index +
1365 le32_to_cpu(ia->index.entries_offset));
1366 /*
1367 * Loop until we exceed valid memory (corruption case) or until we
1368 * reach the last entry or until ntfs_filldir tells us it has had
1369 * enough or signals an error (both covered by the rc test).
1370 */
1371 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
1372 ntfs_log_debug("In index allocation, offset 0x%llx.\n",
1373 (long long)ia_start + ((u8*)ie - (u8*)ia));
1374 /* Bounds checks. */
1375 if ((u8*)ie < (u8*)ia || (u8*)ie +
1376 sizeof(INDEX_ENTRY_HEADER) > index_end ||
1377 (u8*)ie + le16_to_cpu(ie->length) >
1378 index_end) {
1379 ntfs_log_error("Index entry out of bounds in directory inode "
1380 "%lld.\n", (unsigned long long)dir_ni->mft_no);
1381 goto dir_err_out;
1382 }
1383 /* The last entry cannot contain a name. */
1384 if (ie->ie_flags & INDEX_ENTRY_END)
1385 break;
1386
1387 if (!le16_to_cpu(ie->length))
1388 goto dir_err_out;
1389
1390 /* Skip index entry if continuing previous readdir. */
1391 if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
1392 continue;
1393
1394 /* The file name must not overflow from the entry */
1395 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
1396 dir_ni->mft_no)) {
1397 errno = EIO;
1398 goto dir_err_out;
1399 }
1400 /*
1401 * Submit the directory entry to ntfs_filldir(), which will
1402 * invoke the filldir() callback as appropriate.
1403 */
1404 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
1405 INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir);
1406 if (rc)
1407 goto err_out;
1408 }
1409 goto find_next_index_buffer;
1410 EOD:
1411 /* We are finished, set *pos to EOD. */
1412 *pos = i_size + vol->mft_record_size;
1413 done:
1414 free(ia);
1415 free(bmp);
1416 if (bmp_na)
1417 ntfs_attr_close(bmp_na);
1418 if (ia_na)
1419 ntfs_attr_close(ia_na);
1420 ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos);
1421 return 0;
1422 dir_err_out:
1423 errno = EIO;
1424 err_out:
1425 eo = errno;
1426 ntfs_log_trace("failed.\n");
1427 if (ctx)
1428 ntfs_attr_put_search_ctx(ctx);
1429 free(ia);
1430 free(bmp);
1431 if (bmp_na)
1432 ntfs_attr_close(bmp_na);
1433 if (ia_na)
1434 ntfs_attr_close(ia_na);
1435 errno = eo;
1436 return -1;
1437 }
1438
1439
1440 /**
1441 * __ntfs_create - create object on ntfs volume
1442 * @dir_ni: ntfs inode for directory in which create new object
1443 * @securid: id of inheritable security descriptor, 0 if none
1444 * @name: unicode name of new object
1445 * @name_len: length of the name in unicode characters
1446 * @type: type of the object to create
1447 * @dev: major and minor device numbers (obtained from makedev())
1448 * @target: target in unicode (only for symlinks)
1449 * @target_len: length of target in unicode characters
1450 *
1451 * Internal, use ntfs_create{,_device,_symlink} wrappers instead.
1452 *
1453 * @type can be:
1454 * S_IFREG to create regular file
1455 * S_IFDIR to create directory
1456 * S_IFBLK to create block device
1457 * S_IFCHR to create character device
1458 * S_IFLNK to create symbolic link
1459 * S_IFIFO to create FIFO
1460 * S_IFSOCK to create socket
1461 * other values are invalid.
1462 *
1463 * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value
1464 * ignored.
1465 *
1466 * @target and @target_len are used only if @type is S_IFLNK, in other cases
1467 * their value ignored.
1468 *
1469 * Return opened ntfs inode that describes created object on success or NULL
1470 * on error with errno set to the error code.
1471 */
__ntfs_create(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,mode_t type,dev_t dev,const ntfschar * target,int target_len)1472 static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
1473 const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
1474 const ntfschar *target, int target_len)
1475 {
1476 ntfs_inode *ni;
1477 int rollback_data = 0, rollback_sd = 0;
1478 int rollback_dir = 0;
1479 FILE_NAME_ATTR *fn = NULL;
1480 STANDARD_INFORMATION *si = NULL;
1481 int err, fn_len, si_len;
1482 ntfs_volume_special_files special_files;
1483
1484 ntfs_log_trace("Entering.\n");
1485
1486 /* Sanity checks. */
1487 if (!dir_ni || !name || !name_len) {
1488 ntfs_log_error("Invalid arguments.\n");
1489 errno = EINVAL;
1490 return NULL;
1491 }
1492
1493 ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
1494 if (!ni)
1495 return NULL;
1496 #if CACHE_NIDATA_SIZE
1497 ntfs_inode_invalidate(dir_ni->vol, ni->mft_no);
1498 #endif
1499 special_files = dir_ni->vol->special_files;
1500 /*
1501 * Create STANDARD_INFORMATION attribute.
1502 * JPA Depending on available inherited security descriptor,
1503 * Write STANDARD_INFORMATION v1.2 (no inheritance) or v3
1504 */
1505 if (securid)
1506 si_len = sizeof(STANDARD_INFORMATION);
1507 else
1508 si_len = offsetof(STANDARD_INFORMATION, v1_end);
1509 si = ntfs_calloc(si_len);
1510 if (!si) {
1511 err = errno;
1512 goto err_out;
1513 }
1514 si->creation_time = ni->creation_time;
1515 si->last_data_change_time = ni->last_data_change_time;
1516 si->last_mft_change_time = ni->last_mft_change_time;
1517 si->last_access_time = ni->last_access_time;
1518 if (securid) {
1519 set_nino_flag(ni, v3_Extensions);
1520 ni->owner_id = si->owner_id = const_cpu_to_le32(0);
1521 ni->security_id = si->security_id = securid;
1522 ni->quota_charged = si->quota_charged = const_cpu_to_le64(0);
1523 ni->usn = si->usn = const_cpu_to_le64(0);
1524 } else
1525 clear_nino_flag(ni, v3_Extensions);
1526 if (!S_ISREG(type) && !S_ISDIR(type)) {
1527 switch (special_files) {
1528 case NTFS_FILES_WSL :
1529 if (!S_ISLNK(type)) {
1530 si->file_attributes
1531 = FILE_ATTRIBUTE_RECALL_ON_OPEN;
1532 ni->flags = FILE_ATTRIBUTE_RECALL_ON_OPEN;
1533 }
1534 break;
1535 default :
1536 si->file_attributes = FILE_ATTR_SYSTEM;
1537 ni->flags = FILE_ATTR_SYSTEM;
1538 break;
1539 }
1540 }
1541 ni->flags |= FILE_ATTR_ARCHIVE;
1542 if (NVolHideDotFiles(dir_ni->vol)
1543 && (name_len > 1)
1544 && (name[0] == const_cpu_to_le16('.'))
1545 && (name[1] != const_cpu_to_le16('.')))
1546 ni->flags |= FILE_ATTR_HIDDEN;
1547 /*
1548 * Set compression flag according to parent directory
1549 * unless NTFS version < 3.0 or cluster size > 4K
1550 * or compression has been disabled
1551 */
1552 if ((dir_ni->flags & FILE_ATTR_COMPRESSED)
1553 && (dir_ni->vol->major_ver >= 3)
1554 && NVolCompression(dir_ni->vol)
1555 && (dir_ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
1556 && (S_ISREG(type) || S_ISDIR(type)))
1557 ni->flags |= FILE_ATTR_COMPRESSED;
1558 /* Add STANDARD_INFORMATION to inode. */
1559 if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0,
1560 (u8*)si, si_len)) {
1561 err = errno;
1562 ntfs_log_error("Failed to add STANDARD_INFORMATION "
1563 "attribute.\n");
1564 goto err_out;
1565 }
1566
1567 if (!securid) {
1568 if (ntfs_sd_add_everyone(ni)) {
1569 err = errno;
1570 goto err_out;
1571 }
1572 rollback_sd = 1;
1573 }
1574
1575 if (S_ISDIR(type)) {
1576 INDEX_ROOT *ir = NULL;
1577 INDEX_ENTRY *ie;
1578 int ir_len, index_len;
1579
1580 /* Create INDEX_ROOT attribute. */
1581 index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER);
1582 ir_len = offsetof(INDEX_ROOT, index) + index_len;
1583 ir = ntfs_calloc(ir_len);
1584 if (!ir) {
1585 err = errno;
1586 goto err_out;
1587 }
1588 ir->type = AT_FILE_NAME;
1589 ir->collation_rule = COLLATION_FILE_NAME;
1590 ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size);
1591 if (ni->vol->cluster_size <= ni->vol->indx_record_size)
1592 ir->clusters_per_index_block =
1593 ni->vol->indx_record_size >>
1594 ni->vol->cluster_size_bits;
1595 else
1596 ir->clusters_per_index_block =
1597 ni->vol->indx_record_size >>
1598 NTFS_BLOCK_SIZE_BITS;
1599 ir->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER));
1600 ir->index.index_length = cpu_to_le32(index_len);
1601 ir->index.allocated_size = cpu_to_le32(index_len);
1602 ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT));
1603 ie->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
1604 ie->key_length = const_cpu_to_le16(0);
1605 ie->ie_flags = INDEX_ENTRY_END;
1606 /* Add INDEX_ROOT attribute to inode. */
1607 if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4,
1608 (u8*)ir, ir_len)) {
1609 err = errno;
1610 free(ir);
1611 ntfs_log_error("Failed to add INDEX_ROOT attribute.\n");
1612 goto err_out;
1613 }
1614 free(ir);
1615 } else {
1616 INTX_FILE *data;
1617 int data_len;
1618
1619 switch (type) {
1620 case S_IFBLK:
1621 case S_IFCHR:
1622 switch (special_files) {
1623 case NTFS_FILES_WSL :
1624 data_len = 0;
1625 data = (INTX_FILE*)NULL;
1626 break;
1627 default :
1628 data_len = offsetof(INTX_FILE,
1629 device_end);
1630 data = (INTX_FILE*)ntfs_malloc(
1631 data_len);
1632 if (!data) {
1633 err = errno;
1634 goto err_out;
1635 }
1636 data->major = cpu_to_le64(major(dev));
1637 data->minor = cpu_to_le64(minor(dev));
1638 if (type == S_IFBLK)
1639 data->magic
1640 = INTX_BLOCK_DEVICE;
1641 if (type == S_IFCHR)
1642 data->magic
1643 = INTX_CHARACTER_DEVICE;
1644 break;
1645 }
1646 break;
1647 case S_IFLNK:
1648 switch (special_files) {
1649 case NTFS_FILES_WSL :
1650 data_len = 0;
1651 data = (INTX_FILE*)NULL;
1652 break;
1653 default :
1654 data_len = sizeof(INTX_FILE_TYPES) +
1655 target_len * sizeof(ntfschar);
1656 data = (INTX_FILE*)ntfs_malloc(
1657 data_len);
1658 if (!data) {
1659 err = errno;
1660 goto err_out;
1661 }
1662 data->magic = INTX_SYMBOLIC_LINK;
1663 memcpy(data->target, target,
1664 target_len * sizeof(ntfschar));
1665 break;
1666 }
1667 break;
1668 case S_IFSOCK:
1669 data = NULL;
1670 if (special_files == NTFS_FILES_WSL)
1671 data_len = 0;
1672 else
1673 data_len = 1;
1674 break;
1675 default: /* FIFO or regular file. */
1676 data = NULL;
1677 data_len = 0;
1678 break;
1679 }
1680 /* Add DATA attribute to inode. */
1681 if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data,
1682 data_len)) {
1683 err = errno;
1684 ntfs_log_error("Failed to add DATA attribute.\n");
1685 free(data);
1686 goto err_out;
1687 }
1688 rollback_data = 1;
1689 free(data);
1690 }
1691 /* Create FILE_NAME attribute. */
1692 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
1693 fn = ntfs_calloc(fn_len);
1694 if (!fn) {
1695 err = errno;
1696 goto err_out;
1697 }
1698 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
1699 le16_to_cpu(dir_ni->mrec->sequence_number));
1700 fn->file_name_length = name_len;
1701 fn->file_name_type = FILE_NAME_POSIX;
1702 if (S_ISDIR(type))
1703 fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT;
1704 if (!S_ISREG(type) && !S_ISDIR(type)) {
1705 if (special_files == NTFS_FILES_INTERIX)
1706 fn->file_attributes = FILE_ATTR_SYSTEM;
1707 } else
1708 fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED;
1709 fn->file_attributes |= FILE_ATTR_ARCHIVE;
1710 fn->file_attributes |= ni->flags & FILE_ATTR_HIDDEN;
1711 fn->creation_time = ni->creation_time;
1712 fn->last_data_change_time = ni->last_data_change_time;
1713 fn->last_mft_change_time = ni->last_mft_change_time;
1714 fn->last_access_time = ni->last_access_time;
1715 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
1716 fn->data_size = fn->allocated_size = const_cpu_to_sle64(0);
1717 else {
1718 fn->data_size = cpu_to_sle64(ni->data_size);
1719 fn->allocated_size = cpu_to_sle64(ni->allocated_size);
1720 }
1721 memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
1722 /* Add FILE_NAME attribute to inode. */
1723 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
1724 err = errno;
1725 ntfs_log_error("Failed to add FILE_NAME attribute.\n");
1726 goto err_out;
1727 }
1728 /* Add FILE_NAME attribute to index. */
1729 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
1730 le16_to_cpu(ni->mrec->sequence_number)))) {
1731 err = errno;
1732 ntfs_log_perror("Failed to add entry to the index");
1733 goto err_out;
1734 }
1735 rollback_dir = 1;
1736 /* Set hard links count and directory flag. */
1737 ni->mrec->link_count = const_cpu_to_le16(1);
1738 if (S_ISDIR(type))
1739 ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY;
1740 /* Add reparse data */
1741 if (special_files == NTFS_FILES_WSL) {
1742 switch (type) {
1743 case S_IFLNK :
1744 err = ntfs_reparse_set_wsl_symlink(ni, target,
1745 target_len);
1746 break;
1747 case S_IFIFO :
1748 case S_IFSOCK :
1749 case S_IFCHR :
1750 case S_IFBLK :
1751 err = ntfs_reparse_set_wsl_not_symlink(ni,
1752 type);
1753 if (!err) {
1754 err = ntfs_ea_set_wsl_not_symlink(ni,
1755 type, dev);
1756 if (err)
1757 ntfs_remove_ntfs_reparse_data(ni);
1758 }
1759 break;
1760 default :
1761 err = 0;
1762 break;
1763 }
1764 if (err) {
1765 err = errno;
1766 goto err_out;
1767 }
1768 }
1769 ntfs_inode_mark_dirty(ni);
1770 /* Done! */
1771 free(fn);
1772 free(si);
1773 ntfs_log_trace("Done.\n");
1774 return ni;
1775 err_out:
1776 ntfs_log_trace("Failed.\n");
1777
1778 if (rollback_dir)
1779 ntfs_index_remove(dir_ni, ni, fn, fn_len);
1780
1781 if (rollback_sd)
1782 ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
1783
1784 if (rollback_data)
1785 ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
1786 /*
1787 * Free extent MFT records (should not exist any with current
1788 * ntfs_create implementation, but for any case if something will be
1789 * changed in the future).
1790 */
1791 while (ni->nr_extents)
1792 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
1793 err = errno;
1794 ntfs_log_error("Failed to free extent MFT record. "
1795 "Leaving inconsistent metadata.\n");
1796 }
1797 if (ntfs_mft_record_free(ni->vol, ni))
1798 ntfs_log_error("Failed to free MFT record. "
1799 "Leaving inconsistent metadata. Run chkdsk.\n");
1800 free(fn);
1801 free(si);
1802 errno = err;
1803 return NULL;
1804 }
1805
1806 /**
1807 * Some wrappers around __ntfs_create() ...
1808 */
1809
ntfs_create(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,mode_t type)1810 ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name,
1811 u8 name_len, mode_t type)
1812 {
1813 if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
1814 type != S_IFSOCK) {
1815 ntfs_log_error("Invalid arguments.\n");
1816 return NULL;
1817 }
1818 return __ntfs_create(dir_ni, securid, name, name_len, type, 0, NULL, 0);
1819 }
1820
ntfs_create_device(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,mode_t type,dev_t dev)1821 ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
1822 const ntfschar *name, u8 name_len, mode_t type, dev_t dev)
1823 {
1824 if (type != S_IFCHR && type != S_IFBLK) {
1825 ntfs_log_error("Invalid arguments.\n");
1826 return NULL;
1827 }
1828 return __ntfs_create(dir_ni, securid, name, name_len, type, dev, NULL, 0);
1829 }
1830
ntfs_create_symlink(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,const ntfschar * target,int target_len)1831 ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
1832 const ntfschar *name, u8 name_len, const ntfschar *target,
1833 int target_len)
1834 {
1835 if (!target || !target_len) {
1836 ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
1837 target, target_len);
1838 return NULL;
1839 }
1840 return __ntfs_create(dir_ni, securid, name, name_len, S_IFLNK, 0,
1841 target, target_len);
1842 }
1843
ntfs_check_empty_dir(ntfs_inode * ni)1844 int ntfs_check_empty_dir(ntfs_inode *ni)
1845 {
1846 ntfs_attr *na;
1847 int ret = 0;
1848
1849 if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
1850 return 0;
1851
1852 na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);
1853 if (!na) {
1854 errno = EIO;
1855 ntfs_log_perror("Failed to open directory");
1856 return -1;
1857 }
1858
1859 /* Non-empty directory? */
1860 if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
1861 /* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
1862 errno = ENOTEMPTY;
1863 ntfs_log_debug("Directory is not empty\n");
1864 ret = -1;
1865 }
1866
1867 ntfs_attr_close(na);
1868 return ret;
1869 }
1870
ntfs_check_unlinkable_dir(ntfs_inode * ni,FILE_NAME_ATTR * fn)1871 static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn)
1872 {
1873 int link_count = le16_to_cpu(ni->mrec->link_count);
1874 int ret;
1875
1876 ret = ntfs_check_empty_dir(ni);
1877 if (!ret || errno != ENOTEMPTY)
1878 return ret;
1879 /*
1880 * Directory is non-empty, so we can unlink only if there is more than
1881 * one "real" hard link, i.e. links aren't different DOS and WIN32 names
1882 */
1883 if ((link_count == 1) ||
1884 (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
1885 errno = ENOTEMPTY;
1886 ntfs_log_debug("Non-empty directory without hard links\n");
1887 goto no_hardlink;
1888 }
1889
1890 ret = 0;
1891 no_hardlink:
1892 return ret;
1893 }
1894
1895 /**
1896 * ntfs_delete - delete file or directory from ntfs volume
1897 * @ni: ntfs inode for object to delte
1898 * @dir_ni: ntfs inode for directory in which delete object
1899 * @name: unicode name of the object to delete
1900 * @name_len: length of the name in unicode characters
1901 *
1902 * @ni is always closed after the call to this function (even if it failed),
1903 * user does not need to call ntfs_inode_close himself.
1904 *
1905 * Return 0 on success or -1 on error with errno set to the error code.
1906 */
ntfs_delete(ntfs_volume * vol,const char * pathname,ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len)1907 int ntfs_delete(ntfs_volume *vol, const char *pathname,
1908 ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
1909 u8 name_len)
1910 {
1911 ntfs_attr_search_ctx *actx = NULL;
1912 FILE_NAME_ATTR *fn = NULL;
1913 BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE;
1914 BOOL case_sensitive_match = TRUE;
1915 int err = 0;
1916 #if CACHE_NIDATA_SIZE
1917 int i;
1918 #endif
1919 #if CACHE_INODE_SIZE
1920 struct CACHED_INODE item;
1921 const char *p;
1922 u64 inum = (u64)-1;
1923 int count;
1924 #endif
1925 #if CACHE_LOOKUP_SIZE
1926 struct CACHED_LOOKUP lkitem;
1927 #endif
1928
1929 ntfs_log_trace("Entering.\n");
1930
1931 if (!ni || !dir_ni || !name || !name_len) {
1932 ntfs_log_error("Invalid arguments.\n");
1933 errno = EINVAL;
1934 goto err_out;
1935 }
1936 if (ni->nr_extents == -1)
1937 ni = ni->base_ni;
1938 if (dir_ni->nr_extents == -1)
1939 dir_ni = dir_ni->base_ni;
1940 /*
1941 * Search for FILE_NAME attribute with such name. If it's in POSIX or
1942 * WIN32_AND_DOS namespace, then simply remove it from index and inode.
1943 * If filename in DOS or in WIN32 namespace, then remove DOS name first,
1944 * only then remove WIN32 name.
1945 */
1946 actx = ntfs_attr_get_search_ctx(ni, NULL);
1947 if (!actx)
1948 goto err_out;
1949 search:
1950 while (!(err = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
1951 CASE_SENSITIVE, 0, NULL, 0, actx))) {
1952 #ifdef DEBUG
1953 char *s;
1954 #endif
1955 IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
1956
1957 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
1958 le16_to_cpu(actx->attr->value_offset));
1959 #ifdef DEBUG
1960 s = ntfs_attr_name_get(fn->file_name, fn->file_name_length);
1961 ntfs_log_trace("name: '%s' type: %d dos: %d win32: %d "
1962 "case: %d\n", s, fn->file_name_type,
1963 looking_for_dos_name, looking_for_win32_name,
1964 case_sensitive_match);
1965 ntfs_attr_name_free(&s);
1966 #endif
1967 if (looking_for_dos_name) {
1968 if (fn->file_name_type == FILE_NAME_DOS)
1969 break;
1970 else
1971 continue;
1972 }
1973 if (looking_for_win32_name) {
1974 if (fn->file_name_type == FILE_NAME_WIN32)
1975 break;
1976 else
1977 continue;
1978 }
1979
1980 /* Ignore hard links from other directories */
1981 if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
1982 ntfs_log_debug("MFT record numbers don't match "
1983 "(%llu != %llu)\n",
1984 (long long unsigned)dir_ni->mft_no,
1985 (long long unsigned)MREF_LE(fn->parent_directory));
1986 continue;
1987 }
1988 if (case_sensitive_match
1989 || ((fn->file_name_type == FILE_NAME_POSIX)
1990 && NVolCaseSensitive(ni->vol)))
1991 case_sensitive = CASE_SENSITIVE;
1992
1993 if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
1994 name, name_len, case_sensitive,
1995 ni->vol->upcase, ni->vol->upcase_len)){
1996
1997 if (fn->file_name_type == FILE_NAME_WIN32) {
1998 looking_for_dos_name = TRUE;
1999 ntfs_attr_reinit_search_ctx(actx);
2000 continue;
2001 }
2002 if (fn->file_name_type == FILE_NAME_DOS)
2003 looking_for_dos_name = TRUE;
2004 break;
2005 }
2006 }
2007 if (err) {
2008 /*
2009 * If case sensitive search failed, then try once again
2010 * ignoring case.
2011 */
2012 if (errno == ENOENT && case_sensitive_match) {
2013 case_sensitive_match = FALSE;
2014 ntfs_attr_reinit_search_ctx(actx);
2015 goto search;
2016 }
2017 goto err_out;
2018 }
2019
2020 if (ntfs_check_unlinkable_dir(ni, fn) < 0)
2021 goto err_out;
2022
2023 if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
2024 goto err_out;
2025
2026 /*
2027 * Keep the last name in place, this is useful for undeletion
2028 * (Windows also does so), however delete the name if it were
2029 * in an extent, to avoid leaving an attribute list.
2030 */
2031 if ((ni->mrec->link_count == const_cpu_to_le16(1)) && !actx->base_ntfs_ino) {
2032 /* make sure to not loop to another search */
2033 looking_for_dos_name = FALSE;
2034 } else {
2035 if (ntfs_attr_record_rm(actx))
2036 goto err_out;
2037 }
2038
2039 ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
2040 ni->mrec->link_count) - 1);
2041
2042 ntfs_inode_mark_dirty(ni);
2043 if (looking_for_dos_name) {
2044 looking_for_dos_name = FALSE;
2045 looking_for_win32_name = TRUE;
2046 ntfs_attr_reinit_search_ctx(actx);
2047 goto search;
2048 }
2049 /* TODO: Update object id, quota and securiry indexes if required. */
2050 /*
2051 * If hard link count is not equal to zero then we are done. In other
2052 * case there are no reference to this inode left, so we should free all
2053 * non-resident attributes and mark all MFT record as not in use.
2054 */
2055 #if CACHE_LOOKUP_SIZE
2056 /* invalidate entry in lookup cache */
2057 lkitem.name = (const char*)NULL;
2058 lkitem.namesize = 0;
2059 lkitem.inum = ni->mft_no;
2060 lkitem.parent = dir_ni->mft_no;
2061 ntfs_invalidate_cache(vol->lookup_cache, GENERIC(&lkitem),
2062 lookup_cache_inv_compare, CACHE_NOHASH);
2063 #endif
2064 #if CACHE_INODE_SIZE
2065 inum = ni->mft_no;
2066 if (pathname) {
2067 /* invalide cache entry, even if there was an error */
2068 /* Remove leading /'s. */
2069 p = pathname;
2070 while (*p == PATH_SEP)
2071 p++;
2072 if (p[0] && (p[strlen(p)-1] == PATH_SEP))
2073 ntfs_log_error("Unnormalized path %s\n",pathname);
2074 item.pathname = p;
2075 item.varsize = strlen(p);
2076 } else {
2077 item.pathname = (const char*)NULL;
2078 item.varsize = 0;
2079 }
2080 item.inum = inum;
2081 count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item),
2082 inode_cache_inv_compare, CACHE_NOHASH);
2083 if (pathname && !count)
2084 ntfs_log_error("Could not delete inode cache entry for %s\n",
2085 pathname);
2086 #endif
2087 if (ni->mrec->link_count) {
2088 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
2089 goto ok;
2090 }
2091 if (ntfs_delete_reparse_index(ni)) {
2092 /*
2093 * Failed to remove the reparse index : proceed anyway
2094 * This is not a critical error, the entry is useless
2095 * because of sequence_number, and stopping file deletion
2096 * would be much worse as the file is not referenced now.
2097 */
2098 err = errno;
2099 }
2100 if (ntfs_delete_object_id_index(ni)) {
2101 /*
2102 * Failed to remove the object id index : proceed anyway
2103 * This is not a critical error.
2104 */
2105 err = errno;
2106 }
2107 ntfs_attr_reinit_search_ctx(actx);
2108 while (!ntfs_attrs_walk(actx)) {
2109 if (actx->attr->non_resident) {
2110 runlist *rl;
2111
2112 rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr,
2113 NULL);
2114 if (!rl) {
2115 err = errno;
2116 ntfs_log_error("Failed to decompress runlist. "
2117 "Leaving inconsistent metadata.\n");
2118 continue;
2119 }
2120 if (ntfs_cluster_free_from_rl(ni->vol, rl)) {
2121 err = errno;
2122 ntfs_log_error("Failed to free clusters. "
2123 "Leaving inconsistent metadata.\n");
2124 continue;
2125 }
2126 free(rl);
2127 }
2128 }
2129 if (errno != ENOENT) {
2130 err = errno;
2131 ntfs_log_error("Attribute enumeration failed. "
2132 "Probably leaving inconsistent metadata.\n");
2133 }
2134 /* All extents should be attached after attribute walk. */
2135 #if CACHE_NIDATA_SIZE
2136 /*
2137 * Disconnect extents before deleting them, so they are
2138 * not wrongly moved to cache through the chainings
2139 */
2140 for (i=ni->nr_extents-1; i>=0; i--) {
2141 ni->extent_nis[i]->base_ni = (ntfs_inode*)NULL;
2142 ni->extent_nis[i]->nr_extents = 0;
2143 if (ntfs_mft_record_free(ni->vol, ni->extent_nis[i])) {
2144 err = errno;
2145 ntfs_log_error("Failed to free extent MFT record. "
2146 "Leaving inconsistent metadata.\n");
2147 }
2148 }
2149 free(ni->extent_nis);
2150 ni->nr_extents = 0;
2151 ni->extent_nis = (ntfs_inode**)NULL;
2152 #else
2153 while (ni->nr_extents)
2154 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
2155 err = errno;
2156 ntfs_log_error("Failed to free extent MFT record. "
2157 "Leaving inconsistent metadata.\n");
2158 }
2159 #endif
2160 debug_double_inode(ni->mft_no,0);
2161 if (ntfs_mft_record_free(ni->vol, ni)) {
2162 err = errno;
2163 ntfs_log_error("Failed to free base MFT record. "
2164 "Leaving inconsistent metadata.\n");
2165 }
2166 ni = NULL;
2167 ok:
2168 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2169 out:
2170 if (actx)
2171 ntfs_attr_put_search_ctx(actx);
2172 if (ntfs_inode_close(dir_ni) && !err)
2173 err = errno;
2174 if (ntfs_inode_close(ni) && !err)
2175 err = errno;
2176 if (err) {
2177 errno = err;
2178 ntfs_log_debug("Could not delete file: %s\n", strerror(errno));
2179 return -1;
2180 }
2181 ntfs_log_trace("Done.\n");
2182 return 0;
2183 err_out:
2184 err = errno;
2185 goto out;
2186 }
2187
2188 /**
2189 * ntfs_link - create hard link for file or directory
2190 * @ni: ntfs inode for object to create hard link
2191 * @dir_ni: ntfs inode for directory in which new link should be placed
2192 * @name: unicode name of the new link
2193 * @name_len: length of the name in unicode characters
2194 *
2195 * NOTE: At present we allow creating hardlinks to directories, we use them
2196 * in a temporary state during rename. But it's defenitely bad idea to have
2197 * hard links to directories as a result of operation.
2198 * FIXME: Create internal __ntfs_link that allows hard links to a directories
2199 * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link.
2200 *
2201 * Return 0 on success or -1 on error with errno set to the error code.
2202 */
ntfs_link_i(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len,FILE_NAME_TYPE_FLAGS nametype)2203 static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
2204 u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
2205 {
2206 FILE_NAME_ATTR *fn = NULL;
2207 int fn_len, err;
2208
2209 ntfs_log_trace("Entering.\n");
2210
2211 if (!ni || !dir_ni || !name || !name_len ||
2212 ni->mft_no == dir_ni->mft_no) {
2213 err = EINVAL;
2214 ntfs_log_perror("ntfs_link wrong arguments");
2215 goto err_out;
2216 }
2217
2218 if (NVolHideDotFiles(dir_ni->vol)) {
2219 /* Set hidden flag according to the latest name */
2220 if ((name_len > 1)
2221 && (name[0] == const_cpu_to_le16('.'))
2222 && (name[1] != const_cpu_to_le16('.')))
2223 ni->flags |= FILE_ATTR_HIDDEN;
2224 else
2225 ni->flags &= ~FILE_ATTR_HIDDEN;
2226 }
2227
2228 /* Create FILE_NAME attribute. */
2229 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
2230 fn = ntfs_calloc(fn_len);
2231 if (!fn) {
2232 err = errno;
2233 goto err_out;
2234 }
2235 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
2236 le16_to_cpu(dir_ni->mrec->sequence_number));
2237 fn->file_name_length = name_len;
2238 fn->file_name_type = nametype;
2239 fn->file_attributes = ni->flags;
2240 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
2241 fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT;
2242 fn->data_size = fn->allocated_size = const_cpu_to_sle64(0);
2243 } else {
2244 fn->allocated_size = cpu_to_sle64(ni->allocated_size);
2245 fn->data_size = cpu_to_sle64(ni->data_size);
2246 }
2247 fn->creation_time = ni->creation_time;
2248 fn->last_data_change_time = ni->last_data_change_time;
2249 fn->last_mft_change_time = ni->last_mft_change_time;
2250 fn->last_access_time = ni->last_access_time;
2251 memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
2252 /* Add FILE_NAME attribute to index. */
2253 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
2254 le16_to_cpu(ni->mrec->sequence_number)))) {
2255 err = errno;
2256 ntfs_log_perror("Failed to add filename to the index");
2257 goto err_out;
2258 }
2259 /* Add FILE_NAME attribute to inode. */
2260 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
2261 ntfs_log_error("Failed to add FILE_NAME attribute.\n");
2262 err = errno;
2263 /* Try to remove just added attribute from index. */
2264 if (ntfs_index_remove(dir_ni, ni, fn, fn_len))
2265 goto rollback_failed;
2266 goto err_out;
2267 }
2268 /* Increment hard links count. */
2269 ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
2270 ni->mrec->link_count) + 1);
2271 /* Done! */
2272 ntfs_inode_mark_dirty(ni);
2273 free(fn);
2274 ntfs_log_trace("Done.\n");
2275 return 0;
2276 rollback_failed:
2277 ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n");
2278 err_out:
2279 free(fn);
2280 errno = err;
2281 return -1;
2282 }
2283
ntfs_link(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len)2284 int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
2285 u8 name_len)
2286 {
2287 return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
2288 }
2289
2290 /*
2291 * Get a parent directory from an inode entry
2292 *
2293 * This is only used in situations where the path used to access
2294 * the current file is not known for sure. The result may be different
2295 * from the path when the file is linked in several parent directories.
2296 *
2297 * Currently this is only used for translating ".." in the target
2298 * of a Vista relative symbolic link
2299 */
2300
ntfs_dir_parent_inode(ntfs_inode * ni)2301 ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
2302 {
2303 ntfs_inode *dir_ni = (ntfs_inode*)NULL;
2304 u64 inum;
2305 FILE_NAME_ATTR *fn;
2306 ntfs_attr_search_ctx *ctx;
2307
2308 if (ni->mft_no != FILE_root) {
2309 /* find the name in the attributes */
2310 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2311 if (!ctx)
2312 return ((ntfs_inode*)NULL);
2313
2314 if (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2315 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
2316 /* We know this will always be resident. */
2317 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2318 le16_to_cpu(ctx->attr->value_offset));
2319 inum = le64_to_cpu(fn->parent_directory);
2320 if (inum != (u64)-1) {
2321 dir_ni = ntfs_inode_open(ni->vol, MREF(inum));
2322 }
2323 }
2324 ntfs_attr_put_search_ctx(ctx);
2325 }
2326 return (dir_ni);
2327 }
2328
2329 #define MAX_DOS_NAME_LENGTH 12
2330
2331 /*
2332 * Get a DOS name for a file in designated directory
2333 *
2334 * Not allowed if there are several non-dos names (EMLINK)
2335 *
2336 * Returns size if found
2337 * 0 if not found
2338 * -1 if there was an error (described by errno)
2339 */
2340
get_dos_name(ntfs_inode * ni,u64 dnum,ntfschar * dosname)2341 static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
2342 {
2343 size_t outsize = 0;
2344 int namecount = 0;
2345 FILE_NAME_ATTR *fn;
2346 ntfs_attr_search_ctx *ctx;
2347
2348 /* find the name in the attributes */
2349 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2350 if (!ctx)
2351 return -1;
2352
2353 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2354 0, NULL, 0, ctx)) {
2355 /* We know this will always be resident. */
2356 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2357 le16_to_cpu(ctx->attr->value_offset));
2358
2359 if (fn->file_name_type != FILE_NAME_DOS)
2360 namecount++;
2361 if ((fn->file_name_type & FILE_NAME_DOS)
2362 && (MREF_LE(fn->parent_directory) == dnum)) {
2363 /*
2364 * Found a DOS or WIN32+DOS name for the entry
2365 * copy name, after truncation for safety
2366 */
2367 outsize = fn->file_name_length;
2368 /* TODO : reject if name is too long ? */
2369 if (outsize > MAX_DOS_NAME_LENGTH)
2370 outsize = MAX_DOS_NAME_LENGTH;
2371 memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar));
2372 }
2373 }
2374 ntfs_attr_put_search_ctx(ctx);
2375 if ((outsize > 0) && (namecount > 1)) {
2376 outsize = -1;
2377 errno = EMLINK; /* this error implies there is a dos name */
2378 }
2379 return (outsize);
2380 }
2381
2382
2383 /*
2384 * Get a long name for a file in designated directory
2385 *
2386 * Not allowed if there are several non-dos names (EMLINK)
2387 *
2388 * Returns size if found
2389 * 0 if not found
2390 * -1 if there was an error (described by errno)
2391 */
2392
get_long_name(ntfs_inode * ni,u64 dnum,ntfschar * longname)2393 static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
2394 {
2395 size_t outsize = 0;
2396 int namecount = 0;
2397 FILE_NAME_ATTR *fn;
2398 ntfs_attr_search_ctx *ctx;
2399
2400 /* find the name in the attributes */
2401 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2402 if (!ctx)
2403 return -1;
2404
2405 /* first search for WIN32 or DOS+WIN32 names */
2406 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2407 0, NULL, 0, ctx)) {
2408 /* We know this will always be resident. */
2409 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2410 le16_to_cpu(ctx->attr->value_offset));
2411
2412 if (fn->file_name_type != FILE_NAME_DOS)
2413 namecount++;
2414 if ((fn->file_name_type & FILE_NAME_WIN32)
2415 && (MREF_LE(fn->parent_directory) == dnum)) {
2416 /*
2417 * Found a WIN32 or WIN32+DOS name for the entry
2418 * copy name
2419 */
2420 outsize = fn->file_name_length;
2421 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
2422 }
2423 }
2424 if (namecount > 1) {
2425 ntfs_attr_put_search_ctx(ctx);
2426 errno = EMLINK;
2427 return -1;
2428 }
2429 /* if not found search for POSIX names */
2430 if (!outsize) {
2431 ntfs_attr_reinit_search_ctx(ctx);
2432 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2433 0, NULL, 0, ctx)) {
2434 /* We know this will always be resident. */
2435 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2436 le16_to_cpu(ctx->attr->value_offset));
2437
2438 if ((fn->file_name_type == FILE_NAME_POSIX)
2439 && (MREF_LE(fn->parent_directory) == dnum)) {
2440 /*
2441 * Found a POSIX name for the entry
2442 * copy name
2443 */
2444 outsize = fn->file_name_length;
2445 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
2446 }
2447 }
2448 }
2449 ntfs_attr_put_search_ctx(ctx);
2450 return (outsize);
2451 }
2452
2453
2454 /*
2455 * Get the ntfs DOS name into an extended attribute
2456 */
2457
ntfs_get_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni,char * value,size_t size)2458 int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2459 char *value, size_t size)
2460 {
2461 int outsize = 0;
2462 char *outname = (char*)NULL;
2463 u64 dnum;
2464 int doslen;
2465 ntfschar dosname[MAX_DOS_NAME_LENGTH];
2466
2467 dnum = dir_ni->mft_no;
2468 doslen = get_dos_name(ni, dnum, dosname);
2469 if (doslen > 0) {
2470 /*
2471 * Found a DOS name for the entry, make
2472 * uppercase and encode into the buffer
2473 * if there is enough space
2474 */
2475 ntfs_name_upcase(dosname, doslen,
2476 ni->vol->upcase, ni->vol->upcase_len);
2477 outsize = ntfs_ucstombs(dosname, doslen, &outname, 0);
2478 if (outsize < 0) {
2479 ntfs_log_error("Cannot represent dosname in current locale.\n");
2480 outsize = -errno;
2481 } else {
2482 if (value && (outsize <= (int)size))
2483 memcpy(value, outname, outsize);
2484 else
2485 if (size && (outsize > (int)size))
2486 outsize = -ERANGE;
2487 free(outname);
2488 }
2489 } else {
2490 if (doslen == 0)
2491 errno = ENODATA;
2492 outsize = -errno;
2493 }
2494 return (outsize);
2495 }
2496
2497 /*
2498 * Change the name space of an existing file or directory
2499 *
2500 * Returns the old namespace if successful
2501 * -1 if an error occurred (described by errno)
2502 */
2503
set_namespace(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,int len,FILE_NAME_TYPE_FLAGS nametype)2504 static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
2505 const ntfschar *name, int len,
2506 FILE_NAME_TYPE_FLAGS nametype)
2507 {
2508 ntfs_attr_search_ctx *actx;
2509 ntfs_index_context *icx;
2510 FILE_NAME_ATTR *fnx;
2511 FILE_NAME_ATTR *fn = NULL;
2512 BOOL found;
2513 int lkup;
2514 int ret;
2515
2516 ret = -1;
2517 actx = ntfs_attr_get_search_ctx(ni, NULL);
2518 if (actx) {
2519 found = FALSE;
2520 do {
2521 lkup = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2522 CASE_SENSITIVE, 0, NULL, 0, actx);
2523 if (!lkup) {
2524 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
2525 le16_to_cpu(actx->attr->value_offset));
2526 found = (MREF_LE(fn->parent_directory)
2527 == dir_ni->mft_no)
2528 && !memcmp(fn->file_name, name,
2529 len*sizeof(ntfschar));
2530 }
2531 } while (!lkup && !found);
2532 if (found) {
2533 icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
2534 if (icx) {
2535 lkup = ntfs_index_lookup((char*)fn, len, icx);
2536 if (!lkup && icx->data && icx->data_len) {
2537 fnx = (FILE_NAME_ATTR*)icx->data;
2538 ret = fn->file_name_type;
2539 fn->file_name_type = nametype;
2540 fnx->file_name_type = nametype;
2541 ntfs_inode_mark_dirty(ni);
2542 ntfs_index_entry_mark_dirty(icx);
2543 }
2544 ntfs_index_ctx_put(icx);
2545 }
2546 }
2547 ntfs_attr_put_search_ctx(actx);
2548 }
2549 return (ret);
2550 }
2551
2552 /*
2553 * Set a DOS name to a file and adjust name spaces
2554 *
2555 * If the new names are collapsible (same uppercased chars) :
2556 *
2557 * - the existing DOS name or DOS+Win32 name is made Posix
2558 * - if it was a real DOS name, the existing long name is made DOS+Win32
2559 * and the existing DOS name is deleted
2560 * - finally the existing long name is made DOS+Win32 unless already done
2561 *
2562 * If the new names are not collapsible :
2563 *
2564 * - insert the short name as a DOS name
2565 * - delete the old long name or existing short name
2566 * - insert the new long name (as a Win32 or DOS+Win32 name)
2567 *
2568 * Deleting the old long name will not delete the file
2569 * provided the old name was in the Posix name space,
2570 * because the alternate name has been set before.
2571 *
2572 * The inodes of file and parent directory are always closed
2573 *
2574 * Returns 0 if successful
2575 * -1 if failed
2576 */
2577
set_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * shortname,int shortlen,const ntfschar * longname,int longlen,const ntfschar * deletename,int deletelen,BOOL existed)2578 static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2579 const ntfschar *shortname, int shortlen,
2580 const ntfschar *longname, int longlen,
2581 const ntfschar *deletename, int deletelen, BOOL existed)
2582 {
2583 unsigned int linkcount;
2584 ntfs_volume *vol;
2585 BOOL collapsible;
2586 BOOL deleted;
2587 BOOL done;
2588 FILE_NAME_TYPE_FLAGS oldnametype;
2589 u64 dnum;
2590 u64 fnum;
2591 int res;
2592
2593 res = -1;
2594 vol = ni->vol;
2595 dnum = dir_ni->mft_no;
2596 fnum = ni->mft_no;
2597 /* save initial link count */
2598 linkcount = le16_to_cpu(ni->mrec->link_count);
2599
2600 /* check whether the same name may be used as DOS and WIN32 */
2601 collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen,
2602 longname, longlen);
2603 if (collapsible) {
2604 deleted = FALSE;
2605 done = FALSE;
2606 if (existed) {
2607 oldnametype = set_namespace(ni, dir_ni, deletename,
2608 deletelen, FILE_NAME_POSIX);
2609 if (oldnametype == FILE_NAME_DOS) {
2610 if (set_namespace(ni, dir_ni, longname, longlen,
2611 FILE_NAME_WIN32_AND_DOS) >= 0) {
2612 if (!ntfs_delete(vol,
2613 (const char*)NULL, ni, dir_ni,
2614 deletename, deletelen))
2615 res = 0;
2616 deleted = TRUE;
2617 } else
2618 done = TRUE;
2619 }
2620 }
2621 if (!deleted) {
2622 if (!done && (set_namespace(ni, dir_ni,
2623 longname, longlen,
2624 FILE_NAME_WIN32_AND_DOS) >= 0))
2625 res = 0;
2626 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
2627 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2628 if (ntfs_inode_close_in_dir(ni,dir_ni) && !res)
2629 res = -1;
2630 if (ntfs_inode_close(dir_ni) && !res)
2631 res = -1;
2632 }
2633 } else {
2634 if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
2635 FILE_NAME_DOS)
2636 /* make sure a new link was recorded */
2637 && (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
2638 /* delete the existing long name or short name */
2639 // is it ok to not provide the path ?
2640 if (!ntfs_delete(vol, (char*)NULL, ni, dir_ni,
2641 deletename, deletelen)) {
2642 /* delete closes the inodes, so have to open again */
2643 dir_ni = ntfs_inode_open(vol, dnum);
2644 if (dir_ni) {
2645 ni = ntfs_inode_open(vol, fnum);
2646 if (ni) {
2647 if (!ntfs_link_i(ni, dir_ni,
2648 longname, longlen,
2649 FILE_NAME_WIN32))
2650 res = 0;
2651 if (ntfs_inode_close_in_dir(ni,
2652 dir_ni)
2653 && !res)
2654 res = -1;
2655 }
2656 if (ntfs_inode_close(dir_ni) && !res)
2657 res = -1;
2658 }
2659 }
2660 } else {
2661 ntfs_inode_close_in_dir(ni,dir_ni);
2662 ntfs_inode_close(dir_ni);
2663 }
2664 }
2665 return (res);
2666 }
2667
2668
2669 /*
2670 * Set the ntfs DOS name into an extended attribute
2671 *
2672 * The DOS name will be added as another file name attribute
2673 * using the existing file name information from the original
2674 * name or overwriting the DOS Name if one exists.
2675 *
2676 * The inode of the file is always closed
2677 */
2678
ntfs_set_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni,const char * value,size_t size,int flags)2679 int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2680 const char *value, size_t size, int flags)
2681 {
2682 int res = 0;
2683 int longlen = 0;
2684 int shortlen = 0;
2685 char newname[3*MAX_DOS_NAME_LENGTH + 1];
2686 ntfschar oldname[MAX_DOS_NAME_LENGTH];
2687 int oldlen;
2688 u64 dnum;
2689 BOOL closed = FALSE;
2690 ntfschar *shortname = NULL;
2691 ntfschar longname[NTFS_MAX_NAME_LEN];
2692
2693 /* copy the string to insert a null char, and truncate */
2694 if (size > 3*MAX_DOS_NAME_LENGTH)
2695 size = 3*MAX_DOS_NAME_LENGTH;
2696 strncpy(newname, value, size);
2697 /* a long name may be truncated badly and be untranslatable */
2698 newname[size] = 0;
2699 /* convert the string to the NTFS wide chars, and truncate */
2700 shortlen = ntfs_mbstoucs(newname, &shortname);
2701 if (shortlen > MAX_DOS_NAME_LENGTH)
2702 shortlen = MAX_DOS_NAME_LENGTH;
2703
2704 /* Make sure the short name has valid chars.
2705 * Note: the short name cannot end with dot or space, but the
2706 * corresponding long name can. */
2707 if ((shortlen < 0)
2708 || ntfs_forbidden_names(ni->vol,shortname,shortlen,TRUE)) {
2709 ntfs_inode_close_in_dir(ni,dir_ni);
2710 ntfs_inode_close(dir_ni);
2711 res = -errno;
2712 return res;
2713 }
2714 dnum = dir_ni->mft_no;
2715 longlen = get_long_name(ni, dnum, longname);
2716 if (longlen > 0) {
2717 oldlen = get_dos_name(ni, dnum, oldname);
2718 if ((oldlen >= 0)
2719 && !ntfs_forbidden_names(ni->vol, longname, longlen,
2720 FALSE)) {
2721 if (oldlen > 0) {
2722 if (flags & XATTR_CREATE) {
2723 res = -1;
2724 errno = EEXIST;
2725 } else
2726 if ((shortlen == oldlen)
2727 && !memcmp(shortname,oldname,
2728 oldlen*sizeof(ntfschar)))
2729 /* already set, done */
2730 res = 0;
2731 else {
2732 res = set_dos_name(ni, dir_ni,
2733 shortname, shortlen,
2734 longname, longlen,
2735 oldname, oldlen, TRUE);
2736 closed = TRUE;
2737 }
2738 } else {
2739 if (flags & XATTR_REPLACE) {
2740 res = -1;
2741 errno = ENODATA;
2742 } else {
2743 res = set_dos_name(ni, dir_ni,
2744 shortname, shortlen,
2745 longname, longlen,
2746 longname, longlen, FALSE);
2747 closed = TRUE;
2748 }
2749 }
2750 } else
2751 res = -1;
2752 } else {
2753 res = -1;
2754 if (!longlen)
2755 errno = ENOENT;
2756 }
2757 free(shortname);
2758 if (!closed) {
2759 ntfs_inode_close_in_dir(ni,dir_ni);
2760 ntfs_inode_close(dir_ni);
2761 }
2762 return (res ? -1 : 0);
2763 }
2764
2765 /*
2766 * Delete the ntfs DOS name
2767 */
2768
ntfs_remove_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni)2769 int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
2770 {
2771 int res;
2772 int oldnametype;
2773 int longlen = 0;
2774 int shortlen;
2775 u64 dnum;
2776 ntfs_volume *vol;
2777 BOOL deleted = FALSE;
2778 ntfschar shortname[MAX_DOS_NAME_LENGTH];
2779 ntfschar longname[NTFS_MAX_NAME_LEN];
2780
2781 res = -1;
2782 vol = ni->vol;
2783 dnum = dir_ni->mft_no;
2784 longlen = get_long_name(ni, dnum, longname);
2785 if (longlen > 0) {
2786 shortlen = get_dos_name(ni, dnum, shortname);
2787 if (shortlen >= 0) {
2788 /* migrate the long name as Posix */
2789 oldnametype = set_namespace(ni,dir_ni,longname,longlen,
2790 FILE_NAME_POSIX);
2791 switch (oldnametype) {
2792 case FILE_NAME_WIN32_AND_DOS :
2793 /* name was Win32+DOS : done */
2794 res = 0;
2795 break;
2796 case FILE_NAME_DOS :
2797 /* name was DOS, make it back to DOS */
2798 set_namespace(ni,dir_ni,longname,longlen,
2799 FILE_NAME_DOS);
2800 errno = ENOENT;
2801 break;
2802 case FILE_NAME_WIN32 :
2803 /* name was Win32, make it Posix and delete */
2804 if (set_namespace(ni,dir_ni,shortname,shortlen,
2805 FILE_NAME_POSIX) >= 0) {
2806 if (!ntfs_delete(vol,
2807 (const char*)NULL, ni,
2808 dir_ni, shortname,
2809 shortlen))
2810 res = 0;
2811 deleted = TRUE;
2812 } else {
2813 /*
2814 * DOS name has been found, but cannot
2815 * migrate to Posix : something bad
2816 * has happened
2817 */
2818 errno = EIO;
2819 ntfs_log_error("Could not change"
2820 " DOS name of inode %lld to Posix\n",
2821 (long long)ni->mft_no);
2822 }
2823 break;
2824 default :
2825 /* name was Posix or not found : error */
2826 errno = ENOENT;
2827 break;
2828 }
2829 }
2830 } else {
2831 if (!longlen)
2832 errno = ENOENT;
2833 res = -1;
2834 }
2835 if (!deleted) {
2836 ntfs_inode_close_in_dir(ni,dir_ni);
2837 ntfs_inode_close(dir_ni);
2838 }
2839 return (res);
2840 }
2841
2842 /*
2843 * Increment the count of subdirectories
2844 * (excluding entries with a short name)
2845 */
2846
nlink_increment(void * nlink_ptr,const ntfschar * name,const int len,const int type,const s64 pos,const MFT_REF mref,const unsigned int dt_type)2847 static int nlink_increment(void *nlink_ptr,
2848 const ntfschar *name __attribute__((unused)),
2849 const int len __attribute__((unused)),
2850 const int type,
2851 const s64 pos __attribute__((unused)),
2852 const MFT_REF mref __attribute__((unused)),
2853 const unsigned int dt_type)
2854 {
2855 if ((dt_type == NTFS_DT_DIR) && (type != FILE_NAME_DOS))
2856 (*((int*)nlink_ptr))++;
2857 return (0);
2858 }
2859
2860 /*
2861 * Compute the number of hard links according to Posix
2862 * For a directory count the subdirectories whose name is not
2863 * a short one, but count "." and ".."
2864 * Otherwise count the names, excluding the short ones.
2865 *
2866 * if there is an error, a null count is returned.
2867 */
2868
ntfs_dir_link_cnt(ntfs_inode * ni)2869 int ntfs_dir_link_cnt(ntfs_inode *ni)
2870 {
2871 ntfs_attr_search_ctx *actx;
2872 FILE_NAME_ATTR *fn;
2873 s64 pos;
2874 int err = 0;
2875 int nlink = 0;
2876
2877 if (!ni) {
2878 ntfs_log_error("Invalid argument.\n");
2879 errno = EINVAL;
2880 goto err_out;
2881 }
2882 if (ni->nr_extents == -1)
2883 ni = ni->base_ni;
2884 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
2885 /*
2886 * Directory : scan the directory and count
2887 * subdirectories whose name is not DOS-only.
2888 * The directory names are ignored, but "." and ".."
2889 * are taken into account.
2890 */
2891 pos = 0;
2892 err = ntfs_readdir(ni, &pos, &nlink, nlink_increment);
2893 if (err)
2894 nlink = 0;
2895 } else {
2896 /*
2897 * Non-directory : search for FILE_NAME attributes,
2898 * and count those which are not DOS-only ones.
2899 */
2900 actx = ntfs_attr_get_search_ctx(ni, NULL);
2901 if (!actx)
2902 goto err_out;
2903 while (!(err = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2904 CASE_SENSITIVE, 0, NULL, 0, actx))) {
2905 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
2906 le16_to_cpu(actx->attr->value_offset));
2907 if (fn->file_name_type != FILE_NAME_DOS)
2908 nlink++;
2909 }
2910 if (err && (errno != ENOENT))
2911 nlink = 0;
2912 ntfs_attr_put_search_ctx(actx);
2913 }
2914 if (!nlink)
2915 ntfs_log_perror("Failed to compute nlink of inode %lld",
2916 (long long)ni->mft_no);
2917 err_out :
2918 return (nlink);
2919 }
2920