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