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 */
ntfs_mft_get_parent_ref(ntfs_inode * ni)1044 static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
1045 {
1046 MFT_REF mref;
1047 ntfs_attr_search_ctx *ctx;
1048 FILE_NAME_ATTR *fn;
1049 int eo;
1050
1051 ntfs_log_trace("Entering.\n");
1052
1053 if (!ni) {
1054 errno = EINVAL;
1055 return ERR_MREF(-1);
1056 }
1057
1058 ctx = ntfs_attr_get_search_ctx(ni, NULL);
1059 if (!ctx)
1060 return ERR_MREF(-1);
1061 if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
1062 ntfs_log_error("No file name found in inode %lld\n",
1063 (unsigned long long)ni->mft_no);
1064 goto err_out;
1065 }
1066 if (ctx->attr->non_resident) {
1067 ntfs_log_error("File name attribute must be resident (inode "
1068 "%lld)\n", (unsigned long long)ni->mft_no);
1069 goto io_err_out;
1070 }
1071 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
1072 le16_to_cpu(ctx->attr->value_offset));
1073 mref = le64_to_cpu(fn->parent_directory);
1074 ntfs_attr_put_search_ctx(ctx);
1075 return mref;
1076 io_err_out:
1077 errno = EIO;
1078 err_out:
1079 eo = errno;
1080 ntfs_attr_put_search_ctx(ctx);
1081 errno = eo;
1082 return ERR_MREF(-1);
1083 }
1084
1085 /**
1086 * ntfs_readdir - read the contents of an ntfs directory
1087 * @dir_ni: ntfs inode of current directory
1088 * @pos: current position in directory
1089 * @dirent: context for filldir callback supplied by the caller
1090 * @filldir: filldir callback supplied by the caller
1091 *
1092 * Parse the index root and the index blocks that are marked in use in the
1093 * index bitmap and hand each found directory entry to the @filldir callback
1094 * supplied by the caller.
1095 *
1096 * Return 0 on success or -1 on error with errno set to the error code.
1097 *
1098 * Note: Index blocks are parsed in ascending vcn order, from which follows
1099 * that the directory entries are not returned sorted.
1100 */
ntfs_readdir(ntfs_inode * dir_ni,s64 * pos,void * dirent,ntfs_filldir_t filldir)1101 int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
1102 void *dirent, ntfs_filldir_t filldir)
1103 {
1104 s64 i_size, br, ia_pos, bmp_pos, ia_start;
1105 ntfs_volume *vol;
1106 ntfs_attr *ia_na, *bmp_na = NULL;
1107 ntfs_attr_search_ctx *ctx = NULL;
1108 u8 *index_end, *bmp = NULL;
1109 INDEX_ROOT *ir;
1110 INDEX_ENTRY *ie;
1111 INDEX_ALLOCATION *ia = NULL;
1112 int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
1113 u32 index_block_size;
1114 u8 index_block_size_bits, index_vcn_size_bits;
1115
1116 ntfs_log_trace("Entering.\n");
1117
1118 if (!dir_ni || !pos || !filldir) {
1119 errno = EINVAL;
1120 return -1;
1121 }
1122
1123 if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
1124 errno = ENOTDIR;
1125 return -1;
1126 }
1127
1128 vol = dir_ni->vol;
1129
1130 ntfs_log_trace("Entering for inode %lld, *pos 0x%llx.\n",
1131 (unsigned long long)dir_ni->mft_no, (long long)*pos);
1132
1133 /* Open the index allocation attribute. */
1134 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
1135 if (!ia_na) {
1136 if (errno != ENOENT) {
1137 ntfs_log_perror("Failed to open index allocation attribute. "
1138 "Directory inode %lld is corrupt or bug",
1139 (unsigned long long)dir_ni->mft_no);
1140 return -1;
1141 }
1142 i_size = 0;
1143 } else
1144 i_size = ia_na->data_size;
1145
1146 rc = 0;
1147
1148 /* Are we at end of dir yet? */
1149 if (*pos >= i_size + vol->mft_record_size)
1150 goto done;
1151
1152 /* Emulate . and .. for all directories. */
1153 if (!*pos) {
1154 rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos,
1155 MK_MREF(dir_ni->mft_no,
1156 le16_to_cpu(dir_ni->mrec->sequence_number)),
1157 NTFS_DT_DIR);
1158 if (rc)
1159 goto err_out;
1160 ++*pos;
1161 }
1162 if (*pos == 1) {
1163 MFT_REF parent_mref;
1164
1165 parent_mref = ntfs_mft_get_parent_ref(dir_ni);
1166 if (parent_mref == ERR_MREF(-1)) {
1167 ntfs_log_perror("Parent directory not found");
1168 goto dir_err_out;
1169 }
1170
1171 rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos,
1172 parent_mref, NTFS_DT_DIR);
1173 if (rc)
1174 goto err_out;
1175 ++*pos;
1176 }
1177
1178 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
1179 if (!ctx)
1180 goto err_out;
1181
1182 /* Get the offset into the index root attribute. */
1183 ir_pos = (int)*pos;
1184 /* Find the index root attribute in the mft record. */
1185 if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
1186 0, ctx)) {
1187 ntfs_log_perror("Index root attribute missing in directory inode "
1188 "%lld", (unsigned long long)dir_ni->mft_no);
1189 goto dir_err_out;
1190 }
1191 /* Get to the index root value. */
1192 ir = (INDEX_ROOT*)((u8*)ctx->attr +
1193 le16_to_cpu(ctx->attr->value_offset));
1194
1195 /* Determine the size of a vcn in the directory index. */
1196 index_block_size = le32_to_cpu(ir->index_block_size);
1197 if (index_block_size < NTFS_BLOCK_SIZE ||
1198 index_block_size & (index_block_size - 1)) {
1199 ntfs_log_error("Index block size %u is invalid.\n",
1200 (unsigned)index_block_size);
1201 goto dir_err_out;
1202 }
1203 index_block_size_bits = ffs(index_block_size) - 1;
1204 if (vol->cluster_size <= index_block_size) {
1205 index_vcn_size_bits = vol->cluster_size_bits;
1206 } else {
1207 index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
1208 }
1209
1210 /* Are we jumping straight into the index allocation attribute? */
1211 if (*pos >= vol->mft_record_size) {
1212 ntfs_attr_put_search_ctx(ctx);
1213 ctx = NULL;
1214 goto skip_index_root;
1215 }
1216
1217 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
1218 /* The first index entry. */
1219 ie = (INDEX_ENTRY*)((u8*)&ir->index +
1220 le32_to_cpu(ir->index.entries_offset));
1221 /*
1222 * Loop until we exceed valid memory (corruption case) or until we
1223 * reach the last entry or until filldir tells us it has had enough
1224 * or signals an error (both covered by the rc test).
1225 */
1226 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
1227 ntfs_log_debug("In index root, offset %d.\n", (int)((u8*)ie - (u8*)ir));
1228 /* Bounds checks. */
1229 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
1230 sizeof(INDEX_ENTRY_HEADER) > index_end ||
1231 (u8*)ie + le16_to_cpu(ie->length) >
1232 index_end) {
1233 ntfs_log_error("Index root entry out of bounds in"
1234 " inode %lld\n",
1235 (unsigned long long)dir_ni->mft_no);
1236 goto dir_err_out;
1237 }
1238 /* The last entry cannot contain a name. */
1239 if (ie->ie_flags & INDEX_ENTRY_END)
1240 break;
1241
1242 if (!le16_to_cpu(ie->length))
1243 goto dir_err_out;
1244
1245 /* Skip index root entry if continuing previous readdir. */
1246 if (ir_pos > (u8*)ie - (u8*)ir)
1247 continue;
1248
1249 /* The file name must not overflow from the entry */
1250 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
1251 dir_ni->mft_no)) {
1252 errno = EIO;
1253 goto dir_err_out;
1254 }
1255 /*
1256 * Submit the directory entry to ntfs_filldir(), which will
1257 * invoke the filldir() callback as appropriate.
1258 */
1259 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
1260 INDEX_TYPE_ROOT, ir, ie, dirent, filldir);
1261 if (rc) {
1262 ntfs_attr_put_search_ctx(ctx);
1263 ctx = NULL;
1264 goto err_out;
1265 }
1266 }
1267 ntfs_attr_put_search_ctx(ctx);
1268 ctx = NULL;
1269
1270 /* If there is no index allocation attribute we are finished. */
1271 if (!ia_na)
1272 goto EOD;
1273
1274 /* Advance *pos to the beginning of the index allocation. */
1275 *pos = vol->mft_record_size;
1276
1277 skip_index_root:
1278
1279 if (!ia_na)
1280 goto done;
1281
1282 /* Allocate a buffer for the current index block. */
1283 ia = ntfs_malloc(index_block_size);
1284 if (!ia)
1285 goto err_out;
1286
1287 bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4);
1288 if (!bmp_na) {
1289 ntfs_log_perror("Failed to open index bitmap attribute");
1290 goto dir_err_out;
1291 }
1292
1293 /* Get the offset into the index allocation attribute. */
1294 ia_pos = *pos - vol->mft_record_size;
1295
1296 bmp_pos = ia_pos >> index_block_size_bits;
1297 if (bmp_pos >> 3 >= bmp_na->data_size) {
1298 ntfs_log_error("Current index position exceeds index bitmap "
1299 "size.\n");
1300 goto dir_err_out;
1301 }
1302
1303 bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096);
1304 bmp = ntfs_malloc(bmp_buf_size);
1305 if (!bmp)
1306 goto err_out;
1307
1308 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
1309 if (br != bmp_buf_size) {
1310 if (br != -1)
1311 errno = EIO;
1312 ntfs_log_perror("Failed to read from index bitmap attribute");
1313 goto err_out;
1314 }
1315
1316 bmp_buf_pos = 0;
1317 /* If the index block is not in use find the next one that is. */
1318 while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {
1319 find_next_index_buffer:
1320 bmp_pos++;
1321 bmp_buf_pos++;
1322 /* If we have reached the end of the bitmap, we are done. */
1323 if (bmp_pos >> 3 >= bmp_na->data_size)
1324 goto EOD;
1325 ia_pos = bmp_pos << index_block_size_bits;
1326 if (bmp_buf_pos >> 3 < bmp_buf_size)
1327 continue;
1328 /* Read next chunk from the index bitmap. */
1329 bmp_buf_pos = 0;
1330 if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size)
1331 bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3);
1332 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
1333 if (br != bmp_buf_size) {
1334 if (br != -1)
1335 errno = EIO;
1336 ntfs_log_perror("Failed to read from index bitmap attribute");
1337 goto err_out;
1338 }
1339 }
1340
1341 ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos);
1342
1343 /* Read the index block starting at bmp_pos. */
1344 br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1,
1345 index_block_size, ia);
1346 if (br != 1) {
1347 if (br != -1)
1348 errno = EIO;
1349 ntfs_log_perror("Failed to read index block");
1350 goto err_out;
1351 }
1352
1353 ia_start = ia_pos & ~(s64)(index_block_size - 1);
1354 if (ntfs_index_block_inconsistent((INDEX_BLOCK*)ia, index_block_size,
1355 ia_na->ni->mft_no, ia_start >> index_vcn_size_bits)) {
1356 goto dir_err_out;
1357 }
1358 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
1359
1360 /* The first index entry. */
1361 ie = (INDEX_ENTRY*)((u8*)&ia->index +
1362 le32_to_cpu(ia->index.entries_offset));
1363 /*
1364 * Loop until we exceed valid memory (corruption case) or until we
1365 * reach the last entry or until ntfs_filldir tells us it has had
1366 * enough or signals an error (both covered by the rc test).
1367 */
1368 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
1369 ntfs_log_debug("In index allocation, offset 0x%llx.\n",
1370 (long long)ia_start + ((u8*)ie - (u8*)ia));
1371 /* Bounds checks. */
1372 if ((u8*)ie < (u8*)ia || (u8*)ie +
1373 sizeof(INDEX_ENTRY_HEADER) > index_end ||
1374 (u8*)ie + le16_to_cpu(ie->length) >
1375 index_end) {
1376 ntfs_log_error("Index entry out of bounds in directory inode "
1377 "%lld.\n", (unsigned long long)dir_ni->mft_no);
1378 goto dir_err_out;
1379 }
1380 /* The last entry cannot contain a name. */
1381 if (ie->ie_flags & INDEX_ENTRY_END)
1382 break;
1383
1384 if (!le16_to_cpu(ie->length))
1385 goto dir_err_out;
1386
1387 /* Skip index entry if continuing previous readdir. */
1388 if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
1389 continue;
1390
1391 /* The file name must not overflow from the entry */
1392 if (ntfs_index_entry_inconsistent(ie, COLLATION_FILE_NAME,
1393 dir_ni->mft_no)) {
1394 errno = EIO;
1395 goto dir_err_out;
1396 }
1397 /*
1398 * Submit the directory entry to ntfs_filldir(), which will
1399 * invoke the filldir() callback as appropriate.
1400 */
1401 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
1402 INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir);
1403 if (rc)
1404 goto err_out;
1405 }
1406 goto find_next_index_buffer;
1407 EOD:
1408 /* We are finished, set *pos to EOD. */
1409 *pos = i_size + vol->mft_record_size;
1410 done:
1411 free(ia);
1412 free(bmp);
1413 if (bmp_na)
1414 ntfs_attr_close(bmp_na);
1415 if (ia_na)
1416 ntfs_attr_close(ia_na);
1417 ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos);
1418 return 0;
1419 dir_err_out:
1420 errno = EIO;
1421 err_out:
1422 eo = errno;
1423 ntfs_log_trace("failed.\n");
1424 if (ctx)
1425 ntfs_attr_put_search_ctx(ctx);
1426 free(ia);
1427 free(bmp);
1428 if (bmp_na)
1429 ntfs_attr_close(bmp_na);
1430 if (ia_na)
1431 ntfs_attr_close(ia_na);
1432 errno = eo;
1433 return -1;
1434 }
1435
1436
1437 /**
1438 * __ntfs_create - create object on ntfs volume
1439 * @dir_ni: ntfs inode for directory in which create new object
1440 * @securid: id of inheritable security descriptor, 0 if none
1441 * @name: unicode name of new object
1442 * @name_len: length of the name in unicode characters
1443 * @type: type of the object to create
1444 * @dev: major and minor device numbers (obtained from makedev())
1445 * @target: target in unicode (only for symlinks)
1446 * @target_len: length of target in unicode characters
1447 *
1448 * Internal, use ntfs_create{,_device,_symlink} wrappers instead.
1449 *
1450 * @type can be:
1451 * S_IFREG to create regular file
1452 * S_IFDIR to create directory
1453 * S_IFBLK to create block device
1454 * S_IFCHR to create character device
1455 * S_IFLNK to create symbolic link
1456 * S_IFIFO to create FIFO
1457 * S_IFSOCK to create socket
1458 * other values are invalid.
1459 *
1460 * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value
1461 * ignored.
1462 *
1463 * @target and @target_len are used only if @type is S_IFLNK, in other cases
1464 * their value ignored.
1465 *
1466 * Return opened ntfs inode that describes created object on success or NULL
1467 * on error with errno set to the error code.
1468 */
__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)1469 static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
1470 const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
1471 const ntfschar *target, int target_len)
1472 {
1473 ntfs_inode *ni;
1474 int rollback_data = 0, rollback_sd = 0;
1475 int rollback_dir = 0;
1476 FILE_NAME_ATTR *fn = NULL;
1477 STANDARD_INFORMATION *si = NULL;
1478 int err, fn_len, si_len;
1479 ntfs_volume_special_files special_files;
1480
1481 ntfs_log_trace("Entering.\n");
1482
1483 /* Sanity checks. */
1484 if (!dir_ni || !name || !name_len) {
1485 ntfs_log_error("Invalid arguments.\n");
1486 errno = EINVAL;
1487 return NULL;
1488 }
1489
1490 ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
1491 if (!ni)
1492 return NULL;
1493 #if CACHE_NIDATA_SIZE
1494 ntfs_inode_invalidate(dir_ni->vol, ni->mft_no);
1495 #endif
1496 special_files = dir_ni->vol->special_files;
1497 /*
1498 * Create STANDARD_INFORMATION attribute.
1499 * JPA Depending on available inherited security descriptor,
1500 * Write STANDARD_INFORMATION v1.2 (no inheritance) or v3
1501 */
1502 if (securid)
1503 si_len = sizeof(STANDARD_INFORMATION);
1504 else
1505 si_len = offsetof(STANDARD_INFORMATION, v1_end);
1506 si = ntfs_calloc(si_len);
1507 if (!si) {
1508 err = errno;
1509 goto err_out;
1510 }
1511 si->creation_time = ni->creation_time;
1512 si->last_data_change_time = ni->last_data_change_time;
1513 si->last_mft_change_time = ni->last_mft_change_time;
1514 si->last_access_time = ni->last_access_time;
1515 if (securid) {
1516 set_nino_flag(ni, v3_Extensions);
1517 ni->owner_id = si->owner_id = const_cpu_to_le32(0);
1518 ni->security_id = si->security_id = securid;
1519 ni->quota_charged = si->quota_charged = const_cpu_to_le64(0);
1520 ni->usn = si->usn = const_cpu_to_le64(0);
1521 } else
1522 clear_nino_flag(ni, v3_Extensions);
1523 if (!S_ISREG(type) && !S_ISDIR(type)) {
1524 switch (special_files) {
1525 case NTFS_FILES_WSL :
1526 if (!S_ISLNK(type)) {
1527 si->file_attributes
1528 = FILE_ATTRIBUTE_RECALL_ON_OPEN;
1529 ni->flags = FILE_ATTRIBUTE_RECALL_ON_OPEN;
1530 }
1531 break;
1532 default :
1533 si->file_attributes = FILE_ATTR_SYSTEM;
1534 ni->flags = FILE_ATTR_SYSTEM;
1535 break;
1536 }
1537 }
1538 ni->flags |= FILE_ATTR_ARCHIVE;
1539 if (NVolHideDotFiles(dir_ni->vol)
1540 && (name_len > 1)
1541 && (name[0] == const_cpu_to_le16('.'))
1542 && (name[1] != const_cpu_to_le16('.')))
1543 ni->flags |= FILE_ATTR_HIDDEN;
1544 /*
1545 * Set compression flag according to parent directory
1546 * unless NTFS version < 3.0 or cluster size > 4K
1547 * or compression has been disabled
1548 */
1549 if ((dir_ni->flags & FILE_ATTR_COMPRESSED)
1550 && (dir_ni->vol->major_ver >= 3)
1551 && NVolCompression(dir_ni->vol)
1552 && (dir_ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
1553 && (S_ISREG(type) || S_ISDIR(type)))
1554 ni->flags |= FILE_ATTR_COMPRESSED;
1555 /* Add STANDARD_INFORMATION to inode. */
1556 if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0,
1557 (u8*)si, si_len)) {
1558 err = errno;
1559 ntfs_log_error("Failed to add STANDARD_INFORMATION "
1560 "attribute.\n");
1561 goto err_out;
1562 }
1563
1564 if (!securid) {
1565 if (ntfs_sd_add_everyone(ni)) {
1566 err = errno;
1567 goto err_out;
1568 }
1569 rollback_sd = 1;
1570 }
1571
1572 if (S_ISDIR(type)) {
1573 INDEX_ROOT *ir = NULL;
1574 INDEX_ENTRY *ie;
1575 int ir_len, index_len;
1576
1577 /* Create INDEX_ROOT attribute. */
1578 index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER);
1579 ir_len = offsetof(INDEX_ROOT, index) + index_len;
1580 ir = ntfs_calloc(ir_len);
1581 if (!ir) {
1582 err = errno;
1583 goto err_out;
1584 }
1585 ir->type = AT_FILE_NAME;
1586 ir->collation_rule = COLLATION_FILE_NAME;
1587 ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size);
1588 if (ni->vol->cluster_size <= ni->vol->indx_record_size)
1589 ir->clusters_per_index_block =
1590 ni->vol->indx_record_size >>
1591 ni->vol->cluster_size_bits;
1592 else
1593 ir->clusters_per_index_block =
1594 ni->vol->indx_record_size >>
1595 NTFS_BLOCK_SIZE_BITS;
1596 ir->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER));
1597 ir->index.index_length = cpu_to_le32(index_len);
1598 ir->index.allocated_size = cpu_to_le32(index_len);
1599 ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT));
1600 ie->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
1601 ie->key_length = const_cpu_to_le16(0);
1602 ie->ie_flags = INDEX_ENTRY_END;
1603 /* Add INDEX_ROOT attribute to inode. */
1604 if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4,
1605 (u8*)ir, ir_len)) {
1606 err = errno;
1607 free(ir);
1608 ntfs_log_error("Failed to add INDEX_ROOT attribute.\n");
1609 goto err_out;
1610 }
1611 free(ir);
1612 } else {
1613 INTX_FILE *data;
1614 int data_len;
1615
1616 switch (type) {
1617 case S_IFBLK:
1618 case S_IFCHR:
1619 switch (special_files) {
1620 case NTFS_FILES_WSL :
1621 data_len = 0;
1622 data = (INTX_FILE*)NULL;
1623 break;
1624 default :
1625 data_len = offsetof(INTX_FILE,
1626 device_end);
1627 data = (INTX_FILE*)ntfs_malloc(
1628 data_len);
1629 if (!data) {
1630 err = errno;
1631 goto err_out;
1632 }
1633 data->major = cpu_to_le64(major(dev));
1634 data->minor = cpu_to_le64(minor(dev));
1635 if (type == S_IFBLK)
1636 data->magic
1637 = INTX_BLOCK_DEVICE;
1638 if (type == S_IFCHR)
1639 data->magic
1640 = INTX_CHARACTER_DEVICE;
1641 break;
1642 }
1643 break;
1644 case S_IFLNK:
1645 switch (special_files) {
1646 case NTFS_FILES_WSL :
1647 data_len = 0;
1648 data = (INTX_FILE*)NULL;
1649 break;
1650 default :
1651 data_len = sizeof(INTX_FILE_TYPES) +
1652 target_len * sizeof(ntfschar);
1653 data = (INTX_FILE*)ntfs_malloc(
1654 data_len);
1655 if (!data) {
1656 err = errno;
1657 goto err_out;
1658 }
1659 data->magic = INTX_SYMBOLIC_LINK;
1660 memcpy(data->target, target,
1661 target_len * sizeof(ntfschar));
1662 break;
1663 }
1664 break;
1665 case S_IFSOCK:
1666 data = NULL;
1667 if (special_files == NTFS_FILES_WSL)
1668 data_len = 0;
1669 else
1670 data_len = 1;
1671 break;
1672 default: /* FIFO or regular file. */
1673 data = NULL;
1674 data_len = 0;
1675 break;
1676 }
1677 /* Add DATA attribute to inode. */
1678 if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data,
1679 data_len)) {
1680 err = errno;
1681 ntfs_log_error("Failed to add DATA attribute.\n");
1682 free(data);
1683 goto err_out;
1684 }
1685 rollback_data = 1;
1686 free(data);
1687 }
1688 /* Create FILE_NAME attribute. */
1689 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
1690 fn = ntfs_calloc(fn_len);
1691 if (!fn) {
1692 err = errno;
1693 goto err_out;
1694 }
1695 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
1696 le16_to_cpu(dir_ni->mrec->sequence_number));
1697 fn->file_name_length = name_len;
1698 fn->file_name_type = FILE_NAME_POSIX;
1699 if (S_ISDIR(type))
1700 fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT;
1701 if (!S_ISREG(type) && !S_ISDIR(type)) {
1702 if (special_files == NTFS_FILES_INTERIX)
1703 fn->file_attributes = FILE_ATTR_SYSTEM;
1704 } else
1705 fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED;
1706 fn->file_attributes |= FILE_ATTR_ARCHIVE;
1707 fn->file_attributes |= ni->flags & FILE_ATTR_HIDDEN;
1708 fn->creation_time = ni->creation_time;
1709 fn->last_data_change_time = ni->last_data_change_time;
1710 fn->last_mft_change_time = ni->last_mft_change_time;
1711 fn->last_access_time = ni->last_access_time;
1712 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
1713 fn->data_size = fn->allocated_size = const_cpu_to_sle64(0);
1714 else {
1715 fn->data_size = cpu_to_sle64(ni->data_size);
1716 fn->allocated_size = cpu_to_sle64(ni->allocated_size);
1717 }
1718 memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
1719 /* Add FILE_NAME attribute to inode. */
1720 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
1721 err = errno;
1722 ntfs_log_error("Failed to add FILE_NAME attribute.\n");
1723 goto err_out;
1724 }
1725 /* Add FILE_NAME attribute to index. */
1726 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
1727 le16_to_cpu(ni->mrec->sequence_number)))) {
1728 err = errno;
1729 ntfs_log_perror("Failed to add entry to the index");
1730 goto err_out;
1731 }
1732 rollback_dir = 1;
1733 /* Set hard links count and directory flag. */
1734 ni->mrec->link_count = const_cpu_to_le16(1);
1735 if (S_ISDIR(type))
1736 ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY;
1737 /* Add reparse data */
1738 if (special_files == NTFS_FILES_WSL) {
1739 switch (type) {
1740 case S_IFLNK :
1741 err = ntfs_reparse_set_wsl_symlink(ni, target,
1742 target_len);
1743 break;
1744 case S_IFIFO :
1745 case S_IFSOCK :
1746 case S_IFCHR :
1747 case S_IFBLK :
1748 err = ntfs_reparse_set_wsl_not_symlink(ni,
1749 type);
1750 if (!err) {
1751 err = ntfs_ea_set_wsl_not_symlink(ni,
1752 type, dev);
1753 if (err)
1754 ntfs_remove_ntfs_reparse_data(ni);
1755 }
1756 break;
1757 default :
1758 err = 0;
1759 break;
1760 }
1761 if (err) {
1762 err = errno;
1763 goto err_out;
1764 }
1765 }
1766 ntfs_inode_mark_dirty(ni);
1767 /* Done! */
1768 free(fn);
1769 free(si);
1770 ntfs_log_trace("Done.\n");
1771 return ni;
1772 err_out:
1773 ntfs_log_trace("Failed.\n");
1774
1775 if (rollback_dir)
1776 ntfs_index_remove(dir_ni, ni, fn, fn_len);
1777
1778 if (rollback_sd)
1779 ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
1780
1781 if (rollback_data)
1782 ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
1783 /*
1784 * Free extent MFT records (should not exist any with current
1785 * ntfs_create implementation, but for any case if something will be
1786 * changed in the future).
1787 */
1788 while (ni->nr_extents)
1789 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
1790 err = errno;
1791 ntfs_log_error("Failed to free extent MFT record. "
1792 "Leaving inconsistent metadata.\n");
1793 }
1794 if (ntfs_mft_record_free(ni->vol, ni))
1795 ntfs_log_error("Failed to free MFT record. "
1796 "Leaving inconsistent metadata. Run chkdsk.\n");
1797 free(fn);
1798 free(si);
1799 errno = err;
1800 return NULL;
1801 }
1802
1803 /**
1804 * Some wrappers around __ntfs_create() ...
1805 */
1806
ntfs_create(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,mode_t type)1807 ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name,
1808 u8 name_len, mode_t type)
1809 {
1810 if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
1811 type != S_IFSOCK) {
1812 ntfs_log_error("Invalid arguments.\n");
1813 return NULL;
1814 }
1815 return __ntfs_create(dir_ni, securid, name, name_len, type, 0, NULL, 0);
1816 }
1817
ntfs_create_device(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,mode_t type,dev_t dev)1818 ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
1819 const ntfschar *name, u8 name_len, mode_t type, dev_t dev)
1820 {
1821 if (type != S_IFCHR && type != S_IFBLK) {
1822 ntfs_log_error("Invalid arguments.\n");
1823 return NULL;
1824 }
1825 return __ntfs_create(dir_ni, securid, name, name_len, type, dev, NULL, 0);
1826 }
1827
ntfs_create_symlink(ntfs_inode * dir_ni,le32 securid,const ntfschar * name,u8 name_len,const ntfschar * target,int target_len)1828 ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
1829 const ntfschar *name, u8 name_len, const ntfschar *target,
1830 int target_len)
1831 {
1832 if (!target || !target_len) {
1833 ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
1834 target, target_len);
1835 return NULL;
1836 }
1837 return __ntfs_create(dir_ni, securid, name, name_len, S_IFLNK, 0,
1838 target, target_len);
1839 }
1840
ntfs_check_empty_dir(ntfs_inode * ni)1841 int ntfs_check_empty_dir(ntfs_inode *ni)
1842 {
1843 ntfs_attr *na;
1844 int ret = 0;
1845
1846 if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
1847 return 0;
1848
1849 na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);
1850 if (!na) {
1851 errno = EIO;
1852 ntfs_log_perror("Failed to open directory");
1853 return -1;
1854 }
1855
1856 /* Non-empty directory? */
1857 if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
1858 /* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
1859 errno = ENOTEMPTY;
1860 ntfs_log_debug("Directory is not empty\n");
1861 ret = -1;
1862 }
1863
1864 ntfs_attr_close(na);
1865 return ret;
1866 }
1867
ntfs_check_unlinkable_dir(ntfs_inode * ni,FILE_NAME_ATTR * fn)1868 static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn)
1869 {
1870 int link_count = le16_to_cpu(ni->mrec->link_count);
1871 int ret;
1872
1873 ret = ntfs_check_empty_dir(ni);
1874 if (!ret || errno != ENOTEMPTY)
1875 return ret;
1876 /*
1877 * Directory is non-empty, so we can unlink only if there is more than
1878 * one "real" hard link, i.e. links aren't different DOS and WIN32 names
1879 */
1880 if ((link_count == 1) ||
1881 (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
1882 errno = ENOTEMPTY;
1883 ntfs_log_debug("Non-empty directory without hard links\n");
1884 goto no_hardlink;
1885 }
1886
1887 ret = 0;
1888 no_hardlink:
1889 return ret;
1890 }
1891
1892 /**
1893 * ntfs_delete - delete file or directory from ntfs volume
1894 * @ni: ntfs inode for object to delte
1895 * @dir_ni: ntfs inode for directory in which delete object
1896 * @name: unicode name of the object to delete
1897 * @name_len: length of the name in unicode characters
1898 *
1899 * @ni is always closed after the call to this function (even if it failed),
1900 * user does not need to call ntfs_inode_close himself.
1901 *
1902 * Return 0 on success or -1 on error with errno set to the error code.
1903 */
ntfs_delete(ntfs_volume * vol,const char * pathname,ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len)1904 int ntfs_delete(ntfs_volume *vol, const char *pathname,
1905 ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
1906 u8 name_len)
1907 {
1908 ntfs_attr_search_ctx *actx = NULL;
1909 FILE_NAME_ATTR *fn = NULL;
1910 BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE;
1911 BOOL case_sensitive_match = TRUE;
1912 int err = 0;
1913 #if CACHE_NIDATA_SIZE
1914 int i;
1915 #endif
1916 #if CACHE_INODE_SIZE
1917 struct CACHED_INODE item;
1918 const char *p;
1919 u64 inum = (u64)-1;
1920 int count;
1921 #endif
1922 #if CACHE_LOOKUP_SIZE
1923 struct CACHED_LOOKUP lkitem;
1924 #endif
1925
1926 ntfs_log_trace("Entering.\n");
1927
1928 if (!ni || !dir_ni || !name || !name_len) {
1929 ntfs_log_error("Invalid arguments.\n");
1930 errno = EINVAL;
1931 goto err_out;
1932 }
1933 if (ni->nr_extents == -1)
1934 ni = ni->base_ni;
1935 if (dir_ni->nr_extents == -1)
1936 dir_ni = dir_ni->base_ni;
1937 /*
1938 * Search for FILE_NAME attribute with such name. If it's in POSIX or
1939 * WIN32_AND_DOS namespace, then simply remove it from index and inode.
1940 * If filename in DOS or in WIN32 namespace, then remove DOS name first,
1941 * only then remove WIN32 name.
1942 */
1943 actx = ntfs_attr_get_search_ctx(ni, NULL);
1944 if (!actx)
1945 goto err_out;
1946 search:
1947 while (!(err = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
1948 CASE_SENSITIVE, 0, NULL, 0, actx))) {
1949 #ifdef DEBUG
1950 char *s;
1951 #endif
1952 IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
1953
1954 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
1955 le16_to_cpu(actx->attr->value_offset));
1956 #ifdef DEBUG
1957 s = ntfs_attr_name_get(fn->file_name, fn->file_name_length);
1958 ntfs_log_trace("name: '%s' type: %d dos: %d win32: %d "
1959 "case: %d\n", s, fn->file_name_type,
1960 looking_for_dos_name, looking_for_win32_name,
1961 case_sensitive_match);
1962 ntfs_attr_name_free(&s);
1963 #endif
1964 if (looking_for_dos_name) {
1965 if (fn->file_name_type == FILE_NAME_DOS)
1966 break;
1967 else
1968 continue;
1969 }
1970 if (looking_for_win32_name) {
1971 if (fn->file_name_type == FILE_NAME_WIN32)
1972 break;
1973 else
1974 continue;
1975 }
1976
1977 /* Ignore hard links from other directories */
1978 if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
1979 ntfs_log_debug("MFT record numbers don't match "
1980 "(%llu != %llu)\n",
1981 (long long unsigned)dir_ni->mft_no,
1982 (long long unsigned)MREF_LE(fn->parent_directory));
1983 continue;
1984 }
1985 if (case_sensitive_match
1986 || ((fn->file_name_type == FILE_NAME_POSIX)
1987 && NVolCaseSensitive(ni->vol)))
1988 case_sensitive = CASE_SENSITIVE;
1989
1990 if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
1991 name, name_len, case_sensitive,
1992 ni->vol->upcase, ni->vol->upcase_len)){
1993
1994 if (fn->file_name_type == FILE_NAME_WIN32) {
1995 looking_for_dos_name = TRUE;
1996 ntfs_attr_reinit_search_ctx(actx);
1997 continue;
1998 }
1999 if (fn->file_name_type == FILE_NAME_DOS)
2000 looking_for_dos_name = TRUE;
2001 break;
2002 }
2003 }
2004 if (err) {
2005 /*
2006 * If case sensitive search failed, then try once again
2007 * ignoring case.
2008 */
2009 if (errno == ENOENT && case_sensitive_match) {
2010 case_sensitive_match = FALSE;
2011 ntfs_attr_reinit_search_ctx(actx);
2012 goto search;
2013 }
2014 goto err_out;
2015 }
2016
2017 if (ntfs_check_unlinkable_dir(ni, fn) < 0)
2018 goto err_out;
2019
2020 if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
2021 goto err_out;
2022
2023 /*
2024 * Keep the last name in place, this is useful for undeletion
2025 * (Windows also does so), however delete the name if it were
2026 * in an extent, to avoid leaving an attribute list.
2027 */
2028 if ((ni->mrec->link_count == const_cpu_to_le16(1)) && !actx->base_ntfs_ino) {
2029 /* make sure to not loop to another search */
2030 looking_for_dos_name = FALSE;
2031 } else {
2032 if (ntfs_attr_record_rm(actx))
2033 goto err_out;
2034 }
2035
2036 ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
2037 ni->mrec->link_count) - 1);
2038
2039 ntfs_inode_mark_dirty(ni);
2040 if (looking_for_dos_name) {
2041 looking_for_dos_name = FALSE;
2042 looking_for_win32_name = TRUE;
2043 ntfs_attr_reinit_search_ctx(actx);
2044 goto search;
2045 }
2046 /* TODO: Update object id, quota and securiry indexes if required. */
2047 /*
2048 * If hard link count is not equal to zero then we are done. In other
2049 * case there are no reference to this inode left, so we should free all
2050 * non-resident attributes and mark all MFT record as not in use.
2051 */
2052 #if CACHE_LOOKUP_SIZE
2053 /* invalidate entry in lookup cache */
2054 lkitem.name = (const char*)NULL;
2055 lkitem.namesize = 0;
2056 lkitem.inum = ni->mft_no;
2057 lkitem.parent = dir_ni->mft_no;
2058 ntfs_invalidate_cache(vol->lookup_cache, GENERIC(&lkitem),
2059 lookup_cache_inv_compare, CACHE_NOHASH);
2060 #endif
2061 #if CACHE_INODE_SIZE
2062 inum = ni->mft_no;
2063 if (pathname) {
2064 /* invalide cache entry, even if there was an error */
2065 /* Remove leading /'s. */
2066 p = pathname;
2067 while (*p == PATH_SEP)
2068 p++;
2069 if (p[0] && (p[strlen(p)-1] == PATH_SEP))
2070 ntfs_log_error("Unnormalized path %s\n",pathname);
2071 item.pathname = p;
2072 item.varsize = strlen(p);
2073 } else {
2074 item.pathname = (const char*)NULL;
2075 item.varsize = 0;
2076 }
2077 item.inum = inum;
2078 count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item),
2079 inode_cache_inv_compare, CACHE_NOHASH);
2080 if (pathname && !count)
2081 ntfs_log_error("Could not delete inode cache entry for %s\n",
2082 pathname);
2083 #endif
2084 if (ni->mrec->link_count) {
2085 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
2086 goto ok;
2087 }
2088 if (ntfs_delete_reparse_index(ni)) {
2089 /*
2090 * Failed to remove the reparse index : proceed anyway
2091 * This is not a critical error, the entry is useless
2092 * because of sequence_number, and stopping file deletion
2093 * would be much worse as the file is not referenced now.
2094 */
2095 err = errno;
2096 }
2097 if (ntfs_delete_object_id_index(ni)) {
2098 /*
2099 * Failed to remove the object id index : proceed anyway
2100 * This is not a critical error.
2101 */
2102 err = errno;
2103 }
2104 ntfs_attr_reinit_search_ctx(actx);
2105 while (!ntfs_attrs_walk(actx)) {
2106 if (actx->attr->non_resident) {
2107 runlist *rl;
2108
2109 rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr,
2110 NULL);
2111 if (!rl) {
2112 err = errno;
2113 ntfs_log_error("Failed to decompress runlist. "
2114 "Leaving inconsistent metadata.\n");
2115 continue;
2116 }
2117 if (ntfs_cluster_free_from_rl(ni->vol, rl)) {
2118 err = errno;
2119 ntfs_log_error("Failed to free clusters. "
2120 "Leaving inconsistent metadata.\n");
2121 continue;
2122 }
2123 free(rl);
2124 }
2125 }
2126 if (errno != ENOENT) {
2127 err = errno;
2128 ntfs_log_error("Attribute enumeration failed. "
2129 "Probably leaving inconsistent metadata.\n");
2130 }
2131 /* All extents should be attached after attribute walk. */
2132 #if CACHE_NIDATA_SIZE
2133 /*
2134 * Disconnect extents before deleting them, so they are
2135 * not wrongly moved to cache through the chainings
2136 */
2137 for (i=ni->nr_extents-1; i>=0; i--) {
2138 ni->extent_nis[i]->base_ni = (ntfs_inode*)NULL;
2139 ni->extent_nis[i]->nr_extents = 0;
2140 if (ntfs_mft_record_free(ni->vol, ni->extent_nis[i])) {
2141 err = errno;
2142 ntfs_log_error("Failed to free extent MFT record. "
2143 "Leaving inconsistent metadata.\n");
2144 }
2145 }
2146 free(ni->extent_nis);
2147 ni->nr_extents = 0;
2148 ni->extent_nis = (ntfs_inode**)NULL;
2149 #else
2150 while (ni->nr_extents)
2151 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
2152 err = errno;
2153 ntfs_log_error("Failed to free extent MFT record. "
2154 "Leaving inconsistent metadata.\n");
2155 }
2156 #endif
2157 debug_double_inode(ni->mft_no,0);
2158 if (ntfs_mft_record_free(ni->vol, ni)) {
2159 err = errno;
2160 ntfs_log_error("Failed to free base MFT record. "
2161 "Leaving inconsistent metadata.\n");
2162 }
2163 ni = NULL;
2164 ok:
2165 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2166 out:
2167 if (actx)
2168 ntfs_attr_put_search_ctx(actx);
2169 if (ntfs_inode_close(dir_ni) && !err)
2170 err = errno;
2171 if (ntfs_inode_close(ni) && !err)
2172 err = errno;
2173 if (err) {
2174 errno = err;
2175 ntfs_log_debug("Could not delete file: %s\n", strerror(errno));
2176 return -1;
2177 }
2178 ntfs_log_trace("Done.\n");
2179 return 0;
2180 err_out:
2181 err = errno;
2182 goto out;
2183 }
2184
2185 /**
2186 * ntfs_link - create hard link for file or directory
2187 * @ni: ntfs inode for object to create hard link
2188 * @dir_ni: ntfs inode for directory in which new link should be placed
2189 * @name: unicode name of the new link
2190 * @name_len: length of the name in unicode characters
2191 *
2192 * NOTE: At present we allow creating hardlinks to directories, we use them
2193 * in a temporary state during rename. But it's defenitely bad idea to have
2194 * hard links to directories as a result of operation.
2195 * FIXME: Create internal __ntfs_link that allows hard links to a directories
2196 * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link.
2197 *
2198 * Return 0 on success or -1 on error with errno set to the error code.
2199 */
ntfs_link_i(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len,FILE_NAME_TYPE_FLAGS nametype)2200 static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
2201 u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
2202 {
2203 FILE_NAME_ATTR *fn = NULL;
2204 int fn_len, err;
2205
2206 ntfs_log_trace("Entering.\n");
2207
2208 if (!ni || !dir_ni || !name || !name_len ||
2209 ni->mft_no == dir_ni->mft_no) {
2210 err = EINVAL;
2211 ntfs_log_perror("ntfs_link wrong arguments");
2212 goto err_out;
2213 }
2214
2215 if (NVolHideDotFiles(dir_ni->vol)) {
2216 /* Set hidden flag according to the latest name */
2217 if ((name_len > 1)
2218 && (name[0] == const_cpu_to_le16('.'))
2219 && (name[1] != const_cpu_to_le16('.')))
2220 ni->flags |= FILE_ATTR_HIDDEN;
2221 else
2222 ni->flags &= ~FILE_ATTR_HIDDEN;
2223 }
2224
2225 /* Create FILE_NAME attribute. */
2226 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
2227 fn = ntfs_calloc(fn_len);
2228 if (!fn) {
2229 err = errno;
2230 goto err_out;
2231 }
2232 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
2233 le16_to_cpu(dir_ni->mrec->sequence_number));
2234 fn->file_name_length = name_len;
2235 fn->file_name_type = nametype;
2236 fn->file_attributes = ni->flags;
2237 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
2238 fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT;
2239 fn->data_size = fn->allocated_size = const_cpu_to_sle64(0);
2240 } else {
2241 fn->allocated_size = cpu_to_sle64(ni->allocated_size);
2242 fn->data_size = cpu_to_sle64(ni->data_size);
2243 }
2244 fn->creation_time = ni->creation_time;
2245 fn->last_data_change_time = ni->last_data_change_time;
2246 fn->last_mft_change_time = ni->last_mft_change_time;
2247 fn->last_access_time = ni->last_access_time;
2248 memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
2249 /* Add FILE_NAME attribute to index. */
2250 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
2251 le16_to_cpu(ni->mrec->sequence_number)))) {
2252 err = errno;
2253 ntfs_log_perror("Failed to add filename to the index");
2254 goto err_out;
2255 }
2256 /* Add FILE_NAME attribute to inode. */
2257 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
2258 ntfs_log_error("Failed to add FILE_NAME attribute.\n");
2259 err = errno;
2260 /* Try to remove just added attribute from index. */
2261 if (ntfs_index_remove(dir_ni, ni, fn, fn_len))
2262 goto rollback_failed;
2263 goto err_out;
2264 }
2265 /* Increment hard links count. */
2266 ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
2267 ni->mrec->link_count) + 1);
2268 /* Done! */
2269 ntfs_inode_mark_dirty(ni);
2270 free(fn);
2271 ntfs_log_trace("Done.\n");
2272 return 0;
2273 rollback_failed:
2274 ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n");
2275 err_out:
2276 free(fn);
2277 errno = err;
2278 return -1;
2279 }
2280
ntfs_link(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,u8 name_len)2281 int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
2282 u8 name_len)
2283 {
2284 return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
2285 }
2286
2287 /*
2288 * Get a parent directory from an inode entry
2289 *
2290 * This is only used in situations where the path used to access
2291 * the current file is not known for sure. The result may be different
2292 * from the path when the file is linked in several parent directories.
2293 *
2294 * Currently this is only used for translating ".." in the target
2295 * of a Vista relative symbolic link
2296 */
2297
ntfs_dir_parent_inode(ntfs_inode * ni)2298 ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
2299 {
2300 ntfs_inode *dir_ni = (ntfs_inode*)NULL;
2301 u64 inum;
2302 FILE_NAME_ATTR *fn;
2303 ntfs_attr_search_ctx *ctx;
2304
2305 if (ni->mft_no != FILE_root) {
2306 /* find the name in the attributes */
2307 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2308 if (!ctx)
2309 return ((ntfs_inode*)NULL);
2310
2311 if (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2312 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
2313 /* We know this will always be resident. */
2314 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2315 le16_to_cpu(ctx->attr->value_offset));
2316 inum = le64_to_cpu(fn->parent_directory);
2317 if (inum != (u64)-1) {
2318 dir_ni = ntfs_inode_open(ni->vol, MREF(inum));
2319 }
2320 }
2321 ntfs_attr_put_search_ctx(ctx);
2322 }
2323 return (dir_ni);
2324 }
2325
2326 #define MAX_DOS_NAME_LENGTH 12
2327
2328 /*
2329 * Get a DOS name for a file in designated directory
2330 *
2331 * Not allowed if there are several non-dos names (EMLINK)
2332 *
2333 * Returns size if found
2334 * 0 if not found
2335 * -1 if there was an error (described by errno)
2336 */
2337
get_dos_name(ntfs_inode * ni,u64 dnum,ntfschar * dosname)2338 static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
2339 {
2340 size_t outsize = 0;
2341 int namecount = 0;
2342 FILE_NAME_ATTR *fn;
2343 ntfs_attr_search_ctx *ctx;
2344
2345 /* find the name in the attributes */
2346 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2347 if (!ctx)
2348 return -1;
2349
2350 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2351 0, NULL, 0, ctx)) {
2352 /* We know this will always be resident. */
2353 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2354 le16_to_cpu(ctx->attr->value_offset));
2355
2356 if (fn->file_name_type != FILE_NAME_DOS)
2357 namecount++;
2358 if ((fn->file_name_type & FILE_NAME_DOS)
2359 && (MREF_LE(fn->parent_directory) == dnum)) {
2360 /*
2361 * Found a DOS or WIN32+DOS name for the entry
2362 * copy name, after truncation for safety
2363 */
2364 outsize = fn->file_name_length;
2365 /* TODO : reject if name is too long ? */
2366 if (outsize > MAX_DOS_NAME_LENGTH)
2367 outsize = MAX_DOS_NAME_LENGTH;
2368 memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar));
2369 }
2370 }
2371 ntfs_attr_put_search_ctx(ctx);
2372 if ((outsize > 0) && (namecount > 1)) {
2373 outsize = -1;
2374 errno = EMLINK; /* this error implies there is a dos name */
2375 }
2376 return (outsize);
2377 }
2378
2379
2380 /*
2381 * Get a long name for a file in designated directory
2382 *
2383 * Not allowed if there are several non-dos names (EMLINK)
2384 *
2385 * Returns size if found
2386 * 0 if not found
2387 * -1 if there was an error (described by errno)
2388 */
2389
get_long_name(ntfs_inode * ni,u64 dnum,ntfschar * longname)2390 static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
2391 {
2392 size_t outsize = 0;
2393 int namecount = 0;
2394 FILE_NAME_ATTR *fn;
2395 ntfs_attr_search_ctx *ctx;
2396
2397 /* find the name in the attributes */
2398 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2399 if (!ctx)
2400 return -1;
2401
2402 /* first search for WIN32 or DOS+WIN32 names */
2403 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2404 0, NULL, 0, ctx)) {
2405 /* We know this will always be resident. */
2406 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2407 le16_to_cpu(ctx->attr->value_offset));
2408
2409 if (fn->file_name_type != FILE_NAME_DOS)
2410 namecount++;
2411 if ((fn->file_name_type & FILE_NAME_WIN32)
2412 && (MREF_LE(fn->parent_directory) == dnum)) {
2413 /*
2414 * Found a WIN32 or WIN32+DOS name for the entry
2415 * copy name
2416 */
2417 outsize = fn->file_name_length;
2418 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
2419 }
2420 }
2421 if (namecount > 1) {
2422 ntfs_attr_put_search_ctx(ctx);
2423 errno = EMLINK;
2424 return -1;
2425 }
2426 /* if not found search for POSIX names */
2427 if (!outsize) {
2428 ntfs_attr_reinit_search_ctx(ctx);
2429 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
2430 0, NULL, 0, ctx)) {
2431 /* We know this will always be resident. */
2432 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
2433 le16_to_cpu(ctx->attr->value_offset));
2434
2435 if ((fn->file_name_type == FILE_NAME_POSIX)
2436 && (MREF_LE(fn->parent_directory) == dnum)) {
2437 /*
2438 * Found a POSIX name for the entry
2439 * copy name
2440 */
2441 outsize = fn->file_name_length;
2442 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
2443 }
2444 }
2445 }
2446 ntfs_attr_put_search_ctx(ctx);
2447 return (outsize);
2448 }
2449
2450
2451 /*
2452 * Get the ntfs DOS name into an extended attribute
2453 */
2454
ntfs_get_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni,char * value,size_t size)2455 int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2456 char *value, size_t size)
2457 {
2458 int outsize = 0;
2459 char *outname = (char*)NULL;
2460 u64 dnum;
2461 int doslen;
2462 ntfschar dosname[MAX_DOS_NAME_LENGTH];
2463
2464 dnum = dir_ni->mft_no;
2465 doslen = get_dos_name(ni, dnum, dosname);
2466 if (doslen > 0) {
2467 /*
2468 * Found a DOS name for the entry, make
2469 * uppercase and encode into the buffer
2470 * if there is enough space
2471 */
2472 ntfs_name_upcase(dosname, doslen,
2473 ni->vol->upcase, ni->vol->upcase_len);
2474 outsize = ntfs_ucstombs(dosname, doslen, &outname, 0);
2475 if (outsize < 0) {
2476 ntfs_log_error("Cannot represent dosname in current locale.\n");
2477 outsize = -errno;
2478 } else {
2479 if (value && (outsize <= (int)size))
2480 memcpy(value, outname, outsize);
2481 else
2482 if (size && (outsize > (int)size))
2483 outsize = -ERANGE;
2484 free(outname);
2485 }
2486 } else {
2487 if (doslen == 0)
2488 errno = ENODATA;
2489 outsize = -errno;
2490 }
2491 return (outsize);
2492 }
2493
2494 /*
2495 * Change the name space of an existing file or directory
2496 *
2497 * Returns the old namespace if successful
2498 * -1 if an error occurred (described by errno)
2499 */
2500
set_namespace(ntfs_inode * ni,ntfs_inode * dir_ni,const ntfschar * name,int len,FILE_NAME_TYPE_FLAGS nametype)2501 static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
2502 const ntfschar *name, int len,
2503 FILE_NAME_TYPE_FLAGS nametype)
2504 {
2505 ntfs_attr_search_ctx *actx;
2506 ntfs_index_context *icx;
2507 FILE_NAME_ATTR *fnx;
2508 FILE_NAME_ATTR *fn = NULL;
2509 BOOL found;
2510 int lkup;
2511 int ret;
2512
2513 ret = -1;
2514 actx = ntfs_attr_get_search_ctx(ni, NULL);
2515 if (actx) {
2516 found = FALSE;
2517 do {
2518 lkup = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2519 CASE_SENSITIVE, 0, NULL, 0, actx);
2520 if (!lkup) {
2521 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
2522 le16_to_cpu(actx->attr->value_offset));
2523 found = (MREF_LE(fn->parent_directory)
2524 == dir_ni->mft_no)
2525 && !memcmp(fn->file_name, name,
2526 len*sizeof(ntfschar));
2527 }
2528 } while (!lkup && !found);
2529 if (found) {
2530 icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
2531 if (icx) {
2532 lkup = ntfs_index_lookup((char*)fn, len, icx);
2533 if (!lkup && icx->data && icx->data_len) {
2534 fnx = (FILE_NAME_ATTR*)icx->data;
2535 ret = fn->file_name_type;
2536 fn->file_name_type = nametype;
2537 fnx->file_name_type = nametype;
2538 ntfs_inode_mark_dirty(ni);
2539 ntfs_index_entry_mark_dirty(icx);
2540 }
2541 ntfs_index_ctx_put(icx);
2542 }
2543 }
2544 ntfs_attr_put_search_ctx(actx);
2545 }
2546 return (ret);
2547 }
2548
2549 /*
2550 * Set a DOS name to a file and adjust name spaces
2551 *
2552 * If the new names are collapsible (same uppercased chars) :
2553 *
2554 * - the existing DOS name or DOS+Win32 name is made Posix
2555 * - if it was a real DOS name, the existing long name is made DOS+Win32
2556 * and the existing DOS name is deleted
2557 * - finally the existing long name is made DOS+Win32 unless already done
2558 *
2559 * If the new names are not collapsible :
2560 *
2561 * - insert the short name as a DOS name
2562 * - delete the old long name or existing short name
2563 * - insert the new long name (as a Win32 or DOS+Win32 name)
2564 *
2565 * Deleting the old long name will not delete the file
2566 * provided the old name was in the Posix name space,
2567 * because the alternate name has been set before.
2568 *
2569 * The inodes of file and parent directory are always closed
2570 *
2571 * Returns 0 if successful
2572 * -1 if failed
2573 */
2574
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)2575 static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2576 const ntfschar *shortname, int shortlen,
2577 const ntfschar *longname, int longlen,
2578 const ntfschar *deletename, int deletelen, BOOL existed)
2579 {
2580 unsigned int linkcount;
2581 ntfs_volume *vol;
2582 BOOL collapsible;
2583 BOOL deleted;
2584 BOOL done;
2585 FILE_NAME_TYPE_FLAGS oldnametype;
2586 u64 dnum;
2587 u64 fnum;
2588 int res;
2589
2590 res = -1;
2591 vol = ni->vol;
2592 dnum = dir_ni->mft_no;
2593 fnum = ni->mft_no;
2594 /* save initial link count */
2595 linkcount = le16_to_cpu(ni->mrec->link_count);
2596
2597 /* check whether the same name may be used as DOS and WIN32 */
2598 collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen,
2599 longname, longlen);
2600 if (collapsible) {
2601 deleted = FALSE;
2602 done = FALSE;
2603 if (existed) {
2604 oldnametype = set_namespace(ni, dir_ni, deletename,
2605 deletelen, FILE_NAME_POSIX);
2606 if (oldnametype == FILE_NAME_DOS) {
2607 if (set_namespace(ni, dir_ni, longname, longlen,
2608 FILE_NAME_WIN32_AND_DOS) >= 0) {
2609 if (!ntfs_delete(vol,
2610 (const char*)NULL, ni, dir_ni,
2611 deletename, deletelen))
2612 res = 0;
2613 deleted = TRUE;
2614 } else
2615 done = TRUE;
2616 }
2617 }
2618 if (!deleted) {
2619 if (!done && (set_namespace(ni, dir_ni,
2620 longname, longlen,
2621 FILE_NAME_WIN32_AND_DOS) >= 0))
2622 res = 0;
2623 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
2624 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2625 if (ntfs_inode_close_in_dir(ni,dir_ni) && !res)
2626 res = -1;
2627 if (ntfs_inode_close(dir_ni) && !res)
2628 res = -1;
2629 }
2630 } else {
2631 if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
2632 FILE_NAME_DOS)
2633 /* make sure a new link was recorded */
2634 && (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
2635 /* delete the existing long name or short name */
2636 // is it ok to not provide the path ?
2637 if (!ntfs_delete(vol, (char*)NULL, ni, dir_ni,
2638 deletename, deletelen)) {
2639 /* delete closes the inodes, so have to open again */
2640 dir_ni = ntfs_inode_open(vol, dnum);
2641 if (dir_ni) {
2642 ni = ntfs_inode_open(vol, fnum);
2643 if (ni) {
2644 if (!ntfs_link_i(ni, dir_ni,
2645 longname, longlen,
2646 FILE_NAME_WIN32))
2647 res = 0;
2648 if (ntfs_inode_close_in_dir(ni,
2649 dir_ni)
2650 && !res)
2651 res = -1;
2652 }
2653 if (ntfs_inode_close(dir_ni) && !res)
2654 res = -1;
2655 }
2656 }
2657 } else {
2658 ntfs_inode_close_in_dir(ni,dir_ni);
2659 ntfs_inode_close(dir_ni);
2660 }
2661 }
2662 return (res);
2663 }
2664
2665
2666 /*
2667 * Set the ntfs DOS name into an extended attribute
2668 *
2669 * The DOS name will be added as another file name attribute
2670 * using the existing file name information from the original
2671 * name or overwriting the DOS Name if one exists.
2672 *
2673 * The inode of the file is always closed
2674 */
2675
ntfs_set_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni,const char * value,size_t size,int flags)2676 int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
2677 const char *value, size_t size, int flags)
2678 {
2679 int res = 0;
2680 int longlen = 0;
2681 int shortlen = 0;
2682 char newname[3*MAX_DOS_NAME_LENGTH + 1];
2683 ntfschar oldname[MAX_DOS_NAME_LENGTH];
2684 int oldlen;
2685 u64 dnum;
2686 BOOL closed = FALSE;
2687 ntfschar *shortname = NULL;
2688 ntfschar longname[NTFS_MAX_NAME_LEN];
2689
2690 /* copy the string to insert a null char, and truncate */
2691 if (size > 3*MAX_DOS_NAME_LENGTH)
2692 size = 3*MAX_DOS_NAME_LENGTH;
2693 strncpy(newname, value, size);
2694 /* a long name may be truncated badly and be untranslatable */
2695 newname[size] = 0;
2696 /* convert the string to the NTFS wide chars, and truncate */
2697 shortlen = ntfs_mbstoucs(newname, &shortname);
2698 if (shortlen > MAX_DOS_NAME_LENGTH)
2699 shortlen = MAX_DOS_NAME_LENGTH;
2700
2701 /* Make sure the short name has valid chars.
2702 * Note: the short name cannot end with dot or space, but the
2703 * corresponding long name can. */
2704 if ((shortlen < 0)
2705 || ntfs_forbidden_names(ni->vol,shortname,shortlen,TRUE)) {
2706 ntfs_inode_close_in_dir(ni,dir_ni);
2707 ntfs_inode_close(dir_ni);
2708 res = -errno;
2709 return res;
2710 }
2711 dnum = dir_ni->mft_no;
2712 longlen = get_long_name(ni, dnum, longname);
2713 if (longlen > 0) {
2714 oldlen = get_dos_name(ni, dnum, oldname);
2715 if ((oldlen >= 0)
2716 && !ntfs_forbidden_names(ni->vol, longname, longlen,
2717 FALSE)) {
2718 if (oldlen > 0) {
2719 if (flags & XATTR_CREATE) {
2720 res = -1;
2721 errno = EEXIST;
2722 } else
2723 if ((shortlen == oldlen)
2724 && !memcmp(shortname,oldname,
2725 oldlen*sizeof(ntfschar)))
2726 /* already set, done */
2727 res = 0;
2728 else {
2729 res = set_dos_name(ni, dir_ni,
2730 shortname, shortlen,
2731 longname, longlen,
2732 oldname, oldlen, TRUE);
2733 closed = TRUE;
2734 }
2735 } else {
2736 if (flags & XATTR_REPLACE) {
2737 res = -1;
2738 errno = ENODATA;
2739 } else {
2740 res = set_dos_name(ni, dir_ni,
2741 shortname, shortlen,
2742 longname, longlen,
2743 longname, longlen, FALSE);
2744 closed = TRUE;
2745 }
2746 }
2747 } else
2748 res = -1;
2749 } else {
2750 res = -1;
2751 if (!longlen)
2752 errno = ENOENT;
2753 }
2754 free(shortname);
2755 if (!closed) {
2756 ntfs_inode_close_in_dir(ni,dir_ni);
2757 ntfs_inode_close(dir_ni);
2758 }
2759 return (res ? -1 : 0);
2760 }
2761
2762 /*
2763 * Delete the ntfs DOS name
2764 */
2765
ntfs_remove_ntfs_dos_name(ntfs_inode * ni,ntfs_inode * dir_ni)2766 int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
2767 {
2768 int res;
2769 int oldnametype;
2770 int longlen = 0;
2771 int shortlen;
2772 u64 dnum;
2773 ntfs_volume *vol;
2774 BOOL deleted = FALSE;
2775 ntfschar shortname[MAX_DOS_NAME_LENGTH];
2776 ntfschar longname[NTFS_MAX_NAME_LEN];
2777
2778 res = -1;
2779 vol = ni->vol;
2780 dnum = dir_ni->mft_no;
2781 longlen = get_long_name(ni, dnum, longname);
2782 if (longlen > 0) {
2783 shortlen = get_dos_name(ni, dnum, shortname);
2784 if (shortlen >= 0) {
2785 /* migrate the long name as Posix */
2786 oldnametype = set_namespace(ni,dir_ni,longname,longlen,
2787 FILE_NAME_POSIX);
2788 switch (oldnametype) {
2789 case FILE_NAME_WIN32_AND_DOS :
2790 /* name was Win32+DOS : done */
2791 res = 0;
2792 break;
2793 case FILE_NAME_DOS :
2794 /* name was DOS, make it back to DOS */
2795 set_namespace(ni,dir_ni,longname,longlen,
2796 FILE_NAME_DOS);
2797 errno = ENOENT;
2798 break;
2799 case FILE_NAME_WIN32 :
2800 /* name was Win32, make it Posix and delete */
2801 if (set_namespace(ni,dir_ni,shortname,shortlen,
2802 FILE_NAME_POSIX) >= 0) {
2803 if (!ntfs_delete(vol,
2804 (const char*)NULL, ni,
2805 dir_ni, shortname,
2806 shortlen))
2807 res = 0;
2808 deleted = TRUE;
2809 } else {
2810 /*
2811 * DOS name has been found, but cannot
2812 * migrate to Posix : something bad
2813 * has happened
2814 */
2815 errno = EIO;
2816 ntfs_log_error("Could not change"
2817 " DOS name of inode %lld to Posix\n",
2818 (long long)ni->mft_no);
2819 }
2820 break;
2821 default :
2822 /* name was Posix or not found : error */
2823 errno = ENOENT;
2824 break;
2825 }
2826 }
2827 } else {
2828 if (!longlen)
2829 errno = ENOENT;
2830 res = -1;
2831 }
2832 if (!deleted) {
2833 ntfs_inode_close_in_dir(ni,dir_ni);
2834 ntfs_inode_close(dir_ni);
2835 }
2836 return (res);
2837 }
2838
2839 /*
2840 * Increment the count of subdirectories
2841 * (excluding entries with a short name)
2842 */
2843
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)2844 static int nlink_increment(void *nlink_ptr,
2845 const ntfschar *name __attribute__((unused)),
2846 const int len __attribute__((unused)),
2847 const int type,
2848 const s64 pos __attribute__((unused)),
2849 const MFT_REF mref __attribute__((unused)),
2850 const unsigned int dt_type)
2851 {
2852 if ((dt_type == NTFS_DT_DIR) && (type != FILE_NAME_DOS))
2853 (*((int*)nlink_ptr))++;
2854 return (0);
2855 }
2856
2857 /*
2858 * Compute the number of hard links according to Posix
2859 * For a directory count the subdirectories whose name is not
2860 * a short one, but count "." and ".."
2861 * Otherwise count the names, excluding the short ones.
2862 *
2863 * if there is an error, a null count is returned.
2864 */
2865
ntfs_dir_link_cnt(ntfs_inode * ni)2866 int ntfs_dir_link_cnt(ntfs_inode *ni)
2867 {
2868 ntfs_attr_search_ctx *actx;
2869 FILE_NAME_ATTR *fn;
2870 s64 pos;
2871 int err = 0;
2872 int nlink = 0;
2873
2874 if (!ni) {
2875 ntfs_log_error("Invalid argument.\n");
2876 errno = EINVAL;
2877 goto err_out;
2878 }
2879 if (ni->nr_extents == -1)
2880 ni = ni->base_ni;
2881 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
2882 /*
2883 * Directory : scan the directory and count
2884 * subdirectories whose name is not DOS-only.
2885 * The directory names are ignored, but "." and ".."
2886 * are taken into account.
2887 */
2888 pos = 0;
2889 err = ntfs_readdir(ni, &pos, &nlink, nlink_increment);
2890 if (err)
2891 nlink = 0;
2892 } else {
2893 /*
2894 * Non-directory : search for FILE_NAME attributes,
2895 * and count those which are not DOS-only ones.
2896 */
2897 actx = ntfs_attr_get_search_ctx(ni, NULL);
2898 if (!actx)
2899 goto err_out;
2900 while (!(err = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
2901 CASE_SENSITIVE, 0, NULL, 0, actx))) {
2902 fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
2903 le16_to_cpu(actx->attr->value_offset));
2904 if (fn->file_name_type != FILE_NAME_DOS)
2905 nlink++;
2906 }
2907 if (err && (errno != ENOENT))
2908 nlink = 0;
2909 ntfs_attr_put_search_ctx(actx);
2910 }
2911 if (!nlink)
2912 ntfs_log_perror("Failed to compute nlink of inode %lld",
2913 (long long)ni->mft_no);
2914 err_out :
2915 return (nlink);
2916 }
2917