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