"Fossies" - the Fresh Open Source Software Archive

Member "ntfs-3g_ntfsprogs-2017.3.23/src/lowntfs-3g.c" (23 Mar 2017, 114713 Bytes) of package /linux/misc/ntfs-3g_ntfsprogs-2017.3.23.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lowntfs-3g.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3g_ntfsprogs-2016.2.22_vs_3g_ntfsprogs-2017.3.23.

    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  */
  286 static int drop_privs(void)    { return 0; }
  287 #if defined(linux) || defined(__uClinux__)
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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-&gt;vol, NULL, path);
  599     if (!ni)
  600         return -errno;
  601 
  602     if (tv) {
  603         ni-&gt;last_mft_change_time = tv-&gt;tv_sec;
  604         ntfs_fuse_update_times(ni, 0);
  605     }
  606 
  607     if (ntfs_inode_close(ni))
  608         set_fuse_error(&amp;res);
  609     return res;
  610 }
  611 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
  612 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
 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 
 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 
 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                 &current->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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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)
 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 
 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     if (ret < 0)
 3014         fuse_reply_err(req, -ret);
 3015     else
 3016         fuse_reply_bmap(req, lidx);
 3017 }
 3018 
 3019 #ifdef HAVE_SETXATTR
 3020 
 3021 /*
 3022  *        Name space identifications and prefixes
 3023  */
 3024 
 3025 enum {
 3026     XATTRNS_NONE,
 3027     XATTRNS_USER,
 3028     XATTRNS_SYSTEM,
 3029     XATTRNS_SECURITY,
 3030     XATTRNS_TRUSTED,
 3031     XATTRNS_OPEN
 3032 } ;
 3033 
 3034 /*
 3035  *      Check whether access to internal data as an extended
 3036  *  attribute in system name space is allowed
 3037  *
 3038  *  Returns pointer to inode if allowed,
 3039  *      NULL and errno set if not allowed
 3040  */
 3041 
 3042 static ntfs_inode *ntfs_check_access_xattr(fuse_req_t req,
 3043             struct SECURITY_CONTEXT *security,
 3044             fuse_ino_t ino, int attr, BOOL setting)
 3045 {
 3046     ntfs_inode *dir_ni;
 3047     ntfs_inode *ni;
 3048     BOOL foracl;
 3049     BOOL bad;
 3050     mode_t acctype;
 3051 
 3052     ni = (ntfs_inode*)NULL;
 3053     foracl = (attr == XATTR_POSIX_ACC)
 3054          || (attr == XATTR_POSIX_DEF);
 3055     /*
 3056      * When accessing Posix ACL, return unsupported if ACL
 3057      * were disabled or no user mapping has been defined,
 3058      * or trying to change a Windows-inherited ACL.
 3059      * However no error will be returned to getfacl
 3060      */
 3061     if (((!ntfs_fuse_fill_security_context(req, security)
 3062         || (ctx->secure_flags
 3063             & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_RAW))))
 3064         || !(ctx->secure_flags & (1 << SECURITY_ACL))
 3065         || (setting && ctx->inherit))
 3066         && foracl) {
 3067         if (ctx->silent)
 3068             errno = 0;
 3069         else
 3070             errno = EOPNOTSUPP;
 3071     } else {
 3072             /*
 3073              * parent directory must be executable, and
 3074              * for setting a DOS name it must be writeable
 3075              */
 3076         if (setting && (attr == XATTR_NTFS_DOS_NAME))
 3077             acctype = S_IEXEC | S_IWRITE;
 3078         else
 3079             acctype = S_IEXEC;
 3080         ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3081             /* basic access was checked previously in a lookup */
 3082         if (ni && (acctype != S_IEXEC)) {
 3083             bad = FALSE;
 3084                 /* do not reopen root */
 3085             if (ni->mft_no == FILE_root) {
 3086                 /* forbid getting/setting names on root */
 3087                 if ((attr == XATTR_NTFS_DOS_NAME)
 3088                     || !ntfs_real_allowed_access(security,
 3089                         ni, acctype))
 3090                     bad = TRUE;
 3091             } else {
 3092                 dir_ni = ntfs_dir_parent_inode(ni);
 3093                 if (dir_ni) {
 3094                     if (!ntfs_real_allowed_access(security,
 3095                             dir_ni, acctype))
 3096                         bad = TRUE;
 3097                     if (ntfs_inode_close(dir_ni))
 3098                         bad = TRUE;
 3099                 } else
 3100                     bad = TRUE;
 3101             }
 3102             if (bad) {
 3103                 ntfs_inode_close(ni);
 3104                 ni = (ntfs_inode*)NULL;
 3105             }
 3106         }
 3107     }
 3108     return (ni);
 3109 }
 3110 
 3111 /*
 3112  *      Determine the name space of an extended attribute
 3113  */
 3114 
 3115 static int xattr_namespace(const char *name)
 3116 {
 3117     int namespace;
 3118 
 3119     if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) {
 3120         namespace = XATTRNS_NONE;
 3121         if (!strncmp(name, nf_ns_user_prefix, 
 3122             nf_ns_user_prefix_len)
 3123             && (strlen(name) != (size_t)nf_ns_user_prefix_len))
 3124             namespace = XATTRNS_USER;
 3125         else if (!strncmp(name, nf_ns_system_prefix, 
 3126             nf_ns_system_prefix_len)
 3127             && (strlen(name) != (size_t)nf_ns_system_prefix_len))
 3128             namespace = XATTRNS_SYSTEM;
 3129         else if (!strncmp(name, nf_ns_security_prefix, 
 3130             nf_ns_security_prefix_len)
 3131             && (strlen(name) != (size_t)nf_ns_security_prefix_len))
 3132             namespace = XATTRNS_SECURITY;
 3133         else if (!strncmp(name, nf_ns_trusted_prefix, 
 3134             nf_ns_trusted_prefix_len)
 3135             && (strlen(name) != (size_t)nf_ns_trusted_prefix_len))
 3136             namespace = XATTRNS_TRUSTED;
 3137     } else
 3138         namespace = XATTRNS_OPEN;
 3139     return (namespace);
 3140 }
 3141 
 3142 /*
 3143  *      Fix the prefix of an extended attribute
 3144  */
 3145 
 3146 static int fix_xattr_prefix(const char *name, int namespace, ntfschar **lename)
 3147 {
 3148     int len;
 3149     char *prefixed;
 3150 
 3151     *lename = (ntfschar*)NULL;
 3152     switch (namespace) {
 3153     case XATTRNS_USER :
 3154         /*
 3155          * user name space : remove user prefix
 3156          */
 3157         len = ntfs_mbstoucs(name + nf_ns_user_prefix_len, lename);
 3158         break;
 3159     case XATTRNS_SYSTEM :
 3160     case XATTRNS_SECURITY :
 3161     case XATTRNS_TRUSTED :
 3162         /*
 3163          * security, trusted and unmapped system name spaces :
 3164          * insert ntfs-3g prefix
 3165          */
 3166         prefixed = (char*)ntfs_malloc(strlen(xattr_ntfs_3g)
 3167              + strlen(name) + 1);
 3168         if (prefixed) {
 3169             strcpy(prefixed,xattr_ntfs_3g);
 3170             strcat(prefixed,name);
 3171             len = ntfs_mbstoucs(prefixed, lename);
 3172             free(prefixed);
 3173         } else
 3174             len = -1;
 3175         break;
 3176     case XATTRNS_OPEN :
 3177         /*
 3178          * in open name space mode : do no fix prefix
 3179          */
 3180         len = ntfs_mbstoucs(name, lename);
 3181         break;
 3182     default :
 3183         len = -1;
 3184     }
 3185     return (len);
 3186 }
 3187 
 3188 static void ntfs_fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
 3189 {
 3190     ntfs_attr_search_ctx *actx = NULL;
 3191     ntfs_inode *ni;
 3192     char *list = (char*)NULL;
 3193     int ret = 0;
 3194 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3195     struct SECURITY_CONTEXT security;
 3196 #endif
 3197 
 3198 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3199     ntfs_fuse_fill_security_context(req, &security);
 3200 #endif
 3201     ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3202     if (!ni) {
 3203         ret = -errno;
 3204         goto out;
 3205     }
 3206         /* Return with no result for symlinks, fifo, etc. */
 3207     if (!user_xattrs_allowed(ctx, ni))
 3208         goto exit;
 3209         /* otherwise file must be readable */
 3210 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3211     if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
 3212         ret = -EACCES;
 3213         goto exit;
 3214     }
 3215 #endif
 3216     actx = ntfs_attr_get_search_ctx(ni, NULL);
 3217     if (!actx) {
 3218         ret = -errno;
 3219         goto exit;
 3220     }
 3221     if (size) {
 3222         list = (char*)malloc(size);
 3223         if (!list) {
 3224             ret = -errno;
 3225             goto exit;
 3226         }
 3227     }
 3228 
 3229     if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
 3230         || (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
 3231         ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
 3232                 ctx->streams == NF_STREAMS_INTERFACE_XATTR);
 3233         if (ret < 0)
 3234             goto exit;
 3235     }
 3236     if (errno != ENOENT)
 3237         ret = -errno;
 3238 exit:
 3239     if (actx)
 3240         ntfs_attr_put_search_ctx(actx);
 3241     if (ntfs_inode_close(ni))
 3242         set_fuse_error(&ret);
 3243 out :
 3244     if (ret < 0)
 3245         fuse_reply_err(req, -ret);
 3246     else
 3247         if (size)
 3248             fuse_reply_buf(req, list, ret);
 3249         else
 3250             fuse_reply_xattr(req, ret);
 3251     free(list);
 3252 }
 3253 
 3254 static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
 3255               size_t size)
 3256 {
 3257     ntfs_inode *ni;
 3258     ntfs_inode *dir_ni;
 3259     ntfs_attr *na = NULL;
 3260     char *value = (char*)NULL;
 3261     ntfschar *lename = (ntfschar*)NULL;
 3262     int lename_len;
 3263     int res;
 3264     s64 rsize;
 3265     enum SYSTEMXATTRS attr;
 3266     int namespace;
 3267     struct SECURITY_CONTEXT security;
 3268 
 3269     attr = ntfs_xattr_system_type(name,ctx->vol);
 3270     if (attr != XATTR_UNMAPPED) {
 3271         /*
 3272          * hijack internal data and ACL retrieval, whatever
 3273          * mode was selected for xattr (from the user's
 3274          * point of view, ACLs are not xattr)
 3275          */
 3276         if (size)
 3277             value = (char*)ntfs_malloc(size);
 3278 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3279         if (!size || value) {
 3280             ni = ntfs_check_access_xattr(req, &security, ino,
 3281                     attr, FALSE);
 3282             if (ni) {
 3283                 if (ntfs_allowed_access(&security,ni,S_IREAD)) {
 3284                     if (attr == XATTR_NTFS_DOS_NAME)
 3285                         dir_ni = ntfs_dir_parent_inode(ni);
 3286                     else
 3287                         dir_ni = (ntfs_inode*)NULL;
 3288                     res = ntfs_xattr_system_getxattr(&security,
 3289                         attr, ni, dir_ni, value, size);
 3290                     if (dir_ni && ntfs_inode_close(dir_ni))
 3291                         set_fuse_error(&res);
 3292                 } else
 3293                     res = -errno;
 3294                 if (ntfs_inode_close(ni))
 3295                     set_fuse_error(&res);
 3296             } else
 3297                 res = -errno;
 3298 #else
 3299             /*
 3300              * Standard access control has been done by fuse/kernel
 3301              */
 3302         if (!size || value) {
 3303             ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3304             if (ni) {
 3305                     /* user mapping not mandatory */
 3306                 ntfs_fuse_fill_security_context(req, &security);
 3307                 if (attr == XATTR_NTFS_DOS_NAME)
 3308                     dir_ni = ntfs_dir_parent_inode(ni);
 3309                 else
 3310                     dir_ni = (ntfs_inode*)NULL;
 3311                 res = ntfs_xattr_system_getxattr(&security,
 3312                     attr, ni, dir_ni, value, size);
 3313                 if (dir_ni && ntfs_inode_close(dir_ni))
 3314                     set_fuse_error(&res);
 3315                 if (ntfs_inode_close(ni))
 3316                     set_fuse_error(&res);
 3317             } else
 3318                 res = -errno;
 3319 #endif
 3320         } else
 3321             res = -errno;
 3322         if (res < 0)
 3323             fuse_reply_err(req, -res);
 3324         else
 3325             if (size)
 3326                 fuse_reply_buf(req, value, res);
 3327             else
 3328                 fuse_reply_xattr(req, res);
 3329         free(value);
 3330         return;
 3331     }
 3332     if (ctx->streams == NF_STREAMS_INTERFACE_NONE) {
 3333         res = -EOPNOTSUPP;
 3334         goto out;
 3335     }
 3336     namespace = xattr_namespace(name);
 3337     if (namespace == XATTRNS_NONE) {
 3338         res = -EOPNOTSUPP;
 3339         goto out;
 3340     }
 3341 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3342     ntfs_fuse_fill_security_context(req,&security);
 3343         /* trusted only readable by root */
 3344     if ((namespace == XATTRNS_TRUSTED)
 3345         && security.uid) {
 3346         res = -ENODATA;
 3347         goto out;
 3348     }
 3349 #endif
 3350     ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3351     if (!ni) {
 3352         res = -errno;
 3353         goto out;
 3354     }
 3355         /* Return with no result for symlinks, fifo, etc. */
 3356     if (!user_xattrs_allowed(ctx, ni)) {
 3357         res = -ENODATA;
 3358         goto exit;
 3359     }
 3360         /* otherwise file must be readable */
 3361 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3362     if (!ntfs_allowed_access(&security, ni, S_IREAD)) {
 3363         res = -errno;
 3364         goto exit;
 3365     }
 3366 #endif
 3367     lename_len = fix_xattr_prefix(name, namespace, &lename);
 3368     if (lename_len == -1) {
 3369         res = -errno;
 3370         goto exit;
 3371     }
 3372     na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
 3373     if (!na) {
 3374         res = -ENODATA;
 3375         goto exit;
 3376     }
 3377     rsize = na->data_size;
 3378     if (ctx->efs_raw
 3379         && rsize
 3380         && (na->data_flags & ATTR_IS_ENCRYPTED)
 3381         && NAttrNonResident(na))
 3382         rsize = ((na->data_size + 511) & ~511) + 2;
 3383     if (size) {
 3384         if (size >= (size_t)rsize) {
 3385             value = (char*)ntfs_malloc(rsize);
 3386             if (value)
 3387                 res = ntfs_attr_pread(na, 0, rsize, value);
 3388             if (!value || (res != rsize))
 3389                 res = -errno;
 3390         } else
 3391             res = -ERANGE;
 3392     } else
 3393         res = rsize;
 3394 exit:
 3395     if (na)
 3396         ntfs_attr_close(na);
 3397     free(lename);
 3398     if (ntfs_inode_close(ni))
 3399         set_fuse_error(&res);
 3400 
 3401 out :
 3402     if (res < 0)
 3403         fuse_reply_err(req, -res);
 3404     else
 3405         if (size)
 3406             fuse_reply_buf(req, value, res);
 3407         else
 3408             fuse_reply_xattr(req, res);
 3409     free(value);
 3410 }
 3411 
 3412 static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
 3413               const char *value, size_t size, int flags)
 3414 {
 3415     ntfs_inode *ni;
 3416     ntfs_inode *dir_ni;
 3417     ntfs_attr *na = NULL;
 3418     ntfschar *lename = NULL;
 3419     int res, lename_len;
 3420     size_t total;
 3421     s64 part;
 3422     enum SYSTEMXATTRS attr;
 3423     int namespace;
 3424     struct SECURITY_CONTEXT security;
 3425 
 3426     attr = ntfs_xattr_system_type(name,ctx->vol);
 3427     if (attr != XATTR_UNMAPPED) {
 3428         /*
 3429          * hijack internal data and ACL setting, whatever
 3430          * mode was selected for xattr (from the user's
 3431          * point of view, ACLs are not xattr)
 3432          * Note : ctime updated on successful settings
 3433          */
 3434 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3435         ni = ntfs_check_access_xattr(req,&security,ino,attr,TRUE);
 3436         if (ni) {
 3437             if (ntfs_allowed_as_owner(&security, ni)) {
 3438                 if (attr == XATTR_NTFS_DOS_NAME)
 3439                     dir_ni = ntfs_dir_parent_inode(ni);
 3440                 else
 3441                     dir_ni = (ntfs_inode*)NULL;
 3442                 res = ntfs_xattr_system_setxattr(&security,
 3443                     attr, ni, dir_ni, value, size, flags);
 3444                 /* never have to close dir_ni */
 3445                 if (res)
 3446                     res = -errno;
 3447             } else
 3448                 res = -errno;
 3449             if (attr != XATTR_NTFS_DOS_NAME) {
 3450                 if (!res)
 3451                     ntfs_fuse_update_times(ni,
 3452                             NTFS_UPDATE_CTIME);
 3453                 if (ntfs_inode_close(ni))
 3454                     set_fuse_error(&res);
 3455             }
 3456         } else
 3457             res = -errno;
 3458 #else
 3459         /* creation of a new name is not controlled by fuse */
 3460         if (attr == XATTR_NTFS_DOS_NAME)
 3461             ni = ntfs_check_access_xattr(req, &security,
 3462                     ino, attr, TRUE);
 3463         else
 3464             ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3465         if (ni) {
 3466                 /*
 3467                  * user mapping is not mandatory
 3468                  * if defined, only owner is allowed
 3469                  */
 3470             if (!ntfs_fuse_fill_security_context(req, &security)
 3471                || ntfs_allowed_as_owner(&security, ni)) {
 3472                 if (attr == XATTR_NTFS_DOS_NAME)
 3473                     dir_ni = ntfs_dir_parent_inode(ni);
 3474                 else
 3475                     dir_ni = (ntfs_inode*)NULL;
 3476                 res = ntfs_xattr_system_setxattr(&security,
 3477                     attr, ni, dir_ni, value, size, flags);
 3478                 /* never have to close dir_ni */
 3479                 if (res)
 3480                     res = -errno;
 3481             } else
 3482                 res = -errno;
 3483             if (attr != XATTR_NTFS_DOS_NAME) {
 3484                 if (!res)
 3485                     ntfs_fuse_update_times(ni,
 3486                             NTFS_UPDATE_CTIME);
 3487                 if (ntfs_inode_close(ni))
 3488                     set_fuse_error(&res);
 3489             }
 3490         } else
 3491             res = -errno;
 3492 #endif
 3493 #if CACHEING && !defined(FUSE_INTERNAL)
 3494         /*
 3495          * Most of system xattr settings cause changes to some
 3496          * file attribute (st_mode, st_nlink, st_mtime, etc.),
 3497          * so we must invalidate cached data when cacheing is
 3498          * in use (not possible with internal fuse or external
 3499          * fuse before 2.8)
 3500          */
 3501         if ((res >= 0)
 3502             && fuse_lowlevel_notify_inval_inode(ctx->fc, ino, -1, 0))
 3503             res = -errno;
 3504 #endif
 3505         if (res < 0)
 3506             fuse_reply_err(req, -res);
 3507         else
 3508             fuse_reply_err(req, 0);
 3509         return;
 3510     }
 3511     if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
 3512         && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
 3513         res = -EOPNOTSUPP;
 3514         goto out;
 3515         }
 3516     namespace = xattr_namespace(name);
 3517     if (namespace == XATTRNS_NONE) {
 3518         res = -EOPNOTSUPP;
 3519         goto out;
 3520     }
 3521 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3522     ntfs_fuse_fill_security_context(req,&security);
 3523         /* security and trusted only settable by root */
 3524     if (((namespace == XATTRNS_SECURITY)
 3525        || (namespace == XATTRNS_TRUSTED))
 3526         && security.uid) {
 3527             res = -EPERM;
 3528             goto out;
 3529         }
 3530 #endif
 3531     ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3532     if (!ni) {
 3533         res = -errno;
 3534         goto out;
 3535     }
 3536 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3537     switch (namespace) {
 3538     case XATTRNS_SECURITY :
 3539     case XATTRNS_TRUSTED :
 3540         if (security.uid) {
 3541             res = -EPERM;
 3542             goto exit;
 3543         }
 3544         break;
 3545     case XATTRNS_SYSTEM :
 3546         if (!ntfs_allowed_as_owner(&security, ni)) {
 3547             res = -EACCES;
 3548             goto exit;
 3549         }
 3550         break;
 3551     default :
 3552         /* User xattr not allowed for symlinks, fifo, etc. */
 3553         if (!user_xattrs_allowed(ctx, ni)) {
 3554             res = -EPERM;
 3555             goto exit;
 3556         }
 3557         if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
 3558             res = -EACCES;
 3559             goto exit;
 3560         }
 3561         break;
 3562     }
 3563 #else
 3564         /* User xattr not allowed for symlinks, fifo, etc. */
 3565     if ((namespace == XATTRNS_USER)
 3566         && !user_xattrs_allowed(ctx, ni)) {
 3567         res = -EPERM;
 3568         goto exit;
 3569     }
 3570 #endif
 3571     lename_len = fix_xattr_prefix(name, namespace, &lename);
 3572     if ((lename_len == -1)
 3573         || (ctx->windows_names
 3574         && ntfs_forbidden_chars(lename,lename_len,TRUE))) {
 3575         res = -errno;
 3576         goto exit;
 3577     }
 3578     na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
 3579     if (na && flags == XATTR_CREATE) {
 3580         res = -EEXIST;
 3581         goto exit;
 3582     }
 3583     if (!na) {
 3584         if (flags == XATTR_REPLACE) {
 3585             res = -ENODATA;
 3586             goto exit;
 3587         }
 3588         if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {
 3589             res = -errno;
 3590             goto exit;
 3591         }
 3592         if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
 3593             set_archive(ni);
 3594             NInoFileNameSetDirty(ni);
 3595         }
 3596         na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
 3597         if (!na) {
 3598             res = -errno;
 3599             goto exit;
 3600         }
 3601     } else {
 3602             /* currently compressed streams can only be wiped out */
 3603         if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
 3604             res = -errno;
 3605             goto exit;
 3606         }
 3607     }
 3608     total = 0;
 3609     res = 0;
 3610     if (size) {
 3611         do {
 3612             part = ntfs_attr_pwrite(na, total, size - total,
 3613                      &value[total]);
 3614             if (part > 0)
 3615                 total += part;
 3616         } while ((part > 0) && (total < size));
 3617     }
 3618     if ((total != size) || ntfs_attr_pclose(na))
 3619         res = -errno;
 3620     else {
 3621         if (ctx->efs_raw 
 3622            && (ni->flags & FILE_ATTR_ENCRYPTED)) {
 3623             if (ntfs_efs_fixup_attribute(NULL,na))
 3624                 res = -errno;
 3625         }
 3626     }
 3627     if (!res) {
 3628         ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
 3629         if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
 3630             set_archive(ni);
 3631             NInoFileNameSetDirty(ni);
 3632         }
 3633     }
 3634 exit:
 3635     if (na)
 3636         ntfs_attr_close(na);
 3637     free(lename);
 3638     if (ntfs_inode_close(ni))
 3639         set_fuse_error(&res);
 3640 out :
 3641     if (res < 0)
 3642         fuse_reply_err(req, -res);
 3643     else
 3644         fuse_reply_err(req, 0);
 3645 }
 3646 
 3647 static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name)
 3648 {
 3649     ntfs_inode *ni;
 3650     ntfs_inode *dir_ni;
 3651     ntfschar *lename = NULL;
 3652     int res = 0, lename_len;
 3653     enum SYSTEMXATTRS attr;
 3654     int namespace;
 3655     struct SECURITY_CONTEXT security;
 3656 
 3657     attr = ntfs_xattr_system_type(name,ctx->vol);
 3658     if (attr != XATTR_UNMAPPED) {
 3659         switch (attr) {
 3660             /*
 3661              * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
 3662              * is never allowed
 3663              */
 3664         case XATTR_NTFS_ACL :
 3665         case XATTR_NTFS_ATTRIB :
 3666         case XATTR_NTFS_ATTRIB_BE :
 3667         case XATTR_NTFS_EFSINFO :
 3668         case XATTR_NTFS_TIMES :
 3669         case XATTR_NTFS_TIMES_BE :
 3670         case XATTR_NTFS_CRTIME :
 3671         case XATTR_NTFS_CRTIME_BE :
 3672             res = -EPERM;
 3673             break;
 3674         default :
 3675 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3676             ni = ntfs_check_access_xattr(req, &security, ino,
 3677                     attr,TRUE);
 3678             if (ni) {
 3679                 if (ntfs_allowed_as_owner(&security, ni)) {
 3680                     if (attr == XATTR_NTFS_DOS_NAME)
 3681                         dir_ni = ntfs_dir_parent_inode(ni);
 3682                     else
 3683                         dir_ni = (ntfs_inode*)NULL;
 3684                     res = ntfs_xattr_system_removexattr(&security,
 3685                             attr, ni, dir_ni);
 3686                     if (res)
 3687                         res = -errno;
 3688                     /* never have to close dir_ni */
 3689                 } else
 3690                     res = -errno;
 3691                 if (attr != XATTR_NTFS_DOS_NAME) {
 3692                     if (!res)
 3693                         ntfs_fuse_update_times(ni,
 3694                             NTFS_UPDATE_CTIME);
 3695                     if (ntfs_inode_close(ni))
 3696                         set_fuse_error(&res);
 3697                 }
 3698             } else
 3699                 res = -errno;
 3700 #else
 3701             /* creation of a new name is not controlled by fuse */
 3702             if (attr == XATTR_NTFS_DOS_NAME)
 3703                 ni = ntfs_check_access_xattr(req, &security,
 3704                         ino, attr, TRUE);
 3705             else
 3706                 ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3707             if (ni) {
 3708                 /*
 3709                  * user mapping is not mandatory
 3710                  * if defined, only owner is allowed
 3711                  */
 3712                 if (!ntfs_fuse_fill_security_context(req, &security)
 3713                    || ntfs_allowed_as_owner(&security, ni)) {
 3714                     if (attr == XATTR_NTFS_DOS_NAME)
 3715                         dir_ni = ntfs_dir_parent_inode(ni);
 3716                     else
 3717                         dir_ni = (ntfs_inode*)NULL;
 3718                     res = ntfs_xattr_system_removexattr(&security,
 3719                         attr, ni, dir_ni);
 3720                     /* never have to close dir_ni */
 3721                     if (res)
 3722                         res = -errno;
 3723                 } else
 3724                     res = -errno;
 3725                 if (attr != XATTR_NTFS_DOS_NAME) {
 3726                     if (!res)
 3727                         ntfs_fuse_update_times(ni,
 3728                             NTFS_UPDATE_CTIME);
 3729                     if (ntfs_inode_close(ni))
 3730                         set_fuse_error(&res);
 3731                 }
 3732             } else
 3733                 res = -errno;
 3734 #endif
 3735 #if CACHEING && !defined(FUSE_INTERNAL)
 3736         /*
 3737          * Some allowed system xattr removals cause changes to
 3738          * some file attribute (st_mode, st_nlink, etc.),
 3739          * so we must invalidate cached data when cacheing is
 3740          * in use (not possible with internal fuse or external
 3741          * fuse before 2.8)
 3742          */
 3743             if ((res >= 0)
 3744                 && fuse_lowlevel_notify_inval_inode(ctx->fc,
 3745                         ino, -1, 0))
 3746                 res = -errno;
 3747 #endif
 3748             break;
 3749         }
 3750         if (res < 0)
 3751             fuse_reply_err(req, -res);
 3752         else
 3753             fuse_reply_err(req, 0);
 3754         return;
 3755     }
 3756     if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
 3757         && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
 3758         res = -EOPNOTSUPP;
 3759         goto out;
 3760     }
 3761     namespace = xattr_namespace(name);
 3762     if (namespace == XATTRNS_NONE) {
 3763         res = -EOPNOTSUPP;
 3764         goto out;
 3765     }
 3766 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3767     ntfs_fuse_fill_security_context(req,&security);
 3768         /* security and trusted only settable by root */
 3769     if (((namespace == XATTRNS_SECURITY)
 3770        || (namespace == XATTRNS_TRUSTED))
 3771         && security.uid) {
 3772             res = -EACCES;
 3773             goto out;
 3774         }
 3775 #endif
 3776     ni = ntfs_inode_open(ctx->vol, INODE(ino));
 3777     if (!ni) {
 3778         res = -errno;
 3779         goto out;
 3780     }
 3781 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3782     switch (namespace) {
 3783     case XATTRNS_SECURITY :
 3784     case XATTRNS_TRUSTED :
 3785         if (security.uid) {
 3786             res = -EPERM;
 3787             goto exit;
 3788         }
 3789         break;
 3790     case XATTRNS_SYSTEM :
 3791         if (!ntfs_allowed_as_owner(&security, ni)) {
 3792             res = -EACCES;
 3793             goto exit;
 3794         }
 3795         break;
 3796     default :
 3797         /* User xattr not allowed for symlinks, fifo, etc. */
 3798         if (!user_xattrs_allowed(ctx, ni)) {
 3799             res = -EPERM;
 3800             goto exit;
 3801         }
 3802         if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
 3803             res = -EACCES;
 3804             goto exit;
 3805         }
 3806         break;
 3807     }
 3808 #else
 3809         /* User xattr not allowed for symlinks, fifo, etc. */
 3810     if ((namespace == XATTRNS_USER)
 3811         && !user_xattrs_allowed(ctx, ni)) {
 3812         res = -EPERM;
 3813         goto exit;
 3814     }
 3815 #endif
 3816     lename_len = fix_xattr_prefix(name, namespace, &lename);
 3817     if (lename_len == -1) {
 3818         res = -errno;
 3819         goto exit;
 3820     }
 3821     if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {
 3822         if (errno == ENOENT)
 3823             errno = ENODATA;
 3824         res = -errno;
 3825     }
 3826     if (!res) {
 3827         ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
 3828         if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
 3829             set_archive(ni);
 3830             NInoFileNameSetDirty(ni);
 3831         }
 3832     }
 3833 exit:
 3834     free(lename);
 3835     if (ntfs_inode_close(ni))
 3836         set_fuse_error(&res);
 3837 out :
 3838     if (res < 0)
 3839         fuse_reply_err(req, -res);
 3840     else
 3841         fuse_reply_err(req, 0);
 3842     return;
 3843 
 3844 }
 3845 
 3846 #else
 3847 #if POSIXACLS
 3848 #error "Option inconsistency : POSIXACLS requires SETXATTR"
 3849 #endif
 3850 #endif /* HAVE_SETXATTR */
 3851 
 3852 #ifndef DISABLE_PLUGINS
 3853 static void register_internal_reparse_plugins(void)
 3854 {
 3855     static const plugin_operations_t ops = {
 3856         .getattr = junction_getstat,
 3857         .readlink = junction_readlink,
 3858     } ;
 3859     register_reparse_plugin(ctx, IO_REPARSE_TAG_MOUNT_POINT,
 3860                     &ops, (void*)NULL);
 3861     register_reparse_plugin(ctx, IO_REPARSE_TAG_SYMLINK,
 3862                     &ops, (void*)NULL);
 3863 }
 3864 #endif /* DISABLE_PLUGINS */
 3865 
 3866 static void ntfs_close(void)
 3867 {
 3868     struct SECURITY_CONTEXT security;
 3869 
 3870     if (!ctx)
 3871         return;
 3872         
 3873     if (!ctx->vol)
 3874         return;
 3875         
 3876     if (ctx->mounted) {
 3877         ntfs_log_info("Unmounting %s (%s)\n", opts.device, 
 3878                   ctx->vol->vol_name);
 3879         if (ntfs_fuse_fill_security_context((fuse_req_t)NULL, &security)) {
 3880             if (ctx->seccache && ctx->seccache->head.p_reads) {
 3881                 ntfs_log_info("Permissions cache : %lu writes, "
 3882                 "%lu reads, %lu.%1lu%% hits\n",
 3883                   ctx->seccache->head.p_writes,
 3884                   ctx->seccache->head.p_reads,
 3885                   100 * ctx->seccache->head.p_hits
 3886                  / ctx->seccache->head.p_reads,
 3887                   1000 * ctx->seccache->head.p_hits
 3888                  / ctx->seccache->head.p_reads % 10);
 3889             }
 3890         }
 3891         ntfs_destroy_security_context(&security);
 3892     }
 3893         
 3894     if (ntfs_umount(ctx->vol, FALSE))
 3895         ntfs_log_perror("Failed to close volume %s", opts.device);
 3896         
 3897     ctx->vol = NULL;
 3898 }
 3899 
 3900 static void ntfs_fuse_destroy2(void *notused __attribute__((unused)))
 3901 {
 3902     ntfs_close();
 3903 }
 3904 
 3905 static struct fuse_lowlevel_ops ntfs_3g_ops = {
 3906     .lookup     = ntfs_fuse_lookup,
 3907     .getattr    = ntfs_fuse_getattr,
 3908     .readlink   = ntfs_fuse_readlink,
 3909     .opendir    = ntfs_fuse_opendir,
 3910     .readdir    = ntfs_fuse_readdir,
 3911     .releasedir = ntfs_fuse_releasedir,
 3912     .open       = ntfs_fuse_open,
 3913     .release    = ntfs_fuse_release,
 3914     .read       = ntfs_fuse_read,
 3915     .write      = ntfs_fuse_write,
 3916     .setattr    = ntfs_fuse_setattr,
 3917     .statfs     = ntfs_fuse_statfs,
 3918     .create     = ntfs_fuse_create_file,
 3919     .mknod      = ntfs_fuse_mknod,
 3920     .symlink    = ntfs_fuse_symlink,
 3921     .link       = ntfs_fuse_link,
 3922     .unlink     = ntfs_fuse_unlink,
 3923     .rename     = ntfs_fuse_rename,
 3924     .mkdir      = ntfs_fuse_mkdir,
 3925     .rmdir      = ntfs_fuse_rmdir,
 3926     .fsync      = ntfs_fuse_fsync,
 3927     .fsyncdir   = ntfs_fuse_fsync,
 3928     .bmap       = ntfs_fuse_bmap,
 3929     .destroy    = ntfs_fuse_destroy2,
 3930 #if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
 3931     .ioctl      = ntfs_fuse_ioctl,
 3932 #endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
 3933 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
 3934     .access     = ntfs_fuse_access,
 3935 #endif
 3936 #ifdef HAVE_SETXATTR
 3937     .getxattr   = ntfs_fuse_getxattr,
 3938     .setxattr   = ntfs_fuse_setxattr,
 3939     .removexattr    = ntfs_fuse_removexattr,
 3940     .listxattr  = ntfs_fuse_listxattr,
 3941 #endif /* HAVE_SETXATTR */
 3942 #if 0 && (defined(__APPLE__) || defined(__DARWIN__)) /* Unfinished. */
 3943     /* MacFUSE extensions. */
 3944     .getxtimes  = ntfs_macfuse_getxtimes,
 3945     .setcrtime  = ntfs_macfuse_setcrtime,
 3946     .setbkuptime    = ntfs_macfuse_setbkuptime,
 3947     .setchgtime = ntfs_macfuse_setchgtime,
 3948 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
 3949     .init       = ntfs_init
 3950 };
 3951 
 3952 static int ntfs_fuse_init(void)
 3953 {
 3954     ctx = (ntfs_fuse_context_t*)ntfs_calloc(sizeof(ntfs_fuse_context_t));
 3955     if (!ctx)
 3956         return -1;
 3957         
 3958     *ctx = (ntfs_fuse_context_t) {
 3959         .uid     = getuid(),
 3960         .gid     = getgid(),
 3961 #if defined(linux)              
 3962         .streams = NF_STREAMS_INTERFACE_XATTR,
 3963 #else               
 3964         .streams = NF_STREAMS_INTERFACE_NONE,
 3965 #endif              
 3966         .atime   = ATIME_RELATIVE,
 3967         .silent  = TRUE,
 3968         .recover = TRUE
 3969     };
 3970     return 0;
 3971 }
 3972 
 3973 static int ntfs_open(const char *device)
 3974 {
 3975     unsigned long flags = 0;
 3976     ntfs_volume *vol;
 3977         
 3978     if (!ctx->blkdev)
 3979         flags |= NTFS_MNT_EXCLUSIVE;
 3980     if (ctx->ro)
 3981         flags |= NTFS_MNT_RDONLY;
 3982     else
 3983         if (!ctx->hiberfile)
 3984             flags |= NTFS_MNT_MAY_RDONLY;
 3985     if (ctx->recover)
 3986         flags |= NTFS_MNT_RECOVER;
 3987     if (ctx->hiberfile)
 3988         flags |= NTFS_MNT_IGNORE_HIBERFILE;
 3989 
 3990     ctx->vol = vol = ntfs_mount(device, flags);
 3991     if (!vol) {
 3992         ntfs_log_perror("Failed to mount '%s'", device);
 3993         goto err_out;
 3994     }
 3995     if (ctx->sync && ctx->vol->dev)
 3996         NDevSetSync(ctx->vol->dev);
 3997     if (ctx->compression)
 3998         NVolSetCompression(ctx->vol);
 3999     else
 4000         NVolClearCompression(ctx->vol);
 4001 #ifdef HAVE_SETXATTR
 4002             /* archivers must see hidden files */
 4003     if (ctx->efs_raw)
 4004         ctx->hide_hid_files = FALSE;
 4005 #endif
 4006     if (ntfs_set_shown_files(ctx->vol, ctx->show_sys_files,
 4007                 !ctx->hide_hid_files, ctx->hide_dot_files))
 4008         goto err_out;
 4009 
 4010     if (ctx->ignore_case && ntfs_set_ignore_case(vol))
 4011         goto err_out;
 4012         
 4013     vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
 4014     if (vol->free_clusters < 0) {
 4015         ntfs_log_perror("Failed to read NTFS $Bitmap");
 4016         goto err_out;
 4017     }
 4018 
 4019     vol->free_mft_records = ntfs_get_nr_free_mft_records(vol);
 4020     if (vol->free_mft_records < 0) {
 4021         ntfs_log_perror("Failed to calculate free MFT records");
 4022         goto err_out;
 4023     }
 4024 
 4025     if (ctx->hiberfile && ntfs_volume_check_hiberfile(vol, 0)) {
 4026         if (errno != EPERM)
 4027             goto err_out;
 4028         if (ntfs_fuse_rm((fuse_req_t)NULL,FILE_root,"hiberfil.sys",
 4029                     RM_LINK))
 4030             goto err_out;
 4031     }
 4032         
 4033     errno = 0;
 4034 err_out:
 4035     return ntfs_volume_error(errno);
 4036         
 4037 }
 4038 
 4039 static void usage(void)
 4040 {
 4041     ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
 4042             5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING,
 4043             EXEC_NAME, ntfs_home);
 4044 }
 4045 
 4046 #if defined(linux) || defined(__uClinux__)
 4047 
 4048 static const char *dev_fuse_msg =
 4049 "HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
 4050 "      kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'"
 4051 "      or insmod <path_to>/fuse.o'). Make also sure that the fuse device"
 4052 "      exists. It's usually either /dev/fuse or /dev/misc/fuse.";
 4053 
 4054 static const char *fuse26_kmod_msg =
 4055 "WARNING: Deficient Linux kernel detected. Some driver features are\n"
 4056 "         not available (swap file on NTFS, boot from NTFS by LILO), and\n"
 4057 "         unmount is not safe unless it's made sure the ntfs-3g process\n"
 4058 "         naturally terminates after calling 'umount'. If you wish this\n"
 4059 "         message to disappear then you should upgrade to at least kernel\n"
 4060 "         version 2.6.20, or request help from your distribution to fix\n"
 4061 "         the kernel problem. The below web page has more information:\n"
 4062 "         http://tuxera.com/community/ntfs-3g-faq/#fuse26\n"
 4063 "\n";
 4064 
 4065 static void mknod_dev_fuse(const char *dev)
 4066 {
 4067     struct stat st;
 4068         
 4069     if (stat(dev, &st) && (errno == ENOENT)) {
 4070         mode_t mask = umask(0); 
 4071         if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {
 4072             ntfs_log_perror("Failed to create '%s'", dev);
 4073             if (errno == EPERM)
 4074                 ntfs_log_error("%s", dev_fuse_msg);
 4075         }
 4076         umask(mask);
 4077     }
 4078 }
 4079 
 4080 static void create_dev_fuse(void)
 4081 {
 4082     mknod_dev_fuse("/dev/fuse");
 4083 
 4084 #ifdef __UCLIBC__
 4085     {
 4086         struct stat st;
 4087         /* The fuse device is under /dev/misc using devfs. */
 4088         if (stat("/dev/misc", &st) && (errno == ENOENT)) {
 4089             mode_t mask = umask(0); 
 4090             mkdir("/dev/misc", 0775);
 4091             umask(mask);
 4092         }
 4093         mknod_dev_fuse("/dev/misc/fuse");
 4094     }
 4095 #endif
 4096 }
 4097 
 4098 static fuse_fstype get_fuse_fstype(void)
 4099 {
 4100     char buf[256];
 4101     fuse_fstype fstype = FSTYPE_NONE;
 4102         
 4103     FILE *f = fopen("/proc/filesystems", "r");
 4104     if (!f) {
 4105         ntfs_log_perror("Failed to open /proc/filesystems");
 4106         return FSTYPE_UNKNOWN;
 4107     }
 4108         
 4109     while (fgets(buf, sizeof(buf), f)) {
 4110         if (strstr(buf, "fuseblk\n")) {
 4111             fstype = FSTYPE_FUSEBLK;
 4112             break;
 4113         }
 4114         if (strstr(buf, "fuse\n"))
 4115             fstype = FSTYPE_FUSE;
 4116     }
 4117         
 4118     fclose(f);
 4119     return fstype;
 4120 }
 4121 
 4122 static fuse_fstype load_fuse_module(void)
 4123 {
 4124     int i;
 4125     struct stat st;
 4126     pid_t pid;
 4127     const char *cmd = "/sbin/modprobe";
 4128     char *env = (char*)NULL;
 4129     struct timespec req = { 0, 100000000 };   /* 100 msec */
 4130     fuse_fstype fstype;
 4131         
 4132     if (!stat(cmd, &st) && !geteuid()) {
 4133         pid = fork();
 4134         if (!pid) {
 4135             execle(cmd, cmd, "fuse", (char*)NULL, &env);
 4136             _exit(1);
 4137         } else if (pid != -1)
 4138             waitpid(pid, NULL, 0);
 4139     }
 4140         
 4141     for (i = 0; i < 10; i++) {
 4142         /* 
 4143          * We sleep first because despite the detection of the loaded
 4144          * FUSE kernel module, fuse_mount() can still fail if it's not 
 4145          * fully functional/initialized. Note, of course this is still
 4146          * unreliable but usually helps.
 4147          */  
 4148         nanosleep(&req, NULL);
 4149         fstype = get_fuse_fstype();
 4150         if (fstype != FSTYPE_NONE)
 4151             break;
 4152     }
 4153     return fstype;
 4154 }
 4155 
 4156 #endif
 4157 
 4158 static struct fuse_chan *try_fuse_mount(char *parsed_options)
 4159 {
 4160     struct fuse_chan *fc = NULL;
 4161     struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
 4162         
 4163     /* The fuse_mount() options get modified, so we always rebuild it */
 4164     if ((fuse_opt_add_arg(&margs, EXEC_NAME) == -1 ||
 4165          fuse_opt_add_arg(&margs, "-o") == -1 ||
 4166          fuse_opt_add_arg(&margs, parsed_options) == -1)) {
 4167         ntfs_log_error("Failed to set FUSE options.\n");
 4168         goto free_args;
 4169     }
 4170         
 4171     fc = fuse_mount(opts.mnt_point, &margs);
 4172 free_args:
 4173     fuse_opt_free_args(&margs);
 4174     return fc;
 4175             
 4176 }
 4177             
 4178 static int set_fuseblk_options(char **parsed_options)
 4179 {
 4180     char options[64];
 4181     long pagesize; 
 4182     u32 blksize = ctx->vol->cluster_size;
 4183         
 4184     pagesize = sysconf(_SC_PAGESIZE);
 4185     if (pagesize < 1)
 4186         pagesize = 4096;
 4187         
 4188     if (blksize > (u32)pagesize)
 4189         blksize = pagesize;
 4190         
 4191     snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
 4192     if (ntfs_strappend(parsed_options, options))
 4193         return -1;
 4194     return 0;
 4195 }
 4196 
 4197 static struct fuse_session *mount_fuse(char *parsed_options)
 4198 {
 4199     struct fuse_session *se = NULL;
 4200     struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
 4201         
 4202     ctx->fc = try_fuse_mount(parsed_options);
 4203     if (!ctx->fc)
 4204         return NULL;
 4205         
 4206     if (fuse_opt_add_arg(&args, "") == -1)
 4207         goto err;
 4208     if (ctx->debug)
 4209         if (fuse_opt_add_arg(&args, "-odebug") == -1)
 4210             goto err;
 4211         
 4212     se = fuse_lowlevel_new(&args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);
 4213     if (!se)
 4214         goto err;
 4215         
 4216         
 4217     if (fuse_set_signal_handlers(se))
 4218         goto err_destroy;
 4219     fuse_session_add_chan(se, ctx->fc);
 4220 out:
 4221     fuse_opt_free_args(&args);
 4222     return se;
 4223 err_destroy:
 4224     fuse_session_destroy(se);
 4225     se = NULL;
 4226 err:    
 4227     fuse_unmount(opts.mnt_point, ctx->fc);
 4228     goto out;
 4229 }
 4230 
 4231 static void setup_logging(char *parsed_options)
 4232 {
 4233     if (!ctx->no_detach) {
 4234         if (daemon(0, ctx->debug))
 4235             ntfs_log_error("Failed to daemonize.\n");
 4236         else if (!ctx->debug) {
 4237 #ifndef DEBUG
 4238             ntfs_log_set_handler(ntfs_log_handler_syslog);
 4239             /* Override default libntfs identify. */
 4240             openlog(EXEC_NAME, LOG_PID, LOG_DAEMON);
 4241 #endif
 4242         }
 4243     }
 4244 
 4245     ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
 4246 
 4247     ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
 4248     if (strcmp(opts.arg_device,opts.device))
 4249         ntfs_log_info("Requested device %s canonicalized as %s\n",
 4250                 opts.arg_device,opts.device);
 4251     ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
 4252             opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
 4253             ctx->vol->vol_name, ctx->vol->major_ver,
 4254             ctx->vol->minor_ver);
 4255     ntfs_log_info("Cmdline options: %s\n", opts.options ? opts.options : "");
 4256     ntfs_log_info("Mount options: %s\n", parsed_options);
 4257 }
 4258 
 4259 int main(int argc, char *argv[])
 4260 {
 4261     char *parsed_options = NULL;
 4262     struct fuse_session *se;
 4263 #if !(defined(__sun) && defined (__SVR4))
 4264     fuse_fstype fstype = FSTYPE_UNKNOWN;
 4265 #endif
 4266     const char *permissions_mode = (const char*)NULL;
 4267     const char *failed_secure = (const char*)NULL;
 4268 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
 4269     struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
 4270 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
 4271     struct stat sbuf;
 4272     unsigned long existing_mount;
 4273     int err, fd;
 4274 
 4275     /*
 4276      * Make sure file descriptors 0, 1 and 2 are open, 
 4277      * otherwise chaos would ensue.
 4278      */
 4279     do {
 4280         fd = open("/dev/null", O_RDWR);
 4281         if (fd > 2)
 4282             close(fd);
 4283     } while (fd >= 0 && fd <= 2);
 4284 
 4285 #ifndef FUSE_INTERNAL
 4286     if ((getuid() != geteuid()) || (getgid() != getegid())) {
 4287         fprintf(stderr, "%s", setuid_msg);
 4288         return NTFS_VOLUME_INSECURE;
 4289     }
 4290 #endif
 4291     if (drop_privs())
 4292         return NTFS_VOLUME_NO_PRIVILEGE;
 4293         
 4294     ntfs_set_locale();
 4295     ntfs_log_set_handler(ntfs_log_handler_stderr);
 4296 
 4297     if (ntfs_parse_options(&opts, usage, argc, argv)) {
 4298         usage();
 4299         return NTFS_VOLUME_SYNTAX_ERROR;
 4300     }
 4301 
 4302     if (ntfs_fuse_init()) {
 4303         err = NTFS_VOLUME_OUT_OF_MEMORY;
 4304         goto err2;
 4305     }
 4306         
 4307     parsed_options = parse_mount_options(ctx, &opts, TRUE);
 4308     if (!parsed_options) {
 4309         err = NTFS_VOLUME_SYNTAX_ERROR;
 4310         goto err_out;
 4311     }
 4312     if (!ntfs_check_if_mounted(opts.device,&existing_mount)
 4313         && (existing_mount & NTFS_MF_MOUNTED)
 4314         /* accept multiple read-only mounts */
 4315         && (!(existing_mount & NTFS_MF_READONLY) || !ctx->ro)) {
 4316         err = NTFS_VOLUME_LOCKED;
 4317         goto err_out;
 4318     }
 4319 
 4320             /* need absolute mount point for junctions */
 4321     if (opts.mnt_point[0] == '/')
 4322         ctx->abs_mnt_point = strdup(opts.mnt_point);
 4323     else {
 4324         ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
 4325         if (ctx->abs_mnt_point) {
 4326             if (getcwd(ctx->abs_mnt_point,
 4327                      PATH_MAX - strlen(opts.mnt_point) - 1)) {
 4328                 strcat(ctx->abs_mnt_point, "/");
 4329                 strcat(ctx->abs_mnt_point, opts.mnt_point);
 4330 #if defined(__sun) && defined (__SVR4)
 4331             /* Solaris also wants the absolute mount point */
 4332                 opts.mnt_point = ctx->abs_mnt_point;
 4333 #endif /* defined(__sun) && defined (__SVR4) */
 4334             }
 4335         }
 4336     }
 4337     if (!ctx->abs_mnt_point) {
 4338         err = NTFS_VOLUME_OUT_OF_MEMORY;
 4339         goto err_out;
 4340     }
 4341 
 4342     ctx->security.uid = 0;
 4343     ctx->security.gid = 0;
 4344     if ((opts.mnt_point[0] == '/')
 4345        && !stat(opts.mnt_point,&sbuf)) {
 4346         /* collect owner of mount point, useful for default mapping */
 4347         ctx->security.uid = sbuf.st_uid;
 4348         ctx->security.gid = sbuf.st_gid;
 4349     }
 4350 
 4351 #if defined(linux) || defined(__uClinux__)
 4352     fstype = get_fuse_fstype();
 4353 
 4354     err = NTFS_VOLUME_NO_PRIVILEGE;
 4355     if (restore_privs())
 4356         goto err_out;
 4357 
 4358     if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)
 4359         fstype = load_fuse_module();
 4360     create_dev_fuse();
 4361 
 4362     if (drop_privs())
 4363         goto err_out;
 4364 #endif  
 4365     if (stat(opts.device, &sbuf)) {
 4366         ntfs_log_perror("Failed to access '%s'", opts.device);
 4367         err = NTFS_VOLUME_NO_PRIVILEGE;
 4368         goto err_out;
 4369     }
 4370 
 4371 #if !(defined(__sun) && defined (__SVR4))
 4372     /* Always use fuseblk for block devices unless it's surely missing. */
 4373     if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
 4374         ctx->blkdev = TRUE;
 4375 #endif
 4376 
 4377 #ifndef FUSE_INTERNAL
 4378     if (getuid() && ctx->blkdev) {
 4379         ntfs_log_error("%s", unpriv_fuseblk_msg);
 4380         err = NTFS_VOLUME_NO_PRIVILEGE;
 4381         goto err2;
 4382     }
 4383 #endif
 4384     err = ntfs_open(opts.device);
 4385     if (err)
 4386         goto err_out;
 4387         
 4388     /* Force read-only mount if the device was found read-only */
 4389     if (!ctx->ro && NVolReadOnly(ctx->vol)) {
 4390         ctx->ro = TRUE;
 4391         if (ntfs_strinsert(&parsed_options, ",ro")) 
 4392                     goto err_out;
 4393     }
 4394     /* We must do this after ntfs_open() to be able to set the blksize */
 4395     if (ctx->blkdev && set_fuseblk_options(&parsed_options))
 4396         goto err_out;
 4397 
 4398     ctx->security.vol = ctx->vol;
 4399     ctx->vol->secure_flags = ctx->secure_flags;
 4400 #ifdef HAVE_SETXATTR    /* extended attributes interface required */
 4401     ctx->vol->efs_raw = ctx->efs_raw;
 4402 #endif /* HAVE_SETXATTR */
 4403     if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path,
 4404         (ctx->vol->secure_flags
 4405             & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
 4406         && !ctx->inherit
 4407         && !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
 4408 #if POSIXACLS
 4409         /* use basic permissions if requested */
 4410         if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
 4411             permissions_mode = "User mapping built, Posix ACLs not used";
 4412         else {
 4413             permissions_mode = "User mapping built, Posix ACLs in use";
 4414 #if KERNELACLS
 4415             if (ntfs_strinsert(&parsed_options,
 4416                     ",default_permissions,acl")) {
 4417                 err = NTFS_VOLUME_SYNTAX_ERROR;
 4418                 goto err_out;
 4419             }
 4420 #endif /* KERNELACLS */
 4421         }
 4422 #else /* POSIXACLS */
 4423         if (!(ctx->vol->secure_flags
 4424             & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
 4425             /*
 4426              * No explicit option but user mapping found
 4427              * force default security
 4428              */
 4429 #if KERNELPERMS
 4430             ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
 4431             if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
 4432                 err = NTFS_VOLUME_SYNTAX_ERROR;
 4433                 goto err_out;
 4434             }
 4435 #endif /* KERNELPERMS */
 4436         }
 4437         permissions_mode = "User mapping built";
 4438 #endif /* POSIXACLS */
 4439         ctx->dmask = ctx->fmask = 0;
 4440     } else {
 4441         ctx->security.uid = ctx->uid;
 4442         ctx->security.gid = ctx->gid;
 4443         /* same ownership/permissions for all files */
 4444         ctx->security.mapping[MAPUSERS] = (struct MAPPING*)NULL;
 4445         ctx->security.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
 4446         if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
 4447            && !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
 4448             ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
 4449             if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
 4450                 err = NTFS_VOLUME_SYNTAX_ERROR;
 4451                 goto err_out;
 4452             }
 4453         }
 4454         if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) {
 4455             ctx->vol->secure_flags |= (1 << SECURITY_RAW);
 4456             permissions_mode = "Global ownership and permissions enforced";
 4457         } else {
 4458             ctx->vol->secure_flags &= ~(1 << SECURITY_RAW);
 4459             permissions_mode = "Ownership and permissions disabled";
 4460         }
 4461     }
 4462     if (ctx->usermap_path)
 4463         free (ctx->usermap_path);
 4464 
 4465 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
 4466     xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
 4467                 ctx->xattrmap_path);
 4468     ctx->vol->xattr_mapping = xattr_mapping;
 4469     /*
 4470      * Errors are logged, do not refuse mounting, it would be
 4471      * too difficult to fix the unmountable mapping file.
 4472      */
 4473     if (ctx->xattrmap_path)
 4474         free(ctx->xattrmap_path);
 4475 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
 4476 
 4477 #ifndef DISABLE_PLUGINS
 4478     register_internal_reparse_plugins();
 4479 #endif /* DISABLE_PLUGINS */
 4480 
 4481     se = mount_fuse(parsed_options);
 4482     if (!se) {
 4483         err = NTFS_VOLUME_FUSE_ERROR;
 4484         goto err_out;
 4485     }
 4486         
 4487     ctx->mounted = TRUE;
 4488 
 4489 #if defined(linux) || defined(__uClinux__)
 4490     if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
 4491         ntfs_log_info("%s", fuse26_kmod_msg);
 4492 #endif  
 4493     setup_logging(parsed_options);
 4494     if (failed_secure)
 4495         ntfs_log_info("%s\n",failed_secure);
 4496     if (permissions_mode)
 4497         ntfs_log_info("%s, configuration type %d\n",permissions_mode,
 4498             5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING);
 4499         
 4500     fuse_session_loop(se);
 4501     fuse_remove_signal_handlers(se);
 4502         
 4503     err = 0;
 4504 
 4505     fuse_unmount(opts.mnt_point, ctx->fc);
 4506     fuse_session_destroy(se);
 4507 err_out:
 4508     ntfs_mount_error(opts.device, opts.mnt_point, err);
 4509     if (ctx->abs_mnt_point)
 4510         free(ctx->abs_mnt_point);
 4511 #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
 4512     ntfs_xattr_free_mapping(xattr_mapping);
 4513 #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
 4514 err2:
 4515     ntfs_close();
 4516 #ifndef DISABLE_PLUGINS
 4517     close_reparse_plugins(ctx);
 4518 #endif /* DISABLE_PLUGINS */
 4519     free(ctx);
 4520     free(parsed_options);
 4521     free(opts.options);
 4522     free(opts.device);
 4523     return err;
 4524 }
 4525