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