"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/lowntfs-3g.c" between
ntfs-3g_ntfsprogs-2016.2.22.tgz and ntfs-3g_ntfsprogs-2017.3.23.tgz

About: NTFS-3G is a read-write NTFS driver for Linux and other operating systems. It provides safe handling of the Windows XP, Windows Server 2003, Windows 2000, Windows Vista, Windows Server 2008, Windows 7 and Windows 8 NTFS file systems.

lowntfs-3g.c  (ntfs-3g_ntfsprogs-2016.2.22.tgz):lowntfs-3g.c  (ntfs-3g_ntfsprogs-2017.3.23.tgz)
/** /**
* ntfs-3g - Third Generation NTFS Driver * ntfs-3g - Third Generation NTFS Driver
* *
* Copyright (c) 2005-2007 Yura Pakhuchiy * Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2005 Yuval Fledel * Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2006-2009 Szabolcs Szakacsits * Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2007-2015 Jean-Pierre Andre * Copyright (c) 2007-2017 Jean-Pierre Andre
* Copyright (c) 2009 Erik Larsson * Copyright (c) 2009 Erik Larsson
* *
* This file is originated from the Linux-NTFS project. * This file is originated from the Linux-NTFS project.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
skipping to change at line 76 skipping to change at line 76
#include <syslog.h> #include <syslog.h>
#include <sys/wait.h> #include <sys/wait.h>
#ifdef HAVE_SETXATTR #ifdef HAVE_SETXATTR
#include <sys/xattr.h> #include <sys/xattr.h>
#endif #endif
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#ifdef HAVE_SYS_MKDEV_H #ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h> #include <sys/mkdev.h>
#endif #endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
#include <sys/dirent.h> #include <sys/dirent.h>
#elif defined(__sun) && defined (__SVR4) #elif defined(__sun) && defined (__SVR4)
#include <sys/param.h> #include <sys/param.h>
#endif /* defined(__APPLE__) || defined(__DARWIN__), ... */ #endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
#ifdef HAVE_LINUX_FS_H #ifdef HAVE_LINUX_FS_H
#include <linux/fs.h> #include <linux/fs.h>
#endif #endif
#ifndef FUSE_CAP_POSIX_ACL /* until defined in <fuse/fuse_common.h> */
#define FUSE_CAP_POSIX_ACL (1 << 18)
#endif /* FUSE_CAP_POSIX_ACL */
#include "compat.h" #include "compat.h"
#include "bitmap.h" #include "bitmap.h"
#include "attrib.h" #include "attrib.h"
#include "inode.h" #include "inode.h"
#include "volume.h" #include "volume.h"
#include "dir.h" #include "dir.h"
#include "unistr.h" #include "unistr.h"
#include "layout.h" #include "layout.h"
#include "index.h" #include "index.h"
#include "ntfstime.h" #include "ntfstime.h"
#include "security.h" #include "security.h"
#include "reparse.h" #include "reparse.h"
#include "object_id.h" #include "object_id.h"
#include "efs.h" #include "efs.h"
#include "logging.h" #include "logging.h"
#include "xattrs.h" #include "xattrs.h"
#include "misc.h" #include "misc.h"
#include "ioctl.h" #include "ioctl.h"
#include "plugin.h"
#include "ntfs-3g_common.h" #include "ntfs-3g_common.h"
/* /*
* The following permission checking modes are governed by * The following permission checking modes are governed by
* the LPERMSCONFIG value in param.h * the LPERMSCONFIG value in param.h
*/ */
/* ACLS may be checked by kernel (requires a fuse patch) or here */ /* ACLS may be checked by kernel (requires a fuse patch) or here */
#define KERNELACLS ((LPERMSCONFIG > 6) & (LPERMSCONFIG < 10)) #define KERNELACLS ((LPERMSCONFIG > 6) & (LPERMSCONFIG < 10))
skipping to change at line 139 skipping to change at line 147
#define ENTRY_TIMEOUT 0.0 #define ENTRY_TIMEOUT 0.0
#else #else
#if defined(__sun) && defined (__SVR4) #if defined(__sun) && defined (__SVR4)
#define ATTR_TIMEOUT 10.0 #define ATTR_TIMEOUT 10.0
#define ENTRY_TIMEOUT 10.0 #define ENTRY_TIMEOUT 10.0
#else /* defined(__sun) && defined (__SVR4) */ #else /* defined(__sun) && defined (__SVR4) */
/* /*
* FUSE cacheing is only usable with basic permissions * FUSE cacheing is only usable with basic permissions
* checked by the kernel with external fuse >= 2.8 * checked by the kernel with external fuse >= 2.8
*/ */
#if KERNELACLS | !KERNELPERMS #if !KERNELPERMS
#warning "Fuse cacheing is only usable with basic permissions checked by kernel" #warning "Fuse cacheing is only usable with basic permissions checked by kernel"
#endif #endif
#define ATTR_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 1.0 : 0 #if KERNELACLS
.0) #define ATTR_TIMEOUT 10.0
#define ENTRY_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 1.0 : #define ENTRY_TIMEOUT 10.0
0.0) #else /* KERNELACLS */
#define ATTR_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 10.0 :
0.0)
#define ENTRY_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 10.0 :
0.0)
#endif /* KERNELACLS */
#endif /* defined(__sun) && defined (__SVR4) */ #endif /* defined(__sun) && defined (__SVR4) */
#endif #endif /* !CACHEING */
#define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */ #define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */
/* sometimes the kernel cannot check access */ /* sometimes the kernel cannot check access */
#define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, typ e) #define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, typ e)
#if POSIXACLS & KERNELPERMS & !KERNELACLS #if POSIXACLS & KERNELPERMS & !KERNELACLS
/* short-circuit if PERMS checked by kernel and ACLs by fs */ /* short-circuit if PERMS checked by kernel and ACLs by fs */
#define ntfs_allowed_access(scx, ni, type) \ #define ntfs_allowed_access(scx, ni, type) \
((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \ ((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \
? 1 : ntfs_allowed_access(scx, ni, type)) ? 1 : ntfs_allowed_access(scx, ni, type))
#endif #endif
#define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE #define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE
#define INODE(ino) ((ino) == 1 ? (MFT_REF)FILE_root : (MFT_REF)(ino)) #define INODE(ino) ((ino) == 1 ? (MFT_REF)FILE_root : (MFT_REF)(ino))
/*
* Call a function from a reparse plugin (variable arguments)
* Requires "reparse" and "ops" to have been defined
*
* Returns a non-negative value if successful,
* and a negative error code if something fails.
*/
#define CALL_REPARSE_PLUGIN(ni, op_name, ...) \
(reparse = (REPARSE_POINT*)NULL, \
ops = select_reparse_plugin(ctx, ni, &reparse), \
(!ops ? -errno \
: (ops->op_name ? \
ops->op_name(ni, reparse, __VA_ARGS__) \
: -EOPNOTSUPP))), \
free(reparse)
typedef enum { typedef enum {
FSTYPE_NONE, FSTYPE_NONE,
FSTYPE_UNKNOWN, FSTYPE_UNKNOWN,
FSTYPE_FUSE, FSTYPE_FUSE,
FSTYPE_FUSEBLK FSTYPE_FUSEBLK
} fuse_fstype; } fuse_fstype;
typedef struct fill_item { typedef struct fill_item {
struct fill_item *next; struct fill_item *next;
size_t bufsize; size_t bufsize;
skipping to change at line 190 skipping to change at line 219
BOOL filled; BOOL filled;
} ntfs_fuse_fill_context_t; } ntfs_fuse_fill_context_t;
struct open_file { struct open_file {
struct open_file *next; struct open_file *next;
struct open_file *previous; struct open_file *previous;
long long ghost; long long ghost;
fuse_ino_t ino; fuse_ino_t ino;
fuse_ino_t parent; fuse_ino_t parent;
int state; int state;
#ifndef DISABLE_PLUGINS
struct fuse_file_info fi;
#endif /* DISABLE_PLUGINS */
} ; } ;
enum { enum {
CLOSE_GHOST = 1, CLOSE_GHOST = 1,
CLOSE_COMPRESSED = 2, CLOSE_COMPRESSED = 2,
CLOSE_ENCRYPTED = 4, CLOSE_ENCRYPTED = 4,
CLOSE_DMTIME = 8 CLOSE_DMTIME = 8,
CLOSE_REPARSE = 16
}; };
enum RM_TYPES { enum RM_TYPES {
RM_LINK, RM_LINK,
RM_DIR, RM_DIR,
RM_ANY, RM_ANY,
} ; } ;
static struct ntfs_options opts; static struct ntfs_options opts;
skipping to change at line 230 skipping to change at line 263
"XATTRS are off, " "XATTRS are off, "
#endif #endif
#if POSIXACLS #if POSIXACLS
"POSIX ACLS are on\n" "POSIX ACLS are on\n"
#else #else
"POSIX ACLS are off\n" "POSIX ACLS are off\n"
#endif #endif
"\n" "\n"
"Copyright (C) 2005-2007 Yura Pakhuchiy\n" "Copyright (C) 2005-2007 Yura Pakhuchiy\n"
"Copyright (C) 2006-2009 Szabolcs Szakacsits\n" "Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
"Copyright (C) 2007-2016 Jean-Pierre Andre\n" "Copyright (C) 2007-2017 Jean-Pierre Andre\n"
"Copyright (C) 2009 Erik Larsson\n" "Copyright (C) 2009 Erik Larsson\n"
"\n" "\n"
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n" "Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
"\n" "\n"
"Options: ro (read-only mount), windows_names, uid=, gid=,\n" "Options: ro (read-only mount), windows_names, uid=, gid=,\n"
" umask=, fmask=, dmask=, streams_interface=.\n" " umask=, fmask=, dmask=, streams_interface=.\n"
" Please see the details in the manual (type: man ntfs-3g).\n" " Please see the details in the manual (type: man ntfs-3g).\n"
"\n" "\n"
"Example: ntfs-3g /dev/sda1 /mnt/windows\n" "Example: ntfs-3g /dev/sda1 /mnt/windows\n"
"\n" "\n"
skipping to change at line 589 skipping to change at line 622
static void ntfs_init(void *userdata __attribute__((unused)), static void ntfs_init(void *userdata __attribute__((unused)),
struct fuse_conn_info *conn) struct fuse_conn_info *conn)
{ {
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
FUSE_ENABLE_XTIMES(conn); FUSE_ENABLE_XTIMES(conn);
#endif #endif
#ifdef FUSE_CAP_DONT_MASK #ifdef FUSE_CAP_DONT_MASK
/* request umask not to be enforced by fuse */ /* request umask not to be enforced by fuse */
conn->want |= FUSE_CAP_DONT_MASK; conn->want |= FUSE_CAP_DONT_MASK;
#endif /* defined FUSE_CAP_DONT_MASK */ #endif /* defined FUSE_CAP_DONT_MASK */
#if POSIXACLS & KERNELACLS
/* request ACLs to be checked by kernel */
conn->want |= FUSE_CAP_POSIX_ACL;
#endif /* POSIXACLS & KERNELACLS */
#ifdef FUSE_CAP_BIG_WRITES #ifdef FUSE_CAP_BIG_WRITES
if (ctx->big_writes if (ctx->big_writes
&& ((ctx->vol->nr_clusters << ctx->vol->cluster_size_bits) && ((ctx->vol->nr_clusters << ctx->vol->cluster_size_bits)
>= SAFE_CAPACITY_FOR_BIG_WRITES)) >= SAFE_CAPACITY_FOR_BIG_WRITES))
conn->want |= FUSE_CAP_BIG_WRITES; conn->want |= FUSE_CAP_BIG_WRITES;
#endif #endif
#ifdef FUSE_CAP_IOCTL_DIR #ifdef FUSE_CAP_IOCTL_DIR
conn->want |= FUSE_CAP_IOCTL_DIR; conn->want |= FUSE_CAP_IOCTL_DIR;
#endif /* defined(FUSE_CAP_IOCTL_DIR) */ #endif /* defined(FUSE_CAP_IOCTL_DIR) */
} }
#ifndef DISABLE_PLUGINS
/*
* Define attributes for a junction or symlink
* (internal plugin)
*/
static int junction_getstat(ntfs_inode *ni,
const REPARSE_POINT *reparse __attribute__((unused)),
struct stat *stbuf)
{
char *target;
int res;
errno = 0;
target = ntfs_make_symlink(ni, ctx->abs_mnt_point);
/*
* If the reparse point is not a valid
* directory junction, and there is no error
* we still display as a symlink
*/
if (target || (errno == EOPNOTSUPP)) {
if (target)
stbuf->st_size = strlen(target);
else
stbuf->st_size = sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK;
free(target);
res = 0;
} else {
res = -errno;
}
return (res);
}
/*
* Apply permission masks to st_mode returned by reparse handler
*/
static void apply_umask(struct stat *stbuf)
{
switch (stbuf->st_mode & S_IFMT) {
case S_IFREG :
stbuf->st_mode &= ~ctx->fmask;
break;
case S_IFDIR :
stbuf->st_mode &= ~ctx->dmask;
break;
case S_IFLNK :
stbuf->st_mode = (stbuf->st_mode & S_IFMT) | 0777;
break;
default :
break;
}
}
#endif /* DISABLE_PLUGINS */
static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx, static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, struct stat *stbuf) ntfs_inode *ni, struct stat *stbuf)
{ {
int res = 0; int res = 0;
ntfs_attr *na; ntfs_attr *na;
BOOL withusermapping; BOOL withusermapping;
memset(stbuf, 0, sizeof(struct stat)); memset(stbuf, 0, sizeof(struct stat));
withusermapping = (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL); withusermapping = (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL);
stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|| (ni->flags & FILE_ATTR_REPARSE_POINT)) { || (ni->flags & FILE_ATTR_REPARSE_POINT)) {
if (ni->flags & FILE_ATTR_REPARSE_POINT) { if (ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(ni, getattr, stbuf);
if (!res) {
apply_umask(stbuf);
} else {
stbuf->st_size =
sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks =
(ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK;
res = 0;
}
goto ok;
#else /* DISABLE_PLUGINS */
char *target; char *target;
int attr_size;
errno = 0; errno = 0;
target = ntfs_make_symlink(ni, ctx->abs_mnt_point, target = ntfs_make_symlink(ni, ctx->abs_mnt_point);
&attr_size);
/* /*
* If the reparse point is not a valid * If the reparse point is not a valid
* directory junction, and there is no error * directory junction, and there is no error
* we still display as a symlink * we still display as a symlink
*/ */
if (target || (errno == EOPNOTSUPP)) { if (target || (errno == EOPNOTSUPP)) {
/* returning attribute size */
if (target) if (target)
stbuf->st_size = attr_size; stbuf->st_size = strlen(target);
else else
stbuf->st_size = stbuf->st_size =
sizeof(ntfs_bad_reparse); sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks = stbuf->st_blocks =
(ni->allocated_size + 511) >> 9; (ni->allocated_size + 511) >> 9;
stbuf->st_nlink = stbuf->st_nlink =
le16_to_cpu(ni->mrec->link_count); le16_to_cpu(ni->mrec->link_count);
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
free(target); free(target);
} else { } else {
res = -errno; res = -errno;
goto exit; goto exit;
} }
#endif /* DISABLE_PLUGINS */
} else { } else {
/* Directory. */ /* Directory. */
stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask); stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);
/* get index size, if not known */ /* get index size, if not known */
if (!test_nino_flag(ni, KnownSize)) { if (!test_nino_flag(ni, KnownSize)) {
na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION,
NTFS_INDEX_I30, 4); NTFS_INDEX_I30, 4);
if (na) { if (na) {
ni->data_size = na->data_size; ni->data_size = na->data_size;
ni->allocated_size = na->allocated_size; ni->allocated_size = na->allocated_size;
skipping to change at line 678 skipping to change at line 790
if (ctx->efs_raw if (ctx->efs_raw
&& (ni->flags & FILE_ATTR_ENCRYPTED) && (ni->flags & FILE_ATTR_ENCRYPTED)
&& ni->data_size) && ni->data_size)
stbuf->st_size = ((ni->data_size + 511) & ~511) + 2; stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */
/* /*
* Temporary fix to make ActiveSync work via Samba 3.0. * Temporary fix to make ActiveSync work via Samba 3.0.
* See more on the ntfs-3g-devel list. * See more on the ntfs-3g-devel list.
*/ */
stbuf->st_blocks = (ni->allocated_size + 511) >> 9; stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
if (ni->flags & FILE_ATTR_SYSTEM) { if (ni->flags & FILE_ATTR_SYSTEM) {
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
stbuf->st_ino = ni->mft_no; stbuf->st_ino = ni->mft_no;
goto nodata; goto nodata;
} }
/* Check whether it's Interix FIFO or socket. */ /* Check whether it's Interix FIFO or socket. */
if (!(ni->flags & FILE_ATTR_HIDDEN)) { if (!(ni->flags & FILE_ATTR_HIDDEN)) {
/* FIFO. */ /* FIFO. */
if (na->data_size == 0) if (na->data_size == 0)
skipping to change at line 736 skipping to change at line 847
} }
if (intx_file->magic == INTX_CHARACTER_DEVICE && if (intx_file->magic == INTX_CHARACTER_DEVICE &&
na->data_size == (s64)offsetof( na->data_size == (s64)offsetof(
INTX_FILE, device_end)) { INTX_FILE, device_end)) {
stbuf->st_mode = S_IFCHR; stbuf->st_mode = S_IFCHR;
stbuf->st_rdev = makedev(le64_to_cpu( stbuf->st_rdev = makedev(le64_to_cpu(
intx_file->major), intx_file->major),
le64_to_cpu( le64_to_cpu(
intx_file->minor)); intx_file->minor));
} }
if (intx_file->magic == INTX_SYMBOLIC_LINK) if (intx_file->magic == INTX_SYMBOLIC_LINK) {
char *target = NULL;
int len;
/* st_size should be set to length of
* symlink target as multibyte string */
len = ntfs_ucstombs(
intx_file->target,
(na->data_size -
offsetof(INTX_FILE,
target)) /
sizeof(ntfschar),
&target, 0);
if (len < 0) {
res = -errno;
free(intx_file);
ntfs_attr_close(na);
goto exit;
}
free(target);
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
stbuf->st_size = len;
}
free(intx_file); free(intx_file);
} }
ntfs_attr_close(na); ntfs_attr_close(na);
} }
stbuf->st_mode |= (0777 & ~ctx->fmask); stbuf->st_mode |= (0777 & ~ctx->fmask);
} }
#ifndef DISABLE_PLUGINS
ok:
#endif /* DISABLE_PLUGINS */
if (withusermapping) { if (withusermapping) {
if (ntfs_get_owner_mode(scx,ni,stbuf) < 0) if (ntfs_get_owner_mode(scx,ni,stbuf) < 0)
set_fuse_error(&res); set_fuse_error(&res);
} else { } else {
stbuf->st_uid = ctx->uid; stbuf->st_uid = ctx->uid;
stbuf->st_gid = ctx->gid; stbuf->st_gid = ctx->gid;
} }
if (S_ISLNK(stbuf->st_mode)) if (S_ISLNK(stbuf->st_mode))
stbuf->st_mode |= 0777; stbuf->st_mode |= 0777;
nodata : nodata :
skipping to change at line 885 skipping to change at line 1020
#endif #endif
} }
} else } else
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
if (!ok) if (!ok)
fuse_reply_err(req, errno); fuse_reply_err(req, errno);
else else
fuse_reply_entry(req, &entry); fuse_reply_entry(req, &entry);
} }
#ifndef DISABLE_PLUGINS
/*
* Get the link defined by a junction or symlink
* (internal plugin)
*/
static int junction_readlink(ntfs_inode *ni,
const REPARSE_POINT *reparse __attribute__((unused)),
char **pbuf)
{
int res;
errno = 0;
res = 0;
*pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
if (!*pbuf) {
if (errno == EOPNOTSUPP) {
*pbuf = strdup(ntfs_bad_reparse);
if (!*pbuf)
res = -errno;
} else
res = -errno;
}
return (res);
}
#endif /* DISABLE_PLUGINS */
static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino) static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
{ {
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
INTX_FILE *intx_file = NULL; INTX_FILE *intx_file = NULL;
char *buf = (char*)NULL; char *buf = (char*)NULL;
int res = 0; int res = 0;
/* Get inode. */ /* Get inode. */
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
/* /*
* Reparse point : analyze as a junction point * Reparse point : analyze as a junction point
*/ */
if (ni->flags & FILE_ATTR_REPARSE_POINT) { if (ni->flags & FILE_ATTR_REPARSE_POINT) {
int attr_size; #ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(ni, readlink, &buf);
if (res) {
buf = strdup(ntfs_bad_reparse);
if (!buf)
res = -errno;
}
#else /* DISABLE_PLUGINS */
errno = 0; errno = 0;
res = 0; res = 0;
buf = ntfs_make_symlink(ni, ctx->abs_mnt_point, &attr_size); buf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
if (!buf) { if (!buf) {
if (errno == EOPNOTSUPP) if (errno == EOPNOTSUPP)
buf = strdup(ntfs_bad_reparse); buf = strdup(ntfs_bad_reparse);
if (!buf) if (!buf)
res = -errno; res = -errno;
} }
goto exit; #endif /* DISABLE_PLUGINS */
goto exit;
} }
/* Sanity checks. */ /* Sanity checks. */
if (!(ni->flags & FILE_ATTR_SYSTEM)) { if (!(ni->flags & FILE_ATTR_SYSTEM)) {
res = -EINVAL; res = -EINVAL;
goto exit; goto exit;
} }
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
res = -errno; res = -errno;
goto exit; goto exit;
skipping to change at line 1266 skipping to change at line 1440
ntfs_log_error("Uninitialized fuse_readdir()\n"); ntfs_log_error("Uninitialized fuse_readdir()\n");
} }
if (err) if (err)
fuse_reply_err(req, -err); fuse_reply_err(req, -err);
} }
static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino, static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) struct fuse_file_info *fi)
{ {
ntfs_inode *ni; ntfs_inode *ni;
ntfs_attr *na; ntfs_attr *na = NULL;
struct open_file *of; struct open_file *of;
int state = 0; int state = 0;
char *path = NULL;
int res = 0; int res = 0;
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
int accesstype; int accesstype;
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
#endif #endif
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (ni) { if (ni) {
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); if (!(ni->flags & FILE_ATTR_REPARSE_POINT)) {
if (na) { na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) {
res = -errno;
goto close;
}
}
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
if (ntfs_fuse_fill_security_context(req, &security)) { if (ntfs_fuse_fill_security_context(req, &security)) {
if (fi->flags & O_WRONLY) if (fi->flags & O_WRONLY)
accesstype = S_IWRITE; accesstype = S_IWRITE;
else
if (fi->flags & O_RDWR)
accesstype = S_IWRITE | S_IREAD;
else else
if (fi->flags & O_RDWR) accesstype = S_IREAD;
accesstype = S_IWRITE | S_IREAD; /* check whether requested access is allowed */
else if (!ntfs_allowed_access(&security,
accesstype = S_IREAD; ni,accesstype))
/* check whether requested access is allowed */ res = -EACCES;
if (!ntfs_allowed_access(&security, }
ni,accesstype))
res = -EACCES;
}
#endif #endif
if ((res >= 0) if (ni->flags & FILE_ATTR_REPARSE_POINT) {
&& (fi->flags & (O_WRONLY | O_RDWR))) { #ifndef DISABLE_PLUGINS
/* mark a future need to compress the last chunk */ const plugin_operations_t *ops;
if (na->data_flags & ATTR_COMPRESSION_MASK) REPARSE_POINT *reparse;
state |= CLOSE_COMPRESSED;
fi->fh = 0;
res = CALL_REPARSE_PLUGIN(ni, open, fi);
if (!res && fi->fh) {
state = CLOSE_REPARSE;
}
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
goto close;
}
if ((res >= 0)
&& (fi->flags & (O_WRONLY | O_RDWR))) {
/* mark a future need to compress the last chunk */
if (na->data_flags & ATTR_COMPRESSION_MASK)
state |= CLOSE_COMPRESSED;
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
/* mark a future need to fixup encrypted inode */ /* mark a future need to fixup encrypted inode */
if (ctx->efs_raw if (ctx->efs_raw
&& !(na->data_flags & ATTR_IS_ENCRYPTED) && !(na->data_flags & ATTR_IS_ENCRYPTED)
&& (ni->flags & FILE_ATTR_ENCRYPTED)) && (ni->flags & FILE_ATTR_ENCRYPTED))
state |= CLOSE_ENCRYPTED; state |= CLOSE_ENCRYPTED;
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */
/* mark a future need to update the mtime */ /* mark a future need to update the mtime */
if (ctx->dmtime) if (ctx->dmtime)
state |= CLOSE_DMTIME; state |= CLOSE_DMTIME;
/* deny opening metadata files for writing */ /* deny opening metadata files for writing */
if (ino < FILE_first_user) if (ino < FILE_first_user)
res = -EPERM; res = -EPERM;
} }
ntfs_attr_close(na); ntfs_attr_close(na);
} else close:
res = -errno;
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
set_fuse_error(&res); set_fuse_error(&res);
} else } else
res = -errno; res = -errno;
free(path);
if (res >= 0) { if (res >= 0) {
of = (struct open_file*)malloc(sizeof(struct open_file)); of = (struct open_file*)malloc(sizeof(struct open_file));
if (of) { if (of) {
of->parent = 0; of->parent = 0;
of->ino = ino; of->ino = ino;
of->state = state; of->state = state;
#ifndef DISABLE_PLUGINS
memcpy(&of->fi, fi, sizeof(struct fuse_file_info));
#endif /* DISABLE_PLUGINS */
of->next = ctx->open_files; of->next = ctx->open_files;
of->previous = (struct open_file*)NULL; of->previous = (struct open_file*)NULL;
if (ctx->open_files) if (ctx->open_files)
ctx->open_files->previous = of; ctx->open_files->previous = of;
ctx->open_files = of; ctx->open_files = of;
fi->fh = (long)of; fi->fh = (long)of;
} }
} }
if (res) if (res)
fuse_reply_err(req, -res); fuse_reply_err(req, -res);
skipping to change at line 1368 skipping to change at line 1562
if (!buf) { if (!buf) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
struct open_file *of;
of = (struct open_file*)(long)fi->fh;
res = CALL_REPARSE_PLUGIN(ni, read, buf, size, offset, &of->fi);
if (res >= 0) {
goto stamps;
}
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
goto exit;
}
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
max_read = na->data_size; max_read = na->data_size;
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
/* limit reads at next 512 byte boundary for encrypted attributes */ /* limit reads at next 512 byte boundary for encrypted attributes */
if (ctx->efs_raw if (ctx->efs_raw
&& max_read && max_read
skipping to change at line 1403 skipping to change at line 1613
(long long)offset, (long long)size, (long long)re t); (long long)offset, (long long)size, (long long)re t);
if (ret <= 0 || ret > (s64)size) { if (ret <= 0 || ret > (s64)size) {
res = (ret < 0) ? -errno : -EIO; res = (ret < 0) ? -errno : -EIO;
goto exit; goto exit;
} }
size -= ret; size -= ret;
offset += ret; offset += ret;
total += ret; total += ret;
} }
ok: ok:
ntfs_fuse_update_times(na->ni, NTFS_UPDATE_ATIME);
res = total; res = total;
#ifndef DISABLE_PLUGINS
stamps :
#endif /* DISABLE_PLUGINS */
ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
exit: exit:
if (na) if (na)
ntfs_attr_close(na); ntfs_attr_close(na);
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
set_fuse_error(&res); set_fuse_error(&res);
if (res < 0) if (res < 0)
fuse_reply_err(req, -res); fuse_reply_err(req, -res);
else else
fuse_reply_buf(req, buf, res); fuse_reply_buf(req, buf, res);
free(buf); free(buf);
skipping to change at line 1430 skipping to change at line 1643
{ {
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
int res, total = 0; int res, total = 0;
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
struct open_file *of;
of = (struct open_file*)(long)fi->fh;
res = CALL_REPARSE_PLUGIN(ni, write, buf, size, offset,
&of->fi);
if (res >= 0) {
goto stamps;
}
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
goto exit;
}
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
while (size) { while (size) {
s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total); s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total);
if (ret <= 0) { if (ret <= 0) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
size -= ret; size -= ret;
offset += ret; offset += ret;
total += ret; total += ret;
} }
res = total; res = total;
#ifndef DISABLE_PLUGINS
stamps :
#endif /* DISABLE_PLUGINS */
if ((res > 0) if ((res > 0)
&& (!ctx->dmtime && (!ctx->dmtime
|| (sle64_to_cpu(ntfs_current_time()) || (sle64_to_cpu(ntfs_current_time())
- sle64_to_cpu(ni->last_data_change_time)) > ctx->dmtime)) - sle64_to_cpu(ni->last_data_change_time)) > ctx->dmtime))
ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME); ntfs_fuse_update_times(ni, NTFS_UPDATE_MCTIME);
exit: exit:
if (na) if (na)
ntfs_attr_close(na); ntfs_attr_close(na);
if (total) if (res > 0)
set_archive(ni); set_archive(ni);
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
set_fuse_error(&res); set_fuse_error(&res);
if (res < 0) if (res < 0)
fuse_reply_err(req, -res); fuse_reply_err(req, -res);
else else
fuse_reply_write(req, res); fuse_reply_write(req, res);
} }
static int ntfs_fuse_chmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino, static int ntfs_fuse_chmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
skipping to change at line 1607 skipping to change at line 1840
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) if (!ni)
goto exit; goto exit;
/* deny truncating metadata files */ /* deny truncating metadata files */
if (ino < FILE_first_user) { if (ino < FILE_first_user) {
errno = EPERM; errno = EPERM;
goto exit; goto exit;
} }
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); if (!(ni->flags & FILE_ATTR_REPARSE_POINT)) {
if (!na) na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
goto exit; if (!na)
goto exit;
}
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
/* /*
* deny truncation if cannot write to file * deny truncation if cannot write to file
* (already checked for ftruncate()) * (already checked for ftruncate())
*/ */
if (scx->mapping[MAPUSERS] if (scx->mapping[MAPUSERS]
&& chkwrite && chkwrite
&& !ntfs_allowed_access(scx, ni, S_IWRITE)) { && !ntfs_allowed_access(scx, ni, S_IWRITE)) {
errno = EACCES; errno = EACCES;
goto exit; goto exit;
} }
#endif #endif
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(ni, truncate, size);
if (!res) {
set_archive(ni);
goto stamps;
}
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
goto exit;
}
/* /*
* for compressed files, upsizing is done by inserting a final * for compressed files, upsizing is done by inserting a final
* zero, which is optimized as creating a hole when possible. * zero, which is optimized as creating a hole when possible.
*/ */
oldsize = na->data_size; oldsize = na->data_size;
if ((na->data_flags & ATTR_COMPRESSION_MASK) if ((na->data_flags & ATTR_COMPRESSION_MASK)
&& (size > na->initialized_size)) { && (size > na->initialized_size)) {
char zero = 0; char zero = 0;
if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0) if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0)
goto exit; goto exit;
} else } else
if (ntfs_attr_truncate(na, size)) if (ntfs_attr_truncate(na, size))
goto exit; goto exit;
if (oldsize != size) if (oldsize != size)
set_archive(ni); set_archive(ni);
ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME); #ifndef DISABLE_PLUGINS
stamps :
#endif /* DISABLE_PLUGINS */
ntfs_fuse_update_times(ni, NTFS_UPDATE_MCTIME);
res = ntfs_fuse_getstat(scx, ni, stbuf); res = ntfs_fuse_getstat(scx, ni, stbuf);
errno = (res ? -res : 0); errno = (res ? -res : 0);
exit: exit:
res = -errno; res = -errno;
ntfs_attr_close(na); ntfs_attr_close(na);
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
set_fuse_error(&res); set_fuse_error(&res);
return res; return res;
} }
skipping to change at line 1916 skipping to change at line 2169
mode_t dsetgid; mode_t dsetgid;
mode_t type = typemode & ~07777; mode_t type = typemode & ~07777;
mode_t perm; mode_t perm;
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
int res = 0, uname_len, utarget_len; int res = 0, uname_len, utarget_len;
/* Generate unicode filename. */ /* Generate unicode filename. */
uname_len = ntfs_mbstoucs(name, &uname); uname_len = ntfs_mbstoucs(name, &uname);
if ((uname_len < 0) if ((uname_len < 0)
|| (ctx->windows_names || (ctx->windows_names
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) { && ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
/* Deny creating into $Extend */
if (parent == FILE_Extend) {
res = -EPERM;
goto exit;
}
/* Open parent directory. */ /* Open parent directory. */
dir_ni = ntfs_inode_open(ctx->vol, INODE(parent)); dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
if (!dir_ni) { if (!dir_ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
/* make sure parent directory is writeable and executable */ /* make sure parent directory is writeable and executable */
if (!ntfs_fuse_fill_security_context(req, &security) if (!ntfs_fuse_fill_security_context(req, &security)
|| ntfs_allowed_create(&security, || ntfs_allowed_create(&security,
skipping to change at line 2131 skipping to change at line 2389
/* Do not accept linking to a directory (except for renaming) */ /* Do not accept linking to a directory (except for renaming) */
if (e && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { if (e && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
errno = EPERM; errno = EPERM;
res = -errno; res = -errno;
goto exit; goto exit;
} }
/* Generate unicode filename. */ /* Generate unicode filename. */
uname_len = ntfs_mbstoucs(newname, &uname); uname_len = ntfs_mbstoucs(newname, &uname);
if ((uname_len < 0) if ((uname_len < 0)
|| (ctx->windows_names || (ctx->windows_names
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) { && ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
/* Open parent directory. */ /* Open parent directory. */
dir_ni = ntfs_inode_open(ctx->vol, INODE(newparent)); dir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
if (!dir_ni) { if (!dir_ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
skipping to change at line 2210 skipping to change at line 2468
int res = 0, uname_len; int res = 0, uname_len;
int ugname_len; int ugname_len;
u64 iref; u64 iref;
fuse_ino_t ino; fuse_ino_t ino;
struct open_file *of; struct open_file *of;
char ghostname[GHOSTLTH]; char ghostname[GHOSTLTH];
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
#endif #endif
/* Deny removing from $Extend */
if (parent == FILE_Extend) {
res = -EPERM;
goto exit;
}
/* Open parent directory. */ /* Open parent directory. */
dir_ni = ntfs_inode_open(ctx->vol, INODE(parent)); dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
if (!dir_ni) { if (!dir_ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
/* Generate unicode filename. */ /* Generate unicode filename. */
uname_len = ntfs_mbstoucs(name, &uname); uname_len = ntfs_mbstoucs(name, &uname);
if (uname_len < 0) { if (uname_len < 0) {
res = -errno; res = -errno;
skipping to change at line 2549 skipping to change at line 2812
{ {
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
struct open_file *of; struct open_file *of;
char ghostname[GHOSTLTH]; char ghostname[GHOSTLTH];
int res; int res;
of = (struct open_file*)(long)fi->fh; of = (struct open_file*)(long)fi->fh;
/* Only for marked descriptors there is something to do */ /* Only for marked descriptors there is something to do */
if (!of if (!of
|| !(of->state & (CLOSE_COMPRESSED || !(of->state & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED
| CLOSE_ENCRYPTED | CLOSE_DMTIME))) { | CLOSE_DMTIME | CLOSE_REPARSE))) {
res = 0; res = 0;
goto out; goto out;
} }
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(ni, release, &of->fi);
if (!res) {
goto stamps;
}
#else /* DISABLE_PLUGINS */
/* Assume release() was not needed */
res = 0;
#endif /* DISABLE_PLUGINS */
goto exit;
}
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
res = 0; res = 0;
if (of->state & CLOSE_DMTIME)
ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
if (of->state & CLOSE_COMPRESSED) if (of->state & CLOSE_COMPRESSED)
res = ntfs_attr_pclose(na); res = ntfs_attr_pclose(na);
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
if (of->state & CLOSE_ENCRYPTED) if (of->state & CLOSE_ENCRYPTED)
res = ntfs_efs_fixup_attribute(NULL, na); res = ntfs_efs_fixup_attribute(NULL, na);
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */
#ifndef DISABLE_PLUGINS
stamps :
#endif /* DISABLE_PLUGINS */
if (of->state & CLOSE_DMTIME)
ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
exit: exit:
if (na) if (na)
ntfs_attr_close(na); ntfs_attr_close(na);
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
set_fuse_error(&res); set_fuse_error(&res);
out: out:
/* remove the associate ghost file (even if release failed) */ /* remove the associate ghost file (even if release failed) */
if (of) { if (of) {
if (of->state & CLOSE_GHOST) { if (of->state & CLOSE_GHOST) {
sprintf(ghostname,ghostformat,of->ghost); sprintf(ghostname,ghostformat,of->ghost);
skipping to change at line 2922 skipping to change at line 3203
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
ntfs_fuse_fill_security_context(req, &security); ntfs_fuse_fill_security_context(req, &security);
#endif #endif
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
ret = -errno; ret = -errno;
goto out; goto out;
} }
/* Return with no result for symlinks, fifo, etc. */ /* Return with no result for symlinks, fifo, etc. */
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) if (!user_xattrs_allowed(ctx, ni))
goto exit; goto exit;
/* otherwise file must be readable */ /* otherwise file must be readable */
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
if (!ntfs_allowed_access(&security,ni,S_IREAD)) { if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
ret = -EACCES; ret = -EACCES;
goto exit; goto exit;
} }
#endif #endif
actx = ntfs_attr_get_search_ctx(ni, NULL); actx = ntfs_attr_get_search_ctx(ni, NULL);
if (!actx) { if (!actx) {
skipping to change at line 3071 skipping to change at line 3352
res = -ENODATA; res = -ENODATA;
goto out; goto out;
} }
#endif #endif
ni = ntfs_inode_open(ctx->vol, INODE(ino)); ni = ntfs_inode_open(ctx->vol, INODE(ino));
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto out; goto out;
} }
/* Return with no result for symlinks, fifo, etc. */ /* Return with no result for symlinks, fifo, etc. */
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) { if (!user_xattrs_allowed(ctx, ni)) {
res = -ENODATA; res = -ENODATA;
goto exit; goto exit;
} }
/* otherwise file must be readable */ /* otherwise file must be readable */
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS) #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
if (!ntfs_allowed_access(&security, ni, S_IREAD)) { if (!ntfs_allowed_access(&security, ni, S_IREAD)) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
#endif #endif
skipping to change at line 3268 skipping to change at line 3549
} }
break; break;
case XATTRNS_SYSTEM : case XATTRNS_SYSTEM :
if (!ntfs_allowed_as_owner(&security, ni)) { if (!ntfs_allowed_as_owner(&security, ni)) {
res = -EACCES; res = -EACCES;
goto exit; goto exit;
} }
break; break;
default : default :
/* User xattr not allowed for symlinks, fifo, etc. */ /* User xattr not allowed for symlinks, fifo, etc. */
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) { if (!user_xattrs_allowed(ctx, ni)) {
res = -EPERM; res = -EPERM;
goto exit; goto exit;
} }
if (!ntfs_allowed_access(&security,ni,S_IWRITE)) { if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
res = -EACCES; res = -EACCES;
goto exit; goto exit;
} }
break; break;
} }
#else #else
/* User xattr not allowed for symlinks, fifo, etc. */ /* User xattr not allowed for symlinks, fifo, etc. */
if ((namespace == XATTRNS_USER) if ((namespace == XATTRNS_USER)
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) { && !user_xattrs_allowed(ctx, ni)) {
res = -EPERM; res = -EPERM;
goto exit; goto exit;
} }
#endif #endif
lename_len = fix_xattr_prefix(name, namespace, &lename); lename_len = fix_xattr_prefix(name, namespace, &lename);
if ((lename_len == -1) if ((lename_len == -1)
|| (ctx->windows_names || (ctx->windows_names
&& ntfs_forbidden_chars(lename,lename_len))) { && ntfs_forbidden_chars(lename,lename_len,TRUE))) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
na = ntfs_attr_open(ni, AT_DATA, lename, lename_len); na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
if (na && flags == XATTR_CREATE) { if (na && flags == XATTR_CREATE) {
res = -EEXIST; res = -EEXIST;
goto exit; goto exit;
} }
if (!na) { if (!na) {
if (flags == XATTR_REPLACE) { if (flags == XATTR_REPLACE) {
skipping to change at line 3513 skipping to change at line 3794
} }
break; break;
case XATTRNS_SYSTEM : case XATTRNS_SYSTEM :
if (!ntfs_allowed_as_owner(&security, ni)) { if (!ntfs_allowed_as_owner(&security, ni)) {
res = -EACCES; res = -EACCES;
goto exit; goto exit;
} }
break; break;
default : default :
/* User xattr not allowed for symlinks, fifo, etc. */ /* User xattr not allowed for symlinks, fifo, etc. */
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) { if (!user_xattrs_allowed(ctx, ni)) {
res = -EPERM; res = -EPERM;
goto exit; goto exit;
} }
if (!ntfs_allowed_access(&security,ni,S_IWRITE)) { if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
res = -EACCES; res = -EACCES;
goto exit; goto exit;
} }
break; break;
} }
#else #else
/* User xattr not allowed for symlinks, fifo, etc. */ /* User xattr not allowed for symlinks, fifo, etc. */
if ((namespace == XATTRNS_USER) if ((namespace == XATTRNS_USER)
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) { && !user_xattrs_allowed(ctx, ni)) {
res = -EPERM; res = -EPERM;
goto exit; goto exit;
} }
#endif #endif
lename_len = fix_xattr_prefix(name, namespace, &lename); lename_len = fix_xattr_prefix(name, namespace, &lename);
if (lename_len == -1) { if (lename_len == -1) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) { if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {
skipping to change at line 3567 skipping to change at line 3848
return; return;
} }
#else #else
#if POSIXACLS #if POSIXACLS
#error "Option inconsistency : POSIXACLS requires SETXATTR" #error "Option inconsistency : POSIXACLS requires SETXATTR"
#endif #endif
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */
#ifndef DISABLE_PLUGINS
static void register_internal_reparse_plugins(void)
{
static const plugin_operations_t ops = {
.getattr = junction_getstat,
.readlink = junction_readlink,
} ;
register_reparse_plugin(ctx, IO_REPARSE_TAG_MOUNT_POINT,
&ops, (void*)NULL);
register_reparse_plugin(ctx, IO_REPARSE_TAG_SYMLINK,
&ops, (void*)NULL);
}
#endif /* DISABLE_PLUGINS */
static void ntfs_close(void) static void ntfs_close(void)
{ {
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
if (!ctx) if (!ctx)
return; return;
if (!ctx->vol) if (!ctx->vol)
return; return;
skipping to change at line 3592 skipping to change at line 3887
ntfs_log_info("Permissions cache : %lu writes, " ntfs_log_info("Permissions cache : %lu writes, "
"%lu reads, %lu.%1lu%% hits\n", "%lu reads, %lu.%1lu%% hits\n",
ctx->seccache->head.p_writes, ctx->seccache->head.p_writes,
ctx->seccache->head.p_reads, ctx->seccache->head.p_reads,
100 * ctx->seccache->head.p_hits 100 * ctx->seccache->head.p_hits
/ ctx->seccache->head.p_reads, / ctx->seccache->head.p_reads,
1000 * ctx->seccache->head.p_hits 1000 * ctx->seccache->head.p_hits
/ ctx->seccache->head.p_reads % 10); / ctx->seccache->head.p_reads % 10);
} }
} }
ntfs_close_secure(&security); ntfs_destroy_security_context(&security);
} }
if (ntfs_umount(ctx->vol, FALSE)) if (ntfs_umount(ctx->vol, FALSE))
ntfs_log_perror("Failed to close volume %s", opts.device); ntfs_log_perror("Failed to close volume %s", opts.device);
ctx->vol = NULL; ctx->vol = NULL;
} }
static void ntfs_fuse_destroy2(void *notused __attribute__((unused))) static void ntfs_fuse_destroy2(void *notused __attribute__((unused)))
{ {
skipping to change at line 3683 skipping to change at line 3978
static int ntfs_open(const char *device) static int ntfs_open(const char *device)
{ {
unsigned long flags = 0; unsigned long flags = 0;
ntfs_volume *vol; ntfs_volume *vol;
if (!ctx->blkdev) if (!ctx->blkdev)
flags |= NTFS_MNT_EXCLUSIVE; flags |= NTFS_MNT_EXCLUSIVE;
if (ctx->ro) if (ctx->ro)
flags |= NTFS_MNT_RDONLY; flags |= NTFS_MNT_RDONLY;
else
if (!ctx->hiberfile)
flags |= NTFS_MNT_MAY_RDONLY;
if (ctx->recover) if (ctx->recover)
flags |= NTFS_MNT_RECOVER; flags |= NTFS_MNT_RECOVER;
if (ctx->hiberfile) if (ctx->hiberfile)
flags |= NTFS_MNT_IGNORE_HIBERFILE; flags |= NTFS_MNT_IGNORE_HIBERFILE;
ctx->vol = vol = ntfs_mount(device, flags); ctx->vol = vol = ntfs_mount(device, flags);
if (!vol) { if (!vol) {
ntfs_log_perror("Failed to mount '%s'", device); ntfs_log_perror("Failed to mount '%s'", device);
goto err_out; goto err_out;
} }
skipping to change at line 3826 skipping to change at line 4124
fclose(f); fclose(f);
return fstype; return fstype;
} }
static fuse_fstype load_fuse_module(void) static fuse_fstype load_fuse_module(void)
{ {
int i; int i;
struct stat st; struct stat st;
pid_t pid; pid_t pid;
const char *cmd = "/sbin/modprobe"; const char *cmd = "/sbin/modprobe";
char *env = (char*)NULL;
struct timespec req = { 0, 100000000 }; /* 100 msec */ struct timespec req = { 0, 100000000 }; /* 100 msec */
fuse_fstype fstype; fuse_fstype fstype;
if (!stat(cmd, &st) && !geteuid()) { if (!stat(cmd, &st) && !geteuid()) {
pid = fork(); pid = fork();
if (!pid) { if (!pid) {
execl(cmd, cmd, "fuse", NULL); execle(cmd, cmd, "fuse", (char*)NULL, &env);
_exit(1); _exit(1);
} else if (pid != -1) } else if (pid != -1)
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
} }
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
/* /*
* We sleep first because despite the detection of the loaded * We sleep first because despite the detection of the loaded
* FUSE kernel module, fuse_mount() can still fail if it's not * FUSE kernel module, fuse_mount() can still fail if it's not
* fully functional/initialized. Note, of course this is still * fully functional/initialized. Note, of course this is still
skipping to change at line 4099 skipping to change at line 4398
} }
/* We must do this after ntfs_open() to be able to set the blksize */ /* We must do this after ntfs_open() to be able to set the blksize */
if (ctx->blkdev && set_fuseblk_options(&parsed_options)) if (ctx->blkdev && set_fuseblk_options(&parsed_options))
goto err_out; goto err_out;
ctx->security.vol = ctx->vol; ctx->security.vol = ctx->vol;
ctx->vol->secure_flags = ctx->secure_flags; ctx->vol->secure_flags = ctx->secure_flags;
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
ctx->vol->efs_raw = ctx->efs_raw; ctx->vol->efs_raw = ctx->efs_raw;
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */
/* JPA open $Secure, (whatever NTFS version !) */
/* to initialize security data */
if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3))
failed_secure = "Could not open file $Secure";
if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path, if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path,
(ctx->vol->secure_flags (ctx->vol->secure_flags
& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL))) & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
&& !ctx->inherit && !ctx->inherit
&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) { && !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
#if POSIXACLS #if POSIXACLS
/* use basic permissions if requested */ /* use basic permissions if requested */
if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
permissions_mode = "User mapping built, Posix ACLs not us ed"; permissions_mode = "User mapping built, Posix ACLs not us ed";
else { else {
skipping to change at line 4177 skipping to change at line 4472
ctx->xattrmap_path); ctx->xattrmap_path);
ctx->vol->xattr_mapping = xattr_mapping; ctx->vol->xattr_mapping = xattr_mapping;
/* /*
* Errors are logged, do not refuse mounting, it would be * Errors are logged, do not refuse mounting, it would be
* too difficult to fix the unmountable mapping file. * too difficult to fix the unmountable mapping file.
*/ */
if (ctx->xattrmap_path) if (ctx->xattrmap_path)
free(ctx->xattrmap_path); free(ctx->xattrmap_path);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */ #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
#ifndef DISABLE_PLUGINS
register_internal_reparse_plugins();
#endif /* DISABLE_PLUGINS */
se = mount_fuse(parsed_options); se = mount_fuse(parsed_options);
if (!se) { if (!se) {
err = NTFS_VOLUME_FUSE_ERROR; err = NTFS_VOLUME_FUSE_ERROR;
goto err_out; goto err_out;
} }
ctx->mounted = TRUE; ctx->mounted = TRUE;
#if defined(linux) || defined(__uClinux__) #if defined(linux) || defined(__uClinux__)
if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE)) if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
skipping to change at line 4212 skipping to change at line 4511
fuse_session_destroy(se); fuse_session_destroy(se);
err_out: err_out:
ntfs_mount_error(opts.device, opts.mnt_point, err); ntfs_mount_error(opts.device, opts.mnt_point, err);
if (ctx->abs_mnt_point) if (ctx->abs_mnt_point)
free(ctx->abs_mnt_point); free(ctx->abs_mnt_point);
#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) #if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
ntfs_xattr_free_mapping(xattr_mapping); ntfs_xattr_free_mapping(xattr_mapping);
#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */ #endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
err2: err2:
ntfs_close(); ntfs_close();
#ifndef DISABLE_PLUGINS
close_reparse_plugins(ctx);
#endif /* DISABLE_PLUGINS */
free(ctx); free(ctx);
free(parsed_options); free(parsed_options);
free(opts.options); free(opts.options);
free(opts.device); free(opts.device);
return err; return err;
} }
 End of changes. 74 change blocks. 
84 lines changed or deleted 386 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS