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