xref: /haiku/src/add-ons/kernel/file_systems/ntfs/lowntfs.c (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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 
38 static 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 
42 static const char ghostformat[] = ".ghost-ntfs-3g-%020llu";
43 #define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */
44 
45 static u32 ntfs_sequence = 0;
46 
47 
48 static void
49 set_fuse_error(int *err)
50 {
51 	if (!*err)
52 		*err = errno;
53 }
54 
55 static void
56 ntfs_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 
74 static 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 
91 u64
92 ntfs_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 
118 int
119 ntfs_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
302 ok:
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;
314 nodata :
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
354 exit:
355 	return (res);
356 }
357 
358 
359 int
360 ntfs_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 	}
457 exit:
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 
477 int
478 ntfs_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 	}
541 ok:
542 	res = total;
543 #ifndef DISABLE_PLUGINS
544 stamps :
545 #endif /* DISABLE_PLUGINS */
546 	ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
547 exit:
548 	if (na)
549 		ntfs_attr_close(na);
550 	return res;
551 }
552 
553 int
554 ntfs_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
595 stamps :
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);
602 exit:
603 	if (na)
604 		ntfs_attr_close(na);
605 	if (res > 0)
606 		set_archive(ni);
607 	return res;
608 }
609 
610 int
611 ntfs_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 
792 exit:
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 
819 static 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 	}
899 exit:
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 
913 int
914 ntfs_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;
1118 exit:
1119 	if (ntfs_inode_close(ni) && !res)
1120 		res = -errno;
1121 	if (ntfs_inode_close(dir_ni) && !res)
1122 		res = -errno;
1123 out :
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 
1132 int 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
1178 stamps :
1179 #endif /* DISABLE_PLUGINS */
1180 	if (state & CLOSE_DMTIME)
1181 		ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
1182 exit:
1183 	if (na)
1184 		ntfs_attr_close(na);
1185 	if (ntfs_inode_close(ni))
1186 		set_fuse_error(&res);
1187 out:
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 
1214 static 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;
1245 restore:
1246 	if (ntfs_fuse_newlink(ctx, xino, newparent, newname,
1247 				(struct fuse_entry_param*)NULL)) {
1248 err:
1249 		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "
1250 				"to '%s'", newname, tmp);
1251 	} else {
1252 cleanup:
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 
1266 static 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 
1328 int 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 	}
1385 out:
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