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