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