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