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