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