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