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