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