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