1/**
2 * Copyright (c) 2005-2007 Yura Pakhuchiy
3 * Copyright (c) 2005 Yuval Fledel
4 * Copyright (c) 2006-2009 Szabolcs Szakacsits
5 * Copyright (c) 2007-2021 Jean-Pierre Andre
6 * Copyright (c) 2009 Erik Larsson
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program (in the main directory of the NTFS-3G
20 * distribution in the file COPYING); if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23#include "lowntfs.h"
24
25#include <errno.h>
26
27#include "libntfs/dir.h"
28
29
30#define DISABLE_PLUGINS
31#define KERNELPERMS 1
32#define INODE(ino) ino
33#define ntfs_allowed_dir_access(...) (1) /* permissions checks done elsewhere */
34
35#define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE
36
37
38static const char ntfs_bad_reparse[] = "unsupported reparse tag 0x%08lx";
39	 /* exact length of target text, without the terminator */
40#define ntfs_bad_reparse_lth (sizeof(ntfs_bad_reparse) + 2)
41
42static const char ghostformat[] = ".ghost-ntfs-3g-%020llu";
43#define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */
44
45static u32 ntfs_sequence = 0;
46
47
48static void
49set_fuse_error(int *err)
50{
51	if (!*err)
52		*err = errno;
53}
54
55static void
56ntfs_fuse_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
57{
58#ifdef __HAIKU__
59	mask &= ~NTFS_UPDATE_ATIME;
60#else
61	if (ctx->atime == ATIME_DISABLED)
62		mask &= ~NTFS_UPDATE_ATIME;
63	else if (ctx->atime == ATIME_RELATIVE && mask == NTFS_UPDATE_ATIME &&
64			(sle64_to_cpu(ni->last_access_time)
65				>= sle64_to_cpu(ni->last_data_change_time)) &&
66			(sle64_to_cpu(ni->last_access_time)
67				>= sle64_to_cpu(ni->last_mft_change_time)))
68		return;
69#endif
70	ntfs_inode_update_times(ni, mask);
71}
72
73
74static BOOL ntfs_fuse_fill_security_context(struct lowntfs_context *ctx,
75			struct SECURITY_CONTEXT *scx)
76{
77	const struct fuse_ctx *fusecontext;
78
79	scx->vol = ctx->vol;
80	scx->mapping[MAPUSERS] = NULL;
81	scx->mapping[MAPGROUPS] = NULL;
82	scx->pseccache = NULL;
83	scx->uid = 0;
84	scx->gid = 0;
85	scx->tid = 0;
86	scx->umask = 0;
87	return (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL);
88}
89
90
91u64
92ntfs_fuse_inode_lookup(struct lowntfs_context *ctx, u64 parent, const char *name)
93{
94	u64 ino = (u64)-1;
95	u64 inum;
96	ntfs_inode *dir_ni;
97
98	/* Open target directory. */
99	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
100	if (dir_ni) {
101		/* Lookup file */
102		inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
103			/* never return inodes 0 and 1 */
104		if (MREF(inum) <= 1) {
105			inum = (u64)-1;
106			errno = ENOENT;
107		}
108		if (ntfs_inode_close(dir_ni)
109			|| (inum == (u64)-1))
110			ino = (u64)-1;
111		else
112			ino = MREF(inum);
113	}
114	return (ino);
115}
116
117
118int
119ntfs_fuse_getstat(struct lowntfs_context *ctx, struct SECURITY_CONTEXT *scx,
120	ntfs_inode *ni, struct stat *stbuf)
121{
122	int res = 0;
123	ntfs_attr *na;
124	BOOL withusermapping;
125
126	memset(stbuf, 0, sizeof(struct stat));
127	withusermapping = scx && (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL);
128	stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
129	if (ctx->posix_nlink
130		&& !(ni->flags & FILE_ATTR_REPARSE_POINT))
131		stbuf->st_nlink = ntfs_dir_link_cnt(ni);
132	if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
133		|| (ni->flags & FILE_ATTR_REPARSE_POINT)) {
134		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
135#ifndef DISABLE_PLUGINS
136			const plugin_operations_t *ops;
137			REPARSE_POINT *reparse;
138
139			res = CALL_REPARSE_PLUGIN(ni, getattr, stbuf);
140			if (!res) {
141				apply_umask(stbuf);
142			} else {
143				stbuf->st_size = ntfs_bad_reparse_lth;
144				stbuf->st_blocks =
145					(ni->allocated_size + 511) >> 9;
146				stbuf->st_mode = S_IFLNK;
147				res = 0;
148			}
149			goto ok;
150#else /* DISABLE_PLUGINS */
151			char *target;
152
153			errno = 0;
154			target = ntfs_make_symlink(ni, ctx->abs_mnt_point);
155				/*
156				 * If the reparse point is not a valid
157				 * directory junction, and there is no error
158				 * we still display as a symlink
159				 */
160			if (target || (errno == EOPNOTSUPP)) {
161				if (target)
162					stbuf->st_size = strlen(target);
163				else
164					stbuf->st_size = ntfs_bad_reparse_lth;
165				stbuf->st_blocks =
166					(ni->allocated_size + 511) >> 9;
167				stbuf->st_nlink =
168					le16_to_cpu(ni->mrec->link_count);
169				stbuf->st_mode = S_IFLNK;
170				free(target);
171			} else {
172				res = -errno;
173				goto exit;
174			}
175#endif /* DISABLE_PLUGINS */
176		} else {
177			/* Directory. */
178			stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);
179			/* get index size, if not known */
180			if (!test_nino_flag(ni, KnownSize)) {
181				na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION,
182						NTFS_INDEX_I30, 4);
183				if (na) {
184					ni->data_size = na->data_size;
185					ni->allocated_size = na->allocated_size;
186					set_nino_flag(ni, KnownSize);
187					ntfs_attr_close(na);
188				}
189			}
190			stbuf->st_size = ni->data_size;
191			stbuf->st_blocks = ni->allocated_size >> 9;
192			if (!ctx->posix_nlink)
193				stbuf->st_nlink = 1;	/* Make find(1) work */
194		}
195	} else {
196		/* Regular or Interix (INTX) file. */
197		stbuf->st_mode = S_IFREG;
198		stbuf->st_size = ni->data_size;
199#ifdef HAVE_SETXATTR	/* extended attributes interface required */
200		/*
201		 * return data size rounded to next 512 byte boundary for
202		 * encrypted files to include padding required for decryption
203		 * also include 2 bytes for padding info
204		*/
205		if (ctx->efs_raw
206			&& (ni->flags & FILE_ATTR_ENCRYPTED)
207			&& ni->data_size)
208			stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
209#endif /* HAVE_SETXATTR */
210		/*
211		 * Temporary fix to make ActiveSync work via Samba 3.0.
212		 * See more on the ntfs-3g-devel list.
213		 */
214		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
215		if (ni->flags & FILE_ATTR_SYSTEM) {
216			na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
217			if (!na) {
218				stbuf->st_ino = ni->mft_no;
219				goto nodata;
220			}
221			/* Check whether it's Interix FIFO or socket. */
222			if (!(ni->flags & FILE_ATTR_HIDDEN)) {
223				/* FIFO. */
224				if (na->data_size == 0)
225					stbuf->st_mode = S_IFIFO;
226				/* Socket link. */
227				if (na->data_size == 1)
228					stbuf->st_mode = S_IFSOCK;
229			}
230			/*
231			 * Check whether it's Interix symbolic link, block or
232			 * character device.
233			 */
234			if ((u64)na->data_size <= sizeof(INTX_FILE_TYPES)
235					+ sizeof(ntfschar) * PATH_MAX
236				&& (u64)na->data_size >
237					sizeof(INTX_FILE_TYPES)) {
238				INTX_FILE *intx_file;
239
240				intx_file =
241					(INTX_FILE*)ntfs_malloc(na->data_size);
242				if (!intx_file) {
243					res = -errno;
244					ntfs_attr_close(na);
245					goto exit;
246				}
247				if (ntfs_attr_pread(na, 0, na->data_size,
248						intx_file) != na->data_size) {
249					res = -errno;
250					free(intx_file);
251					ntfs_attr_close(na);
252					goto exit;
253				}
254				if (intx_file->magic == INTX_BLOCK_DEVICE &&
255						na->data_size == (s64)offsetof(
256						INTX_FILE, device_end)) {
257					stbuf->st_mode = S_IFBLK;
258					stbuf->st_rdev = makedev(le64_to_cpu(
259							intx_file->major),
260							le64_to_cpu(
261							intx_file->minor));
262				}
263				if (intx_file->magic == INTX_CHARACTER_DEVICE &&
264						na->data_size == (s64)offsetof(
265						INTX_FILE, device_end)) {
266					stbuf->st_mode = S_IFCHR;
267					stbuf->st_rdev = makedev(le64_to_cpu(
268							intx_file->major),
269							le64_to_cpu(
270							intx_file->minor));
271				}
272				if (intx_file->magic == INTX_SYMBOLIC_LINK) {
273					char *target = NULL;
274					int len;
275
276					/* st_size should be set to length of
277					 * symlink target as multibyte string */
278					len = ntfs_ucstombs(
279							intx_file->target,
280							(na->data_size -
281								offsetof(INTX_FILE,
282									 target)) /
283								   sizeof(ntfschar),
284								 &target, 0);
285					if (len < 0) {
286						res = -errno;
287						free(intx_file);
288						ntfs_attr_close(na);
289						goto exit;
290					}
291					free(target);
292					stbuf->st_mode = S_IFLNK;
293					stbuf->st_size = len;
294				}
295				free(intx_file);
296			}
297			ntfs_attr_close(na);
298		}
299		stbuf->st_mode |= (0777 & ~ctx->fmask);
300	}
301#ifndef DISABLE_PLUGINS
302ok:
303#endif /* DISABLE_PLUGINS */
304	if (withusermapping) {
305		ntfs_get_owner_mode(scx,ni,stbuf);
306	} else {
307#ifndef __HAIKU__
308		stbuf->st_uid = ctx->uid;
309		stbuf->st_gid = ctx->gid;
310#endif
311	}
312	if (S_ISLNK(stbuf->st_mode))
313		stbuf->st_mode |= 0777;
314nodata :
315	stbuf->st_ino = ni->mft_no;
316#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
317	stbuf->st_atimespec = ntfs2timespec(ni->last_access_time);
318	stbuf->st_ctimespec = ntfs2timespec(ni->last_mft_change_time);
319	stbuf->st_mtimespec = ntfs2timespec(ni->last_data_change_time);
320#elif defined(HAVE_STRUCT_STAT_ST_ATIM)
321	stbuf->st_atim = ntfs2timespec(ni->last_access_time);
322	stbuf->st_ctim = ntfs2timespec(ni->last_mft_change_time);
323	stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
324#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
325	{
326	struct timespec ts;
327
328	ts = ntfs2timespec(ni->last_access_time);
329	stbuf->st_atime = ts.tv_sec;
330	stbuf->st_atimensec = ts.tv_nsec;
331	ts = ntfs2timespec(ni->last_mft_change_time);
332	stbuf->st_ctime = ts.tv_sec;
333	stbuf->st_ctimensec = ts.tv_nsec;
334	ts = ntfs2timespec(ni->last_data_change_time);
335	stbuf->st_mtime = ts.tv_sec;
336	stbuf->st_mtimensec = ts.tv_nsec;
337	}
338#else
339#warning "No known way to set nanoseconds in struct stat !"
340	{
341	struct timespec ts;
342
343	ts = ntfs2timespec(ni->last_access_time);
344	stbuf->st_atime = ts.tv_sec;
345	ts = ntfs2timespec(ni->last_mft_change_time);
346	stbuf->st_ctime = ts.tv_sec;
347	ts = ntfs2timespec(ni->last_data_change_time);
348	stbuf->st_mtime = ts.tv_sec;
349	}
350#endif
351#ifdef __HAIKU__
352	stbuf->st_crtim = ntfs2timespec(ni->creation_time);
353#endif
354exit:
355	return (res);
356}
357
358
359int
360ntfs_fuse_readlink(struct lowntfs_context* ctx, u64 ino, void* buffer, size_t* bufferSize)
361{
362	ntfs_inode *ni = NULL;
363	ntfs_attr *na = NULL;
364	INTX_FILE *intx_file = NULL;
365	char *buf = (char*)NULL;
366	int res = 0;
367
368	/* Get inode. */
369	ni = ntfs_inode_open(ctx->vol, INODE(ino));
370	if (!ni) {
371		res = -errno;
372		goto exit;
373	}
374		/*
375		 * Reparse point : analyze as a junction point
376		 */
377	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
378		REPARSE_POINT *reparse;
379		le32 tag;
380		int lth;
381#ifndef DISABLE_PLUGINS
382		const plugin_operations_t *ops;
383
384		res = CALL_REPARSE_PLUGIN(ni, readlink, &buf);
385			/* plugin missing or reparse tag failing the check */
386		if (res && ((errno == ELIBACC) || (errno == EINVAL)))
387			errno = EOPNOTSUPP;
388#else /* DISABLE_PLUGINS */
389		errno = 0;
390		res = 0;
391		buf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
392#endif /* DISABLE_PLUGINS */
393		if (!buf && (errno == EOPNOTSUPP)) {
394			buf = (char*)malloc(ntfs_bad_reparse_lth + 1);
395			if (buf) {
396				reparse = ntfs_get_reparse_point(ni);
397				if (reparse) {
398					tag = reparse->reparse_tag;
399					free(reparse);
400				} else
401					tag = const_cpu_to_le32(0);
402				lth = snprintf(buf, ntfs_bad_reparse_lth + 1,
403						ntfs_bad_reparse,
404						(long)le32_to_cpu(tag));
405				res = 0;
406				if (lth != ntfs_bad_reparse_lth) {
407					free(buf);
408					buf = (char*)NULL;
409				}
410			}
411		}
412		if (!buf)
413			res = -errno;
414		goto exit;
415	}
416	/* Sanity checks. */
417	if (!(ni->flags & FILE_ATTR_SYSTEM)) {
418		res = -EINVAL;
419		goto exit;
420	}
421	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
422	if (!na) {
423		res = -errno;
424		goto exit;
425	}
426	if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES)) {
427		res = -EINVAL;
428		goto exit;
429	}
430	if ((size_t)na->data_size > sizeof(INTX_FILE_TYPES) +
431			sizeof(ntfschar) * PATH_MAX) {
432		res = -ENAMETOOLONG;
433		goto exit;
434	}
435	/* Receive file content. */
436	intx_file = (INTX_FILE*)ntfs_malloc(na->data_size);
437	if (!intx_file) {
438		res = -errno;
439		goto exit;
440	}
441	if (ntfs_attr_pread(na, 0, na->data_size, intx_file) != na->data_size) {
442		res = -errno;
443		goto exit;
444	}
445	/* Sanity check. */
446	if (intx_file->magic != INTX_SYMBOLIC_LINK) {
447		res = -EINVAL;
448		goto exit;
449	}
450	/* Convert link from unicode to local encoding. */
451	if (ntfs_ucstombs(intx_file->target, (na->data_size -
452			offsetof(INTX_FILE, target)) / sizeof(ntfschar),
453			&buf, 0) < 0) {
454		res = -errno;
455		goto exit;
456	}
457exit:
458	if (intx_file)
459		free(intx_file);
460	if (na)
461		ntfs_attr_close(na);
462	ntfs_inode_close(ni);
463
464#ifdef __HAIKU__
465	if (buf && !res) {
466		strlcpy(buffer, buf, *bufferSize);
467		*bufferSize = strlen(buf);
468			// Indicate the actual length of the link.
469	}
470#endif
471
472	free(buf);
473	return res;
474}
475
476
477int
478ntfs_fuse_read(ntfs_inode* ni, off_t offset, char* buf, size_t size)
479{
480	ntfs_attr *na = NULL;
481	int res;
482	s64 total = 0;
483	s64 max_read;
484
485	if (!size) {
486		res = 0;
487		goto exit;
488	}
489
490	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
491#ifndef DISABLE_PLUGINS
492		const plugin_operations_t *ops;
493		REPARSE_POINT *reparse;
494		struct open_file *of;
495
496		of = (struct open_file*)(long)fi->fh;
497		res = CALL_REPARSE_PLUGIN(ni, read, buf, size, offset, &of->fi);
498		if (res >= 0) {
499			goto stamps;
500		}
501#else /* DISABLE_PLUGINS */
502		errno = EOPNOTSUPP;
503		res = errno;
504#endif /* DISABLE_PLUGINS */
505		goto exit;
506	}
507	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
508	if (!na) {
509		res = errno;
510		goto exit;
511	}
512	max_read = na->data_size;
513#ifdef HAVE_SETXATTR	/* extended attributes interface required */
514	/* limit reads at next 512 byte boundary for encrypted attributes */
515	if (ctx->efs_raw
516		&& max_read
517		&& (na->data_flags & ATTR_IS_ENCRYPTED)
518		&& NAttrNonResident(na)) {
519		max_read = ((na->data_size+511) & ~511) + 2;
520	}
521#endif /* HAVE_SETXATTR */
522	if (offset + (off_t)size > max_read) {
523		if (max_read < offset)
524			goto ok;
525		size = max_read - offset;
526	}
527	while (size > 0) {
528		s64 ret = ntfs_attr_pread(na, offset, size, buf + total);
529		if (ret != (s64)size)
530			ntfs_log_perror("ntfs_attr_pread error reading inode %lld at "
531				"offset %lld: %lld <> %lld", (long long)ni->mft_no,
532				(long long)offset, (long long)size, (long long)ret);
533		if (ret <= 0 || ret > (s64)size) {
534			res = (ret < 0) ? errno : EIO;
535			goto exit;
536		}
537		size -= ret;
538		offset += ret;
539		total += ret;
540	}
541ok:
542	res = total;
543#ifndef DISABLE_PLUGINS
544stamps :
545#endif /* DISABLE_PLUGINS */
546	ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
547exit:
548	if (na)
549		ntfs_attr_close(na);
550	return res;
551}
552
553int
554ntfs_fuse_write(struct lowntfs_context* ctx, ntfs_inode* ni, const char *buf,
555	size_t size, off_t offset)
556{
557	ntfs_attr *na = NULL;
558	int res, total = 0;
559
560	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
561#ifndef DISABLE_PLUGINS
562		const plugin_operations_t *ops;
563		REPARSE_POINT *reparse;
564		struct open_file *of;
565
566		of = (struct open_file*)(long)fi->fh;
567		res = CALL_REPARSE_PLUGIN(ni, write, buf, size, offset,
568								&of->fi);
569		if (res >= 0) {
570			goto stamps;
571		}
572#else /* DISABLE_PLUGINS */
573		res = EOPNOTSUPP;
574		errno = EOPNOTSUPP;
575#endif /* DISABLE_PLUGINS */
576		goto exit;
577	}
578	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
579	if (!na) {
580		res = errno;
581		goto exit;
582	}
583	while (size) {
584		s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total);
585		if (ret <= 0) {
586			res = errno;
587			goto exit;
588		}
589		size   -= ret;
590		offset += ret;
591		total  += ret;
592	}
593	res = total;
594#ifndef DISABLE_PLUGINS
595stamps :
596#endif /* DISABLE_PLUGINS */
597	if ((res > 0)
598		&& (!ctx->dmtime
599		|| (sle64_to_cpu(ntfs_current_time())
600			 - sle64_to_cpu(ni->last_data_change_time)) > ctx->dmtime))
601		ntfs_fuse_update_times(ni, NTFS_UPDATE_MCTIME);
602exit:
603	if (na)
604		ntfs_attr_close(na);
605	if (res > 0)
606		set_archive(ni);
607	return res;
608}
609
610int
611ntfs_fuse_create(struct lowntfs_context *ctx, ino_t parent, const char *name,
612	mode_t typemode, dev_t dev, const char *target, ino_t* ino)
613{
614	ntfschar *uname = NULL, *utarget = NULL;
615	ntfs_inode *dir_ni = NULL, *ni;
616	struct open_file *of;
617	int state = 0;
618	le32 securid;
619	gid_t gid;
620	mode_t dsetgid;
621	mode_t type = typemode & ~07777;
622	mode_t perm;
623	struct SECURITY_CONTEXT security;
624	int res = 0, uname_len, utarget_len;
625	const int fi = 1;
626
627	/* Generate unicode filename. */
628	uname_len = ntfs_mbstoucs(name, &uname);
629	if ((uname_len < 0)
630		|| (ctx->windows_names
631		&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
632		res = -errno;
633		goto exit;
634	}
635	/* Deny creating into $Extend */
636	if (parent == FILE_Extend) {
637		errno = EPERM;
638		res = -errno;
639		goto exit;
640	}
641	/* Open parent directory. */
642	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
643	if (!dir_ni) {
644		res = -errno;
645		goto exit;
646	}
647#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
648		/* make sure parent directory is writeable and executable */
649	if (!ntfs_fuse_fill_security_context(ctx, &security)
650		   || ntfs_allowed_create(&security,
651				dir_ni, &gid, &dsetgid)) {
652#else
653		ntfs_fuse_fill_security_context(ctx, &security);
654		ntfs_allowed_create(&security, dir_ni, &gid, &dsetgid);
655#endif
656		if (S_ISDIR(type))
657			perm = (typemode & ~ctx->dmask & 0777)
658				| (dsetgid & S_ISGID);
659		else
660			if ((ctx->special_files == NTFS_FILES_WSL)
661				&& S_ISLNK(type))
662				perm = typemode | 0777;
663			else
664				perm = typemode & ~ctx->fmask & 0777;
665			/*
666			 * Try to get a security id available for
667			 * file creation (from inheritance or argument).
668			 * This is not possible for NTFS 1.x, and we will
669			 * have to build a security attribute later.
670			 */
671		if (!security.mapping[MAPUSERS])
672			securid = const_cpu_to_le32(0);
673		else
674			if (ctx->inherit)
675				securid = ntfs_inherited_id(&security,
676					dir_ni, S_ISDIR(type));
677			else
678#if POSIXACLS
679				securid = ntfs_alloc_securid(&security,
680					security.uid, gid,
681					dir_ni, perm, S_ISDIR(type));
682#else
683				securid = ntfs_alloc_securid(&security,
684					security.uid, gid,
685					perm & ~security.umask, S_ISDIR(type));
686#endif
687		/* Create object specified in @type. */
688		if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
689#ifndef DISABLE_PLUGINS
690			const plugin_operations_t *ops;
691			REPARSE_POINT *reparse;
692
693			reparse = (REPARSE_POINT*)NULL;
694			ops = select_reparse_plugin(ctx, dir_ni, &reparse);
695			if (ops && ops->create) {
696				ni = (*ops->create)(dir_ni, reparse,
697					securid, uname, uname_len, type);
698			} else {
699				ni = (ntfs_inode*)NULL;
700				errno = EOPNOTSUPP;
701			}
702			free(reparse);
703#else /* DISABLE_PLUGINS */
704			ni = (ntfs_inode*)NULL;
705			errno = EOPNOTSUPP;
706			res = -errno;
707#endif /* DISABLE_PLUGINS */
708		} else {
709			switch (type) {
710				case S_IFCHR:
711				case S_IFBLK:
712					ni = ntfs_create_device(dir_ni, securid,
713							uname, uname_len,
714							type, dev);
715					break;
716				case S_IFLNK:
717					utarget_len = ntfs_mbstoucs(target,
718							&utarget);
719					if (utarget_len < 0) {
720						res = -errno;
721						goto exit;
722					}
723					ni = ntfs_create_symlink(dir_ni,
724							securid,
725							uname, uname_len,
726							utarget, utarget_len);
727					break;
728				default:
729					ni = ntfs_create(dir_ni, securid, uname,
730							uname_len, type);
731					break;
732			}
733		}
734		if (ni) {
735				/*
736				 * set the security attribute if a security id
737				 * could not be allocated (eg NTFS 1.x)
738				 */
739			if (security.mapping[MAPUSERS]) {
740#if POSIXACLS
741				if (!securid
742				   && ntfs_set_inherited_posix(&security, ni,
743					security.uid, gid,
744					dir_ni, perm) < 0)
745					set_fuse_error(&res);
746#else
747				if (!securid
748				   && ntfs_set_owner_mode(&security, ni,
749					security.uid, gid,
750					perm & ~security.umask) < 0)
751					set_fuse_error(&res);
752#endif
753			}
754			set_archive(ni);
755			/* mark a need to compress the end of file */
756			if (fi && (ni->flags & FILE_ATTR_COMPRESSED)) {
757				state |= CLOSE_COMPRESSED;
758			}
759#ifdef HAVE_SETXATTR	/* extended attributes interface required */
760			/* mark a future need to fixup encrypted inode */
761			if (fi
762				&& ctx->efs_raw
763				&& (ni->flags & FILE_ATTR_ENCRYPTED))
764				state |= CLOSE_ENCRYPTED;
765#endif /* HAVE_SETXATTR */
766			if (fi && ctx->dmtime)
767				state |= CLOSE_DMTIME;
768			ntfs_inode_update_mbsname(dir_ni, name, ni->mft_no);
769			NInoSetDirty(ni);
770			*ino = ni->mft_no;
771#ifndef __HAIKU__
772			e->ino = ni->mft_no;
773			e->generation = 1;
774			e->attr_timeout = ATTR_TIMEOUT;
775			e->entry_timeout = ENTRY_TIMEOUT;
776			res = ntfs_fuse_getstat(&security, ni, &e->attr);
777#endif
778			/*
779			 * closing ni requires access to dir_ni to
780			 * synchronize the index, avoid double opening.
781			 */
782			if (ntfs_inode_close_in_dir(ni, dir_ni))
783				set_fuse_error(&res);
784			ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
785		} else
786			res = -errno;
787#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
788	} else
789		res = -errno;
790#endif
791
792exit:
793	free(uname);
794	if (ntfs_inode_close(dir_ni))
795		set_fuse_error(&res);
796	if (utarget)
797		free(utarget);
798#ifndef __HAIKU__
799	if ((res >= 0) && fi) {
800		of = (struct open_file*)malloc(sizeof(struct open_file));
801		if (of) {
802			of->parent = 0;
803			of->ino = e->ino;
804			of->state = state;
805			of->next = ctx->open_files;
806			of->previous = (struct open_file*)NULL;
807			if (ctx->open_files)
808				ctx->open_files->previous = of;
809			ctx->open_files = of;
810			fi->fh = (long)of;
811		}
812	}
813#else
814	// FIXME: store "state" somewhere
815#endif
816	return res;
817}
818
819static int ntfs_fuse_newlink(struct lowntfs_context *ctx,
820		ino_t ino, ino_t newparent,
821		const char *newname, struct fuse_entry_param *e)
822{
823	ntfschar *uname = NULL;
824	ntfs_inode *dir_ni = NULL, *ni;
825	int res = 0, uname_len;
826	struct SECURITY_CONTEXT security;
827
828	/* Open file for which create hard link. */
829	ni = ntfs_inode_open(ctx->vol, INODE(ino));
830	if (!ni) {
831		res = -errno;
832		goto exit;
833	}
834
835	/* Do not accept linking to a directory (except for renaming) */
836	if (e && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
837		errno = EPERM;
838		res = -errno;
839		goto exit;
840	}
841	/* Generate unicode filename. */
842	uname_len = ntfs_mbstoucs(newname, &uname);
843	if ((uname_len < 0)
844			|| (ctx->windows_names
845				&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
846		res = -errno;
847		goto exit;
848	}
849	/* Open parent directory. */
850	dir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
851	if (!dir_ni) {
852		res = -errno;
853		goto exit;
854	}
855
856#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
857		/* make sure the target parent directory is writeable */
858	if (ntfs_fuse_fill_security_context(ctx, &security)
859		&& !ntfs_allowed_access(&security,dir_ni,S_IWRITE + S_IEXEC))
860		res = -EACCES;
861	else
862#else
863	ntfs_fuse_fill_security_context(ctx, &security);
864#endif
865		{
866		if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
867#ifndef DISABLE_PLUGINS
868			const plugin_operations_t *ops;
869			REPARSE_POINT *reparse;
870
871			res = CALL_REPARSE_PLUGIN(dir_ni, link,
872					ni, uname, uname_len);
873			if (res < 0)
874				goto exit;
875#else /* DISABLE_PLUGINS */
876			res = -EOPNOTSUPP;
877			goto exit;
878#endif /* DISABLE_PLUGINS */
879		} else {
880			if (ntfs_link(ni, dir_ni, uname, uname_len)) {
881				res = -errno;
882				goto exit;
883			}
884		}
885		ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
886#ifndef __HAIKU__
887		if (e) {
888			e->ino = ni->mft_no;
889			e->generation = 1;
890			e->attr_timeout = ATTR_TIMEOUT;
891			e->entry_timeout = ENTRY_TIMEOUT;
892			res = ntfs_fuse_getstat(&security, ni, &e->attr);
893		}
894#endif
895		set_archive(ni);
896		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
897		ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
898	}
899exit:
900	/*
901	 * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni)
902	 * may fail because ni may not be in parent's index on the disk yet.
903	 */
904	if (ntfs_inode_close(dir_ni))
905		set_fuse_error(&res);
906	if (ntfs_inode_close(ni))
907		set_fuse_error(&res);
908	free(uname);
909	return (res);
910}
911
912
913int
914ntfs_fuse_rm(struct lowntfs_context *ctx, ino_t parent, const char *name,
915	enum RM_TYPES rm_type)
916{
917	ntfschar *uname = NULL;
918	ntfschar *ugname;
919	ntfs_inode *dir_ni = NULL, *ni = NULL;
920	int res = 0, uname_len;
921	int ugname_len;
922	u64 iref;
923	ino_t ino;
924	char ghostname[GHOSTLTH];
925#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
926	struct SECURITY_CONTEXT security;
927#endif
928#if defined(__sun) && defined (__SVR4)
929	int isdir;
930#endif /* defined(__sun) && defined (__SVR4) */
931	int no_check_open = (rm_type & RM_NO_CHECK_OPEN) != 0;
932	rm_type &= ~RM_NO_CHECK_OPEN;
933
934	/* Deny removing from $Extend */
935	if (parent == FILE_Extend) {
936		res = -EPERM;
937		goto exit;
938	}
939	/* Open parent directory. */
940	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
941	if (!dir_ni) {
942		res = -errno;
943		goto exit;
944	}
945	/* Generate unicode filename. */
946	uname_len = ntfs_mbstoucs(name, &uname);
947	if (uname_len < 0) {
948		res = -errno;
949		goto exit;
950	}
951	/* Open object for delete. */
952	iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
953	if (iref == (u64)-1) {
954		res = -errno;
955		goto exit;
956	}
957	ino = (ino_t)MREF(iref);
958	/* deny unlinking metadata files */
959	if (ino < FILE_first_user) {
960		errno = EPERM;
961		res = -errno;
962		goto exit;
963	}
964
965	ni = ntfs_inode_open(ctx->vol, ino);
966	if (!ni) {
967		res = -errno;
968		goto exit;
969	}
970
971#if defined(__sun) && defined (__SVR4)
972	/* on Solaris : deny unlinking directories */
973	isdir = ni->mrec->flags & MFT_RECORD_IS_DIRECTORY;
974#ifndef DISABLE_PLUGINS
975		/* get emulated type from plugin if available */
976	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
977		struct stat st;
978		const plugin_operations_t *ops;
979		REPARSE_POINT *reparse;
980
981			/* Avoid double opening of parent directory */
982		res = ntfs_inode_close(dir_ni);
983		if (res)
984			goto exit;
985		dir_ni = (ntfs_inode*)NULL;
986		res = CALL_REPARSE_PLUGIN(ni, getattr, &st);
987		if (res)
988			goto exit;
989		isdir = S_ISDIR(st.st_mode);
990		dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
991		if (!dir_ni) {
992			res = -errno;
993			goto exit;
994		}
995	}
996#endif /* DISABLE_PLUGINS */
997	if (rm_type == (isdir ? RM_LINK : RM_DIR)) {
998		errno = (isdir ? EISDIR : ENOTDIR);
999		res = -errno;
1000		goto exit;
1001	}
1002#endif /* defined(__sun) && defined (__SVR4) */
1003
1004#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1005	/* JPA deny unlinking if directory is not writable and executable */
1006	if (ntfs_fuse_fill_security_context(ctx, &security)
1007		&& !ntfs_allowed_dir_access(&security, dir_ni, ino, ni,
1008				   S_IEXEC + S_IWRITE + S_ISVTX)) {
1009		errno = EACCES;
1010		res = -errno;
1011		goto exit;
1012	}
1013#endif
1014#ifndef __HAIKU__
1015		/*
1016		 * We keep one open_file record per opening, to avoid
1017		 * having to check the list of open files when opening
1018		 * and closing (which are more frequent than unlinking).
1019		 * As a consequence, we may have to create several
1020		 * ghosts names for the same file.
1021		 * The file may have been opened with a different name
1022		 * in a different parent directory. The ghost is
1023		 * nevertheless created in the parent directory of the
1024		 * name being unlinked, and permissions to do so are the
1025		 * same as required for unlinking.
1026		 */
1027	for (of=ctx->open_files; of; of = of->next) {
1028		if ((of->ino == ino) && !(of->state & CLOSE_GHOST)) {
1029#else
1030	int* close_state = NULL;
1031	if (!no_check_open) {
1032		close_state = ntfs_haiku_get_close_state(ctx, ino);
1033		if (close_state && (*close_state & CLOSE_GHOST) == 0) {
1034#endif
1035			/* file was open, create a ghost in unlink parent */
1036			ntfs_inode *gni;
1037			u64 gref;
1038
1039			/* ni has to be closed for linking ghost */
1040			if (ni) {
1041				if (ntfs_inode_close(ni)) {
1042					res = -errno;
1043					goto exit;
1044				}
1045				ni = (ntfs_inode*)NULL;
1046			}
1047			*close_state |= CLOSE_GHOST;
1048			u64 ghost = ++ctx->latest_ghost;
1049
1050			sprintf(ghostname,ghostformat,ghost);
1051				/* Generate unicode filename. */
1052			ugname = (ntfschar*)NULL;
1053			ugname_len = ntfs_mbstoucs(ghostname, &ugname);
1054			if (ugname_len < 0) {
1055				res = -errno;
1056				goto exit;
1057			}
1058			/* sweep existing ghost if any, ignoring errors */
1059			gref = ntfs_inode_lookup_by_mbsname(dir_ni, ghostname);
1060			if (gref != (u64)-1) {
1061				gni = ntfs_inode_open(ctx->vol, MREF(gref));
1062				ntfs_delete(ctx->vol, (char*)NULL, gni, dir_ni,
1063					 ugname, ugname_len);
1064				/* ntfs_delete() always closes gni and dir_ni */
1065				dir_ni = (ntfs_inode*)NULL;
1066			} else {
1067				if (ntfs_inode_close(dir_ni)) {
1068					res = -errno;
1069					goto out;
1070				}
1071				dir_ni = (ntfs_inode*)NULL;
1072			}
1073			free(ugname);
1074			res = ntfs_fuse_newlink(ctx, ino, parent, ghostname,
1075					(struct fuse_entry_param*)NULL);
1076			if (res)
1077				goto out;
1078
1079#ifdef __HAIKU__
1080			// We have to do this before the parent directory is reopened.
1081			ntfs_haiku_put_close_state(ctx, ino, ghost);
1082			close_state = NULL;
1083#endif
1084
1085				/* now reopen then parent directory */
1086			dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
1087			if (!dir_ni) {
1088				res = -errno;
1089				goto exit;
1090			}
1091		}
1092	}
1093	if (!ni) {
1094		ni = ntfs_inode_open(ctx->vol, ino);
1095		if (!ni) {
1096			res = -errno;
1097			goto exit;
1098		}
1099	}
1100	if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
1101#ifndef DISABLE_PLUGINS
1102		const plugin_operations_t *ops;
1103		REPARSE_POINT *reparse;
1104
1105		res = CALL_REPARSE_PLUGIN(dir_ni, unlink, (char*)NULL,
1106				ni, uname, uname_len);
1107#else /* DISABLE_PLUGINS */
1108		errno = EOPNOTSUPP;
1109		res = -errno;
1110#endif /* DISABLE_PLUGINS */
1111	} else {
1112		if (ntfs_delete(ctx->vol, (char*)NULL, ni, dir_ni,
1113					 uname, uname_len))
1114			res = -errno;
1115		/* ntfs_delete() always closes ni and dir_ni */
1116	}
1117	ni = dir_ni = NULL;
1118exit:
1119	if (ntfs_inode_close(ni) && !res)
1120		res = -errno;
1121	if (ntfs_inode_close(dir_ni) && !res)
1122		res = -errno;
1123out :
1124#ifdef __HAIKU__
1125	if (close_state)
1126		ntfs_haiku_put_close_state(ctx, ino, -1);
1127#endif
1128	free(uname);
1129	return res;
1130}
1131
1132int ntfs_fuse_release(struct lowntfs_context *ctx, ino_t parent, ino_t ino, int state, u64 ghost)
1133{
1134	ntfs_inode *ni = NULL;
1135	ntfs_attr *na = NULL;
1136	char ghostname[GHOSTLTH];
1137	int res;
1138
1139	/* Only for marked descriptors there is something to do */
1140	if (!(state & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED
1141				| CLOSE_DMTIME | CLOSE_REPARSE))) {
1142		res = 0;
1143		goto out;
1144	}
1145	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1146	if (!ni) {
1147		res = -errno;
1148		goto exit;
1149	}
1150	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1151#ifndef DISABLE_PLUGINS
1152		const plugin_operations_t *ops;
1153		REPARSE_POINT *reparse;
1154
1155		res = CALL_REPARSE_PLUGIN(ni, release, &of->fi);
1156		if (!res) {
1157			goto stamps;
1158		}
1159#else /* DISABLE_PLUGINS */
1160			/* Assume release() was not needed */
1161		res = 0;
1162#endif /* DISABLE_PLUGINS */
1163		goto exit;
1164	}
1165	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1166	if (!na) {
1167		res = -errno;
1168		goto exit;
1169	}
1170	res = 0;
1171	if (state & CLOSE_COMPRESSED)
1172		res = ntfs_attr_pclose(na);
1173#ifdef HAVE_SETXATTR	/* extended attributes interface required */
1174	if (of->state & CLOSE_ENCRYPTED)
1175		res = ntfs_efs_fixup_attribute(NULL, na);
1176#endif /* HAVE_SETXATTR */
1177#ifndef DISABLE_PLUGINS
1178stamps :
1179#endif /* DISABLE_PLUGINS */
1180	if (state & CLOSE_DMTIME)
1181		ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
1182exit:
1183	if (na)
1184		ntfs_attr_close(na);
1185	if (ntfs_inode_close(ni))
1186		set_fuse_error(&res);
1187out:
1188		/* remove the associate ghost file (even if release failed) */
1189	if (1) {
1190		if (state & CLOSE_GHOST) {
1191			sprintf(ghostname,ghostformat,ghost);
1192			ntfs_fuse_rm(ctx, parent, ghostname, RM_ANY | RM_NO_CHECK_OPEN);
1193		}
1194#ifndef __HAIKU__
1195			/* remove from open files list */
1196		if (of->next)
1197			of->next->previous = of->previous;
1198		if (of->previous)
1199			of->previous->next = of->next;
1200		else
1201			ctx->open_files = of->next;
1202		free(of);
1203#endif
1204	}
1205#ifndef __HAIKU__
1206	if (res)
1207		fuse_reply_err(req, -res);
1208	else
1209		fuse_reply_err(req, 0);
1210#endif
1211	return res;
1212}
1213
1214static int ntfs_fuse_safe_rename(struct lowntfs_context *ctx, ino_t ino,
1215			ino_t parent, const char *name, ino_t xino,
1216			ino_t newparent, const char *newname,
1217			const char *tmp)
1218{
1219	int ret;
1220
1221	ntfs_log_trace("Entering\n");
1222
1223	ret = ntfs_fuse_newlink(ctx, xino, newparent, tmp,
1224				(struct fuse_entry_param*)NULL);
1225	if (ret)
1226		return ret;
1227
1228	ret = ntfs_fuse_rm(ctx, newparent, newname, RM_ANY);
1229	if (!ret) {
1230
1231		ret = ntfs_fuse_newlink(ctx, ino, newparent, newname,
1232					(struct fuse_entry_param*)NULL);
1233		if (ret)
1234			goto restore;
1235
1236		ret = ntfs_fuse_rm(ctx, parent, name, RM_ANY | RM_NO_CHECK_OPEN);
1237		if (ret) {
1238			if (ntfs_fuse_rm(ctx, newparent, newname, RM_ANY))
1239				goto err;
1240			goto restore;
1241		}
1242	}
1243
1244	goto cleanup;
1245restore:
1246	if (ntfs_fuse_newlink(ctx, xino, newparent, newname,
1247				(struct fuse_entry_param*)NULL)) {
1248err:
1249		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "
1250				"to '%s'", newname, tmp);
1251	} else {
1252cleanup:
1253		/*
1254		 * Condition for this unlink has already been checked in
1255		 * "ntfs_fuse_rename_existing_dest()", so it should never
1256		 * fail (unless concurrent access to directories when fuse
1257		 * is multithreaded)
1258		 */
1259		if (ntfs_fuse_rm(ctx, newparent, tmp, RM_ANY) < 0)
1260			ntfs_log_perror("Rename failed. Existing file '%s' still present "
1261				"as '%s'", newname, tmp);
1262	}
1263	return	ret;
1264}
1265
1266static int ntfs_fuse_rename_existing_dest(struct lowntfs_context *ctx, ino_t ino,
1267			ino_t parent, const char *name,
1268			ino_t xino, ino_t newparent,
1269			const char *newname)
1270{
1271	int ret, len;
1272	char *tmp;
1273	const char *ext = ".ntfs-3g-";
1274#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1275	ntfs_inode *newdir_ni;
1276	struct SECURITY_CONTEXT security;
1277#endif
1278
1279	ntfs_log_trace("Entering\n");
1280
1281	len = strlen(newname) + strlen(ext) + 10 + 1; /* wc(str(2^32)) + \0 */
1282	tmp = (char*)ntfs_malloc(len);
1283	if (!tmp)
1284		return -errno;
1285
1286	ret = snprintf(tmp, len, "%s%s%010d", newname, ext, ++ntfs_sequence);
1287	if (ret != len - 1) {
1288		ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);
1289		ret = -EOVERFLOW;
1290	} else {
1291#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1292			/*
1293			 * Make sure existing dest can be removed.
1294			 * This is only needed if parent directory is
1295			 * sticky, because in this situation condition
1296			 * for unlinking is different from condition for
1297			 * linking
1298			 */
1299		newdir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
1300		if (newdir_ni) {
1301			if (!ntfs_fuse_fill_security_context(ctx,&security)
1302				|| ntfs_allowed_dir_access(&security, newdir_ni,
1303					xino, (ntfs_inode*)NULL,
1304					S_IEXEC + S_IWRITE + S_ISVTX)) {
1305				if (ntfs_inode_close(newdir_ni))
1306					ret = -errno;
1307				else
1308					ret = ntfs_fuse_safe_rename(ctx, ino,
1309							parent, name, xino,
1310							newparent, newname,
1311							tmp);
1312			} else {
1313				ntfs_inode_close(newdir_ni);
1314				ret = -EACCES;
1315			}
1316		} else
1317			ret = -errno;
1318#else
1319		ret = ntfs_fuse_safe_rename(ctx, ino, parent, name,
1320					xino, newparent, newname, tmp);
1321#endif
1322	}
1323	free(tmp);
1324	return	ret;
1325}
1326
1327
1328int ntfs_fuse_rename(struct lowntfs_context *ctx, ino_t parent,
1329			const char *name, ino_t newparent,
1330			const char *newname)
1331{
1332	int ret;
1333	ino_t ino;
1334	ino_t xino;
1335	ntfs_inode *ni;
1336
1337	ntfs_log_debug("rename: old: '%s'  new: '%s'\n", name, newname);
1338
1339	/*
1340	 *  FIXME: Rename should be atomic.
1341	 */
1342
1343	ino = ntfs_fuse_inode_lookup(ctx, parent, name);
1344	if (ino == (ino_t)-1) {
1345		ret = -errno;
1346		goto out;
1347	}
1348	/* Check whether target is present */
1349	xino = ntfs_fuse_inode_lookup(ctx, newparent, newname);
1350	if (xino != (ino_t)-1) {
1351			/*
1352			 * Target exists : no need to check whether it
1353			 * designates the same inode, this has already
1354			 * been checked (by fuse ?)
1355			 */
1356		ni = ntfs_inode_open(ctx->vol, INODE(xino));
1357		if (!ni)
1358			ret = -errno;
1359		else {
1360			ret = ntfs_check_empty_dir(ni);
1361			if (ret < 0) {
1362				ret = -errno;
1363				ntfs_inode_close(ni);
1364				goto out;
1365			}
1366
1367			if (ntfs_inode_close(ni)) {
1368				set_fuse_error(&ret);
1369				goto out;
1370			}
1371			ret = ntfs_fuse_rename_existing_dest(ctx, ino, parent,
1372						name, xino, newparent, newname);
1373		}
1374	} else {
1375			/* target does not exist */
1376		ret = ntfs_fuse_newlink(ctx, ino, newparent, newname,
1377					(struct fuse_entry_param*)NULL);
1378		if (ret)
1379			goto out;
1380
1381		ret = ntfs_fuse_rm(ctx, parent, name, RM_ANY | RM_NO_CHECK_OPEN);
1382		if (ret)
1383			ntfs_fuse_rm(ctx, newparent, newname, RM_ANY);
1384	}
1385out:
1386#ifndef __HAIKU__
1387	if (ret)
1388		fuse_reply_err(req, -ret);
1389	else
1390		fuse_reply_err(req, 0);
1391#endif
1392	return ret;
1393}
1394