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