• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * ntfs-3g - Third Generation NTFS Driver
3  *
4  * Copyright (c) 2005-2007 Yura Pakhuchiy
5  * Copyright (c) 2005 Yuval Fledel
6  * Copyright (c) 2006-2009 Szabolcs Szakacsits
7  * Copyright (c) 2007-2021 Jean-Pierre Andre
8  * Copyright (c) 2009 Erik Larsson
9  *
10  * This file is originated from the Linux-NTFS project.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program (in the main directory of the NTFS-3G
24  * distribution in the file COPYING); if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #include "config.h"
29 
30 #include <fuse.h>
31 #include <fuse_lowlevel.h>
32 
33 #if !defined(FUSE_VERSION) || (FUSE_VERSION < 26)
34 #error "***********************************************************"
35 #error "*                                                         *"
36 #error "*     Compilation requires at least FUSE version 2.6.0!   *"
37 #error "*                                                         *"
38 #error "***********************************************************"
39 #endif
40 
41 #ifdef HAVE_STDIO_H
42 #include <stdio.h>
43 #endif
44 #ifdef HAVE_STRING_H
45 #include <string.h>
46 #endif
47 #ifdef HAVE_ERRNO_H
48 #include <errno.h>
49 #endif
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #ifdef HAVE_STDLIB_H
57 #include <stdlib.h>
58 #endif
59 #ifdef HAVE_LOCALE_H
60 #include <locale.h>
61 #endif
62 #include <signal.h>
63 #ifdef HAVE_LIMITS_H
64 #include <limits.h>
65 #endif
66 #include <syslog.h>
67 #include <sys/wait.h>
68 
69 #ifdef HAVE_SETXATTR
70 #include <sys/xattr.h>
71 #endif
72 
73 #ifdef HAVE_SYS_TYPES_H
74 #include <sys/types.h>
75 #endif
76 #ifdef MAJOR_IN_MKDEV
77 #include <sys/mkdev.h>
78 #endif
79 #ifdef MAJOR_IN_SYSMACROS
80 #include <sys/sysmacros.h>
81 #endif
82 
83 #if defined(__APPLE__) || defined(__DARWIN__)
84 #include <sys/dirent.h>
85 #elif defined(__sun) && defined (__SVR4)
86 #include <sys/param.h>
87 #endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
88 
89 #ifndef FUSE_CAP_POSIX_ACL  /* until defined in <fuse/fuse_common.h> */
90 #define FUSE_CAP_POSIX_ACL (1 << 18)
91 #endif /* FUSE_CAP_POSIX_ACL */
92 
93 #include "compat.h"
94 #include "bitmap.h"
95 #include "attrib.h"
96 #include "inode.h"
97 #include "volume.h"
98 #include "dir.h"
99 #include "unistr.h"
100 #include "layout.h"
101 #include "index.h"
102 #include "ntfstime.h"
103 #include "security.h"
104 #include "reparse.h"
105 #include "ea.h"
106 #include "object_id.h"
107 #include "efs.h"
108 #include "logging.h"
109 #include "xattrs.h"
110 #include "misc.h"
111 #include "ioctl.h"
112 #include "plugin.h"
113 
114 #include "ntfs-3g_common.h"
115 
116 /*
117  *	The following permission checking modes are governed by
118  *	the LPERMSCONFIG value in param.h
119  */
120 
121 /*	ACLS may be checked by kernel (requires a fuse patch) or here */
122 #define KERNELACLS ((LPERMSCONFIG > 6) & (LPERMSCONFIG < 10))
123 /*	basic permissions may be checked by kernel or here */
124 #define KERNELPERMS (((LPERMSCONFIG - 1) % 6) < 3)
125 /*	may want to use fuse/kernel cacheing */
126 #define CACHEING (!(LPERMSCONFIG % 3))
127 
128 #if KERNELACLS & !KERNELPERMS
129 #error "Incompatible options KERNELACLS and KERNELPERMS"
130 #endif
131 
132 #if !CACHEING
133 #define ATTR_TIMEOUT (ctx->ro ? TIMEOUT_RO : 0.0)
134 #define ENTRY_TIMEOUT (ctx->ro ? TIMEOUT_RO : 0.0)
135 #else
136 #if defined(__sun) && defined (__SVR4)
137 #define ATTR_TIMEOUT (ctx->ro ? TIMEOUT_RO : 10.0)
138 #define ENTRY_TIMEOUT (ctx->ro ? TIMEOUT_RO : 10.0)
139 #else /* defined(__sun) && defined (__SVR4) */
140 	/*
141 	 * FUSE cacheing is only usable with basic permissions
142 	 * checked by the kernel with external fuse >= 2.8
143 	 */
144 #if !KERNELPERMS
145 #warning "Fuse cacheing is only usable with basic permissions checked by kernel"
146 #endif
147 #if KERNELACLS
148 #define ATTR_TIMEOUT (ctx->ro ? TIMEOUT_RO : 10.0)
149 #define ENTRY_TIMEOUT (ctx->ro ? TIMEOUT_RO : 10.0)
150 #else /* KERNELACLS */
151 #define ATTR_TIMEOUT (ctx->ro ? TIMEOUT_RO : \
152 	(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 10.0 : 0.0))
153 #define ENTRY_TIMEOUT (ctx->ro ? TIMEOUT_RO : \
154 	(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 10.0 : 0.0))
155 #endif /* KERNELACLS */
156 #endif /* defined(__sun) && defined (__SVR4) */
157 #endif /* !CACHEING */
158 #define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */
159 
160 		/* sometimes the kernel cannot check access */
161 #define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, type)
162 #if POSIXACLS & KERNELPERMS & !KERNELACLS
163 		/* short-circuit if PERMS checked by kernel and ACLs by fs */
164 #define ntfs_allowed_access(scx, ni, type) \
165 	((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \
166 	    ? 1 : ntfs_allowed_access(scx, ni, type))
167 #endif
168 
169 #define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE
170 #define INODE(ino) ((ino) == 1 ? (MFT_REF)FILE_root : (MFT_REF)(ino))
171 
172 /*
173  *		Call a function from a reparse plugin (variable arguments)
174  *	Requires "reparse" and "ops" to have been defined
175  *
176  *	Returns a non-negative value if successful,
177  *		and a negative error code if something fails.
178  */
179 #define CALL_REPARSE_PLUGIN(ni, op_name, ...)			\
180 	 (reparse = (REPARSE_POINT*)NULL,			 \
181 	 ops = select_reparse_plugin(ctx, ni, &reparse),	 \
182 	 (!ops ? -errno						 \
183 		 : (ops->op_name ?				 \
184 			 ops->op_name(ni, reparse, __VA_ARGS__)  \
185 			 : -EOPNOTSUPP))),			 \
186 		 free(reparse)
187 
188 typedef enum {
189 	FSTYPE_NONE,
190 	FSTYPE_UNKNOWN,
191 	FSTYPE_FUSE,
192 	FSTYPE_FUSEBLK
193 } fuse_fstype;
194 
195 typedef struct fill_item {
196 	struct fill_item *next;
197 	size_t bufsize;
198 	size_t off;
199 	char buf[0];
200 } ntfs_fuse_fill_item_t;
201 
202 typedef struct fill_context {
203 	struct fill_item *first;
204 	struct fill_item *last;
205 #ifndef DISABLE_PLUGINS
206 	u64 fh;
207 #endif /* DISABLE_PLUGINS */
208 	off_t off;
209 	fuse_req_t req;
210 	fuse_ino_t ino;
211 	BOOL filled;
212 } ntfs_fuse_fill_context_t;
213 
214 struct open_file {
215 	struct open_file *next;
216 	struct open_file *previous;
217 	long long ghost;
218 	fuse_ino_t ino;
219 	fuse_ino_t parent;
220 	int state;
221 #ifndef DISABLE_PLUGINS
222 	struct fuse_file_info fi;
223 #endif /* DISABLE_PLUGINS */
224 } ;
225 
226 enum {
227 	CLOSE_GHOST = 1,
228 	CLOSE_COMPRESSED = 2,
229 	CLOSE_ENCRYPTED = 4,
230 	CLOSE_DMTIME = 8,
231 	CLOSE_REPARSE = 16
232 };
233 
234 enum RM_TYPES {
235 	RM_LINK,
236 	RM_DIR,
237 	RM_ANY,
238 } ;
239 
240 static struct ntfs_options opts;
241 
242 const char *EXEC_NAME = "lowntfs-3g";
243 
244 static ntfs_fuse_context_t *ctx;
245 static u32 ntfs_sequence;
246 static const char ghostformat[] = ".ghost-ntfs-3g-%020llu";
247 
248 static const char *usage_msg =
249 "\n"
250 "%s %s %s %d - Third Generation NTFS Driver\n"
251 "\t\tConfiguration type %d, "
252 #ifdef HAVE_SETXATTR
253 "XATTRS are on, "
254 #else
255 "XATTRS are off, "
256 #endif
257 #if POSIXACLS
258 "POSIX ACLS are on\n"
259 #else
260 "POSIX ACLS are off\n"
261 #endif
262 "\n"
263 "Copyright (C) 2005-2007 Yura Pakhuchiy\n"
264 "Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
265 "Copyright (C) 2007-2022 Jean-Pierre Andre\n"
266 "Copyright (C) 2009-2020 Erik Larsson\n"
267 "\n"
268 "Usage:    %s [-o option[,...]] <device|image_file> <mount_point>\n"
269 "\n"
270 "Options:  ro (read-only mount), windows_names, uid=, gid=,\n"
271 "          umask=, fmask=, dmask=, streams_interface=.\n"
272 "          Please see the details in the manual (type: man ntfs-3g).\n"
273 "\n"
274 "Example: lowntfs-3g /dev/sda1 /mnt/windows\n"
275 "\n"
276 #ifdef PLUGIN_DIR
277 "Plugin path: " PLUGIN_DIR "\n\n"
278 #endif /* PLUGIN_DIR */
279 "%s";
280 
281 static const char ntfs_bad_reparse[] = "unsupported reparse tag 0x%08lx";
282      /* exact length of target text, without the terminator */
283 #define ntfs_bad_reparse_lth (sizeof(ntfs_bad_reparse) + 2)
284 
285 #ifdef FUSE_INTERNAL
286 int drop_privs(void);
287 int restore_privs(void);
288 #else
289 /*
290  * setuid and setgid root ntfs-3g denies to start with external FUSE,
291  * therefore the below functions are no-op in such case.
292  */
drop_privs(void)293 static int drop_privs(void)    { return 0; }
294 #if defined(linux) || defined(__uClinux__)
restore_privs(void)295 static int restore_privs(void) { return 0; }
296 #endif
297 
298 static const char *setuid_msg =
299 "Mount is denied because setuid and setgid root ntfs-3g is insecure with the\n"
300 "external FUSE library. Either remove the setuid/setgid bit from the binary\n"
301 "or rebuild NTFS-3G with integrated FUSE support and make it setuid root.\n"
302 "Please see more information at\n"
303 "https://github.com/tuxera/ntfs-3g/wiki/NTFS-3G-FAQ\n";
304 
305 static const char *unpriv_fuseblk_msg =
306 "Unprivileged user can not mount NTFS block devices using the external FUSE\n"
307 "library. Either mount the volume as root, or rebuild NTFS-3G with integrated\n"
308 "FUSE support and make it setuid root. Please see more information at\n"
309 "https://github.com/tuxera/ntfs-3g/wiki/NTFS-3G-FAQ\n";
310 #endif
311 
312 
ntfs_fuse_update_times(ntfs_inode * ni,ntfs_time_update_flags mask)313 static void ntfs_fuse_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
314 {
315 	if (ctx->atime == ATIME_DISABLED)
316 		mask &= ~NTFS_UPDATE_ATIME;
317 	else if (ctx->atime == ATIME_RELATIVE && mask == NTFS_UPDATE_ATIME &&
318 			(sle64_to_cpu(ni->last_access_time)
319 				>= sle64_to_cpu(ni->last_data_change_time)) &&
320 			(sle64_to_cpu(ni->last_access_time)
321 				>= sle64_to_cpu(ni->last_mft_change_time)))
322 		return;
323 	ntfs_inode_update_times(ni, mask);
324 }
325 
ntfs_get_nr_free_mft_records(ntfs_volume * vol)326 static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol)
327 {
328 	ntfs_attr *na = vol->mftbmp_na;
329 	s64 nr_free = ntfs_attr_get_free_bits(na);
330 
331 	if (nr_free >= 0)
332 		nr_free += (na->allocated_size - na->data_size) << 3;
333 	return nr_free;
334 }
335 
336 /*
337  *	Fill a security context as needed by security functions
338  *	returns TRUE if there is a user mapping,
339  *		FALSE if there is none
340  *			This is not an error and the context is filled anyway,
341  *			it is used for implicit Windows-like inheritance
342  */
343 
ntfs_fuse_fill_security_context(fuse_req_t req,struct SECURITY_CONTEXT * scx)344 static BOOL ntfs_fuse_fill_security_context(fuse_req_t req,
345 			struct SECURITY_CONTEXT *scx)
346 {
347 	const struct fuse_ctx *fusecontext;
348 
349 	scx->vol = ctx->vol;
350 	scx->mapping[MAPUSERS] = ctx->security.mapping[MAPUSERS];
351 	scx->mapping[MAPGROUPS] = ctx->security.mapping[MAPGROUPS];
352 	scx->pseccache = &ctx->seccache;
353 	if (req) {
354 		fusecontext = fuse_req_ctx(req);
355 		scx->uid = fusecontext->uid;
356 		scx->gid = fusecontext->gid;
357 		scx->tid = fusecontext->pid;
358 #ifdef FUSE_CAP_DONT_MASK
359 			/* the umask can be processed by the file system */
360 		scx->umask = fusecontext->umask;
361 #else
362 			/* the umask if forced by fuse on creation */
363 		scx->umask = 0;
364 #endif
365 
366 	} else {
367 		scx->uid = 0;
368 		scx->gid = 0;
369 		scx->tid = 0;
370 		scx->umask = 0;
371 	}
372 	return (ctx->security.mapping[MAPUSERS] != (struct MAPPING*)NULL);
373 }
374 
ntfs_fuse_inode_lookup(fuse_ino_t parent,const char * name)375 static u64 ntfs_fuse_inode_lookup(fuse_ino_t parent, const char *name)
376 {
377 	u64 ino = (u64)-1;
378 	u64 inum;
379 	ntfs_inode *dir_ni;
380 
381 	/* Open target directory. */
382 	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
383 	if (dir_ni) {
384 		/* Lookup file */
385 		inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
386 			/* never return inodes 0 and 1 */
387 		if (MREF(inum) <= 1) {
388 			inum = (u64)-1;
389 			errno = ENOENT;
390 		}
391 		if (ntfs_inode_close(dir_ni)
392 		    || (inum == (u64)-1))
393 			ino = (u64)-1;
394 		else
395 			ino = MREF(inum);
396 	}
397 	return (ino);
398 }
399 
400 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
401 
402 /*
403  *		Check access to parent directory
404  *
405  *	file inode is only opened when not fed in and S_ISVTX is requested,
406  *	when already open and S_ISVTX, it *HAS TO* be fed in.
407  *
408  *	returns 1 if allowed,
409  *		0 if not allowed or some error occurred (errno tells why)
410  */
411 
ntfs_allowed_dir_access(struct SECURITY_CONTEXT * scx,ntfs_inode * dir_ni,fuse_ino_t ino,ntfs_inode * ni,mode_t accesstype)412 static int ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
413 			ntfs_inode *dir_ni, fuse_ino_t ino,
414 			ntfs_inode *ni, mode_t accesstype)
415 {
416 	int allowed;
417 	ntfs_inode *ni2;
418 	struct stat stbuf;
419 
420 	allowed = ntfs_allowed_access(scx, dir_ni, accesstype);
421 		/*
422 		 * for an not-owned sticky directory, have to
423 		 * check whether file itself is owned
424 		 */
425 	if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX))
426 	   && (allowed == 2)) {
427 		if (ni)
428 			ni2 = ni;
429 		else
430 			ni2 = ntfs_inode_open(ctx->vol, INODE(ino));
431 		allowed = 0;
432 		if (ni2) {
433 			allowed = (ntfs_get_owner_mode(scx,ni2,&stbuf) >= 0)
434 				&& (stbuf.st_uid == scx->uid);
435 			if (!ni)
436 				ntfs_inode_close(ni2);
437 		}
438 	}
439 	return (allowed);
440 }
441 
442 #endif /* !KERNELPERMS | (POSIXACLS & !KERNELACLS) */
443 
444 /**
445  * ntfs_fuse_statfs - return information about mounted NTFS volume
446  * @path:	ignored (but fuse requires it)
447  * @sfs:	statfs structure in which to return the information
448  *
449  * Return information about the mounted NTFS volume @sb in the statfs structure
450  * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
451  * called). We interpret the values to be correct of the moment in time at
452  * which we are called. Most values are variable otherwise and this isn't just
453  * the free values but the totals as well. For example we can increase the
454  * total number of file nodes if we run out and we can keep doing this until
455  * there is no more space on the volume left at all.
456  *
457  * This code based on ntfs_statfs from ntfs kernel driver.
458  *
459  * Returns 0 on success or -errno on error.
460  */
461 
ntfs_fuse_statfs(fuse_req_t req,fuse_ino_t ino)462 static void ntfs_fuse_statfs(fuse_req_t req,
463 			fuse_ino_t ino __attribute__((unused)))
464 {
465 	struct statvfs sfs;
466 	s64 size;
467 	int delta_bits;
468 	ntfs_volume *vol;
469 
470 	vol = ctx->vol;
471 	if (vol) {
472 	/*
473 	 * File system block size. Used to calculate used/free space by df.
474 	 * Incorrectly documented as "optimal transfer block size".
475 	 */
476 		sfs.f_bsize = vol->cluster_size;
477 
478 	/* Fundamental file system block size, used as the unit. */
479 		sfs.f_frsize = vol->cluster_size;
480 
481 	/*
482 	 * Total number of blocks on file system in units of f_frsize.
483 	 * Since inodes are also stored in blocks ($MFT is a file) hence
484 	 * this is the number of clusters on the volume.
485 	 */
486 		sfs.f_blocks = vol->nr_clusters;
487 
488 	/* Free blocks available for all and for non-privileged processes. */
489 		size = vol->free_clusters;
490 		if (size < 0)
491 			size = 0;
492 		sfs.f_bavail = sfs.f_bfree = size;
493 
494 	/* Free inodes on the free space */
495 		delta_bits = vol->cluster_size_bits - vol->mft_record_size_bits;
496 		if (delta_bits >= 0)
497 			size <<= delta_bits;
498 		else
499 			size >>= -delta_bits;
500 
501 	/* Number of inodes at this point in time. */
502 		sfs.f_files = (vol->mftbmp_na->allocated_size << 3) + size;
503 
504 	/* Free inodes available for all and for non-privileged processes. */
505 		size += vol->free_mft_records;
506 		if (size < 0)
507 			size = 0;
508 		sfs.f_ffree = sfs.f_favail = size;
509 
510 	/* Maximum length of filenames. */
511 		sfs.f_namemax = NTFS_MAX_NAME_LEN;
512 		fuse_reply_statfs(req, &sfs);
513 	} else
514 		fuse_reply_err(req, ENODEV);
515 
516 }
517 
set_fuse_error(int * err)518 static void set_fuse_error(int *err)
519 {
520 	if (!*err)
521 		*err = -errno;
522 }
523 
524 #if 0 && (defined(__APPLE__) || defined(__DARWIN__)) /* Unfinished. */
525 static int ntfs_macfuse_getxtimes(const char *org_path,
526 		struct timespec *bkuptime, struct timespec *crtime)
527 {
528 	int res = 0;
529 	ntfs_inode *ni;
530 	char *path = NULL;
531 	ntfschar *stream_name;
532 	int stream_name_len;
533 
534 	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
535 	if (stream_name_len < 0)
536 		return stream_name_len;
537 	memset(bkuptime, 0, sizeof(struct timespec));
538 	memset(crtime, 0, sizeof(struct timespec));
539 	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
540 	if (!ni) {
541 		res = -errno;
542 		goto exit;
543 	}
544 
545 	/* We have no backup timestamp in NTFS. */
546 	crtime->tv_sec = ni->creation_time;
547 exit:
548 	if (ntfs_inode_close(ni))
549 		set_fuse_error(&res);
550 	free(path);
551 	if (stream_name_len)
552 		free(stream_name);
553 	return res;
554 }
555 
556 int ntfs_macfuse_setcrtime(const char *path, const struct timespec *tv)
557 {
558 	ntfs_inode *ni;
559 	int res = 0;
560 
561 	if (ntfs_fuse_is_named_data_stream(path))
562 		return -EINVAL; /* n/a for named data streams. */
563 	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
564 	if (!ni)
565 		return -errno;
566 
567 	if (tv) {
568 		ni->creation_time = tv->tv_sec;
569 		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
570 	}
571 
572 	if (ntfs_inode_close(ni))
573 		set_fuse_error(&res);
574 	return res;
575 }
576 
577 int ntfs_macfuse_setbkuptime(const char *path, const struct timespec *tv)
578 {
579 	ntfs_inode *ni;
580 	int res = 0;
581 
582 	if (ntfs_fuse_is_named_data_stream(path))
583 		return -EINVAL; /* n/a for named data streams. */
584 	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
585 	if (!ni)
586 		return -errno;
587 
588 	/*
589 	 * Only pretending to set backup time successfully to please the APIs of
590 	 * Mac OS X. In reality, NTFS has no backup time.
591 	 */
592 
593 	if (ntfs_inode_close(ni))
594 		set_fuse_error(&res);
595 	return res;
596 }
597 
598 int ntfs_macfuse_setchgtime(const char *path, const struct timespec *tv)
599 {
600 	ntfs_inode *ni;
601 	int res = 0;
602 
603 	if (ntfs_fuse_is_named_data_stream(path))
604 		return -EINVAL; /* n/a for named data streams. */
605 	ni = ntfs_pathname_to_inode(ctx-&gt;vol, NULL, path);
606 	if (!ni)
607 		return -errno;
608 
609 	if (tv) {
610 		ni-&gt;last_mft_change_time = tv-&gt;tv_sec;
611 		ntfs_fuse_update_times(ni, 0);
612 	}
613 
614 	if (ntfs_inode_close(ni))
615 		set_fuse_error(&amp;res);
616 	return res;
617 }
618 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
619 
ntfs_init(void * userdata,struct fuse_conn_info * conn)620 static void ntfs_init(void *userdata __attribute__((unused)),
621 			struct fuse_conn_info *conn)
622 {
623 #if defined(__APPLE__) || defined(__DARWIN__)
624 	FUSE_ENABLE_XTIMES(conn);
625 #endif
626 #ifdef FUSE_CAP_DONT_MASK
627 		/* request umask not to be enforced by fuse */
628 	conn->want |= FUSE_CAP_DONT_MASK;
629 #endif /* defined FUSE_CAP_DONT_MASK */
630 #if POSIXACLS & KERNELACLS
631 		/* request ACLs to be checked by kernel */
632 	conn->want |= FUSE_CAP_POSIX_ACL;
633 #endif /* POSIXACLS & KERNELACLS */
634 #ifdef FUSE_CAP_BIG_WRITES
635 	if (ctx->big_writes
636 	    && ((ctx->vol->nr_clusters << ctx->vol->cluster_size_bits)
637 			>= SAFE_CAPACITY_FOR_BIG_WRITES))
638 		conn->want |= FUSE_CAP_BIG_WRITES;
639 #endif
640 #ifdef FUSE_CAP_IOCTL_DIR
641 	conn->want |= FUSE_CAP_IOCTL_DIR;
642 #endif /* defined(FUSE_CAP_IOCTL_DIR) */
643 }
644 
645 #ifndef DISABLE_PLUGINS
646 
647 /*
648  *		Define attributes for a junction or symlink
649  *		(internal plugin)
650  */
651 
junction_getstat(ntfs_inode * ni,const REPARSE_POINT * reparse,struct stat * stbuf)652 static int junction_getstat(ntfs_inode *ni,
653 			const REPARSE_POINT *reparse __attribute__((unused)),
654 			struct stat *stbuf)
655 {
656 	char *target;
657 	int res;
658 
659 	errno = 0;
660 	target = ntfs_make_symlink(ni, ctx->abs_mnt_point);
661 		/*
662 		 * If the reparse point is not a valid
663 		 * directory junction, and there is no error
664 		 * we still display as a symlink
665 		 */
666 	if (target || (errno == EOPNOTSUPP)) {
667 		if (target)
668 			stbuf->st_size = strlen(target);
669 		else
670 			stbuf->st_size = ntfs_bad_reparse_lth;
671 		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
672 		stbuf->st_mode = S_IFLNK;
673 		free(target);
674 		res = 0;
675 	} else {
676 		res = -errno;
677 	}
678 	return (res);
679 }
680 
wsl_getstat(ntfs_inode * ni,const REPARSE_POINT * reparse,struct stat * stbuf)681 static int wsl_getstat(ntfs_inode *ni, const REPARSE_POINT *reparse,
682 			struct stat *stbuf)
683 {
684 	dev_t rdev;
685 	int res;
686 
687 	res = ntfs_reparse_check_wsl(ni, reparse);
688 	if (!res) {
689 		switch (reparse->reparse_tag) {
690 		case IO_REPARSE_TAG_AF_UNIX :
691 			stbuf->st_mode = S_IFSOCK;
692 			break;
693 		case IO_REPARSE_TAG_LX_FIFO :
694 			stbuf->st_mode = S_IFIFO;
695 			break;
696 		case IO_REPARSE_TAG_LX_CHR :
697 			stbuf->st_mode = S_IFCHR;
698 			res = ntfs_ea_check_wsldev(ni, &rdev);
699 			stbuf->st_rdev = rdev;
700 			break;
701 		case IO_REPARSE_TAG_LX_BLK :
702 			stbuf->st_mode = S_IFBLK;
703 			res = ntfs_ea_check_wsldev(ni, &rdev);
704 			stbuf->st_rdev = rdev;
705 			break;
706 		default :
707 			stbuf->st_size = ntfs_bad_reparse_lth;
708 			stbuf->st_mode = S_IFLNK;
709 			break;
710 		}
711 	}
712 		/*
713 		 * If the reparse point is not a valid wsl special file
714 		 * we display as a symlink
715 		 */
716 	if (res) {
717 		stbuf->st_size = ntfs_bad_reparse_lth;
718 		stbuf->st_mode = S_IFLNK;
719 		res = 0;
720 	}
721 	return (res);
722 }
723 
724 /*
725  *		Apply permission masks to st_mode returned by reparse handler
726  */
727 
apply_umask(struct stat * stbuf)728 static void apply_umask(struct stat *stbuf)
729 {
730 	switch (stbuf->st_mode & S_IFMT) {
731 	case S_IFREG :
732 		stbuf->st_mode &= ~ctx->fmask;
733 		break;
734 	case S_IFDIR :
735 		stbuf->st_mode &= ~ctx->dmask;
736 		break;
737 	case S_IFLNK :
738 		stbuf->st_mode = (stbuf->st_mode & S_IFMT) | 0777;
739 		break;
740 	default :
741 		break;
742 	}
743 }
744 
745 #endif /* DISABLE_PLUGINS */
746 
ntfs_fuse_getstat(struct SECURITY_CONTEXT * scx,ntfs_inode * ni,struct stat * stbuf)747 static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
748 				ntfs_inode *ni, struct stat *stbuf)
749 {
750 	int res = 0;
751 	ntfs_attr *na;
752 	BOOL withusermapping;
753 
754 	memset(stbuf, 0, sizeof(struct stat));
755 	withusermapping = (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL);
756 	stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
757 	if (ctx->posix_nlink
758 	    && !(ni->flags & FILE_ATTR_REPARSE_POINT))
759 		stbuf->st_nlink = ntfs_dir_link_cnt(ni);
760 	if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
761 	    || (ni->flags & FILE_ATTR_REPARSE_POINT)) {
762 		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
763 #ifndef DISABLE_PLUGINS
764 			const plugin_operations_t *ops;
765 			REPARSE_POINT *reparse;
766 
767 			res = CALL_REPARSE_PLUGIN(ni, getattr, stbuf);
768 			if (!res) {
769 				apply_umask(stbuf);
770 			} else {
771 				stbuf->st_size = ntfs_bad_reparse_lth;
772 				stbuf->st_blocks =
773 					(ni->allocated_size + 511) >> 9;
774 				stbuf->st_mode = S_IFLNK;
775 				res = 0;
776 			}
777 			goto ok;
778 #else /* DISABLE_PLUGINS */
779 			char *target;
780 
781 			errno = 0;
782 			target = ntfs_make_symlink(ni, ctx->abs_mnt_point);
783 				/*
784 				 * If the reparse point is not a valid
785 				 * directory junction, and there is no error
786 				 * we still display as a symlink
787 				 */
788 			if (target || (errno == EOPNOTSUPP)) {
789 				if (target)
790 					stbuf->st_size = strlen(target);
791 				else
792 					stbuf->st_size = ntfs_bad_reparse_lth;
793 				stbuf->st_blocks =
794 					(ni->allocated_size + 511) >> 9;
795 				stbuf->st_nlink =
796 					le16_to_cpu(ni->mrec->link_count);
797 				stbuf->st_mode = S_IFLNK;
798 				free(target);
799 			} else {
800 				res = -errno;
801 				goto exit;
802 			}
803 #endif /* DISABLE_PLUGINS */
804 		} else {
805 			/* Directory. */
806 			stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);
807 			/* get index size, if not known */
808 			if (!test_nino_flag(ni, KnownSize)) {
809 				na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION,
810 						NTFS_INDEX_I30, 4);
811 				if (na) {
812 					ni->data_size = na->data_size;
813 					ni->allocated_size = na->allocated_size;
814 					set_nino_flag(ni, KnownSize);
815 					ntfs_attr_close(na);
816 				}
817 			}
818 			stbuf->st_size = ni->data_size;
819 			stbuf->st_blocks = ni->allocated_size >> 9;
820 			if (!ctx->posix_nlink)
821 				stbuf->st_nlink = 1;	/* Make find(1) work */
822 		}
823 	} else {
824 		/* Regular or Interix (INTX) file. */
825 		stbuf->st_mode = S_IFREG;
826 		stbuf->st_size = ni->data_size;
827 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
828 		/*
829 		 * return data size rounded to next 512 byte boundary for
830 		 * encrypted files to include padding required for decryption
831 		 * also include 2 bytes for padding info
832 		*/
833 		if (ctx->efs_raw
834 		    && (ni->flags & FILE_ATTR_ENCRYPTED)
835 		    && ni->data_size)
836 			stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
837 #endif /* HAVE_SETXATTR */
838 		/*
839 		 * Temporary fix to make ActiveSync work via Samba 3.0.
840 		 * See more on the ntfs-3g-devel list.
841 		 */
842 		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
843 		if (ni->flags & FILE_ATTR_SYSTEM) {
844 			na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
845 			if (!na) {
846 				stbuf->st_ino = ni->mft_no;
847 				goto nodata;
848 			}
849 			/* Check whether it's Interix FIFO or socket. */
850 			if (!(ni->flags & FILE_ATTR_HIDDEN)) {
851 				/* FIFO. */
852 				if (na->data_size == 0)
853 					stbuf->st_mode = S_IFIFO;
854 				/* Socket link. */
855 				if (na->data_size == 1)
856 					stbuf->st_mode = S_IFSOCK;
857 			}
858 			/*
859 			 * Check whether it's Interix symbolic link, block or
860 			 * character device.
861 			 */
862 			if ((u64)na->data_size <= sizeof(INTX_FILE_TYPES)
863 					+ sizeof(ntfschar) * PATH_MAX
864 				&& (u64)na->data_size >
865 					sizeof(INTX_FILE_TYPES)) {
866 				INTX_FILE *intx_file;
867 
868 				intx_file =
869 					(INTX_FILE*)ntfs_malloc(na->data_size);
870 				if (!intx_file) {
871 					res = -errno;
872 					ntfs_attr_close(na);
873 					goto exit;
874 				}
875 				if (ntfs_attr_pread(na, 0, na->data_size,
876 						intx_file) != na->data_size) {
877 					res = -errno;
878 					free(intx_file);
879 					ntfs_attr_close(na);
880 					goto exit;
881 				}
882 				if (intx_file->magic == INTX_BLOCK_DEVICE &&
883 						na->data_size == (s64)offsetof(
884 						INTX_FILE, device_end)) {
885 					stbuf->st_mode = S_IFBLK;
886 					stbuf->st_rdev = makedev(le64_to_cpu(
887 							intx_file->major),
888 							le64_to_cpu(
889 							intx_file->minor));
890 				}
891 				if (intx_file->magic == INTX_CHARACTER_DEVICE &&
892 						na->data_size == (s64)offsetof(
893 						INTX_FILE, device_end)) {
894 					stbuf->st_mode = S_IFCHR;
895 					stbuf->st_rdev = makedev(le64_to_cpu(
896 							intx_file->major),
897 							le64_to_cpu(
898 							intx_file->minor));
899 				}
900 				if (intx_file->magic == INTX_SYMBOLIC_LINK) {
901 					char *target = NULL;
902 					int len;
903 
904 					/* st_size should be set to length of
905 					 * symlink target as multibyte string */
906 					len = ntfs_ucstombs(
907 							intx_file->target,
908 							(na->data_size -
909 							    offsetof(INTX_FILE,
910 								     target)) /
911 							       sizeof(ntfschar),
912 							     &target, 0);
913 					if (len < 0) {
914 						res = -errno;
915 						free(intx_file);
916 						ntfs_attr_close(na);
917 						goto exit;
918 					}
919 					free(target);
920 					stbuf->st_mode = S_IFLNK;
921 					stbuf->st_size = len;
922 				}
923 				free(intx_file);
924 			}
925 			ntfs_attr_close(na);
926 		}
927 		stbuf->st_mode |= (0777 & ~ctx->fmask);
928 	}
929 #ifndef DISABLE_PLUGINS
930 ok:
931 #endif /* DISABLE_PLUGINS */
932 	if (withusermapping) {
933 		if (ntfs_get_owner_mode(scx,ni,stbuf) < 0)
934 			set_fuse_error(&res);
935 	} else {
936 		stbuf->st_uid = ctx->uid;
937 		stbuf->st_gid = ctx->gid;
938 	}
939 	if (S_ISLNK(stbuf->st_mode))
940 		stbuf->st_mode |= 0777;
941 nodata :
942 	stbuf->st_ino = ni->mft_no;
943 #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
944 	stbuf->st_atimespec = ntfs2timespec(ni->last_access_time);
945 	stbuf->st_ctimespec = ntfs2timespec(ni->last_mft_change_time);
946 	stbuf->st_mtimespec = ntfs2timespec(ni->last_data_change_time);
947 #elif defined(HAVE_STRUCT_STAT_ST_ATIM)
948 	stbuf->st_atim = ntfs2timespec(ni->last_access_time);
949 	stbuf->st_ctim = ntfs2timespec(ni->last_mft_change_time);
950 	stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
951 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
952 	{
953 	struct timespec ts;
954 
955 	ts = ntfs2timespec(ni->last_access_time);
956 	stbuf->st_atime = ts.tv_sec;
957 	stbuf->st_atimensec = ts.tv_nsec;
958 	ts = ntfs2timespec(ni->last_mft_change_time);
959 	stbuf->st_ctime = ts.tv_sec;
960 	stbuf->st_ctimensec = ts.tv_nsec;
961 	ts = ntfs2timespec(ni->last_data_change_time);
962 	stbuf->st_mtime = ts.tv_sec;
963 	stbuf->st_mtimensec = ts.tv_nsec;
964 	}
965 #else
966 #warning "No known way to set nanoseconds in struct stat !"
967 	{
968 	struct timespec ts;
969 
970 	ts = ntfs2timespec(ni->last_access_time);
971 	stbuf->st_atime = ts.tv_sec;
972 	ts = ntfs2timespec(ni->last_mft_change_time);
973 	stbuf->st_ctime = ts.tv_sec;
974 	ts = ntfs2timespec(ni->last_data_change_time);
975 	stbuf->st_mtime = ts.tv_sec;
976 	}
977 #endif
978 exit:
979 	return (res);
980 }
981 
ntfs_fuse_getattr(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)982 static void ntfs_fuse_getattr(fuse_req_t req, fuse_ino_t ino,
983 			struct fuse_file_info *fi __attribute__((unused)))
984 {
985 	int res;
986 	ntfs_inode *ni;
987 	struct stat stbuf;
988 	struct SECURITY_CONTEXT security;
989 
990 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
991 	if (!ni)
992 		res = -errno;
993 	else {
994 		ntfs_fuse_fill_security_context(req, &security);
995 		res = ntfs_fuse_getstat(&security, ni, &stbuf);
996 		if (ntfs_inode_close(ni))
997 			set_fuse_error(&res);
998 	}
999 	if (!res)
1000 		fuse_reply_attr(req, &stbuf, ATTR_TIMEOUT);
1001 	else
1002 		fuse_reply_err(req, -res);
1003 }
1004 
ntfs_fuse_fillstat(struct SECURITY_CONTEXT * scx,struct fuse_entry_param * pentry,u64 iref)1005 static __inline__ BOOL ntfs_fuse_fillstat(struct SECURITY_CONTEXT *scx,
1006 			struct fuse_entry_param *pentry, u64 iref)
1007 {
1008 	ntfs_inode *ni;
1009 	BOOL ok = FALSE;
1010 
1011 	pentry->ino = MREF(iref);
1012 	ni = ntfs_inode_open(ctx->vol, pentry->ino);
1013 	if (ni) {
1014 		if (!ntfs_fuse_getstat(scx, ni, &pentry->attr)) {
1015 			pentry->generation = 1;
1016 			pentry->attr_timeout = ATTR_TIMEOUT;
1017 			pentry->entry_timeout = ENTRY_TIMEOUT;
1018 			ok = TRUE;
1019 		}
1020 		if (ntfs_inode_close(ni))
1021 		       ok = FALSE;
1022 	}
1023 	return (ok);
1024 }
1025 
1026 
ntfs_fuse_lookup(fuse_req_t req,fuse_ino_t parent,const char * name)1027 static void ntfs_fuse_lookup(fuse_req_t req, fuse_ino_t parent,
1028 			const char *name)
1029 {
1030 	struct SECURITY_CONTEXT security;
1031 	struct fuse_entry_param entry;
1032 	ntfs_inode *dir_ni;
1033 	u64 iref;
1034 	BOOL ok = FALSE;
1035 
1036 	if (strlen(name) < 256) {
1037 		dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
1038 		if (dir_ni) {
1039 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1040 			/*
1041 			 * make sure the parent directory is searchable
1042 			 */
1043 			if (ntfs_fuse_fill_security_context(req, &security)
1044 			    && !ntfs_allowed_access(&security,dir_ni,S_IEXEC)) {
1045 				ntfs_inode_close(dir_ni);
1046 				errno = EACCES;
1047 			} else {
1048 #else
1049 				ntfs_fuse_fill_security_context(req, &security);
1050 #endif
1051 				iref = ntfs_inode_lookup_by_mbsname(dir_ni,
1052 								name);
1053 					/* never return inodes 0 and 1 */
1054 				if (MREF(iref) <= 1) {
1055 					iref = (u64)-1;
1056 					errno = ENOENT;
1057 				}
1058 				ok = !ntfs_inode_close(dir_ni)
1059 					&& (iref != (u64)-1)
1060 					&& ntfs_fuse_fillstat(
1061 						&security,&entry,iref);
1062 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1063 			}
1064 #endif
1065 		}
1066 	} else
1067 		errno = ENAMETOOLONG;
1068 	if (!ok)
1069 		fuse_reply_err(req, errno);
1070 	else
1071 		fuse_reply_entry(req, &entry);
1072 }
1073 
1074 #ifndef DISABLE_PLUGINS
1075 
1076 /*
1077  *		Get the link defined by a junction or symlink
1078  *		(internal plugin)
1079  */
1080 
junction_readlink(ntfs_inode * ni,const REPARSE_POINT * reparse,char ** pbuf)1081 static int junction_readlink(ntfs_inode *ni,
1082 			const REPARSE_POINT *reparse, char **pbuf)
1083 {
1084 	int res;
1085 	le32 tag;
1086 	int lth;
1087 
1088 	errno = 0;
1089 	res = 0;
1090 	*pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
1091 	if (!*pbuf) {
1092 		if (errno == EOPNOTSUPP) {
1093 			*pbuf = (char*)ntfs_malloc(ntfs_bad_reparse_lth + 1);
1094 			if (*pbuf) {
1095 				if (reparse)
1096 					tag = reparse->reparse_tag;
1097 				else
1098 					tag = const_cpu_to_le32(0);
1099 				lth = snprintf(*pbuf, ntfs_bad_reparse_lth + 1,
1100 						ntfs_bad_reparse,
1101 						(long)le32_to_cpu(tag));
1102 				if (lth != ntfs_bad_reparse_lth) {
1103 					free(*pbuf);
1104 					*pbuf = (char*)NULL;
1105 					res = -errno;
1106 				}
1107 			} else
1108 				res = -ENOMEM;
1109 		} else
1110 			res = -errno;
1111 	}
1112 	return (res);
1113 }
1114 
1115 #endif /* DISABLE_PLUGINS */
1116 
ntfs_fuse_readlink(fuse_req_t req,fuse_ino_t ino)1117 static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
1118 {
1119 	ntfs_inode *ni = NULL;
1120 	ntfs_attr *na = NULL;
1121 	INTX_FILE *intx_file = NULL;
1122 	char *buf = (char*)NULL;
1123 	int res = 0;
1124 
1125 	/* Get inode. */
1126 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1127 	if (!ni) {
1128 		res = -errno;
1129 		goto exit;
1130 	}
1131 		/*
1132 		 * Reparse point : analyze as a junction point
1133 		 */
1134 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1135 		REPARSE_POINT *reparse;
1136 		le32 tag;
1137 		int lth;
1138 #ifndef DISABLE_PLUGINS
1139 		const plugin_operations_t *ops;
1140 
1141 		res = CALL_REPARSE_PLUGIN(ni, readlink, &buf);
1142 			/* plugin missing or reparse tag failing the check */
1143 		if (res && ((errno == ELIBACC) || (errno == EINVAL)))
1144 			errno = EOPNOTSUPP;
1145 #else /* DISABLE_PLUGINS */
1146 		errno = 0;
1147 		res = 0;
1148 		buf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
1149 #endif /* DISABLE_PLUGINS */
1150 		if (!buf && (errno == EOPNOTSUPP)) {
1151 			buf = (char*)malloc(ntfs_bad_reparse_lth + 1);
1152 			if (buf) {
1153 				reparse = ntfs_get_reparse_point(ni);
1154 				if (reparse) {
1155 					tag = reparse->reparse_tag;
1156 					free(reparse);
1157 				} else
1158 					tag = const_cpu_to_le32(0);
1159 				lth = snprintf(buf, ntfs_bad_reparse_lth + 1,
1160 						ntfs_bad_reparse,
1161 						(long)le32_to_cpu(tag));
1162 				res = 0;
1163 				if (lth != ntfs_bad_reparse_lth) {
1164 					free(buf);
1165 					buf = (char*)NULL;
1166 				}
1167 			}
1168 		}
1169 		if (!buf)
1170 			res = -errno;
1171  		goto exit;
1172 	}
1173 	/* Sanity checks. */
1174 	if (!(ni->flags & FILE_ATTR_SYSTEM)) {
1175 		res = -EINVAL;
1176 		goto exit;
1177 	}
1178 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1179 	if (!na) {
1180 		res = -errno;
1181 		goto exit;
1182 	}
1183 	if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES)) {
1184 		res = -EINVAL;
1185 		goto exit;
1186 	}
1187 	if ((size_t)na->data_size > sizeof(INTX_FILE_TYPES) +
1188 			sizeof(ntfschar) * PATH_MAX) {
1189 		res = -ENAMETOOLONG;
1190 		goto exit;
1191 	}
1192 	/* Receive file content. */
1193 	intx_file = (INTX_FILE*)ntfs_malloc(na->data_size);
1194 	if (!intx_file) {
1195 		res = -errno;
1196 		goto exit;
1197 	}
1198 	if (ntfs_attr_pread(na, 0, na->data_size, intx_file) != na->data_size) {
1199 		res = -errno;
1200 		goto exit;
1201 	}
1202 	/* Sanity check. */
1203 	if (intx_file->magic != INTX_SYMBOLIC_LINK) {
1204 		res = -EINVAL;
1205 		goto exit;
1206 	}
1207 	/* Convert link from unicode to local encoding. */
1208 	if (ntfs_ucstombs(intx_file->target, (na->data_size -
1209 			offsetof(INTX_FILE, target)) / sizeof(ntfschar),
1210 			&buf, 0) < 0) {
1211 		res = -errno;
1212 		goto exit;
1213 	}
1214 exit:
1215 	if (intx_file)
1216 		free(intx_file);
1217 	if (na)
1218 		ntfs_attr_close(na);
1219 	if (ntfs_inode_close(ni))
1220 		set_fuse_error(&res);
1221 
1222 	if (res < 0)
1223 		fuse_reply_err(req, -res);
1224 	else
1225 		fuse_reply_readlink(req, buf);
1226 	free(buf);
1227 }
1228 
ntfs_fuse_filler(ntfs_fuse_fill_context_t * fill_ctx,const ntfschar * name,const int name_len,const int name_type,const s64 pos,const MFT_REF mref,const unsigned dt_type)1229 static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,
1230 		const ntfschar *name, const int name_len, const int name_type,
1231 		const s64 pos __attribute__((unused)), const MFT_REF mref,
1232 		const unsigned dt_type __attribute__((unused)))
1233 {
1234 	char *filename = NULL;
1235 	int ret = 0;
1236 	int filenamelen = -1;
1237 	size_t sz;
1238 	ntfs_fuse_fill_item_t *current;
1239 	ntfs_fuse_fill_item_t *newone;
1240 
1241 	if (name_type == FILE_NAME_DOS)
1242 		return 0;
1243 
1244 	if ((filenamelen = ntfs_ucstombs(name, name_len, &filename, 0)) < 0) {
1245 		ntfs_log_perror("Filename decoding failed (inode %llu)",
1246 				(unsigned long long)MREF(mref));
1247 		return -1;
1248 	}
1249 		/* never return inodes 0 and 1 */
1250 	if (MREF(mref) > 1) {
1251 		struct stat st = { .st_ino = MREF(mref) };
1252 #ifndef DISABLE_PLUGINS
1253 		ntfs_inode *ni;
1254 #endif /* DISABLE_PLUGINS */
1255 
1256 		switch (dt_type) {
1257 		case NTFS_DT_DIR :
1258 			st.st_mode = S_IFDIR | (0777 & ~ctx->dmask);
1259 			break;
1260 		case NTFS_DT_LNK :
1261 			st.st_mode = S_IFLNK | 0777;
1262 			break;
1263 		case NTFS_DT_FIFO :
1264 			st.st_mode = S_IFIFO;
1265 			break;
1266 		case NTFS_DT_SOCK :
1267 			st.st_mode = S_IFSOCK;
1268 			break;
1269 		case NTFS_DT_BLK :
1270 			st.st_mode = S_IFBLK;
1271 			break;
1272 		case NTFS_DT_CHR :
1273 			st.st_mode = S_IFCHR;
1274 			break;
1275 		case NTFS_DT_REPARSE :
1276 			st.st_mode = S_IFLNK | 0777; /* default */
1277 #ifndef DISABLE_PLUGINS
1278 			/* get emulated type from plugin if available */
1279 			ni = ntfs_inode_open(ctx->vol, mref);
1280 			if (ni && (ni->flags & FILE_ATTR_REPARSE_POINT)) {
1281 				const plugin_operations_t *ops;
1282 				REPARSE_POINT *reparse;
1283 				int res;
1284 
1285 				res = CALL_REPARSE_PLUGIN(ni, getattr, &st);
1286 				if (!res)
1287 					apply_umask(&st);
1288 				else
1289 					st.st_mode = S_IFLNK;
1290 			}
1291 			if (ni)
1292 				ntfs_inode_close(ni);
1293 #endif /* DISABLE_PLUGINS */
1294 			break;
1295 		default : /* unexpected types shown as plain files */
1296 		case NTFS_DT_REG :
1297 			st.st_mode = S_IFREG | (0777 & ~ctx->fmask);
1298 			break;
1299 		}
1300 
1301 #if defined(__APPLE__) || defined(__DARWIN__)
1302 		/*
1303 		 * Returning file names larger than MAXNAMLEN (255) bytes
1304 		 * causes Darwin/Mac OS X to bug out and skip the entry.
1305 		 */
1306 		if (filenamelen > MAXNAMLEN) {
1307 			ntfs_log_debug("Truncating %d byte filename to "
1308 				       "%d bytes.\n", filenamelen, MAXNAMLEN);
1309 			ntfs_log_debug("  before: '%s'\n", filename);
1310 			memset(filename + MAXNAMLEN, 0, filenamelen - MAXNAMLEN);
1311 			ntfs_log_debug("   after: '%s'\n", filename);
1312 		}
1313 #elif defined(__sun) && defined (__SVR4)
1314 		/*
1315 		 * Returning file names larger than MAXNAMELEN (256) bytes
1316 		 * causes Solaris/Illumos to return an I/O error from the system
1317 		 * call.
1318 		 * However we also need space for a terminating NULL, or user
1319 		 * space tools will bug out since they expect a NULL terminator.
1320 		 * Effectively the maximum length of a file name is MAXNAMELEN -
1321 		 * 1 (255).
1322 		 */
1323 		if (filenamelen > (MAXNAMELEN - 1)) {
1324 			ntfs_log_debug("Truncating %d byte filename to %d "
1325 				"bytes.\n", filenamelen, MAXNAMELEN - 1);
1326 			ntfs_log_debug("  before: '%s'\n", filename);
1327 			memset(&filename[MAXNAMELEN - 1], 0,
1328 				filenamelen - (MAXNAMELEN - 1));
1329 			ntfs_log_debug("   after: '%s'\n", filename);
1330 		}
1331 #endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
1332 
1333 		current = fill_ctx->last;
1334 		sz = fuse_add_direntry(fill_ctx->req,
1335 				&current->buf[current->off],
1336 				current->bufsize - current->off,
1337 				filename, &st, current->off + fill_ctx->off);
1338 		if (!sz || ((current->off + sz) > current->bufsize)) {
1339 			newone = (ntfs_fuse_fill_item_t*)ntfs_malloc
1340 				(sizeof(ntfs_fuse_fill_item_t)
1341 				     + current->bufsize);
1342 			if (newone) {
1343 				newone->off = 0;
1344 				newone->bufsize = current->bufsize;
1345 				newone->next = (ntfs_fuse_fill_item_t*)NULL;
1346 				current->next = newone;
1347 				fill_ctx->last = newone;
1348 				fill_ctx->off += current->off;
1349 				current = newone;
1350 				sz = fuse_add_direntry(fill_ctx->req,
1351 					current->buf,
1352 					current->bufsize - current->off,
1353 					filename, &st, fill_ctx->off);
1354 				if (!sz) {
1355 					errno = EIO;
1356 					ntfs_log_error("Could not add a"
1357 						" directory entry (inode %lld)\n",
1358 						(unsigned long long)MREF(mref));
1359 				}
1360 			} else {
1361 				sz = 0;
1362 				errno = ENOMEM;
1363 			}
1364 		}
1365 		if (sz) {
1366 			current->off += sz;
1367 		} else {
1368 			ret = -1;
1369 		}
1370 	}
1371 
1372 	free(filename);
1373 	return ret;
1374 }
1375 
ntfs_fuse_opendir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)1376 static void ntfs_fuse_opendir(fuse_req_t req, fuse_ino_t ino,
1377 			 struct fuse_file_info *fi)
1378 {
1379 	int res = 0;
1380 	ntfs_inode *ni;
1381 	int accesstype;
1382 	ntfs_fuse_fill_context_t *fill;
1383 	struct SECURITY_CONTEXT security;
1384 
1385 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1386 	if (ni) {
1387 		if (ntfs_fuse_fill_security_context(req, &security)) {
1388 			if (fi->flags & O_WRONLY)
1389 				accesstype = S_IWRITE;
1390 			else
1391 				if (fi->flags & O_RDWR)
1392 					accesstype = S_IWRITE | S_IREAD;
1393 				else
1394 					accesstype = S_IREAD;
1395 			if (!ntfs_allowed_access(&security,ni,accesstype))
1396 				res = -EACCES;
1397 		}
1398 		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1399 #ifndef DISABLE_PLUGINS
1400 			const plugin_operations_t *ops;
1401 			REPARSE_POINT *reparse;
1402 
1403 			fi->fh = 0;
1404 			res = CALL_REPARSE_PLUGIN(ni, opendir, fi);
1405 #else /* DISABLE_PLUGINS */
1406 			res = -EOPNOTSUPP;
1407 #endif /* DISABLE_PLUGINS */
1408 		}
1409 		if (ntfs_inode_close(ni))
1410 			set_fuse_error(&res);
1411 		if (!res) {
1412 			fill = (ntfs_fuse_fill_context_t*)
1413 				ntfs_malloc(sizeof(ntfs_fuse_fill_context_t));
1414 			if (!fill)
1415 				res = -errno;
1416 			else {
1417 				fill->first = fill->last
1418 					= (ntfs_fuse_fill_item_t*)NULL;
1419 				fill->filled = FALSE;
1420 				fill->ino = ino;
1421 				fill->off = 0;
1422 #ifndef DISABLE_PLUGINS
1423 				fill->fh = fi->fh;
1424 #endif /* DISABLE_PLUGINS */
1425 			}
1426 			fi->fh = (long)fill;
1427 		}
1428 	} else
1429 		res = -errno;
1430 	if (!res)
1431 		fuse_reply_open(req, fi);
1432 	else
1433 		fuse_reply_err(req, -res);
1434 }
1435 
1436 
ntfs_fuse_releasedir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)1437 static void ntfs_fuse_releasedir(fuse_req_t req,
1438 			fuse_ino_t ino __attribute__((unused)),
1439 			struct fuse_file_info *fi)
1440 {
1441 #ifndef DISABLE_PLUGINS
1442 	struct fuse_file_info ufi;
1443 	ntfs_inode *ni;
1444 #endif /* DISABLE_PLUGINS */
1445 	ntfs_fuse_fill_context_t *fill;
1446 	ntfs_fuse_fill_item_t *current;
1447 	int res;
1448 
1449 	res = 0;
1450 	fill = (ntfs_fuse_fill_context_t*)(long)fi->fh;
1451 	if (fill && (fill->ino == ino)) {
1452 			/* make sure to clear results */
1453 		current = fill->first;
1454 		while (current) {
1455 			current = current->next;
1456 			free(fill->first);
1457 			fill->first = current;
1458 		}
1459 #ifndef DISABLE_PLUGINS
1460 		if (fill->fh) {
1461 			const plugin_operations_t *ops;
1462 			REPARSE_POINT *reparse;
1463 
1464 			ni = ntfs_inode_open(ctx->vol, INODE(ino));
1465 			if (ni) {
1466 				if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1467 					memcpy(&ufi, fi, sizeof(ufi));
1468 					ufi.fh = fill->fh;
1469 					res = CALL_REPARSE_PLUGIN(ni, release,
1470 								 &ufi);
1471 				}
1472 				if (ntfs_inode_close(ni) && !res)
1473 					res = -errno;
1474 			} else
1475 				res = -errno;
1476 		}
1477 #endif /* DISABLE_PLUGINS */
1478 		fill->ino = 0;
1479 		free(fill);
1480 	}
1481 	fuse_reply_err(req, -res);
1482 }
1483 
ntfs_fuse_readdir(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * fi)1484 static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1485 			off_t off __attribute__((unused)),
1486 			struct fuse_file_info *fi __attribute__((unused)))
1487 {
1488 #ifndef DISABLE_PLUGINS
1489 	struct fuse_file_info ufi;
1490 #endif /* DISABLE_PLUGINS */
1491 	ntfs_fuse_fill_item_t *first;
1492 	ntfs_fuse_fill_item_t *current;
1493 	ntfs_fuse_fill_context_t *fill;
1494 	ntfs_inode *ni;
1495 	s64 pos = 0;
1496 	int err = 0;
1497 
1498 	fill = (ntfs_fuse_fill_context_t*)(long)fi->fh;
1499 	if (fill && (fill->ino == ino)) {
1500 		if (fill->filled && !off) {
1501 			/* Rewinding : make sure to clear existing results */
1502 			current = fill->first;
1503 			while (current) {
1504 				current = current->next;
1505 				free(fill->first);
1506 				fill->first = current;
1507 			}
1508 			fill->filled = FALSE;
1509 		}
1510 		if (!fill->filled) {
1511 				/* initial call : build the full list */
1512 			current = (ntfs_fuse_fill_item_t*)NULL;
1513 			first = (ntfs_fuse_fill_item_t*)ntfs_malloc
1514 				(sizeof(ntfs_fuse_fill_item_t) + size);
1515 			if (first) {
1516 				first->bufsize = size;
1517 				first->off = 0;
1518 				first->next = (ntfs_fuse_fill_item_t*)NULL;
1519 				fill->req = req;
1520 				fill->first = first;
1521 				fill->last = first;
1522 				fill->off = 0;
1523 				ni = ntfs_inode_open(ctx->vol,INODE(ino));
1524 				if (!ni)
1525 					err = -errno;
1526 				else {
1527 					if (ni->flags
1528 						& FILE_ATTR_REPARSE_POINT) {
1529 #ifndef DISABLE_PLUGINS
1530 						const plugin_operations_t *ops;
1531 						REPARSE_POINT *reparse;
1532 
1533 						memcpy(&ufi, fi, sizeof(ufi));
1534 						ufi.fh = fill->fh;
1535 						err = CALL_REPARSE_PLUGIN(ni,
1536 							readdir, &pos, fill,
1537 							(ntfs_filldir_t)
1538 							ntfs_fuse_filler, &ufi);
1539 #else /* DISABLE_PLUGINS */
1540 						err = -EOPNOTSUPP;
1541 #endif /* DISABLE_PLUGINS */
1542 					} else {
1543 						if (ntfs_readdir(ni, &pos, fill,
1544 							(ntfs_filldir_t)
1545 							ntfs_fuse_filler))
1546 							err = -errno;
1547 					}
1548 					fill->filled = TRUE;
1549 					ntfs_fuse_update_times(ni,
1550 						NTFS_UPDATE_ATIME);
1551 					if (ntfs_inode_close(ni))
1552 						set_fuse_error(&err);
1553 				}
1554 				if (!err) {
1555 					off_t loc = 0;
1556 				/*
1557 				 * In some circumstances, the queue gets
1558 				 * reinitialized by releasedir() + opendir(),
1559 				 * apparently always on end of partial buffer.
1560 				 * Files may be missing or duplicated.
1561 				 */
1562 					while (first
1563 					    && ((loc < off) || !first->off)) {
1564 						loc += first->off;
1565 						fill->first = first->next;
1566 						free(first);
1567 						first = fill->first;
1568 					}
1569 					current = first;
1570 				}
1571 			} else
1572 				err = -errno;
1573 		} else {
1574 			/* subsequent call : return next non-empty buffer */
1575 			current = fill->first;
1576 			while (current && !current->off) {
1577 				current = current->next;
1578 				free(fill->first);
1579 				fill->first = current;
1580 			}
1581 		}
1582 		if (!err) {
1583 			if (current) {
1584 				fuse_reply_buf(req, current->buf, current->off);
1585 				fill->first = current->next;
1586 				free(current);
1587 			} else {
1588 				fuse_reply_buf(req, (char*)NULL, 0);
1589 				/* reply sent, now must exit with no error */
1590 			}
1591 		}
1592 	} else {
1593 		errno = EIO;
1594 		err = -errno;
1595 		ntfs_log_error("Uninitialized fuse_readdir()\n");
1596 	}
1597 	if (err)
1598 		fuse_reply_err(req, -err);
1599 }
1600 
ntfs_fuse_open(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)1601 static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino,
1602 		      struct fuse_file_info *fi)
1603 {
1604 	ntfs_inode *ni;
1605 	ntfs_attr *na = NULL;
1606 	struct open_file *of;
1607 	int state = 0;
1608 	int res = 0;
1609 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1610 	int accesstype;
1611 	struct SECURITY_CONTEXT security;
1612 #endif
1613 
1614 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1615 	if (ni) {
1616 		if (!(ni->flags & FILE_ATTR_REPARSE_POINT)) {
1617 			na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1618 			if (!na) {
1619 				res = -errno;
1620 				goto close;
1621 			}
1622 		}
1623 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1624 		if (ntfs_fuse_fill_security_context(req, &security)) {
1625 			if (fi->flags & O_WRONLY)
1626 				accesstype = S_IWRITE;
1627 			else
1628 				if (fi->flags & O_RDWR)
1629 					accesstype = S_IWRITE | S_IREAD;
1630 				else
1631 					accesstype = S_IREAD;
1632 		     /* check whether requested access is allowed */
1633 			if (!ntfs_allowed_access(&security,
1634 					ni,accesstype))
1635 				res = -EACCES;
1636 		}
1637 #endif
1638 		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1639 #ifndef DISABLE_PLUGINS
1640 			const plugin_operations_t *ops;
1641 			REPARSE_POINT *reparse;
1642 
1643 			fi->fh = 0;
1644 			res = CALL_REPARSE_PLUGIN(ni, open, fi);
1645 			if (!res && fi->fh) {
1646 				state = CLOSE_REPARSE;
1647 			}
1648 #else /* DISABLE_PLUGINS */
1649 			res = -EOPNOTSUPP;
1650 #endif /* DISABLE_PLUGINS */
1651 			goto close;
1652 		}
1653 		if ((res >= 0)
1654 		    && (fi->flags & (O_WRONLY | O_RDWR))) {
1655 		/* mark a future need to compress the last chunk */
1656 			if (na->data_flags & ATTR_COMPRESSION_MASK)
1657 				state |= CLOSE_COMPRESSED;
1658 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
1659 		/* mark a future need to fixup encrypted inode */
1660 			if (ctx->efs_raw
1661 			    && !(na->data_flags & ATTR_IS_ENCRYPTED)
1662 			    && (ni->flags & FILE_ATTR_ENCRYPTED))
1663 				state |= CLOSE_ENCRYPTED;
1664 #endif /* HAVE_SETXATTR */
1665 		/* mark a future need to update the mtime */
1666 			if (ctx->dmtime)
1667 				state |= CLOSE_DMTIME;
1668 			/* deny opening metadata files for writing */
1669 			if (ino < FILE_first_user)
1670 				res = -EPERM;
1671 		}
1672 		ntfs_attr_close(na);
1673 close:
1674 		if (ntfs_inode_close(ni))
1675 			set_fuse_error(&res);
1676 	} else
1677 		res = -errno;
1678 	if (res >= 0) {
1679 		of = (struct open_file*)malloc(sizeof(struct open_file));
1680 		if (of) {
1681 			of->parent = 0;
1682 			of->ino = ino;
1683 			of->state = state;
1684 #ifndef DISABLE_PLUGINS
1685 			memcpy(&of->fi, fi, sizeof(struct fuse_file_info));
1686 #endif /* DISABLE_PLUGINS */
1687 			of->next = ctx->open_files;
1688 			of->previous = (struct open_file*)NULL;
1689 			if (ctx->open_files)
1690 				ctx->open_files->previous = of;
1691 			ctx->open_files = of;
1692 			fi->fh = (long)of;
1693 		}
1694 	}
1695 	if (res)
1696 		fuse_reply_err(req, -res);
1697 	else
1698 		fuse_reply_open(req, fi);
1699 }
1700 
ntfs_fuse_read(fuse_req_t req,fuse_ino_t ino,size_t size,off_t offset,struct fuse_file_info * fi)1701 static void ntfs_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size,
1702 			off_t offset,
1703 			struct fuse_file_info *fi __attribute__((unused)))
1704 {
1705 	ntfs_inode *ni = NULL;
1706 	ntfs_attr *na = NULL;
1707 	int res;
1708 	char *buf = (char*)NULL;
1709 	s64 total = 0;
1710 	s64 max_read;
1711 
1712 	if (!size) {
1713 		res = 0;
1714 		goto exit;
1715 	}
1716 	buf = (char*)ntfs_malloc(size);
1717 	if (!buf) {
1718 		res = -errno;
1719 		goto exit;
1720 	}
1721 
1722 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1723 	if (!ni) {
1724 		res = -errno;
1725 		goto exit;
1726 	}
1727 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1728 #ifndef DISABLE_PLUGINS
1729 		const plugin_operations_t *ops;
1730 		REPARSE_POINT *reparse;
1731 		struct open_file *of;
1732 
1733 		of = (struct open_file*)(long)fi->fh;
1734 		res = CALL_REPARSE_PLUGIN(ni, read, buf, size, offset, &of->fi);
1735 		if (res >= 0) {
1736 			goto stamps;
1737 		}
1738 #else /* DISABLE_PLUGINS */
1739 		res = -EOPNOTSUPP;
1740 #endif /* DISABLE_PLUGINS */
1741 		goto exit;
1742 	}
1743 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1744 	if (!na) {
1745 		res = -errno;
1746 		goto exit;
1747 	}
1748 	max_read = na->data_size;
1749 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
1750 	/* limit reads at next 512 byte boundary for encrypted attributes */
1751 	if (ctx->efs_raw
1752 	    && max_read
1753 	    && (na->data_flags & ATTR_IS_ENCRYPTED)
1754 	    && NAttrNonResident(na)) {
1755 		max_read = ((na->data_size+511) & ~511) + 2;
1756 	}
1757 #endif /* HAVE_SETXATTR */
1758 	if (offset + (off_t)size > max_read) {
1759 		if (max_read < offset)
1760 			goto ok;
1761 		size = max_read - offset;
1762 	}
1763 	while (size > 0) {
1764 		s64 ret = ntfs_attr_pread(na, offset, size, buf + total);
1765 		if (ret != (s64)size)
1766 			ntfs_log_perror("ntfs_attr_pread error reading inode %lld at "
1767 				"offset %lld: %lld <> %lld", (long long)ni->mft_no,
1768 				(long long)offset, (long long)size, (long long)ret);
1769 		if (ret <= 0 || ret > (s64)size) {
1770 			res = (ret < 0) ? -errno : -EIO;
1771 			goto exit;
1772 		}
1773 		size -= ret;
1774 		offset += ret;
1775 		total += ret;
1776 	}
1777 ok:
1778 	res = total;
1779 #ifndef DISABLE_PLUGINS
1780 stamps :
1781 #endif /* DISABLE_PLUGINS */
1782 	ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
1783 exit:
1784 	if (na)
1785 		ntfs_attr_close(na);
1786 	if (ntfs_inode_close(ni))
1787 		set_fuse_error(&res);
1788 	if (res < 0)
1789 		fuse_reply_err(req, -res);
1790 	else
1791 		fuse_reply_buf(req, buf, res);
1792 	free(buf);
1793 }
1794 
ntfs_fuse_write(fuse_req_t req,fuse_ino_t ino,const char * buf,size_t size,off_t offset,struct fuse_file_info * fi)1795 static void ntfs_fuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
1796 			size_t size, off_t offset,
1797 			struct fuse_file_info *fi __attribute__((unused)))
1798 {
1799 	ntfs_inode *ni = NULL;
1800 	ntfs_attr *na = NULL;
1801 	int res, total = 0;
1802 
1803 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1804 	if (!ni) {
1805 		res = -errno;
1806 		goto exit;
1807 	}
1808 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
1809 #ifndef DISABLE_PLUGINS
1810 		const plugin_operations_t *ops;
1811 		REPARSE_POINT *reparse;
1812 		struct open_file *of;
1813 
1814 		of = (struct open_file*)(long)fi->fh;
1815 		res = CALL_REPARSE_PLUGIN(ni, write, buf, size, offset,
1816 								&of->fi);
1817 		if (res >= 0) {
1818 			goto stamps;
1819 		}
1820 #else /* DISABLE_PLUGINS */
1821 		res = -EOPNOTSUPP;
1822 #endif /* DISABLE_PLUGINS */
1823 		goto exit;
1824 	}
1825 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1826 	if (!na) {
1827 		res = -errno;
1828 		goto exit;
1829 	}
1830 	while (size) {
1831 		s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total);
1832 		if (ret <= 0) {
1833 			res = -errno;
1834 			goto exit;
1835 		}
1836 		size   -= ret;
1837 		offset += ret;
1838 		total  += ret;
1839 	}
1840 	res = total;
1841 #ifndef DISABLE_PLUGINS
1842 stamps :
1843 #endif /* DISABLE_PLUGINS */
1844 	if ((res > 0)
1845 	    && (!ctx->dmtime
1846 		|| (sle64_to_cpu(ntfs_current_time())
1847 		     - sle64_to_cpu(ni->last_data_change_time)) > ctx->dmtime))
1848 		ntfs_fuse_update_times(ni, NTFS_UPDATE_MCTIME);
1849 exit:
1850 	if (na)
1851 		ntfs_attr_close(na);
1852 	if (res > 0)
1853 		set_archive(ni);
1854 	if (ntfs_inode_close(ni))
1855 		set_fuse_error(&res);
1856 	if (res < 0)
1857 		fuse_reply_err(req, -res);
1858 	else
1859 		fuse_reply_write(req, res);
1860 }
1861 
ntfs_fuse_chmod(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,mode_t mode,struct stat * stbuf)1862 static int ntfs_fuse_chmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
1863 		mode_t mode, struct stat *stbuf)
1864 {
1865 	int res = 0;
1866 	ntfs_inode *ni;
1867 
1868 	  /* Unsupported if inherit or no user mapping has been defined */
1869 	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
1870 	    && !ctx->silent) {
1871 		res = -EOPNOTSUPP;
1872 	} else {
1873 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
1874 		if (!ni)
1875 			res = -errno;
1876 		else {
1877 			/* ignore if Windows inheritance is forced */
1878 			if (scx->mapping[MAPUSERS] && !ctx->inherit) {
1879 				if (ntfs_set_mode(scx, ni, mode))
1880 					res = -errno;
1881 				else {
1882 					ntfs_fuse_update_times(ni,
1883 							NTFS_UPDATE_CTIME);
1884 					/*
1885 					 * Must return updated times, and
1886 					 * inode has been updated, so hope
1887 					 * we get no further errors
1888 					 */
1889 					res = ntfs_fuse_getstat(scx, ni, stbuf);
1890 				}
1891 				NInoSetDirty(ni);
1892 			} else
1893 				res = ntfs_fuse_getstat(scx, ni, stbuf);
1894 			if (ntfs_inode_close(ni))
1895 				set_fuse_error(&res);
1896 		}
1897 	}
1898 	return res;
1899 }
1900 
ntfs_fuse_chown(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,uid_t uid,gid_t gid,struct stat * stbuf)1901 static int ntfs_fuse_chown(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
1902 			uid_t uid, gid_t gid, struct stat *stbuf)
1903 {
1904 	ntfs_inode *ni;
1905 	int res;
1906 
1907 	  /* Unsupported if inherit or no user mapping has been defined */
1908 	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
1909 			&& !ctx->silent
1910 			&& ((uid != ctx->uid) || (gid != ctx->gid)))
1911 		res = -EOPNOTSUPP;
1912 	else {
1913 		res = 0;
1914 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
1915 		if (!ni)
1916 			res = -errno;
1917 		else {
1918 			/* ignore if Windows inheritance is forced */
1919 			if (scx->mapping[MAPUSERS]
1920 			  && !ctx->inherit
1921 			  && (((int)uid != -1) || ((int)gid != -1))) {
1922 				if (ntfs_set_owner(scx, ni, uid, gid))
1923 					res = -errno;
1924 				else {
1925 					ntfs_fuse_update_times(ni,
1926 							NTFS_UPDATE_CTIME);
1927 				/*
1928 				 * Must return updated times, and
1929 				 * inode has been updated, so hope
1930 				 * we get no further errors
1931 				 */
1932 					res = ntfs_fuse_getstat(scx, ni, stbuf);
1933 				}
1934 			} else
1935 				res = ntfs_fuse_getstat(scx, ni, stbuf);
1936 			if (ntfs_inode_close(ni))
1937 				set_fuse_error(&res);
1938 		}
1939 	}
1940 	return (res);
1941 }
1942 
ntfs_fuse_chownmod(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,uid_t uid,gid_t gid,mode_t mode,struct stat * stbuf)1943 static int ntfs_fuse_chownmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
1944 			uid_t uid, gid_t gid, mode_t mode, struct stat *stbuf)
1945 {
1946 	ntfs_inode *ni;
1947 	int res;
1948 
1949 	  /* Unsupported if inherit or no user mapping has been defined */
1950 	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
1951 			&& !ctx->silent
1952 			&& ((uid != ctx->uid) || (gid != ctx->gid)))
1953 		res = -EOPNOTSUPP;
1954 	else {
1955 		res = 0;
1956 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
1957 		if (!ni)
1958 			res = -errno;
1959 		else {
1960 			/* ignore if Windows inheritance is forced */
1961 			if (scx->mapping[MAPUSERS] && !ctx->inherit) {
1962 				if (ntfs_set_ownmod(scx, ni, uid, gid, mode))
1963 					res = -errno;
1964 				else {
1965 					ntfs_fuse_update_times(ni,
1966 							NTFS_UPDATE_CTIME);
1967 					/*
1968 					 * Must return updated times, and
1969 					 * inode has been updated, so hope
1970 					 * we get no further errors
1971 					 */
1972 					res = ntfs_fuse_getstat(scx, ni, stbuf);
1973 				}
1974 			} else
1975 				res = ntfs_fuse_getstat(scx, ni, stbuf);
1976 			if (ntfs_inode_close(ni))
1977 				set_fuse_error(&res);
1978 		}
1979 	}
1980 	return (res);
1981 }
1982 
ntfs_fuse_trunc(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,off_t size,BOOL chkwrite,struct stat * stbuf)1983 static int ntfs_fuse_trunc(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
1984 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1985 		off_t size, BOOL chkwrite, struct stat *stbuf)
1986 #else
1987 		off_t size, BOOL chkwrite __attribute__((unused)),
1988 		struct stat *stbuf)
1989 #endif
1990 {
1991 	ntfs_inode *ni = NULL;
1992 	ntfs_attr *na = NULL;
1993 	int res;
1994 	s64 oldsize;
1995 
1996 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
1997 	if (!ni)
1998 		goto exit;
1999 
2000 	/* deny truncating metadata files */
2001 	if (ino < FILE_first_user) {
2002 		errno = EPERM;
2003 		goto exit;
2004 	}
2005 	if (!(ni->flags & FILE_ATTR_REPARSE_POINT)) {
2006 		na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
2007 		if (!na)
2008 			goto exit;
2009 	}
2010 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2011 	/*
2012 	 * deny truncation if cannot write to file
2013 	 * (already checked for ftruncate())
2014 	 */
2015 	if (scx->mapping[MAPUSERS]
2016 	    && chkwrite
2017 	    && !ntfs_allowed_access(scx, ni, S_IWRITE)) {
2018 		errno = EACCES;
2019 		goto exit;
2020 	}
2021 #endif
2022 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
2023 #ifndef DISABLE_PLUGINS
2024 		const plugin_operations_t *ops;
2025 		REPARSE_POINT *reparse;
2026 
2027 		res = CALL_REPARSE_PLUGIN(ni, truncate, size);
2028 		if (!res) {
2029 			set_archive(ni);
2030 			goto stamps;
2031 		}
2032 #else /* DISABLE_PLUGINS */
2033 		res = -EOPNOTSUPP;
2034 #endif /* DISABLE_PLUGINS */
2035 		goto exit;
2036 	}
2037 		/*
2038 		 * for compressed files, upsizing is done by inserting a final
2039 		 * zero, which is optimized as creating a hole when possible.
2040 		 */
2041 	oldsize = na->data_size;
2042 	if ((na->data_flags & ATTR_COMPRESSION_MASK)
2043 	    && (size > na->initialized_size)) {
2044 		char zero = 0;
2045 		if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0)
2046 			goto exit;
2047 	} else
2048 		if (ntfs_attr_truncate(na, size))
2049 			goto exit;
2050 	if (oldsize != size)
2051 		set_archive(ni);
2052 
2053 #ifndef DISABLE_PLUGINS
2054 stamps :
2055 #endif /* DISABLE_PLUGINS */
2056 	ntfs_fuse_update_times(ni, NTFS_UPDATE_MCTIME);
2057 	res = ntfs_fuse_getstat(scx, ni, stbuf);
2058 	errno = (res ? -res : 0);
2059 exit:
2060 	res = -errno;
2061 	ntfs_attr_close(na);
2062 	if (ntfs_inode_close(ni))
2063 		set_fuse_error(&res);
2064 	return res;
2065 }
2066 
2067 #if defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW)
2068 
ntfs_fuse_utimens(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,struct stat * stin,struct stat * stbuf,int to_set)2069 static int ntfs_fuse_utimens(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
2070 		struct stat *stin, struct stat *stbuf, int to_set)
2071 {
2072 	ntfs_inode *ni;
2073 	int res = 0;
2074 
2075 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
2076 	if (!ni)
2077 		return -errno;
2078 
2079 			/* no check or update if both UTIME_OMIT */
2080 	if (to_set & (FUSE_SET_ATTR_ATIME + FUSE_SET_ATTR_MTIME)) {
2081 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2082 		if (ntfs_allowed_as_owner(scx, ni)
2083 		    || ((to_set & FUSE_SET_ATTR_ATIME_NOW)
2084 			&& (to_set & FUSE_SET_ATTR_MTIME_NOW)
2085 			&& ntfs_allowed_access(scx, ni, S_IWRITE))) {
2086 #endif
2087 			ntfs_time_update_flags mask = NTFS_UPDATE_CTIME;
2088 
2089 			if (to_set & FUSE_SET_ATTR_ATIME_NOW)
2090 				mask |= NTFS_UPDATE_ATIME;
2091 			else
2092 				if (to_set & FUSE_SET_ATTR_ATIME) {
2093 #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
2094 					ni->last_access_time
2095 						= timespec2ntfs(stin->st_atimespec);
2096 #elif defined(HAVE_STRUCT_STAT_ST_ATIM)
2097 					ni->last_access_time
2098 						= timespec2ntfs(stin->st_atim);
2099 #else
2100 					ni->last_access_time.tv_sec
2101 						= stin->st_atime;
2102 #ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
2103 					ni->last_access_time.tv_nsec
2104 						= stin->st_atimensec;
2105 #endif
2106 #endif
2107 				}
2108 			if (to_set & FUSE_SET_ATTR_MTIME_NOW)
2109 				mask |= NTFS_UPDATE_MTIME;
2110 			else
2111 				if (to_set & FUSE_SET_ATTR_MTIME) {
2112 #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
2113 					ni->last_data_change_time
2114 						= timespec2ntfs(stin->st_mtimespec);
2115 #elif defined(HAVE_STRUCT_STAT_ST_ATIM)
2116 					ni->last_data_change_time
2117 						= timespec2ntfs(stin->st_mtim);
2118 #else
2119 					ni->last_data_change_time.tv_sec
2120 						= stin->st_mtime;
2121 #ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
2122 					ni->last_data_change_time.tv_nsec
2123 						= stin->st_mtimensec;
2124 #endif
2125 #endif
2126 				}
2127 			ntfs_inode_update_times(ni, mask);
2128 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2129 		} else
2130 			res = -errno;
2131 #endif
2132 	}
2133 	if (!res)
2134 		res = ntfs_fuse_getstat(scx, ni, stbuf);
2135 	if (ntfs_inode_close(ni))
2136 		set_fuse_error(&res);
2137 	return res;
2138 }
2139 
2140 #else /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
2141 
ntfs_fuse_utime(struct SECURITY_CONTEXT * scx,fuse_ino_t ino,struct stat * stin,struct stat * stbuf)2142 static int ntfs_fuse_utime(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
2143 		struct stat *stin, struct stat *stbuf)
2144 {
2145 	ntfs_inode *ni;
2146 	int res = 0;
2147 	struct timespec actime;
2148 	struct timespec modtime;
2149 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2150 	BOOL ownerok;
2151 	BOOL writeok;
2152 #endif
2153 
2154 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
2155 	if (!ni)
2156 		return -errno;
2157 
2158 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2159 	ownerok = ntfs_allowed_as_owner(scx, ni);
2160 	if (stin) {
2161 		/*
2162 		 * fuse never calls with a NULL buf and we do not
2163 		 * know whether the specific condition can be applied
2164 		 * So we have to accept updating by a non-owner having
2165 		 * write access.
2166 		 */
2167 		writeok = !ownerok
2168 			&& (stin->st_atime == stin->st_mtime)
2169 			&& ntfs_allowed_access(scx, ni, S_IWRITE);
2170 			/* Must be owner */
2171 		if (!ownerok && !writeok)
2172 			res = (stin->st_atime == stin->st_mtime
2173 					? -EACCES : -EPERM);
2174 		else {
2175 			actime.tv_sec = stin->st_atime;
2176 			actime.tv_nsec = 0;
2177 			modtime.tv_sec = stin->st_mtime;
2178 			modtime.tv_nsec = 0;
2179 			ni->last_access_time = timespec2ntfs(actime);
2180 			ni->last_data_change_time = timespec2ntfs(modtime);
2181 			ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
2182 		}
2183 	} else {
2184 			/* Must be owner or have write access */
2185 		writeok = !ownerok
2186 			&& ntfs_allowed_access(scx, ni, S_IWRITE);
2187 		if (!ownerok && !writeok)
2188 			res = -EACCES;
2189 		else
2190 			ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
2191 	}
2192 #else
2193 	if (stin) {
2194 		actime.tv_sec = stin->st_atime;
2195 		actime.tv_nsec = 0;
2196 		modtime.tv_sec = stin->st_mtime;
2197 		modtime.tv_nsec = 0;
2198 		ni->last_access_time = timespec2ntfs(actime);
2199 		ni->last_data_change_time = timespec2ntfs(modtime);
2200 		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
2201 	} else
2202 		ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
2203 #endif
2204 
2205 	res = ntfs_fuse_getstat(scx, ni, stbuf);
2206 	if (ntfs_inode_close(ni))
2207 		set_fuse_error(&res);
2208 	return res;
2209 }
2210 
2211 #endif /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
2212 
ntfs_fuse_setattr(fuse_req_t req,fuse_ino_t ino,struct stat * attr,int to_set,struct fuse_file_info * fi)2213 static void ntfs_fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2214 			 int to_set, struct fuse_file_info *fi __attribute__((unused)))
2215 {
2216 	struct stat stbuf;
2217 	ntfs_inode *ni;
2218 	int res;
2219 	struct SECURITY_CONTEXT security;
2220 
2221 	res = 0;
2222 	ntfs_fuse_fill_security_context(req, &security);
2223 						/* no flags */
2224 	if (!(to_set
2225 		    & (FUSE_SET_ATTR_MODE
2226 			| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID
2227 			| FUSE_SET_ATTR_SIZE
2228 			| FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2229 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
2230 		if (!ni)
2231 			res = -errno;
2232 		else {
2233 			res = ntfs_fuse_getstat(&security, ni, &stbuf);
2234 			if (ntfs_inode_close(ni))
2235 				set_fuse_error(&res);
2236 		}
2237 	}
2238 						/* some set of uid/gid/mode */
2239 	if (to_set
2240 		    & (FUSE_SET_ATTR_MODE
2241 			| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
2242 		switch (to_set
2243 			    & (FUSE_SET_ATTR_MODE
2244 				| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
2245 		case FUSE_SET_ATTR_MODE :
2246 			res = ntfs_fuse_chmod(&security, ino,
2247 						attr->st_mode & 07777, &stbuf);
2248 			break;
2249 		case FUSE_SET_ATTR_UID :
2250 			res = ntfs_fuse_chown(&security, ino, attr->st_uid,
2251 						(gid_t)-1, &stbuf);
2252 			break;
2253 		case FUSE_SET_ATTR_GID :
2254 			res = ntfs_fuse_chown(&security, ino, (uid_t)-1,
2255 						attr->st_gid, &stbuf);
2256 			break;
2257 		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_GID :
2258 			res = ntfs_fuse_chown(&security, ino, attr->st_uid,
2259 						attr->st_gid, &stbuf);
2260 			break;
2261 		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_MODE:
2262 			res = ntfs_fuse_chownmod(&security, ino, attr->st_uid,
2263 						(gid_t)-1,attr->st_mode,
2264 						&stbuf);
2265 			break;
2266 		case FUSE_SET_ATTR_GID + FUSE_SET_ATTR_MODE:
2267 			res = ntfs_fuse_chownmod(&security, ino, (uid_t)-1,
2268 						attr->st_gid,attr->st_mode,
2269 						&stbuf);
2270 			break;
2271 		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_GID + FUSE_SET_ATTR_MODE:
2272 			res = ntfs_fuse_chownmod(&security, ino, attr->st_uid,
2273 					attr->st_gid,attr->st_mode, &stbuf);
2274 			break;
2275 		default :
2276 			break;
2277 		}
2278 	}
2279 						/* size */
2280 	if (!res && (to_set & FUSE_SET_ATTR_SIZE)) {
2281 		res = ntfs_fuse_trunc(&security, ino, attr->st_size,
2282 					!fi, &stbuf);
2283 	}
2284 						/* some set of atime/mtime */
2285 	if (!res && (to_set & (FUSE_SET_ATTR_ATIME + FUSE_SET_ATTR_MTIME))) {
2286 #if defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW)
2287 		res = ntfs_fuse_utimens(&security, ino, attr, &stbuf, to_set);
2288 #else /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
2289 		res = ntfs_fuse_utime(&security, ino, attr, &stbuf);
2290 #endif /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
2291 	}
2292 	if (res)
2293 		fuse_reply_err(req, -res);
2294 	else
2295 		fuse_reply_attr(req, &stbuf, ATTR_TIMEOUT);
2296 }
2297 
2298 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2299 
ntfs_fuse_access(fuse_req_t req,fuse_ino_t ino,int mask)2300 static void ntfs_fuse_access(fuse_req_t req, fuse_ino_t ino, int mask)
2301 {
2302 	int res = 0;
2303 	int mode;
2304 	ntfs_inode *ni;
2305 	struct SECURITY_CONTEXT security;
2306 
2307 	  /* JPA return unsupported if no user mapping has been defined */
2308 	if (!ntfs_fuse_fill_security_context(req, &security)) {
2309 		if (ctx->silent)
2310 			res = 0;
2311 		else
2312 			res = -EOPNOTSUPP;
2313 	} else {
2314 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
2315 		if (!ni) {
2316 			res = -errno;
2317 		} else {
2318 			mode = 0;
2319 			if (mask & (X_OK | W_OK | R_OK)) {
2320 				if (mask & X_OK) mode += S_IEXEC;
2321 				if (mask & W_OK) mode += S_IWRITE;
2322 				if (mask & R_OK) mode += S_IREAD;
2323 				if (!ntfs_allowed_access(&security,
2324 						ni, mode))
2325 					res = -errno;
2326 			}
2327 			if (ntfs_inode_close(ni))
2328 				set_fuse_error(&res);
2329 		}
2330 	}
2331 	if (res < 0)
2332 		fuse_reply_err(req, -res);
2333 	else
2334 		fuse_reply_err(req, 0);
2335 }
2336 
2337 #endif /* !KERNELPERMS | (POSIXACLS & !KERNELACLS) */
2338 
ntfs_fuse_create(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t typemode,dev_t dev,struct fuse_entry_param * e,const char * target,struct fuse_file_info * fi)2339 static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name,
2340 		mode_t typemode, dev_t dev,
2341 		struct fuse_entry_param *e,
2342 		const char *target, struct fuse_file_info *fi)
2343 {
2344 	ntfschar *uname = NULL, *utarget = NULL;
2345 	ntfs_inode *dir_ni = NULL, *ni;
2346 	struct open_file *of;
2347 	int state = 0;
2348 	le32 securid;
2349 	gid_t gid;
2350 	mode_t dsetgid;
2351 	mode_t type = typemode & ~07777;
2352 	mode_t perm;
2353 	struct SECURITY_CONTEXT security;
2354 	int res = 0, uname_len, utarget_len;
2355 
2356 	/* Generate unicode filename. */
2357 	uname_len = ntfs_mbstoucs(name, &uname);
2358 	if ((uname_len < 0)
2359 	    || (ctx->windows_names
2360 		&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
2361 		res = -errno;
2362 		goto exit;
2363 	}
2364 	/* Deny creating into $Extend */
2365 	if (parent == FILE_Extend) {
2366 		res = -EPERM;
2367 		goto exit;
2368 	}
2369 	/* Open parent directory. */
2370 	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
2371 	if (!dir_ni) {
2372 		res = -errno;
2373 		goto exit;
2374 	}
2375 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2376 		/* make sure parent directory is writeable and executable */
2377 	if (!ntfs_fuse_fill_security_context(req, &security)
2378 	       || ntfs_allowed_create(&security,
2379 				dir_ni, &gid, &dsetgid)) {
2380 #else
2381 		ntfs_fuse_fill_security_context(req, &security);
2382 		ntfs_allowed_create(&security, dir_ni, &gid, &dsetgid);
2383 #endif
2384 		if (S_ISDIR(type))
2385 			perm = (typemode & ~ctx->dmask & 0777)
2386 				| (dsetgid & S_ISGID);
2387 		else
2388 			if ((ctx->special_files == NTFS_FILES_WSL)
2389 			    && S_ISLNK(type))
2390 				perm = typemode | 0777;
2391 			else
2392 				perm = typemode & ~ctx->fmask & 0777;
2393 			/*
2394 			 * Try to get a security id available for
2395 			 * file creation (from inheritance or argument).
2396 			 * This is not possible for NTFS 1.x, and we will
2397 			 * have to build a security attribute later.
2398 			 */
2399 		if (!ctx->security.mapping[MAPUSERS])
2400 			securid = const_cpu_to_le32(0);
2401 		else
2402 			if (ctx->inherit)
2403 				securid = ntfs_inherited_id(&security,
2404 					dir_ni, S_ISDIR(type));
2405 			else
2406 #if POSIXACLS
2407 				securid = ntfs_alloc_securid(&security,
2408 					security.uid, gid,
2409 					dir_ni, perm, S_ISDIR(type));
2410 #else
2411 				securid = ntfs_alloc_securid(&security,
2412 					security.uid, gid,
2413 					perm & ~security.umask, S_ISDIR(type));
2414 #endif
2415 		/* Create object specified in @type. */
2416 		if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
2417 #ifndef DISABLE_PLUGINS
2418 			const plugin_operations_t *ops;
2419 			REPARSE_POINT *reparse;
2420 
2421 			reparse = (REPARSE_POINT*)NULL;
2422 			ops = select_reparse_plugin(ctx, dir_ni, &reparse);
2423 			if (ops && ops->create) {
2424 				ni = (*ops->create)(dir_ni, reparse,
2425 					securid, uname, uname_len, type);
2426 			} else {
2427 				ni = (ntfs_inode*)NULL;
2428 				errno = EOPNOTSUPP;
2429 			}
2430 			free(reparse);
2431 #else /* DISABLE_PLUGINS */
2432 			ni = (ntfs_inode*)NULL;
2433 			errno = EOPNOTSUPP;
2434 #endif /* DISABLE_PLUGINS */
2435 		} else {
2436 			switch (type) {
2437 				case S_IFCHR:
2438 				case S_IFBLK:
2439 					ni = ntfs_create_device(dir_ni, securid,
2440 							uname, uname_len,
2441 							type, dev);
2442 					break;
2443 				case S_IFLNK:
2444 					utarget_len = ntfs_mbstoucs(target,
2445 							&utarget);
2446 					if (utarget_len < 0) {
2447 						res = -errno;
2448 						goto exit;
2449 					}
2450 					ni = ntfs_create_symlink(dir_ni,
2451 							securid,
2452 							uname, uname_len,
2453 							utarget, utarget_len);
2454 					break;
2455 				default:
2456 					ni = ntfs_create(dir_ni, securid, uname,
2457 							uname_len, type);
2458 					break;
2459 			}
2460 		}
2461 		if (ni) {
2462 				/*
2463 				 * set the security attribute if a security id
2464 				 * could not be allocated (eg NTFS 1.x)
2465 				 */
2466 			if (ctx->security.mapping[MAPUSERS]) {
2467 #if POSIXACLS
2468 				if (!securid
2469 				   && ntfs_set_inherited_posix(&security, ni,
2470 					security.uid, gid,
2471 					dir_ni, perm) < 0)
2472 					set_fuse_error(&res);
2473 #else
2474 				if (!securid
2475 				   && ntfs_set_owner_mode(&security, ni,
2476 					security.uid, gid,
2477 					perm & ~security.umask) < 0)
2478 					set_fuse_error(&res);
2479 #endif
2480 			}
2481 			set_archive(ni);
2482 			/* mark a need to compress the end of file */
2483 			if (fi && (ni->flags & FILE_ATTR_COMPRESSED)) {
2484 				state |= CLOSE_COMPRESSED;
2485 			}
2486 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
2487 			/* mark a future need to fixup encrypted inode */
2488 			if (fi
2489 			    && ctx->efs_raw
2490 			    && (ni->flags & FILE_ATTR_ENCRYPTED))
2491 				state |= CLOSE_ENCRYPTED;
2492 #endif /* HAVE_SETXATTR */
2493 			if (fi && ctx->dmtime)
2494 				state |= CLOSE_DMTIME;
2495 			ntfs_inode_update_mbsname(dir_ni, name, ni->mft_no);
2496 			NInoSetDirty(ni);
2497 			e->ino = ni->mft_no;
2498 			e->generation = 1;
2499 			e->attr_timeout = ATTR_TIMEOUT;
2500 			e->entry_timeout = ENTRY_TIMEOUT;
2501 			res = ntfs_fuse_getstat(&security, ni, &e->attr);
2502 			/*
2503 			 * closing ni requires access to dir_ni to
2504 			 * synchronize the index, avoid double opening.
2505 			 */
2506 			if (ntfs_inode_close_in_dir(ni, dir_ni))
2507 				set_fuse_error(&res);
2508 			ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2509 		} else
2510 			res = -errno;
2511 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2512 	} else
2513 		res = -errno;
2514 #endif
2515 
2516 exit:
2517 	free(uname);
2518 	if (ntfs_inode_close(dir_ni))
2519 		set_fuse_error(&res);
2520 	if (utarget)
2521 		free(utarget);
2522 	if ((res >= 0) && fi) {
2523 		of = (struct open_file*)malloc(sizeof(struct open_file));
2524 		if (of) {
2525 			of->parent = 0;
2526 			of->ino = e->ino;
2527 			of->state = state;
2528 			of->next = ctx->open_files;
2529 			of->previous = (struct open_file*)NULL;
2530 			if (ctx->open_files)
2531 				ctx->open_files->previous = of;
2532 			ctx->open_files = of;
2533 			fi->fh = (long)of;
2534 		}
2535 	}
2536 	return res;
2537 }
2538 
ntfs_fuse_create_file(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,struct fuse_file_info * fi)2539 static void ntfs_fuse_create_file(fuse_req_t req, fuse_ino_t parent,
2540 			const char *name, mode_t mode,
2541 			struct fuse_file_info *fi)
2542 {
2543 	int res;
2544 	struct fuse_entry_param entry;
2545 
2546 	res = ntfs_fuse_create(req, parent, name, mode & (S_IFMT | 07777),
2547 				0, &entry, NULL, fi);
2548 	if (res < 0)
2549 		fuse_reply_err(req, -res);
2550 	else
2551 		fuse_reply_create(req, &entry, fi);
2552 }
2553 
ntfs_fuse_mknod(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,dev_t rdev)2554 static void ntfs_fuse_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2555 		       mode_t mode, dev_t rdev)
2556 {
2557 	int res;
2558 	struct fuse_entry_param e;
2559 
2560 	res = ntfs_fuse_create(req, parent, name, mode & (S_IFMT | 07777),
2561 				rdev, &e,NULL,(struct fuse_file_info*)NULL);
2562 	if (res < 0)
2563 		fuse_reply_err(req, -res);
2564 	else
2565 		fuse_reply_entry(req, &e);
2566 }
2567 
ntfs_fuse_symlink(fuse_req_t req,const char * target,fuse_ino_t parent,const char * name)2568 static void ntfs_fuse_symlink(fuse_req_t req, const char *target,
2569 			fuse_ino_t parent, const char *name)
2570 {
2571 	int res;
2572 	struct fuse_entry_param entry;
2573 
2574 	res = ntfs_fuse_create(req, parent, name, S_IFLNK, 0,
2575 			&entry, target, (struct fuse_file_info*)NULL);
2576 	if (res < 0)
2577 		fuse_reply_err(req, -res);
2578 	else
2579 		fuse_reply_entry(req, &entry);
2580 }
2581 
2582 
ntfs_fuse_newlink(fuse_req_t req,fuse_ino_t ino,fuse_ino_t newparent,const char * newname,struct fuse_entry_param * e)2583 static int ntfs_fuse_newlink(fuse_req_t req __attribute__((unused)),
2584 			fuse_ino_t ino, fuse_ino_t newparent,
2585 			const char *newname, struct fuse_entry_param *e)
2586 {
2587 	ntfschar *uname = NULL;
2588 	ntfs_inode *dir_ni = NULL, *ni;
2589 	int res = 0, uname_len;
2590 	struct SECURITY_CONTEXT security;
2591 
2592 	/* Open file for which create hard link. */
2593 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
2594 	if (!ni) {
2595 		res = -errno;
2596 		goto exit;
2597 	}
2598 
2599 	/* Do not accept linking to a directory (except for renaming) */
2600 	if (e && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
2601 		errno = EPERM;
2602 		res = -errno;
2603 		goto exit;
2604 	}
2605 	/* Generate unicode filename. */
2606 	uname_len = ntfs_mbstoucs(newname, &uname);
2607 	if ((uname_len < 0)
2608             || (ctx->windows_names
2609                 && ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
2610 		res = -errno;
2611 		goto exit;
2612 	}
2613 	/* Open parent directory. */
2614 	dir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
2615 	if (!dir_ni) {
2616 		res = -errno;
2617 		goto exit;
2618 	}
2619 
2620 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2621 		/* make sure the target parent directory is writeable */
2622 	if (ntfs_fuse_fill_security_context(req, &security)
2623 	    && !ntfs_allowed_access(&security,dir_ni,S_IWRITE + S_IEXEC))
2624 		res = -EACCES;
2625 	else
2626 #else
2627 	ntfs_fuse_fill_security_context(req, &security);
2628 #endif
2629 		{
2630 		if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
2631 #ifndef DISABLE_PLUGINS
2632 			const plugin_operations_t *ops;
2633 			REPARSE_POINT *reparse;
2634 
2635 			res = CALL_REPARSE_PLUGIN(dir_ni, link,
2636 					ni, uname, uname_len);
2637 			if (res < 0)
2638 				goto exit;
2639 #else /* DISABLE_PLUGINS */
2640 			res = -EOPNOTSUPP;
2641 			goto exit;
2642 #endif /* DISABLE_PLUGINS */
2643 		} else {
2644 			if (ntfs_link(ni, dir_ni, uname, uname_len)) {
2645 				res = -errno;
2646 				goto exit;
2647 			}
2648 		}
2649 		ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
2650 		if (e) {
2651 			e->ino = ni->mft_no;
2652 			e->generation = 1;
2653 			e->attr_timeout = ATTR_TIMEOUT;
2654 			e->entry_timeout = ENTRY_TIMEOUT;
2655 			res = ntfs_fuse_getstat(&security, ni, &e->attr);
2656 		}
2657 		set_archive(ni);
2658 		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
2659 		ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
2660 	}
2661 exit:
2662 	/*
2663 	 * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni)
2664 	 * may fail because ni may not be in parent's index on the disk yet.
2665 	 */
2666 	if (ntfs_inode_close(dir_ni))
2667 		set_fuse_error(&res);
2668 	if (ntfs_inode_close(ni))
2669 		set_fuse_error(&res);
2670 	free(uname);
2671 	return (res);
2672 }
2673 
ntfs_fuse_link(fuse_req_t req,fuse_ino_t ino,fuse_ino_t newparent,const char * newname)2674 static void ntfs_fuse_link(fuse_req_t req, fuse_ino_t ino,
2675 			fuse_ino_t newparent, const char *newname)
2676 {
2677 	struct fuse_entry_param entry;
2678 	int res;
2679 
2680 	res = ntfs_fuse_newlink(req, ino, newparent, newname, &entry);
2681 	if (res)
2682 		fuse_reply_err(req, -res);
2683 	else
2684 		fuse_reply_entry(req, &entry);
2685 }
2686 
ntfs_fuse_rm(fuse_req_t req,fuse_ino_t parent,const char * name,enum RM_TYPES rm_type)2687 static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name,
2688 			enum RM_TYPES rm_type __attribute__((unused)))
2689 {
2690 	ntfschar *uname = NULL;
2691 	ntfschar *ugname;
2692 	ntfs_inode *dir_ni = NULL, *ni = NULL;
2693 	int res = 0, uname_len;
2694 	int ugname_len;
2695 	u64 iref;
2696 	fuse_ino_t ino;
2697 	struct open_file *of;
2698 	char ghostname[GHOSTLTH];
2699 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2700 	struct SECURITY_CONTEXT security;
2701 #endif
2702 #if defined(__sun) && defined (__SVR4)
2703 	int isdir;
2704 #endif /* defined(__sun) && defined (__SVR4) */
2705 
2706 	/* Deny removing from $Extend */
2707 	if (parent == FILE_Extend) {
2708 		res = -EPERM;
2709 		goto exit;
2710 	}
2711 	/* Open parent directory. */
2712 	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
2713 	if (!dir_ni) {
2714 		res = -errno;
2715 		goto exit;
2716 	}
2717 	/* Generate unicode filename. */
2718 	uname_len = ntfs_mbstoucs(name, &uname);
2719 	if (uname_len < 0) {
2720 		res = -errno;
2721 		goto exit;
2722 	}
2723 	/* Open object for delete. */
2724 	iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
2725 	if (iref == (u64)-1) {
2726 		res = -errno;
2727 		goto exit;
2728 	}
2729 	ino = (fuse_ino_t)MREF(iref);
2730 	/* deny unlinking metadata files */
2731 	if (ino < FILE_first_user) {
2732 		res = -EPERM;
2733 		goto exit;
2734 	}
2735 
2736 	ni = ntfs_inode_open(ctx->vol, ino);
2737 	if (!ni) {
2738 		res = -errno;
2739 		goto exit;
2740 	}
2741 
2742 #if defined(__sun) && defined (__SVR4)
2743 	/* on Solaris : deny unlinking directories */
2744 	isdir = ni->mrec->flags & MFT_RECORD_IS_DIRECTORY;
2745 #ifndef DISABLE_PLUGINS
2746 		/* get emulated type from plugin if available */
2747 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
2748 		struct stat st;
2749 		const plugin_operations_t *ops;
2750 		REPARSE_POINT *reparse;
2751 
2752 			/* Avoid double opening of parent directory */
2753 		res = ntfs_inode_close(dir_ni);
2754 		if (res)
2755 			goto exit;
2756 		dir_ni = (ntfs_inode*)NULL;
2757 		res = CALL_REPARSE_PLUGIN(ni, getattr, &st);
2758 		if (res)
2759 			goto exit;
2760 		isdir = S_ISDIR(st.st_mode);
2761 		dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
2762 		if (!dir_ni) {
2763 			res = -errno;
2764 			goto exit;
2765 		}
2766 	}
2767 #endif /* DISABLE_PLUGINS */
2768 	if (rm_type == (isdir ? RM_LINK : RM_DIR)) {
2769 		errno = (isdir ? EISDIR : ENOTDIR);
2770 		res = -errno;
2771 		goto exit;
2772 	}
2773 #endif /* defined(__sun) && defined (__SVR4) */
2774 
2775 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2776 	/* JPA deny unlinking if directory is not writable and executable */
2777 	if (ntfs_fuse_fill_security_context(req, &security)
2778 	    && !ntfs_allowed_dir_access(&security, dir_ni, ino, ni,
2779 				   S_IEXEC + S_IWRITE + S_ISVTX)) {
2780 		errno = EACCES;
2781 		res = -errno;
2782 		goto exit;
2783 	}
2784 #endif
2785 		/*
2786 		 * We keep one open_file record per opening, to avoid
2787 		 * having to check the list of open files when opening
2788 		 * and closing (which are more frequent than unlinking).
2789 		 * As a consequence, we may have to create several
2790 		 * ghosts names for the same file.
2791 		 * The file may have been opened with a different name
2792 		 * in a different parent directory. The ghost is
2793 		 * nevertheless created in the parent directory of the
2794 		 * name being unlinked, and permissions to do so are the
2795 		 * same as required for unlinking.
2796 		 */
2797 	for (of=ctx->open_files; of; of = of->next) {
2798 		if ((of->ino == ino) && !(of->state & CLOSE_GHOST)) {
2799 			/* file was open, create a ghost in unlink parent */
2800 			ntfs_inode *gni;
2801 			u64 gref;
2802 
2803 			/* ni has to be closed for linking ghost */
2804 			if (ni) {
2805 				if (ntfs_inode_close(ni)) {
2806 					res = -errno;
2807 					goto exit;
2808 				}
2809 				ni = (ntfs_inode*)NULL;
2810 			}
2811 			of->state |= CLOSE_GHOST;
2812 			of->parent = parent;
2813 			of->ghost = ++ctx->latest_ghost;
2814 			sprintf(ghostname,ghostformat,of->ghost);
2815 				/* Generate unicode filename. */
2816 			ugname = (ntfschar*)NULL;
2817 			ugname_len = ntfs_mbstoucs(ghostname, &ugname);
2818 			if (ugname_len < 0) {
2819 				res = -errno;
2820 				goto exit;
2821 			}
2822 			/* sweep existing ghost if any, ignoring errors */
2823 			gref = ntfs_inode_lookup_by_mbsname(dir_ni, ghostname);
2824 			if (gref != (u64)-1) {
2825 				gni = ntfs_inode_open(ctx->vol, MREF(gref));
2826 				ntfs_delete(ctx->vol, (char*)NULL, gni, dir_ni,
2827 					 ugname, ugname_len);
2828 				/* ntfs_delete() always closes gni and dir_ni */
2829 				dir_ni = (ntfs_inode*)NULL;
2830 			} else {
2831 				if (ntfs_inode_close(dir_ni)) {
2832 					res = -errno;
2833 					goto out;
2834 				}
2835 				dir_ni = (ntfs_inode*)NULL;
2836 			}
2837 			free(ugname);
2838 			res = ntfs_fuse_newlink(req, of->ino, parent, ghostname,
2839 					(struct fuse_entry_param*)NULL);
2840 			if (res)
2841 				goto out;
2842 				/* now reopen then parent directory */
2843 			dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
2844 			if (!dir_ni) {
2845 				res = -errno;
2846 				goto exit;
2847 			}
2848 		}
2849 	}
2850 	if (!ni) {
2851 		ni = ntfs_inode_open(ctx->vol, ino);
2852 		if (!ni) {
2853 			res = -errno;
2854 			goto exit;
2855 		}
2856 	}
2857 	if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
2858 #ifndef DISABLE_PLUGINS
2859 		const plugin_operations_t *ops;
2860 		REPARSE_POINT *reparse;
2861 
2862 		res = CALL_REPARSE_PLUGIN(dir_ni, unlink, (char*)NULL,
2863 				ni, uname, uname_len);
2864 #else /* DISABLE_PLUGINS */
2865 		res = -EOPNOTSUPP;
2866 #endif /* DISABLE_PLUGINS */
2867 	} else
2868 		if (ntfs_delete(ctx->vol, (char*)NULL, ni, dir_ni,
2869 					 uname, uname_len))
2870 			res = -errno;
2871 		/* ntfs_delete() always closes ni and dir_ni */
2872 	ni = dir_ni = NULL;
2873 exit:
2874 	if (ntfs_inode_close(ni) && !res)
2875 		res = -errno;
2876 	if (ntfs_inode_close(dir_ni) && !res)
2877 		res = -errno;
2878 out :
2879 	free(uname);
2880 	return res;
2881 }
2882 
ntfs_fuse_unlink(fuse_req_t req,fuse_ino_t parent,const char * name)2883 static void ntfs_fuse_unlink(fuse_req_t req, fuse_ino_t parent,
2884 				const char *name)
2885 {
2886 	int res;
2887 
2888 	res = ntfs_fuse_rm(req, parent, name, RM_LINK);
2889 	if (res)
2890 		fuse_reply_err(req, -res);
2891 	else
2892 		fuse_reply_err(req, 0);
2893 }
2894 
ntfs_fuse_safe_rename(fuse_req_t req,fuse_ino_t ino,fuse_ino_t parent,const char * name,fuse_ino_t xino,fuse_ino_t newparent,const char * newname,const char * tmp)2895 static int ntfs_fuse_safe_rename(fuse_req_t req, fuse_ino_t ino,
2896 			fuse_ino_t parent, const char *name, fuse_ino_t xino,
2897 			fuse_ino_t newparent, const char *newname,
2898 			const char *tmp)
2899 {
2900 	int ret;
2901 
2902 	ntfs_log_trace("Entering\n");
2903 
2904 	ret = ntfs_fuse_newlink(req, xino, newparent, tmp,
2905 				(struct fuse_entry_param*)NULL);
2906 	if (ret)
2907 		return ret;
2908 
2909 	ret = ntfs_fuse_rm(req, newparent, newname, RM_ANY);
2910 	if (!ret) {
2911 
2912 		ret = ntfs_fuse_newlink(req, ino, newparent, newname,
2913 					(struct fuse_entry_param*)NULL);
2914 		if (ret)
2915 			goto restore;
2916 
2917 		ret = ntfs_fuse_rm(req, parent, name, RM_ANY);
2918 		if (ret) {
2919 			if (ntfs_fuse_rm(req, newparent, newname, RM_ANY))
2920 				goto err;
2921 			goto restore;
2922 		}
2923 	}
2924 
2925 	goto cleanup;
2926 restore:
2927 	if (ntfs_fuse_newlink(req, xino, newparent, newname,
2928 				(struct fuse_entry_param*)NULL)) {
2929 err:
2930 		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "
2931 				"to '%s'", newname, tmp);
2932 	} else {
2933 cleanup:
2934 		/*
2935 		 * Condition for this unlink has already been checked in
2936 		 * "ntfs_fuse_rename_existing_dest()", so it should never
2937 		 * fail (unless concurrent access to directories when fuse
2938 		 * is multithreaded)
2939 		 */
2940 		if (ntfs_fuse_rm(req, newparent, tmp, RM_ANY) < 0)
2941 			ntfs_log_perror("Rename failed. Existing file '%s' still present "
2942 				"as '%s'", newname, tmp);
2943 	}
2944 	return	ret;
2945 }
2946 
ntfs_fuse_rename_existing_dest(fuse_req_t req,fuse_ino_t ino,fuse_ino_t parent,const char * name,fuse_ino_t xino,fuse_ino_t newparent,const char * newname)2947 static int ntfs_fuse_rename_existing_dest(fuse_req_t req, fuse_ino_t ino,
2948 			fuse_ino_t parent, const char *name,
2949 			fuse_ino_t xino, fuse_ino_t newparent,
2950 			const char *newname)
2951 {
2952 	int ret, len;
2953 	char *tmp;
2954 	const char *ext = ".ntfs-3g-";
2955 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2956 	ntfs_inode *newdir_ni;
2957 	struct SECURITY_CONTEXT security;
2958 #endif
2959 
2960 	ntfs_log_trace("Entering\n");
2961 
2962 	len = strlen(newname) + strlen(ext) + 10 + 1; /* wc(str(2^32)) + \0 */
2963 	tmp = (char*)ntfs_malloc(len);
2964 	if (!tmp)
2965 		return -errno;
2966 
2967 	ret = snprintf(tmp, len, "%s%s%010d", newname, ext, ++ntfs_sequence);
2968 	if (ret != len - 1) {
2969 		ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);
2970 		ret = -EOVERFLOW;
2971 	} else {
2972 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
2973 			/*
2974 			 * Make sure existing dest can be removed.
2975 			 * This is only needed if parent directory is
2976 			 * sticky, because in this situation condition
2977 			 * for unlinking is different from condition for
2978 			 * linking
2979 			 */
2980 		newdir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
2981 		if (newdir_ni) {
2982 			if (!ntfs_fuse_fill_security_context(req,&security)
2983 			    || ntfs_allowed_dir_access(&security, newdir_ni,
2984 					xino, (ntfs_inode*)NULL,
2985 					S_IEXEC + S_IWRITE + S_ISVTX)) {
2986 				if (ntfs_inode_close(newdir_ni))
2987 					ret = -errno;
2988 				else
2989 					ret = ntfs_fuse_safe_rename(req, ino,
2990 							parent, name, xino,
2991 							newparent, newname,
2992 							tmp);
2993 			} else {
2994 				ntfs_inode_close(newdir_ni);
2995 				ret = -EACCES;
2996 			}
2997 		} else
2998 			ret = -errno;
2999 #else
3000 		ret = ntfs_fuse_safe_rename(req, ino, parent, name,
3001 					xino, newparent, newname, tmp);
3002 #endif
3003 	}
3004 	free(tmp);
3005 	return	ret;
3006 }
3007 
ntfs_fuse_rename(fuse_req_t req,fuse_ino_t parent,const char * name,fuse_ino_t newparent,const char * newname)3008 static void ntfs_fuse_rename(fuse_req_t req, fuse_ino_t parent,
3009 			const char *name, fuse_ino_t newparent,
3010 			const char *newname)
3011 {
3012 	int ret;
3013 	fuse_ino_t ino;
3014 	fuse_ino_t xino;
3015 	ntfs_inode *ni;
3016 
3017 	ntfs_log_debug("rename: old: '%s'  new: '%s'\n", name, newname);
3018 
3019 	/*
3020 	 *  FIXME: Rename should be atomic.
3021 	 */
3022 
3023 	ino = ntfs_fuse_inode_lookup(parent, name);
3024 	if (ino == (fuse_ino_t)-1) {
3025 		ret = -errno;
3026 		goto out;
3027 	}
3028 	/* Check whether target is present */
3029 	xino = ntfs_fuse_inode_lookup(newparent, newname);
3030 	if (xino != (fuse_ino_t)-1) {
3031 			/*
3032 			 * Target exists : no need to check whether it
3033 			 * designates the same inode, this has already
3034 			 * been checked (by fuse ?)
3035 			 */
3036 		ni = ntfs_inode_open(ctx->vol, INODE(xino));
3037 		if (!ni)
3038 			ret = -errno;
3039 		else {
3040 			ret = ntfs_check_empty_dir(ni);
3041 			if (ret < 0) {
3042 				ret = -errno;
3043 				ntfs_inode_close(ni);
3044 				goto out;
3045 			}
3046 
3047 			if (ntfs_inode_close(ni)) {
3048 				set_fuse_error(&ret);
3049 				goto out;
3050 			}
3051 			ret = ntfs_fuse_rename_existing_dest(req, ino, parent,
3052 						name, xino, newparent, newname);
3053 		}
3054 	} else {
3055 			/* target does not exist */
3056 		ret = ntfs_fuse_newlink(req, ino, newparent, newname,
3057 					(struct fuse_entry_param*)NULL);
3058 		if (ret)
3059 			goto out;
3060 
3061 		ret = ntfs_fuse_rm(req, parent, name, RM_ANY);
3062 		if (ret)
3063 			ntfs_fuse_rm(req, newparent, newname, RM_ANY);
3064 	}
3065 out:
3066 	if (ret)
3067 		fuse_reply_err(req, -ret);
3068 	else
3069 		fuse_reply_err(req, 0);
3070 }
3071 
ntfs_fuse_release(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3072 static void ntfs_fuse_release(fuse_req_t req, fuse_ino_t ino,
3073 			 struct fuse_file_info *fi)
3074 {
3075 	ntfs_inode *ni = NULL;
3076 	ntfs_attr *na = NULL;
3077 	struct open_file *of;
3078 	char ghostname[GHOSTLTH];
3079 	int res;
3080 
3081 	of = (struct open_file*)(long)fi->fh;
3082 	/* Only for marked descriptors there is something to do */
3083 	if (!of
3084 	    || !(of->state & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED
3085 				| CLOSE_DMTIME | CLOSE_REPARSE))) {
3086 		res = 0;
3087 		goto out;
3088 	}
3089 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
3090 	if (!ni) {
3091 		res = -errno;
3092 		goto exit;
3093 	}
3094 	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
3095 #ifndef DISABLE_PLUGINS
3096 		const plugin_operations_t *ops;
3097 		REPARSE_POINT *reparse;
3098 
3099 		res = CALL_REPARSE_PLUGIN(ni, release, &of->fi);
3100 		if (!res) {
3101 			goto stamps;
3102 		}
3103 #else /* DISABLE_PLUGINS */
3104 			/* Assume release() was not needed */
3105 		res = 0;
3106 #endif /* DISABLE_PLUGINS */
3107 		goto exit;
3108 	}
3109 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
3110 	if (!na) {
3111 		res = -errno;
3112 		goto exit;
3113 	}
3114 	res = 0;
3115 	if (of->state & CLOSE_COMPRESSED)
3116 		res = ntfs_attr_pclose(na);
3117 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
3118 	if (of->state & CLOSE_ENCRYPTED)
3119 		res = ntfs_efs_fixup_attribute(NULL, na);
3120 #endif /* HAVE_SETXATTR */
3121 #ifndef DISABLE_PLUGINS
3122 stamps :
3123 #endif /* DISABLE_PLUGINS */
3124 	if (of->state & CLOSE_DMTIME)
3125 		ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
3126 exit:
3127 	if (na)
3128 		ntfs_attr_close(na);
3129 	if (ntfs_inode_close(ni))
3130 		set_fuse_error(&res);
3131 out:
3132 		/* remove the associate ghost file (even if release failed) */
3133 	if (of) {
3134 		if (of->state & CLOSE_GHOST) {
3135 			sprintf(ghostname,ghostformat,of->ghost);
3136 			ntfs_fuse_rm(req, of->parent, ghostname, RM_ANY);
3137 		}
3138 			/* remove from open files list */
3139 		if (of->next)
3140 			of->next->previous = of->previous;
3141 		if (of->previous)
3142 			of->previous->next = of->next;
3143 		else
3144 			ctx->open_files = of->next;
3145 		free(of);
3146 	}
3147 	if (res)
3148 		fuse_reply_err(req, -res);
3149 	else
3150 		fuse_reply_err(req, 0);
3151 }
3152 
ntfs_fuse_mkdir(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode)3153 static void ntfs_fuse_mkdir(fuse_req_t req, fuse_ino_t parent,
3154 		       const char *name, mode_t mode)
3155 {
3156 	int res;
3157 	struct fuse_entry_param entry;
3158 
3159 	res = ntfs_fuse_create(req, parent, name, S_IFDIR | (mode & 07777),
3160 			0, &entry, (char*)NULL, (struct fuse_file_info*)NULL);
3161 	if (res < 0)
3162 		fuse_reply_err(req, -res);
3163 	else
3164 		fuse_reply_entry(req, &entry);
3165 }
3166 
ntfs_fuse_rmdir(fuse_req_t req,fuse_ino_t parent,const char * name)3167 static void ntfs_fuse_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
3168 {
3169 	int res;
3170 
3171 	res = ntfs_fuse_rm(req, parent, name, RM_DIR);
3172 	if (res)
3173 		fuse_reply_err(req, -res);
3174 	else
3175 		fuse_reply_err(req, 0);
3176 }
3177 
ntfs_fuse_fsync(fuse_req_t req,fuse_ino_t ino,int type,struct fuse_file_info * fi)3178 static void ntfs_fuse_fsync(fuse_req_t req,
3179 			fuse_ino_t ino __attribute__((unused)),
3180 			int type __attribute__((unused)),
3181 			struct fuse_file_info *fi __attribute__((unused)))
3182 {
3183 		/* sync the full device */
3184 	if (ntfs_device_sync(ctx->vol->dev))
3185 		fuse_reply_err(req, errno);
3186 	else
3187 		fuse_reply_err(req, 0);
3188 }
3189 
3190 #if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
ntfs_fuse_ioctl(fuse_req_t req,fuse_ino_t ino,int cmd,void * arg,struct fuse_file_info * fi,unsigned flags,const void * data,size_t in_bufsz,size_t out_bufsz)3191 static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)),
3192 			fuse_ino_t ino __attribute__((unused)),
3193 			int cmd, void *arg,
3194 			struct fuse_file_info *fi __attribute__((unused)),
3195 			unsigned flags, const void *data,
3196 			size_t in_bufsz, size_t out_bufsz)
3197 {
3198 	ntfs_inode *ni;
3199 	char *buf = (char*)NULL;
3200 	int bufsz;
3201 	int ret = 0;
3202 
3203 	if (flags & FUSE_IOCTL_COMPAT) {
3204 		ret = -ENOSYS;
3205 	} else {
3206 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
3207 		if (!ni) {
3208 			ret = -errno;
3209 			goto fail;
3210 		}
3211 		bufsz = (in_bufsz > out_bufsz ? in_bufsz : out_bufsz);
3212 		if (bufsz) {
3213 			buf = ntfs_malloc(bufsz);
3214 			if (!buf) {
3215 				ret = ENOMEM;
3216 				goto fail;
3217 			}
3218 			memcpy(buf, data, in_bufsz);
3219 		}
3220 		/*
3221 		 * Linux defines the request argument of ioctl() to be an
3222 		 * unsigned long, which fuse 2.x forwards as a signed int
3223 		 * into which the request sometimes does not fit.
3224 		 * So we must expand the value and make sure it is not
3225 		 * sign-extended.
3226 		 */
3227 		ret = ntfs_ioctl(ni, (unsigned int)cmd, arg, flags, buf);
3228 		if (ntfs_inode_close (ni))
3229 			set_fuse_error(&ret);
3230 	}
3231 	if (ret)
3232 fail :
3233 		fuse_reply_err(req, -ret);
3234 	else
3235 		fuse_reply_ioctl(req, 0, buf, out_bufsz);
3236 	if (buf)
3237 		free(buf);
3238 }
3239 #endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
3240 
ntfs_fuse_bmap(fuse_req_t req,fuse_ino_t ino,size_t blocksize,uint64_t vidx)3241 static void ntfs_fuse_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
3242 		      uint64_t vidx)
3243 {
3244 	ntfs_inode *ni;
3245 	ntfs_attr *na;
3246 	LCN lcn;
3247 	uint64_t lidx = 0;
3248 	int ret = 0;
3249 	int cl_per_bl = ctx->vol->cluster_size / blocksize;
3250 
3251 	if (blocksize > ctx->vol->cluster_size) {
3252 		ret = -EINVAL;
3253 		goto done;
3254 	}
3255 
3256 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
3257 	if (!ni) {
3258 		ret = -errno;
3259 		goto done;
3260 	}
3261 
3262 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
3263 	if (!na) {
3264 		ret = -errno;
3265 		goto close_inode;
3266 	}
3267 
3268 	if ((na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED))
3269 			 || !NAttrNonResident(na)) {
3270 		ret = -EINVAL;
3271 		goto close_attr;
3272 	}
3273 
3274 	if (ntfs_attr_map_whole_runlist(na)) {
3275 		ret = -errno;
3276 		goto close_attr;
3277 	}
3278 
3279 	lcn = ntfs_rl_vcn_to_lcn(na->rl, vidx / cl_per_bl);
3280 	lidx = (lcn > 0) ? lcn * cl_per_bl + vidx % cl_per_bl : 0;
3281 
3282 close_attr:
3283 	ntfs_attr_close(na);
3284 close_inode:
3285 	if (ntfs_inode_close(ni))
3286 		set_fuse_error(&ret);
3287 done :
3288 	if (ret < 0)
3289 		fuse_reply_err(req, -ret);
3290 	else
3291 		fuse_reply_bmap(req, lidx);
3292 }
3293 
3294 #ifdef HAVE_SETXATTR
3295 
3296 /*
3297  *		  Name space identifications and prefixes
3298  */
3299 
3300 enum {
3301 	XATTRNS_NONE,
3302 	XATTRNS_USER,
3303 	XATTRNS_SYSTEM,
3304 	XATTRNS_SECURITY,
3305 	XATTRNS_TRUSTED,
3306 	XATTRNS_OPEN
3307 } ;
3308 
3309 /*
3310  *		Check whether access to internal data as an extended
3311  *	attribute in system name space is allowed
3312  *
3313  *	Returns pointer to inode if allowed,
3314  *		NULL and errno set if not allowed
3315  */
3316 
ntfs_check_access_xattr(fuse_req_t req,struct SECURITY_CONTEXT * security,fuse_ino_t ino,int attr,BOOL setting)3317 static ntfs_inode *ntfs_check_access_xattr(fuse_req_t req,
3318 			struct SECURITY_CONTEXT *security,
3319 			fuse_ino_t ino, int attr, BOOL setting)
3320 {
3321 	ntfs_inode *dir_ni;
3322 	ntfs_inode *ni;
3323 	BOOL foracl;
3324 	BOOL bad;
3325 	mode_t acctype;
3326 
3327 	ni = (ntfs_inode*)NULL;
3328 	foracl = (attr == XATTR_POSIX_ACC)
3329 		 || (attr == XATTR_POSIX_DEF);
3330 	/*
3331 	 * When accessing Posix ACL, return unsupported if ACL
3332 	 * were disabled or no user mapping has been defined,
3333 	 * or trying to change a Windows-inherited ACL.
3334 	 * However no error will be returned to getfacl
3335 	 */
3336 	if (((!ntfs_fuse_fill_security_context(req, security)
3337 		|| (ctx->secure_flags
3338 		    & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_RAW))))
3339 		|| !(ctx->secure_flags & (1 << SECURITY_ACL))
3340 		|| (setting && ctx->inherit))
3341 	    && foracl) {
3342 		if (ctx->silent && !ctx->security.mapping[MAPUSERS])
3343 			errno = 0;
3344 		else
3345 			errno = EOPNOTSUPP;
3346 	} else {
3347 			/*
3348 			 * parent directory must be executable, and
3349 			 * for setting a DOS name it must be writeable
3350 			 */
3351 		if (setting && (attr == XATTR_NTFS_DOS_NAME))
3352 			acctype = S_IEXEC | S_IWRITE;
3353 		else
3354 			acctype = S_IEXEC;
3355 		ni = ntfs_inode_open(ctx->vol, INODE(ino));
3356 			/* basic access was checked previously in a lookup */
3357 		if (ni && (acctype != S_IEXEC)) {
3358 			bad = FALSE;
3359 				/* do not reopen root */
3360 			if (ni->mft_no == FILE_root) {
3361 				/* forbid getting/setting names on root */
3362 				if ((attr == XATTR_NTFS_DOS_NAME)
3363 				    || !ntfs_real_allowed_access(security,
3364 						ni, acctype))
3365 					bad = TRUE;
3366 			} else {
3367 				dir_ni = ntfs_dir_parent_inode(ni);
3368 				if (dir_ni) {
3369 					if (!ntfs_real_allowed_access(security,
3370 							dir_ni, acctype))
3371 						bad = TRUE;
3372 					if (ntfs_inode_close(dir_ni))
3373 						bad = TRUE;
3374 				} else
3375 					bad = TRUE;
3376 			}
3377 			if (bad) {
3378 				ntfs_inode_close(ni);
3379 				ni = (ntfs_inode*)NULL;
3380 			}
3381 		}
3382 	}
3383 	return (ni);
3384 }
3385 
3386 /*
3387  *		Determine the name space of an extended attribute
3388  */
3389 
xattr_namespace(const char * name)3390 static int xattr_namespace(const char *name)
3391 {
3392 	int namespace;
3393 
3394 	if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) {
3395 		namespace = XATTRNS_NONE;
3396 		if (!strncmp(name, nf_ns_user_prefix,
3397 			nf_ns_user_prefix_len)
3398 		    && (strlen(name) != (size_t)nf_ns_user_prefix_len))
3399 			namespace = XATTRNS_USER;
3400 		else if (!strncmp(name, nf_ns_system_prefix,
3401 			nf_ns_system_prefix_len)
3402 		    && (strlen(name) != (size_t)nf_ns_system_prefix_len))
3403 			namespace = XATTRNS_SYSTEM;
3404 		else if (!strncmp(name, nf_ns_security_prefix,
3405 			nf_ns_security_prefix_len)
3406 		    && (strlen(name) != (size_t)nf_ns_security_prefix_len))
3407 			namespace = XATTRNS_SECURITY;
3408 		else if (!strncmp(name, nf_ns_trusted_prefix,
3409 			nf_ns_trusted_prefix_len)
3410 		    && (strlen(name) != (size_t)nf_ns_trusted_prefix_len))
3411 			namespace = XATTRNS_TRUSTED;
3412 	} else
3413 		namespace = XATTRNS_OPEN;
3414 	return (namespace);
3415 }
3416 
3417 /*
3418  *		Fix the prefix of an extended attribute
3419  */
3420 
fix_xattr_prefix(const char * name,int namespace,ntfschar ** lename)3421 static int fix_xattr_prefix(const char *name, int namespace, ntfschar **lename)
3422 {
3423 	int len;
3424 	char *prefixed;
3425 
3426 	*lename = (ntfschar*)NULL;
3427 	switch (namespace) {
3428 	case XATTRNS_USER :
3429 		/*
3430 		 * user name space : remove user prefix
3431 		 */
3432 		len = ntfs_mbstoucs(name + nf_ns_user_prefix_len, lename);
3433 		break;
3434 	case XATTRNS_SYSTEM :
3435 	case XATTRNS_SECURITY :
3436 	case XATTRNS_TRUSTED :
3437 		/*
3438 		 * security, trusted and unmapped system name spaces :
3439 		 * insert ntfs-3g prefix
3440 		 */
3441 		prefixed = (char*)ntfs_malloc(strlen(xattr_ntfs_3g)
3442 			 + strlen(name) + 1);
3443 		if (prefixed) {
3444 			strcpy(prefixed,xattr_ntfs_3g);
3445 			strcat(prefixed,name);
3446 			len = ntfs_mbstoucs(prefixed, lename);
3447 			free(prefixed);
3448 		} else
3449 			len = -1;
3450 		break;
3451 	case XATTRNS_OPEN :
3452 		/*
3453 		 * in open name space mode : do no fix prefix
3454 		 */
3455 		len = ntfs_mbstoucs(name, lename);
3456 		break;
3457 	default :
3458 		len = -1;
3459 	}
3460 	return (len);
3461 }
3462 
ntfs_fuse_listxattr(fuse_req_t req,fuse_ino_t ino,size_t size)3463 static void ntfs_fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3464 {
3465 	ntfs_attr_search_ctx *actx = NULL;
3466 	ntfs_inode *ni;
3467 	char *list = (char*)NULL;
3468 	int ret = 0;
3469 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3470 	struct SECURITY_CONTEXT security;
3471 #endif
3472 
3473 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3474 	ntfs_fuse_fill_security_context(req, &security);
3475 #endif
3476 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
3477 	if (!ni) {
3478 		ret = -errno;
3479 		goto out;
3480 	}
3481 		/* Return with no result for symlinks, fifo, etc. */
3482 	if (!user_xattrs_allowed(ctx, ni))
3483 		goto exit;
3484 		/* otherwise file must be readable */
3485 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3486 	if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
3487 		ret = -EACCES;
3488 		goto exit;
3489 	}
3490 #endif
3491 	actx = ntfs_attr_get_search_ctx(ni, NULL);
3492 	if (!actx) {
3493 		ret = -errno;
3494 		goto exit;
3495 	}
3496 	if (size) {
3497 		list = (char*)malloc(size);
3498 		if (!list) {
3499 			ret = -errno;
3500 			goto exit;
3501 		}
3502 	}
3503 
3504 	if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
3505 	    || (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
3506 		ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
3507 				ctx->streams == NF_STREAMS_INTERFACE_XATTR);
3508 		if (ret < 0)
3509 			goto exit;
3510 	}
3511 	if (errno != ENOENT)
3512 		ret = -errno;
3513 exit:
3514 	if (actx)
3515 		ntfs_attr_put_search_ctx(actx);
3516 	if (ntfs_inode_close(ni))
3517 		set_fuse_error(&ret);
3518 out :
3519 	if (ret < 0)
3520 		fuse_reply_err(req, -ret);
3521 	else
3522 		if (size)
3523 			fuse_reply_buf(req, list, ret);
3524 		else
3525 			fuse_reply_xattr(req, ret);
3526 	free(list);
3527 }
3528 
3529 #if defined(__APPLE__) || defined(__DARWIN__)
ntfs_fuse_getxattr(fuse_req_t req,fuse_ino_t ino,const char * name,size_t size,uint32_t position)3530 static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3531 			  size_t size, uint32_t position)
3532 #else
3533 static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3534 			  size_t size)
3535 #endif
3536 {
3537 #if !(defined(__APPLE__) || defined(__DARWIN__))
3538 	static const unsigned int position = 0U;
3539 #endif
3540 
3541 	ntfs_inode *ni;
3542 	ntfs_inode *dir_ni;
3543 	ntfs_attr *na = NULL;
3544 	char *value = (char*)NULL;
3545 	ntfschar *lename = (ntfschar*)NULL;
3546 	int lename_len;
3547 	int res;
3548 	s64 rsize;
3549 	enum SYSTEMXATTRS attr;
3550 	int namespace;
3551 	struct SECURITY_CONTEXT security;
3552 
3553 #if defined(__APPLE__) || defined(__DARWIN__)
3554 	/* If the attribute is not a resource fork attribute and the position
3555 	 * parameter is non-zero, we return with EINVAL as requesting position
3556 	 * is not permitted for non-resource fork attributes. */
3557 	if (position && strcmp(name, XATTR_RESOURCEFORK_NAME)) {
3558 		fuse_reply_err(req, EINVAL);
3559 		return;
3560 	}
3561 #endif
3562 
3563 	attr = ntfs_xattr_system_type(name,ctx->vol);
3564 	if (attr != XATTR_UNMAPPED) {
3565 		/*
3566 		 * hijack internal data and ACL retrieval, whatever
3567 		 * mode was selected for xattr (from the user's
3568 		 * point of view, ACLs are not xattr)
3569 		 */
3570 		if (size)
3571 			value = (char*)ntfs_malloc(size);
3572 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3573 		if (!size || value) {
3574 			ni = ntfs_check_access_xattr(req, &security, ino,
3575 					attr, FALSE);
3576 			if (ni) {
3577 				if (ntfs_allowed_access(&security,ni,S_IREAD)) {
3578 					if (attr == XATTR_NTFS_DOS_NAME)
3579 						dir_ni = ntfs_dir_parent_inode(ni);
3580 					else
3581 						dir_ni = (ntfs_inode*)NULL;
3582 					res = ntfs_xattr_system_getxattr(&security,
3583 						attr, ni, dir_ni, value, size);
3584 					if (dir_ni && ntfs_inode_close(dir_ni))
3585 						set_fuse_error(&res);
3586 				} else
3587 					res = -errno;
3588 				if (ntfs_inode_close(ni))
3589 					set_fuse_error(&res);
3590 			} else
3591 				res = -errno;
3592 #else
3593 			/*
3594 			 * Standard access control has been done by fuse/kernel
3595 			 */
3596 		if (!size || value) {
3597 			ni = ntfs_inode_open(ctx->vol, INODE(ino));
3598 			if (ni) {
3599 					/* user mapping not mandatory */
3600 				ntfs_fuse_fill_security_context(req, &security);
3601 				if (attr == XATTR_NTFS_DOS_NAME)
3602 					dir_ni = ntfs_dir_parent_inode(ni);
3603 				else
3604 					dir_ni = (ntfs_inode*)NULL;
3605 				res = ntfs_xattr_system_getxattr(&security,
3606 					attr, ni, dir_ni, value, size);
3607 				if (dir_ni && ntfs_inode_close(dir_ni))
3608 					set_fuse_error(&res);
3609 				if (ntfs_inode_close(ni))
3610 					set_fuse_error(&res);
3611 			} else
3612 				res = -errno;
3613 #endif
3614 		} else
3615 			res = -errno;
3616 		if (res < 0)
3617 			fuse_reply_err(req, -res);
3618 		else
3619 			if (size)
3620 				fuse_reply_buf(req, value, res);
3621 			else
3622 				fuse_reply_xattr(req, res);
3623 		free(value);
3624 		return;
3625 	}
3626 	if (ctx->streams == NF_STREAMS_INTERFACE_NONE) {
3627 		res = -EOPNOTSUPP;
3628 		goto out;
3629 	}
3630 	namespace = xattr_namespace(name);
3631 	if (namespace == XATTRNS_NONE) {
3632 		res = -EOPNOTSUPP;
3633 		goto out;
3634 	}
3635 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3636 	ntfs_fuse_fill_security_context(req,&security);
3637 		/* trusted only readable by root */
3638 	if ((namespace == XATTRNS_TRUSTED)
3639 	    && security.uid) {
3640 		res = -NTFS_NOXATTR_ERRNO;
3641 		goto out;
3642 	}
3643 #endif
3644 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
3645 	if (!ni) {
3646 		res = -errno;
3647 		goto out;
3648 	}
3649 		/* Return with no result for symlinks, fifo, etc. */
3650 	if (!user_xattrs_allowed(ctx, ni)) {
3651 		res = -NTFS_NOXATTR_ERRNO;
3652 		goto exit;
3653 	}
3654 		/* otherwise file must be readable */
3655 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3656 	if (!ntfs_allowed_access(&security, ni, S_IREAD)) {
3657 		res = -errno;
3658 		goto exit;
3659 	}
3660 #endif
3661 	lename_len = fix_xattr_prefix(name, namespace, &lename);
3662 	if (lename_len == -1) {
3663 		res = -errno;
3664 		goto exit;
3665 	}
3666 	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
3667 	if (!na) {
3668 		res = -NTFS_NOXATTR_ERRNO;
3669 		goto exit;
3670 	}
3671 	rsize = na->data_size;
3672 	if (ctx->efs_raw
3673 	    && rsize
3674 	    && (na->data_flags & ATTR_IS_ENCRYPTED)
3675 	    && NAttrNonResident(na))
3676 		rsize = ((na->data_size + 511) & ~511) + 2;
3677 	rsize -= position;
3678 	if (size) {
3679 		if (size >= (size_t)rsize) {
3680 			value = (char*)ntfs_malloc(rsize);
3681 			if (value)
3682 				res = ntfs_attr_pread(na, position, rsize,
3683 						value);
3684 			if (!value || (res != rsize))
3685 				res = -errno;
3686 		} else
3687 			res = -ERANGE;
3688 	} else
3689 		res = rsize;
3690 exit:
3691 	if (na)
3692 		ntfs_attr_close(na);
3693 	free(lename);
3694 	if (ntfs_inode_close(ni))
3695 		set_fuse_error(&res);
3696 
3697 out :
3698 	if (res < 0)
3699 		fuse_reply_err(req, -res);
3700 	else
3701 		if (size)
3702 			fuse_reply_buf(req, value, res);
3703 		else
3704 			fuse_reply_xattr(req, res);
3705 	free(value);
3706 }
3707 
3708 #if defined(__APPLE__) || defined(__DARWIN__)
3709 static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3710 			  const char *value, size_t size, int flags,
3711 			  uint32_t position)
3712 #else
3713 static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3714 			  const char *value, size_t size, int flags)
3715 #endif
3716 {
3717 #if !(defined(__APPLE__) || defined(__DARWIN__))
3718 	static const unsigned int position = 0U;
3719 #else
3720 	BOOL is_resource_fork;
3721 #endif
3722 
3723 	ntfs_inode *ni;
3724 	ntfs_inode *dir_ni;
3725 	ntfs_attr *na = NULL;
3726 	ntfschar *lename = NULL;
3727 	int res, lename_len;
3728 	size_t total;
3729 	s64 part;
3730 	enum SYSTEMXATTRS attr;
3731 	int namespace;
3732 	struct SECURITY_CONTEXT security;
3733 
3734 #if defined(__APPLE__) || defined(__DARWIN__)
3735 	/* If the attribute is not a resource fork attribute and the position
3736 	 * parameter is non-zero, we return with EINVAL as requesting position
3737 	 * is not permitted for non-resource fork attributes. */
3738 	is_resource_fork = strcmp(name, XATTR_RESOURCEFORK_NAME) ? FALSE : TRUE;
3739 	if (position && !is_resource_fork) {
3740 		fuse_reply_err(req, EINVAL);
3741 		return;
3742 	}
3743 #endif
3744 
3745 	attr = ntfs_xattr_system_type(name,ctx->vol);
3746 	if (attr != XATTR_UNMAPPED) {
3747 		/*
3748 		 * hijack internal data and ACL setting, whatever
3749 		 * mode was selected for xattr (from the user's
3750 		 * point of view, ACLs are not xattr)
3751 		 * Note : ctime updated on successful settings
3752 		 */
3753 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3754 		ni = ntfs_check_access_xattr(req,&security,ino,attr,TRUE);
3755 		if (ni) {
3756 			if (ntfs_allowed_as_owner(&security, ni)) {
3757 				if (attr == XATTR_NTFS_DOS_NAME)
3758 					dir_ni = ntfs_dir_parent_inode(ni);
3759 				else
3760 					dir_ni = (ntfs_inode*)NULL;
3761 				res = ntfs_xattr_system_setxattr(&security,
3762 					attr, ni, dir_ni, value, size, flags);
3763 				/* never have to close dir_ni */
3764 				if (res)
3765 					res = -errno;
3766 			} else
3767 				res = -errno;
3768 			if (attr != XATTR_NTFS_DOS_NAME) {
3769 				if (!res)
3770 					ntfs_fuse_update_times(ni,
3771 							NTFS_UPDATE_CTIME);
3772 				if (ntfs_inode_close(ni))
3773 					set_fuse_error(&res);
3774 			}
3775 		} else
3776 			res = -errno;
3777 #else
3778 		/* creation of a new name is not controlled by fuse */
3779 		if (attr == XATTR_NTFS_DOS_NAME)
3780 			ni = ntfs_check_access_xattr(req, &security,
3781 					ino, attr, TRUE);
3782 		else
3783 			ni = ntfs_inode_open(ctx->vol, INODE(ino));
3784 		if (ni) {
3785 				/*
3786 				 * user mapping is not mandatory
3787 				 * if defined, only owner is allowed
3788 				 */
3789 			if (!ntfs_fuse_fill_security_context(req, &security)
3790 			   || ntfs_allowed_as_owner(&security, ni)) {
3791 				if (attr == XATTR_NTFS_DOS_NAME)
3792 					dir_ni = ntfs_dir_parent_inode(ni);
3793 				else
3794 					dir_ni = (ntfs_inode*)NULL;
3795 				res = ntfs_xattr_system_setxattr(&security,
3796 					attr, ni, dir_ni, value, size, flags);
3797 				/* never have to close dir_ni */
3798 				if (res)
3799 					res = -errno;
3800 			} else
3801 				res = -errno;
3802 			if (attr != XATTR_NTFS_DOS_NAME) {
3803 				if (!res)
3804 					ntfs_fuse_update_times(ni,
3805 							NTFS_UPDATE_CTIME);
3806 				if (ntfs_inode_close(ni))
3807 					set_fuse_error(&res);
3808 			}
3809 		} else
3810 			res = -errno;
3811 #endif
3812 #if CACHEING && !defined(FUSE_INTERNAL) && FUSE_VERSION >= 28
3813 		/*
3814 		 * Most of system xattr settings cause changes to some
3815 		 * file attribute (st_mode, st_nlink, st_mtime, etc.),
3816 		 * so we must invalidate cached data when cacheing is
3817 		 * in use (not possible with internal fuse or external
3818 		 * fuse before 2.8)
3819 		 */
3820 		if ((res >= 0)
3821 		    && fuse_lowlevel_notify_inval_inode(ctx->fc, ino, -1, 0))
3822 			res = -errno;
3823 #endif
3824 		if (res < 0)
3825 			fuse_reply_err(req, -res);
3826 		else
3827 			fuse_reply_err(req, 0);
3828 		return;
3829 	}
3830 	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
3831 	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
3832 		res = -EOPNOTSUPP;
3833 		goto out;
3834 		}
3835 	namespace = xattr_namespace(name);
3836 	if (namespace == XATTRNS_NONE) {
3837 		res = -EOPNOTSUPP;
3838 		goto out;
3839 	}
3840 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3841 	ntfs_fuse_fill_security_context(req,&security);
3842 		/* security and trusted only settable by root */
3843 	if (((namespace == XATTRNS_SECURITY)
3844 	   || (namespace == XATTRNS_TRUSTED))
3845 		&& security.uid) {
3846 			res = -EPERM;
3847 			goto out;
3848 		}
3849 #endif
3850 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
3851 	if (!ni) {
3852 		res = -errno;
3853 		goto out;
3854 	}
3855 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
3856 	switch (namespace) {
3857 	case XATTRNS_SECURITY :
3858 	case XATTRNS_TRUSTED :
3859 		if (security.uid) {
3860 			res = -EPERM;
3861 			goto exit;
3862 		}
3863 		break;
3864 	case XATTRNS_SYSTEM :
3865 		if (!ntfs_allowed_as_owner(&security, ni)) {
3866 			res = -EACCES;
3867 			goto exit;
3868 		}
3869 		break;
3870 	default :
3871 		/* User xattr not allowed for symlinks, fifo, etc. */
3872 		if (!user_xattrs_allowed(ctx, ni)) {
3873 			res = -EPERM;
3874 			goto exit;
3875 		}
3876 		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
3877 			res = -EACCES;
3878 			goto exit;
3879 		}
3880 		break;
3881 	}
3882 #else
3883 		/* User xattr not allowed for symlinks, fifo, etc. */
3884 	if ((namespace == XATTRNS_USER)
3885 	    && !user_xattrs_allowed(ctx, ni)) {
3886 		res = -EPERM;
3887 		goto exit;
3888 	}
3889 #endif
3890 	lename_len = fix_xattr_prefix(name, namespace, &lename);
3891 	if ((lename_len == -1)
3892 	    || (ctx->windows_names
3893 		&& ntfs_forbidden_chars(lename,lename_len,TRUE))) {
3894 		res = -errno;
3895 		goto exit;
3896 	}
3897 	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
3898 	if (na && flags == XATTR_CREATE) {
3899 		res = -EEXIST;
3900 		goto exit;
3901 	}
3902 	if (!na) {
3903 		if (flags == XATTR_REPLACE) {
3904 			res = -NTFS_NOXATTR_ERRNO;
3905 			goto exit;
3906 		}
3907 		if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {
3908 			res = -errno;
3909 			goto exit;
3910 		}
3911 		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
3912 			set_archive(ni);
3913 			NInoFileNameSetDirty(ni);
3914 		}
3915 		na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
3916 		if (!na) {
3917 			res = -errno;
3918 			goto exit;
3919 		}
3920 #if defined(__APPLE__) || defined(__DARWIN__)
3921 	} else if (is_resource_fork) {
3922 		/* In macOS, the resource fork is a special case. It doesn't
3923 		 * ever shrink (it would have to be removed and re-added). */
3924 #endif
3925 	} else {
3926 			/* currently compressed streams can only be wiped out */
3927 		if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
3928 			res = -errno;
3929 			goto exit;
3930 		}
3931 	}
3932 	total = 0;
3933 	res = 0;
3934 	if (size) {
3935 		do {
3936 			part = ntfs_attr_pwrite(na, position + total,
3937 					 size - total, &value[total]);
3938 			if (part > 0)
3939 				total += part;
3940 		} while ((part > 0) && (total < size));
3941 	}
3942 	if ((total != size) || ntfs_attr_pclose(na))
3943 		res = -errno;
3944 	else {
3945 		if (ctx->efs_raw
3946 		   && (ni->flags & FILE_ATTR_ENCRYPTED)) {
3947 			if (ntfs_efs_fixup_attribute(NULL,na))
3948 				res = -errno;
3949 		}
3950 	}
3951 	if (!res) {
3952 		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
3953 		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
3954 			set_archive(ni);
3955 			NInoFileNameSetDirty(ni);
3956 		}
3957 	}
3958 exit:
3959 	if (na)
3960 		ntfs_attr_close(na);
3961 	free(lename);
3962 	if (ntfs_inode_close(ni))
3963 		set_fuse_error(&res);
3964 out :
3965 	if (res < 0)
3966 		fuse_reply_err(req, -res);
3967 	else
3968 		fuse_reply_err(req, 0);
3969 }
3970 
3971 static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name)
3972 {
3973 	ntfs_inode *ni;
3974 	ntfs_inode *dir_ni;
3975 	ntfschar *lename = NULL;
3976 	int res = 0, lename_len;
3977 	enum SYSTEMXATTRS attr;
3978 	int namespace;
3979 	struct SECURITY_CONTEXT security;
3980 
3981 	attr = ntfs_xattr_system_type(name,ctx->vol);
3982 	if (attr != XATTR_UNMAPPED) {
3983 		switch (attr) {
3984 			/*
3985 			 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
3986 			 * is never allowed
3987 			 */
3988 		case XATTR_NTFS_ACL :
3989 		case XATTR_NTFS_ATTRIB :
3990 		case XATTR_NTFS_ATTRIB_BE :
3991 		case XATTR_NTFS_EFSINFO :
3992 		case XATTR_NTFS_TIMES :
3993 		case XATTR_NTFS_TIMES_BE :
3994 		case XATTR_NTFS_CRTIME :
3995 		case XATTR_NTFS_CRTIME_BE :
3996 			res = -EPERM;
3997 			break;
3998 		default :
3999 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
4000 			ni = ntfs_check_access_xattr(req, &security, ino,
4001 					attr,TRUE);
4002 			if (ni) {
4003 				if (ntfs_allowed_as_owner(&security, ni)) {
4004 					if (attr == XATTR_NTFS_DOS_NAME)
4005 						dir_ni = ntfs_dir_parent_inode(ni);
4006 					else
4007 						dir_ni = (ntfs_inode*)NULL;
4008 					res = ntfs_xattr_system_removexattr(&security,
4009 							attr, ni, dir_ni);
4010 					if (res)
4011 						res = -errno;
4012 					/* never have to close dir_ni */
4013 				} else
4014 					res = -errno;
4015 				if (attr != XATTR_NTFS_DOS_NAME) {
4016 					if (!res)
4017 						ntfs_fuse_update_times(ni,
4018 							NTFS_UPDATE_CTIME);
4019 					if (ntfs_inode_close(ni))
4020 						set_fuse_error(&res);
4021 				}
4022 			} else
4023 				res = -errno;
4024 #else
4025 			/* creation of a new name is not controlled by fuse */
4026 			if (attr == XATTR_NTFS_DOS_NAME)
4027 				ni = ntfs_check_access_xattr(req, &security,
4028 						ino, attr, TRUE);
4029 			else
4030 				ni = ntfs_inode_open(ctx->vol, INODE(ino));
4031 			if (ni) {
4032 				/*
4033 				 * user mapping is not mandatory
4034 				 * if defined, only owner is allowed
4035 				 */
4036 				if (!ntfs_fuse_fill_security_context(req, &security)
4037 				   || ntfs_allowed_as_owner(&security, ni)) {
4038 					if (attr == XATTR_NTFS_DOS_NAME)
4039 						dir_ni = ntfs_dir_parent_inode(ni);
4040 					else
4041 						dir_ni = (ntfs_inode*)NULL;
4042 					res = ntfs_xattr_system_removexattr(&security,
4043 						attr, ni, dir_ni);
4044 					/* never have to close dir_ni */
4045 					if (res)
4046 						res = -errno;
4047 				} else
4048 					res = -errno;
4049 				if (attr != XATTR_NTFS_DOS_NAME) {
4050 					if (!res)
4051 						ntfs_fuse_update_times(ni,
4052 							NTFS_UPDATE_CTIME);
4053 					if (ntfs_inode_close(ni))
4054 						set_fuse_error(&res);
4055 				}
4056 			} else
4057 				res = -errno;
4058 #endif
4059 #if CACHEING && !defined(FUSE_INTERNAL) && FUSE_VERSION >= 28
4060 		/*
4061 		 * Some allowed system xattr removals cause changes to
4062 		 * some file attribute (st_mode, st_nlink, etc.),
4063 		 * so we must invalidate cached data when cacheing is
4064 		 * in use (not possible with internal fuse or external
4065 		 * fuse before 2.8)
4066 		 */
4067 			if ((res >= 0)
4068 			    && fuse_lowlevel_notify_inval_inode(ctx->fc,
4069 						ino, -1, 0))
4070 				res = -errno;
4071 #endif
4072 			break;
4073 		}
4074 		if (res < 0)
4075 			fuse_reply_err(req, -res);
4076 		else
4077 			fuse_reply_err(req, 0);
4078 		return;
4079 	}
4080 	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
4081 	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
4082 		res = -EOPNOTSUPP;
4083 		goto out;
4084 	}
4085 	namespace = xattr_namespace(name);
4086 	if (namespace == XATTRNS_NONE) {
4087 		res = -EOPNOTSUPP;
4088 		goto out;
4089 	}
4090 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
4091 	ntfs_fuse_fill_security_context(req,&security);
4092 		/* security and trusted only settable by root */
4093 	if (((namespace == XATTRNS_SECURITY)
4094 	   || (namespace == XATTRNS_TRUSTED))
4095 		&& security.uid) {
4096 			res = -EACCES;
4097 			goto out;
4098 		}
4099 #endif
4100 	ni = ntfs_inode_open(ctx->vol, INODE(ino));
4101 	if (!ni) {
4102 		res = -errno;
4103 		goto out;
4104 	}
4105 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
4106 	switch (namespace) {
4107 	case XATTRNS_SECURITY :
4108 	case XATTRNS_TRUSTED :
4109 		if (security.uid) {
4110 			res = -EPERM;
4111 			goto exit;
4112 		}
4113 		break;
4114 	case XATTRNS_SYSTEM :
4115 		if (!ntfs_allowed_as_owner(&security, ni)) {
4116 			res = -EACCES;
4117 			goto exit;
4118 		}
4119 		break;
4120 	default :
4121 		/* User xattr not allowed for symlinks, fifo, etc. */
4122 		if (!user_xattrs_allowed(ctx, ni)) {
4123 			res = -EPERM;
4124 			goto exit;
4125 		}
4126 		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
4127 			res = -EACCES;
4128 			goto exit;
4129 		}
4130 		break;
4131 	}
4132 #else
4133 		/* User xattr not allowed for symlinks, fifo, etc. */
4134 	if ((namespace == XATTRNS_USER)
4135 	    && !user_xattrs_allowed(ctx, ni)) {
4136 		res = -EPERM;
4137 		goto exit;
4138 	}
4139 #endif
4140 	lename_len = fix_xattr_prefix(name, namespace, &lename);
4141 	if (lename_len == -1) {
4142 		res = -errno;
4143 		goto exit;
4144 	}
4145 	if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {
4146 		if (errno == ENOENT)
4147 			errno = NTFS_NOXATTR_ERRNO;
4148 		res = -errno;
4149 	}
4150 	if (!res) {
4151 		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
4152 		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
4153 			set_archive(ni);
4154 			NInoFileNameSetDirty(ni);
4155 		}
4156 	}
4157 exit:
4158 	free(lename);
4159 	if (ntfs_inode_close(ni))
4160 		set_fuse_error(&res);
4161 out :
4162 	if (res < 0)
4163 		fuse_reply_err(req, -res);
4164 	else
4165 		fuse_reply_err(req, 0);
4166 	return;
4167 
4168 }
4169 
4170 #else
4171 #if POSIXACLS
4172 #error "Option inconsistency : POSIXACLS requires SETXATTR"
4173 #endif
4174 #endif /* HAVE_SETXATTR */
4175 
4176 #ifndef DISABLE_PLUGINS
4177 static void register_internal_reparse_plugins(void)
4178 {
4179 	static const plugin_operations_t ops = {
4180 		.getattr = junction_getstat,
4181 		.readlink = junction_readlink,
4182 	} ;
4183 	static const plugin_operations_t wsl_ops = {
4184 		.getattr = wsl_getstat,
4185 	} ;
4186 	register_reparse_plugin(ctx, IO_REPARSE_TAG_MOUNT_POINT,
4187 					&ops, (void*)NULL);
4188 	register_reparse_plugin(ctx, IO_REPARSE_TAG_SYMLINK,
4189 					&ops, (void*)NULL);
4190 	register_reparse_plugin(ctx, IO_REPARSE_TAG_LX_SYMLINK,
4191 					&ops, (void*)NULL);
4192 	register_reparse_plugin(ctx, IO_REPARSE_TAG_AF_UNIX,
4193 					&wsl_ops, (void*)NULL);
4194 	register_reparse_plugin(ctx, IO_REPARSE_TAG_LX_FIFO,
4195 					&wsl_ops, (void*)NULL);
4196 	register_reparse_plugin(ctx, IO_REPARSE_TAG_LX_CHR,
4197 					&wsl_ops, (void*)NULL);
4198 	register_reparse_plugin(ctx, IO_REPARSE_TAG_LX_BLK,
4199 					&wsl_ops, (void*)NULL);
4200 }
4201 #endif /* DISABLE_PLUGINS */
4202 
4203 static void ntfs_close(void)
4204 {
4205 	struct SECURITY_CONTEXT security;
4206 
4207 	if (!ctx)
4208 		return;
4209 
4210 	if (!ctx->vol)
4211 		return;
4212 
4213 	if (ctx->mounted) {
4214 		ntfs_log_info("Unmounting %s (%s)\n", opts.device,
4215 			      ctx->vol->vol_name);
4216 		if (ntfs_fuse_fill_security_context((fuse_req_t)NULL, &security)) {
4217 			if (ctx->seccache && ctx->seccache->head.p_reads) {
4218 				ntfs_log_info("Permissions cache : %lu writes, "
4219 				"%lu reads, %lu.%1lu%% hits\n",
4220 			      ctx->seccache->head.p_writes,
4221 			      ctx->seccache->head.p_reads,
4222 			      100 * ctx->seccache->head.p_hits
4223 				 / ctx->seccache->head.p_reads,
4224 			      1000 * ctx->seccache->head.p_hits
4225 				 / ctx->seccache->head.p_reads % 10);
4226 			}
4227 		}
4228 		ntfs_destroy_security_context(&security);
4229 	}
4230 
4231 	if (ntfs_umount(ctx->vol, FALSE))
4232 		ntfs_log_perror("Failed to close volume %s", opts.device);
4233 
4234 	ctx->vol = NULL;
4235 }
4236 
4237 static void ntfs_fuse_destroy2(void *notused __attribute__((unused)))
4238 {
4239 	ntfs_close();
4240 }
4241 
4242 static struct fuse_lowlevel_ops ntfs_3g_ops = {
4243 	.lookup 	= ntfs_fuse_lookup,
4244 	.getattr	= ntfs_fuse_getattr,
4245 	.readlink	= ntfs_fuse_readlink,
4246 	.opendir	= ntfs_fuse_opendir,
4247 	.readdir	= ntfs_fuse_readdir,
4248 	.releasedir	= ntfs_fuse_releasedir,
4249 	.open		= ntfs_fuse_open,
4250 	.release	= ntfs_fuse_release,
4251 	.read		= ntfs_fuse_read,
4252 	.write		= ntfs_fuse_write,
4253 	.setattr	= ntfs_fuse_setattr,
4254 	.statfs 	= ntfs_fuse_statfs,
4255 	.create 	= ntfs_fuse_create_file,
4256 	.mknod		= ntfs_fuse_mknod,
4257 	.symlink	= ntfs_fuse_symlink,
4258 	.link		= ntfs_fuse_link,
4259 	.unlink 	= ntfs_fuse_unlink,
4260 	.rename 	= ntfs_fuse_rename,
4261 	.mkdir		= ntfs_fuse_mkdir,
4262 	.rmdir		= ntfs_fuse_rmdir,
4263 	.fsync		= ntfs_fuse_fsync,
4264 	.fsyncdir	= ntfs_fuse_fsync,
4265 	.bmap		= ntfs_fuse_bmap,
4266 	.destroy	= ntfs_fuse_destroy2,
4267 #if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
4268 	.ioctl		= ntfs_fuse_ioctl,
4269 #endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
4270 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
4271 	.access 	= ntfs_fuse_access,
4272 #endif
4273 #ifdef HAVE_SETXATTR
4274 	.getxattr	= ntfs_fuse_getxattr,
4275 	.setxattr	= ntfs_fuse_setxattr,
4276 	.removexattr	= ntfs_fuse_removexattr,
4277 	.listxattr	= ntfs_fuse_listxattr,
4278 #endif /* HAVE_SETXATTR */
4279 #if 0 && (defined(__APPLE__) || defined(__DARWIN__)) /* Unfinished. */
4280 	/* MacFUSE extensions. */
4281 	.getxtimes	= ntfs_macfuse_getxtimes,
4282 	.setcrtime	= ntfs_macfuse_setcrtime,
4283 	.setbkuptime	= ntfs_macfuse_setbkuptime,
4284 	.setchgtime	= ntfs_macfuse_setchgtime,
4285 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
4286 	.init		= ntfs_init
4287 };
4288 
4289 static int ntfs_fuse_init(void)
4290 {
4291 	ctx = (ntfs_fuse_context_t*)ntfs_calloc(sizeof(ntfs_fuse_context_t));
4292 	if (!ctx)
4293 		return -1;
4294 
4295 	*ctx = (ntfs_fuse_context_t) {
4296 		.uid	 = getuid(),
4297 		.gid	 = getgid(),
4298 #if defined(linux)
4299 		.streams = NF_STREAMS_INTERFACE_XATTR,
4300 #else
4301 		.streams = NF_STREAMS_INTERFACE_NONE,
4302 #endif
4303 		.atime	 = ATIME_RELATIVE,
4304 		.silent  = TRUE,
4305 		.recover = TRUE
4306 	};
4307 	return 0;
4308 }
4309 
4310 static int ntfs_open(const char *device)
4311 {
4312 	unsigned long flags = 0;
4313 	ntfs_volume *vol;
4314 
4315 	if (!ctx->blkdev)
4316 		flags |= NTFS_MNT_EXCLUSIVE;
4317 	if (ctx->ro)
4318 		flags |= NTFS_MNT_RDONLY;
4319 	else
4320 		if (!ctx->hiberfile)
4321 			flags |= NTFS_MNT_MAY_RDONLY;
4322 	if (ctx->recover)
4323 		flags |= NTFS_MNT_RECOVER;
4324 	if (ctx->hiberfile)
4325 		flags |= NTFS_MNT_IGNORE_HIBERFILE;
4326 
4327 	ctx->vol = vol = ntfs_mount(device, flags);
4328 	if (!vol) {
4329 		ntfs_log_perror("Failed to mount '%s'", device);
4330 		goto err_out;
4331 	}
4332 	if (ctx->sync && ctx->vol->dev)
4333 		NDevSetSync(ctx->vol->dev);
4334 	if (ctx->compression)
4335 		NVolSetCompression(ctx->vol);
4336 	else
4337 		NVolClearCompression(ctx->vol);
4338 #ifdef HAVE_SETXATTR
4339 			/* archivers must see hidden files */
4340 	if (ctx->efs_raw)
4341 		ctx->hide_hid_files = FALSE;
4342 #endif
4343 	if (ntfs_set_shown_files(ctx->vol, ctx->show_sys_files,
4344 				!ctx->hide_hid_files, ctx->hide_dot_files))
4345 		goto err_out;
4346 
4347 	if (ctx->ignore_case && ntfs_set_ignore_case(vol))
4348 		goto err_out;
4349 
4350 	if (ntfs_volume_get_free_space(ctx->vol)) {
4351 		ntfs_log_perror("Failed to read NTFS $Bitmap");
4352 		goto err_out;
4353 	}
4354 
4355 	vol->free_mft_records = ntfs_get_nr_free_mft_records(vol);
4356 	if (vol->free_mft_records < 0) {
4357 		ntfs_log_perror("Failed to calculate free MFT records");
4358 		goto err_out;
4359 	}
4360 
4361 	if (ctx->hiberfile && ntfs_volume_check_hiberfile(vol, 0)) {
4362 		if (errno != EPERM)
4363 			goto err_out;
4364 		if (ntfs_fuse_rm((fuse_req_t)NULL,FILE_root,"hiberfil.sys",
4365 					RM_LINK))
4366 			goto err_out;
4367 	}
4368 
4369 	errno = 0;
4370 	goto out;
4371 err_out:
4372 	if (!errno)	/* Make sure to return an error */
4373 		errno = EIO;
4374 out :
4375 	return ntfs_volume_error(errno);
4376 }
4377 
4378 static void usage(void)
4379 {
4380 	ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
4381 			5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING,
4382 			EXEC_NAME, ntfs_home);
4383 }
4384 
4385 #if defined(linux) || defined(__uClinux__)
4386 
4387 static const char *dev_fuse_msg =
4388 "HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
4389 "      kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'"
4390 "      or insmod <path_to>/fuse.o'). Make also sure that the fuse device"
4391 "      exists. It's usually either /dev/fuse or /dev/misc/fuse.";
4392 
4393 static const char *fuse26_kmod_msg =
4394 "WARNING: Deficient Linux kernel detected. Some driver features are\n"
4395 "         not available (swap file on NTFS, boot from NTFS by LILO), and\n"
4396 "         unmount is not safe unless it's made sure the ntfs-3g process\n"
4397 "         naturally terminates after calling 'umount'. If you wish this\n"
4398 "         message to disappear then you should upgrade to at least kernel\n"
4399 "         version 2.6.20, or request help from your distribution to fix\n"
4400 "         the kernel problem. The below web page has more information:\n"
4401 "         https://github.com/tuxera/ntfs-3g/wiki/NTFS-3G-FAQ\n"
4402 "\n";
4403 
4404 static void mknod_dev_fuse(const char *dev)
4405 {
4406 	struct stat st;
4407 
4408 	if (stat(dev, &st) && (errno == ENOENT)) {
4409 		mode_t mask = umask(0);
4410 		if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {
4411 			ntfs_log_perror("Failed to create '%s'", dev);
4412 			if (errno == EPERM)
4413 				ntfs_log_error("%s", dev_fuse_msg);
4414 		}
4415 		umask(mask);
4416 	}
4417 }
4418 
4419 static void create_dev_fuse(void)
4420 {
4421 	mknod_dev_fuse("/dev/fuse");
4422 
4423 #ifdef __UCLIBC__
4424 	{
4425 		struct stat st;
4426 		/* The fuse device is under /dev/misc using devfs. */
4427 		if (stat("/dev/misc", &st) && (errno == ENOENT)) {
4428 			mode_t mask = umask(0);
4429 			mkdir("/dev/misc", 0775);
4430 			umask(mask);
4431 		}
4432 		mknod_dev_fuse("/dev/misc/fuse");
4433 	}
4434 #endif
4435 }
4436 
4437 static fuse_fstype get_fuse_fstype(void)
4438 {
4439 	char buf[256];
4440 	fuse_fstype fstype = FSTYPE_NONE;
4441 
4442 	FILE *f = fopen("/proc/filesystems", "r");
4443 	if (!f) {
4444 		ntfs_log_perror("Failed to open /proc/filesystems");
4445 		return FSTYPE_UNKNOWN;
4446 	}
4447 
4448 	while (fgets(buf, sizeof(buf), f)) {
4449 		if (strstr(buf, "fuseblk\n")) {
4450 			fstype = FSTYPE_FUSEBLK;
4451 			break;
4452 		}
4453 		if (strstr(buf, "fuse\n"))
4454 			fstype = FSTYPE_FUSE;
4455 	}
4456 
4457 	fclose(f);
4458 	return fstype;
4459 }
4460 
4461 static fuse_fstype load_fuse_module(void)
4462 {
4463 	int i;
4464 	struct stat st;
4465 	pid_t pid;
4466 	const char *cmd = "/sbin/modprobe";
4467 	char *env = (char*)NULL;
4468 	struct timespec req = { 0, 100000000 };   /* 100 msec */
4469 	fuse_fstype fstype;
4470 
4471 	if (!stat(cmd, &st) && !geteuid()) {
4472 		pid = fork();
4473 		if (!pid) {
4474 			execle(cmd, cmd, "fuse", (char*)NULL, &env);
4475 			_exit(1);
4476 		} else if (pid != -1)
4477 			waitpid(pid, NULL, 0);
4478 	}
4479 
4480 	for (i = 0; i < 10; i++) {
4481 		/*
4482 		 * We sleep first because despite the detection of the loaded
4483 		 * FUSE kernel module, fuse_mount() can still fail if it's not
4484 		 * fully functional/initialized. Note, of course this is still
4485 		 * unreliable but usually helps.
4486 		 */
4487 		nanosleep(&req, NULL);
4488 		fstype = get_fuse_fstype();
4489 		if (fstype != FSTYPE_NONE)
4490 			break;
4491 	}
4492 	return fstype;
4493 }
4494 
4495 #endif
4496 
4497 static struct fuse_chan *try_fuse_mount(char *parsed_options)
4498 {
4499 	struct fuse_chan *fc = NULL;
4500 	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
4501 
4502 	/* The fuse_mount() options get modified, so we always rebuild it */
4503 	if ((fuse_opt_add_arg(&margs, EXEC_NAME) == -1 ||
4504 	     fuse_opt_add_arg(&margs, "-o") == -1 ||
4505 	     fuse_opt_add_arg(&margs, parsed_options) == -1)) {
4506 		ntfs_log_error("Failed to set FUSE options.\n");
4507 		goto free_args;
4508 	}
4509 
4510 	fc = fuse_mount(opts.mnt_point, &margs);
4511 free_args:
4512 	fuse_opt_free_args(&margs);
4513 	return fc;
4514 
4515 }
4516 
4517 static int set_fuseblk_options(char **parsed_options)
4518 {
4519 	char options[64];
4520 	long pagesize;
4521 	u32 blksize = ctx->vol->cluster_size;
4522 
4523 	pagesize = sysconf(_SC_PAGESIZE);
4524 	if (pagesize < 1)
4525 		pagesize = 4096;
4526 
4527 	if (blksize > (u32)pagesize)
4528 		blksize = pagesize;
4529 
4530 	snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
4531 	if (ntfs_strappend(parsed_options, options))
4532 		return -1;
4533 	return 0;
4534 }
4535 
4536 static struct fuse_session *mount_fuse(char *parsed_options)
4537 {
4538 	struct fuse_session *se = NULL;
4539 	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4540 
4541 	ctx->fc = try_fuse_mount(parsed_options);
4542 	if (!ctx->fc)
4543 		return NULL;
4544 
4545 	if (fuse_opt_add_arg(&args, "") == -1)
4546 		goto err;
4547 	if (ctx->debug)
4548 		if (fuse_opt_add_arg(&args, "-odebug") == -1)
4549 			goto err;
4550 
4551 	se = fuse_lowlevel_new(&args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);
4552 	if (!se)
4553 		goto err;
4554 
4555 
4556 	if (fuse_set_signal_handlers(se))
4557 		goto err_destroy;
4558 	fuse_session_add_chan(se, ctx->fc);
4559 out:
4560 	fuse_opt_free_args(&args);
4561 	return se;
4562 err_destroy:
4563 	fuse_session_destroy(se);
4564 	se = NULL;
4565 err:
4566 	fuse_unmount(opts.mnt_point, ctx->fc);
4567 	goto out;
4568 }
4569 
4570 static void setup_logging(char *parsed_options)
4571 {
4572 	if (!ctx->no_detach) {
4573 		if (daemon(0, ctx->debug))
4574 			ntfs_log_error("Failed to daemonize.\n");
4575 		else if (!ctx->debug) {
4576 #ifndef DEBUG
4577 			ntfs_log_set_handler(ntfs_log_handler_syslog);
4578 			/* Override default libntfs identify. */
4579 			openlog(EXEC_NAME, LOG_PID, LOG_DAEMON);
4580 #endif
4581 		}
4582 	}
4583 
4584 	ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
4585 
4586 	ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
4587 	if (strcmp(opts.arg_device,opts.device))
4588 		ntfs_log_info("Requested device %s canonicalized as %s\n",
4589 				opts.arg_device,opts.device);
4590 	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
4591 			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
4592 			ctx->vol->vol_name, ctx->vol->major_ver,
4593 			ctx->vol->minor_ver);
4594 	ntfs_log_info("Cmdline options: %s\n", opts.options ? opts.options : "");
4595 	ntfs_log_info("Mount options: %s\n", parsed_options);
4596 }
4597 
4598 int main(int argc, char *argv[])
4599 {
4600 	char *parsed_options = NULL;
4601 	struct fuse_session *se;
4602 #if !(defined(__sun) && defined (__SVR4))
4603 	fuse_fstype fstype = FSTYPE_UNKNOWN;
4604 #endif
4605 	const char *permissions_mode = (const char*)NULL;
4606 	const char *failed_secure = (const char*)NULL;
4607 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
4608 	struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
4609 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
4610 	struct stat sbuf;
4611 	unsigned long existing_mount;
4612 	int err, fd;
4613 
4614 	/*
4615 	 * Make sure file descriptors 0, 1 and 2 are open,
4616 	 * otherwise chaos would ensue.
4617 	 */
4618 	do {
4619 		fd = open("/dev/null", O_RDWR);
4620 		if (fd > 2)
4621 			close(fd);
4622 	} while (fd >= 0 && fd <= 2);
4623 
4624 #ifndef FUSE_INTERNAL
4625 	if ((getuid() != geteuid()) || (getgid() != getegid())) {
4626 		fprintf(stderr, "%s", setuid_msg);
4627 		return NTFS_VOLUME_INSECURE;
4628 	}
4629 #endif
4630 	if (drop_privs())
4631 		return NTFS_VOLUME_NO_PRIVILEGE;
4632 
4633 	ntfs_set_locale();
4634 	ntfs_log_set_handler(ntfs_log_handler_stderr);
4635 
4636 	if (ntfs_parse_options(&opts, usage, argc, argv)) {
4637 		usage();
4638 		return NTFS_VOLUME_SYNTAX_ERROR;
4639 	}
4640 
4641 	if (ntfs_fuse_init()) {
4642 		err = NTFS_VOLUME_OUT_OF_MEMORY;
4643 		goto err2;
4644 	}
4645 
4646 	parsed_options = parse_mount_options(ctx, &opts, TRUE);
4647 	if (!parsed_options) {
4648 		err = NTFS_VOLUME_SYNTAX_ERROR;
4649 		goto err_out;
4650 	}
4651 	if (!ntfs_check_if_mounted(opts.device,&existing_mount)
4652 	    && (existing_mount & NTFS_MF_MOUNTED)
4653 		/* accept multiple read-only mounts */
4654 	    && (!(existing_mount & NTFS_MF_READONLY) || !ctx->ro)) {
4655 		err = NTFS_VOLUME_LOCKED;
4656 		goto err_out;
4657 	}
4658 
4659 			/* need absolute mount point for junctions */
4660 	if (opts.mnt_point[0] == '/')
4661 		ctx->abs_mnt_point = strdup(opts.mnt_point);
4662 	else {
4663 		ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
4664 		if (ctx->abs_mnt_point) {
4665 			if ((strlen(opts.mnt_point) < PATH_MAX)
4666 			    && getcwd(ctx->abs_mnt_point,
4667 				     PATH_MAX - strlen(opts.mnt_point) - 1)) {
4668 				strcat(ctx->abs_mnt_point, "/");
4669 				strcat(ctx->abs_mnt_point, opts.mnt_point);
4670 #if defined(__sun) && defined (__SVR4)
4671 			/* Solaris also wants the absolute mount point */
4672 				opts.mnt_point = ctx->abs_mnt_point;
4673 #endif /* defined(__sun) && defined (__SVR4) */
4674 			} else {
4675 				free(ctx->abs_mnt_point);
4676 				ctx->abs_mnt_point = (char*)NULL;
4677 			}
4678 		}
4679 	}
4680 	if (!ctx->abs_mnt_point) {
4681 		err = NTFS_VOLUME_OUT_OF_MEMORY;
4682 		goto err_out;
4683 	}
4684 
4685 	ctx->security.uid = 0;
4686 	ctx->security.gid = 0;
4687 	if ((opts.mnt_point[0] == '/')
4688 	   && !stat(opts.mnt_point,&sbuf)) {
4689 		/* collect owner of mount point, useful for default mapping */
4690 		ctx->security.uid = sbuf.st_uid;
4691 		ctx->security.gid = sbuf.st_gid;
4692 	}
4693 
4694 #if defined(linux) || defined(__uClinux__)
4695 	fstype = get_fuse_fstype();
4696 
4697 	err = NTFS_VOLUME_NO_PRIVILEGE;
4698 	if (restore_privs())
4699 		goto err_out;
4700 
4701 	if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)
4702 		fstype = load_fuse_module();
4703 	create_dev_fuse();
4704 
4705 	if (drop_privs())
4706 		goto err_out;
4707 #endif
4708 	if (stat(opts.device, &sbuf)) {
4709 		ntfs_log_perror("Failed to access '%s'", opts.device);
4710 		err = NTFS_VOLUME_NO_PRIVILEGE;
4711 		goto err_out;
4712 	}
4713 
4714 #if !(defined(__sun) && defined (__SVR4))
4715 	/* Always use fuseblk for block devices unless it's surely missing. */
4716 	if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
4717 		ctx->blkdev = TRUE;
4718 #endif
4719 
4720 #ifndef FUSE_INTERNAL
4721 	if (getuid() && ctx->blkdev) {
4722 		ntfs_log_error("%s", unpriv_fuseblk_msg);
4723 		err = NTFS_VOLUME_NO_PRIVILEGE;
4724 		goto err2;
4725 	}
4726 #endif
4727 	err = ntfs_open(opts.device);
4728 	if (err)
4729 		goto err_out;
4730 
4731 	/* Force read-only mount if the device was found read-only */
4732 	if (!ctx->ro && NVolReadOnly(ctx->vol)) {
4733 		ctx->rw = FALSE;
4734 		ctx->ro = TRUE;
4735 		if (ntfs_strinsert(&parsed_options, ",ro"))
4736                 	goto err_out;
4737 		ntfs_log_info("Could not mount read-write, trying read-only\n");
4738 	} else
4739 		if (ctx->rw && ntfs_strinsert(&parsed_options, ",rw"))
4740 			goto err_out;
4741 	/* We must do this after ntfs_open() to be able to set the blksize */
4742 	if (ctx->blkdev && set_fuseblk_options(&parsed_options))
4743 		goto err_out;
4744 
4745 	ctx->vol->abs_mnt_point = ctx->abs_mnt_point;
4746 	ctx->vol->special_files = ctx->special_files;
4747 	ctx->security.vol = ctx->vol;
4748 	ctx->vol->secure_flags = ctx->secure_flags;
4749 #ifdef HAVE_SETXATTR	/* extended attributes interface required */
4750 	ctx->vol->efs_raw = ctx->efs_raw;
4751 #endif /* HAVE_SETXATTR */
4752 	if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path,
4753 		(ctx->vol->secure_flags
4754 			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
4755 		&& !ctx->inherit
4756 		&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
4757 #if POSIXACLS
4758 		/* use basic permissions if requested */
4759 		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
4760 			permissions_mode = "User mapping built, Posix ACLs not used";
4761 		else {
4762 			permissions_mode = "User mapping built, Posix ACLs in use";
4763 #if KERNELACLS
4764 			if (ntfs_strinsert(&parsed_options,
4765 					",default_permissions,acl")) {
4766 				err = NTFS_VOLUME_SYNTAX_ERROR;
4767 				goto err_out;
4768 			}
4769 #endif /* KERNELACLS */
4770 		}
4771 #else /* POSIXACLS */
4772 		if (!(ctx->vol->secure_flags
4773 			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
4774 			/*
4775 			 * No explicit option but user mapping found
4776 			 * force default security
4777 			 */
4778 #if KERNELPERMS
4779 			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
4780 			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
4781 				err = NTFS_VOLUME_SYNTAX_ERROR;
4782 				goto err_out;
4783 			}
4784 #endif /* KERNELPERMS */
4785 		}
4786 		permissions_mode = "User mapping built";
4787 #endif /* POSIXACLS */
4788 		ctx->dmask = ctx->fmask = 0;
4789 	} else {
4790 		ctx->security.uid = ctx->uid;
4791 		ctx->security.gid = ctx->gid;
4792 		/* same ownership/permissions for all files */
4793 		ctx->security.mapping[MAPUSERS] = (struct MAPPING*)NULL;
4794 		ctx->security.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
4795 		if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
4796 		   && !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
4797 			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
4798 			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
4799 				err = NTFS_VOLUME_SYNTAX_ERROR;
4800 				goto err_out;
4801 			}
4802 		}
4803 		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) {
4804 			ctx->vol->secure_flags |= (1 << SECURITY_RAW);
4805 			permissions_mode = "Global ownership and permissions enforced";
4806 		} else {
4807 			ctx->vol->secure_flags &= ~(1 << SECURITY_RAW);
4808 			permissions_mode = "Ownership and permissions disabled";
4809 		}
4810 	}
4811 	if (ctx->usermap_path)
4812 		free (ctx->usermap_path);
4813 
4814 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
4815 	xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
4816 				ctx->xattrmap_path);
4817 	ctx->vol->xattr_mapping = xattr_mapping;
4818 	/*
4819 	 * Errors are logged, do not refuse mounting, it would be
4820 	 * too difficult to fix the unmountable mapping file.
4821 	 */
4822 	if (ctx->xattrmap_path)
4823 		free(ctx->xattrmap_path);
4824 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
4825 
4826 #ifndef DISABLE_PLUGINS
4827 	register_internal_reparse_plugins();
4828 #endif /* DISABLE_PLUGINS */
4829 
4830 	se = mount_fuse(parsed_options);
4831 	if (!se) {
4832 		err = NTFS_VOLUME_FUSE_ERROR;
4833 		goto err_out;
4834 	}
4835 
4836 	ctx->mounted = TRUE;
4837 
4838 #if defined(linux) || defined(__uClinux__)
4839 	if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
4840 		ntfs_log_info("%s", fuse26_kmod_msg);
4841 #endif
4842 	setup_logging(parsed_options);
4843 	if (failed_secure)
4844 		ntfs_log_info("%s\n",failed_secure);
4845 	if (permissions_mode)
4846 		ntfs_log_info("%s, configuration type %d\n",permissions_mode,
4847 			5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING);
4848 
4849 	fuse_session_loop(se);
4850 	fuse_remove_signal_handlers(se);
4851 
4852 	err = 0;
4853 
4854 	fuse_unmount(opts.mnt_point, ctx->fc);
4855 	fuse_session_destroy(se);
4856 err_out:
4857 	ntfs_mount_error(opts.device, opts.mnt_point, err);
4858 	if (ctx->abs_mnt_point)
4859 		free(ctx->abs_mnt_point);
4860 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
4861 	ntfs_xattr_free_mapping(xattr_mapping);
4862 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
4863 err2:
4864 	ntfs_close();
4865 #ifndef DISABLE_PLUGINS
4866 	close_reparse_plugins(ctx);
4867 #endif /* DISABLE_PLUGINS */
4868 	free(ctx);
4869 	free(parsed_options);
4870 	free(opts.options);
4871 	free(opts.device);
4872 	return err;
4873 }
4874 
4875