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