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