Adapted to ntfs-3g.1.2812

This commit is contained in:
jpandre 2008-08-16 15:17:47 +00:00
parent ca9e62559a
commit 499e106341
11 changed files with 271 additions and 113 deletions

View File

@ -5,6 +5,7 @@ Jean-Pierre Andre
Alon Bar-Lev Alon Bar-Lev
Dominique L Bouix Dominique L Bouix
Csaba Henk Csaba Henk
Bernhard Kaindl
Erik Larsson Erik Larsson
Alejandro Pulver Alejandro Pulver
Szabolcs Szakacsits Szabolcs Szakacsits

View File

@ -186,7 +186,8 @@ struct _ntfs_attr {
}; };
/** /**
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr structure * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
* structure
*/ */
typedef enum { typedef enum {
NA_Initialized, /* 1: structure is initialized. */ NA_Initialized, /* 1: structure is initialized. */

View File

@ -27,13 +27,20 @@
#include "config.h" #include "config.h"
#endif #endif
#ifdef WINDOWS
#ifndef HAVE_FFS #ifndef HAVE_FFS
#define HAVE_FFS
extern int ffs(int i); extern int ffs(int i);
#endif /* HAVE_FFS */ #endif /* HAVE_FFS */
#ifndef HAVE_DAEMON
extern int daemon(int nochdir, int noclose);
#endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP
extern char *strsep(char **stringp, const char *delim);
#endif /* HAVE_STRSEP */
#ifdef WINDOWS
#define HAVE_STDIO_H /* mimic config.h */ #define HAVE_STDIO_H /* mimic config.h */
#define HAVE_STDARG_H #define HAVE_STDARG_H

View File

@ -128,12 +128,14 @@ struct _ntfs_inode {
inode of the base mft record. */ inode of the base mft record. */
}; };
/* Temp: for directory handling */
void *private_data; /* ntfs_dt containing this inode */
int ref_count;
/* Below fields are valid only for base inode. */ /* Below fields are valid only for base inode. */
s64 data_size; /* Data size stored in the filename index. */
/*
* These two fields are used to sync filename index and guaranteed to be
* correct, however value in index itself maybe wrong (windows itself
* do not update them properly).
*/
s64 data_size; /* Data size of unnamed DATA attribute. */
s64 allocated_size; /* Allocated size stored in the filename s64 allocated_size; /* Allocated size stored in the filename
index. (NOTE: Equal to allocated size of index. (NOTE: Equal to allocated size of
the unnamed data attribute for normal or the unnamed data attribute for normal or
@ -141,6 +143,11 @@ struct _ntfs_inode {
of the unnamed data attribute for sparse or of the unnamed data attribute for sparse or
compressed files.) */ compressed files.) */
/*
* These four fields are copy of relevant fields from
* STANDARD_INFORMATION attribute and used to sync it and FILE_NAME
* attribute in the index.
*/
time_t creation_time; time_t creation_time;
time_t last_data_change_time; time_t last_data_change_time;
time_t last_mft_change_time; time_t last_mft_change_time;

View File

@ -239,10 +239,6 @@ struct _ntfs_volume {
struct CACHE_HEADER *legacy_cache; struct CACHE_HEADER *legacy_cache;
#endif #endif
/* Temp: for directory handling */
void *private_data; /* ntfs_dir for . */
void *private_bmp1; /* ntfs_bmp for $MFT/$BITMAP */
void *private_bmp2; /* ntfs_bmp for $Bitmap */
}; };
extern ntfs_volume *ntfs_volume_alloc(void); extern ntfs_volume *ntfs_volume_alloc(void);

View File

@ -506,7 +506,7 @@ void ntfs_attr_close(ntfs_attr *na)
* @na: ntfs attribute for which to map (part of) a runlist * @na: ntfs attribute for which to map (part of) a runlist
* @vcn: map runlist part containing this vcn * @vcn: map runlist part containing this vcn
* *
* Map the part of a runlist containing the @vcn of an the ntfs attribute @na. * Map the part of a runlist containing the @vcn of the ntfs attribute @na.
* *
* Return 0 on success and -1 on error with errno set to the error code. * Return 0 on success and -1 on error with errno set to the error code.
*/ */
@ -549,8 +549,8 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
* ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
* @na: ntfs attribute for which to map the runlist * @na: ntfs attribute for which to map the runlist
* *
* Map the whole runlist of an the ntfs attribute @na. For an attribute made * Map the whole runlist of the ntfs attribute @na. For an attribute made up
* up of only one attribute extent this is the same as calling * of only one attribute extent this is the same as calling
* ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this * ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
* will map the runlist fragments from each of the extents thus giving access * will map the runlist fragments from each of the extents thus giving access
* to the entirety of the disk allocation of an attribute. * to the entirety of the disk allocation of an attribute.
@ -2998,7 +2998,7 @@ int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx)
NInoAttrListClearDirty(base_ni); NInoAttrListClearDirty(base_ni);
} }
/* Free MFT record, if it isn't contain attributes. */ /* Free MFT record, if it doesn't contain attributes. */
if (le32_to_cpu(ctx->mrec->bytes_in_use) - if (le32_to_cpu(ctx->mrec->bytes_in_use) -
le16_to_cpu(ctx->mrec->attrs_offset) == 8) { le16_to_cpu(ctx->mrec->attrs_offset) == 8) {
if (ntfs_mft_record_free(ni->vol, ni)) { if (ntfs_mft_record_free(ni->vol, ni)) {
@ -3260,9 +3260,9 @@ rm_attr_err_out:
(ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0)) (ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0))
ntfs_log_perror("Failed to remove just added attribute #2"); ntfs_log_perror("Failed to remove just added attribute #2");
free_err_out: free_err_out:
/* Free MFT record, if it isn't contain attributes. */ /* Free MFT record, if it doesn't contain attributes. */
if (le32_to_cpu(attr_ni->mrec->bytes_in_use) - if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
le32_to_cpu(attr_ni->mrec->attrs_offset) == 8) le16_to_cpu(attr_ni->mrec->attrs_offset) == 8)
if (ntfs_mft_record_free(attr_ni->vol, attr_ni)) if (ntfs_mft_record_free(attr_ni->vol, attr_ni))
ntfs_log_perror("Failed to free MFT record"); ntfs_log_perror("Failed to free MFT record");
err_out: err_out:
@ -4325,7 +4325,7 @@ retry:
*/ */
first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn); first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn);
if (first_lcn == LCN_EINVAL) { if (first_lcn == LCN_EINVAL) {
err = EIO; errno = EIO;
ntfs_log_perror("Bad runlist"); ntfs_log_perror("Bad runlist");
goto put_err_out; goto put_err_out;
} }
@ -4349,8 +4349,7 @@ retry:
continue; continue;
} }
err = ntfs_attr_update_meta(a, na, m, ctx); switch (ntfs_attr_update_meta(a, na, m, ctx)) {
switch (err) {
case -1: return -1; case -1: return -1;
case -2: goto retry; case -2: goto retry;
case -3: goto put_err_out; case -3: goto put_err_out;
@ -4360,7 +4359,6 @@ retry:
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl, mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl,
stop_vcn); stop_vcn);
if (mp_size <= 0) { if (mp_size <= 0) {
err = errno;
ntfs_log_perror("%s: get MP size failed", __FUNCTION__); ntfs_log_perror("%s: get MP size failed", __FUNCTION__);
goto put_err_out; goto put_err_out;
} }
@ -4419,8 +4417,8 @@ retry:
if (ntfs_attr_record_resize(m, a, if (ntfs_attr_record_resize(m, a,
le16_to_cpu(a->mapping_pairs_offset) + le16_to_cpu(a->mapping_pairs_offset) +
mp_size)) { mp_size)) {
errno = EIO;
ntfs_log_perror("Failed to resize attribute"); ntfs_log_perror("Failed to resize attribute");
err = EIO;
goto put_err_out; goto put_err_out;
} }
} }
@ -4444,7 +4442,6 @@ retry:
stop_vcn, &stop_vcn)) stop_vcn, &stop_vcn))
finished_build = TRUE; finished_build = TRUE;
if (!finished_build && errno != ENOSPC) { if (!finished_build && errno != ENOSPC) {
err = errno;
ntfs_log_perror("Failed to build mapping pairs"); ntfs_log_perror("Failed to build mapping pairs");
goto put_err_out; goto put_err_out;
} }
@ -4452,7 +4449,6 @@ retry:
} }
/* Check whether error occurred. */ /* Check whether error occurred. */
if (errno != ENOENT) { if (errno != ENOENT) {
err = errno;
ntfs_log_perror("%s: Attribute lookup failed", __FUNCTION__); ntfs_log_perror("%s: Attribute lookup failed", __FUNCTION__);
goto put_err_out; goto put_err_out;
} }
@ -4468,14 +4464,12 @@ retry:
continue; continue;
/* Remove unused attribute record. */ /* Remove unused attribute record. */
if (ntfs_attr_record_rm(ctx)) { if (ntfs_attr_record_rm(ctx)) {
err = errno;
ntfs_log_perror("Could not remove unused attr"); ntfs_log_perror("Could not remove unused attr");
goto put_err_out; goto put_err_out;
} }
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
} }
if (errno != ENOENT) { if (errno != ENOENT) {
err = errno;
ntfs_log_perror("%s: Attr lookup failed", __FUNCTION__); ntfs_log_perror("%s: Attr lookup failed", __FUNCTION__);
goto put_err_out; goto put_err_out;
} }
@ -4492,14 +4486,12 @@ retry:
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol,
na->rl, stop_vcn); na->rl, stop_vcn);
if (mp_size <= 0) { if (mp_size <= 0) {
err = errno;
ntfs_log_perror("%s: get mp size failed", __FUNCTION__); ntfs_log_perror("%s: get mp size failed", __FUNCTION__);
goto put_err_out; goto put_err_out;
} }
/* Allocate new mft record. */ /* Allocate new mft record. */
ni = ntfs_mft_record_alloc(na->ni->vol, base_ni); ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
if (!ni) { if (!ni) {
err = errno;
ntfs_log_perror("Could not allocate new MFT record"); ntfs_log_perror("Could not allocate new MFT record");
goto put_err_out; goto put_err_out;
} }
@ -4524,6 +4516,7 @@ retry:
ntfs_log_perror("Could not add attribute extent"); ntfs_log_perror("Could not add attribute extent");
if (ntfs_mft_record_free(na->ni->vol, ni)) if (ntfs_mft_record_free(na->ni->vol, ni))
ntfs_log_perror("Could not free MFT record"); ntfs_log_perror("Could not free MFT record");
errno = err;
goto put_err_out; goto put_err_out;
} }
a = (ATTR_RECORD*)((u8*)m + err); a = (ATTR_RECORD*)((u8*)m + err);
@ -4536,6 +4529,7 @@ retry:
ntfs_log_perror("Failed to build MP"); ntfs_log_perror("Failed to build MP");
if (ntfs_mft_record_free(na->ni->vol, ni)) if (ntfs_mft_record_free(na->ni->vol, ni))
ntfs_log_perror("Couldn't free MFT record"); ntfs_log_perror("Couldn't free MFT record");
errno = err;
goto put_err_out; goto put_err_out;
} }
a->highest_vcn = cpu_to_sle64(stop_vcn - 1); a->highest_vcn = cpu_to_sle64(stop_vcn - 1);
@ -4551,7 +4545,6 @@ out:
put_err_out: put_err_out:
if (ctx) if (ctx)
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
errno = err;
goto out; goto out;
} }
#undef NTFS_VCN_DELETE_MARK #undef NTFS_VCN_DELETE_MARK
@ -4916,7 +4909,7 @@ rollback:
ntfs_log_perror("Couldn't truncate runlist. Rollback failed"); ntfs_log_perror("Couldn't truncate runlist. Rollback failed");
} else { } else {
/* Prepare to mapping pairs update. */ /* Prepare to mapping pairs update. */
na->allocated_size = org_alloc_size << vol->cluster_size_bits; na->allocated_size = org_alloc_size;
/* Restore mapping pairs. */ /* Restore mapping pairs. */
if (ntfs_attr_update_mapping_pairs(na, 0 /*na->allocated_size >> if (ntfs_attr_update_mapping_pairs(na, 0 /*na->allocated_size >>
vol->cluster_size_bits*/)) { vol->cluster_size_bits*/)) {

View File

@ -20,16 +20,12 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef WINDOWS
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "compat.h" #include "compat.h"
/* TODO: Add check for FFS in the configure script... (AIA) */
#ifndef HAVE_FFS #ifndef HAVE_FFS
/** /**
* ffs - Find the first set bit in an int * ffs - Find the first set bit in an int
@ -69,5 +65,186 @@ int ffs(int x)
} }
#endif /* HAVE_FFS */ #endif /* HAVE_FFS */
#endif /* WINDOWS */ #ifndef HAVE_DAEMON
/* ************************************************************
* From: src.opensolaris.org
* src/lib/libresolv2/common/bsd/daemon.c
*/
/*
* Copyright (c) 1997-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpandre Exp $";
#endif /* LIBC_SCCS and not lint */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
int daemon(int nochdir, int noclose) {
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, 0);
(void)dup2(fd, 1);
(void)dup2(fd, 2);
if (fd > 2)
(void)close (fd);
}
return (0);
}
/*
* End: src/lib/libresolv2/common/bsd/daemon.c
*************************************************************/
#endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP
/* ************************************************************
* From: src.opensolaris.org
* src/lib/libresolv2/common/bsd/strsep.c
*/
/*
* Copyright (c) 1997, by Sun Microsystems, Inc.
* All rights reserved.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpandre Exp $";
#endif /* LIBC_SCCS and not lint */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
/*
* Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strsep returns NULL.
*/
char *strsep(char **stringp, const char *delim) {
char *s;
const char *spanp;
int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
/*
* End: src/lib/libresolv2/common/bsd/strsep.c
*************************************************************/
#endif /* HAVE_STRSEP */

View File

@ -1419,21 +1419,21 @@ static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib)
return ret; return ret;
} }
/* JPA static */ /* JPA static */
int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie)
{ {
INDEX_HEADER *ih; INDEX_HEADER *ih;
int allocated_size, new_size; int allocated_size, new_size;
int ret = STATUS_ERROR; int ret = STATUS_ERROR;
#ifdef DEBUG
/* removed by JPA to make function usable for security indexes /* removed by JPA to make function usable for security indexes
char *fn; char *fn;
fn = ntfs_ie_filename_get(ie); fn = ntfs_ie_filename_get(ie);
ntfs_log_trace("file: '%s'\n", fn); ntfs_log_trace("file: '%s'\n", fn);
ntfs_attr_name_free(&fn); ntfs_attr_name_free(&fn);
*/ */
#endif
while (1) { while (1) {

View File

@ -275,6 +275,8 @@ err_out:
* If it is an extent inode, we disconnect it from its base inode before we * If it is an extent inode, we disconnect it from its base inode before we
* destroy it. * destroy it.
* *
* It is OK to pass NULL to this function, it is just noop in this case.
*
* Return 0 on success or -1 on error with errno set to the error code. On * Return 0 on success or -1 on error with errno set to the error code. On
* error, @ni has not been freed. The user should attempt to handle the error * error, @ni has not been freed. The user should attempt to handle the error
* and call ntfs_inode_close() again. The following error codes are defined: * and call ntfs_inode_close() again. The following error codes are defined:

View File

@ -52,6 +52,10 @@ typedef struct ntfs_volume ntfs_volume;
#include "types.h" #include "types.h"
#include "device.h" #include "device.h"
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
#ifndef NTFS_BLOCK_SIZE #ifndef NTFS_BLOCK_SIZE
#define NTFS_BLOCK_SIZE 512 #define NTFS_BLOCK_SIZE 512
#define NTFS_BLOCK_SIZE_BITS 9 #define NTFS_BLOCK_SIZE_BITS 9

View File

@ -75,6 +75,14 @@
#include <sys/xattr.h> #include <sys/xattr.h>
#endif #endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_MKDEV_H
#include <sys/mkdev.h>
#endif
#include "compat.h"
#include "attrib.h" #include "attrib.h"
#include "inode.h" #include "inode.h"
#include "volume.h" #include "volume.h"
@ -376,18 +384,16 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
int res = 0; int res = 0;
ntfs_inode *ni; ntfs_inode *ni;
ntfs_attr *na; ntfs_attr *na;
ntfs_volume *vol;
char *path = NULL; char *path = NULL;
ntfschar *stream_name; ntfschar *stream_name;
int stream_name_len; int stream_name_len;
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
vol = ctx->vol;
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
if (stream_name_len < 0) if (stream_name_len < 0)
return stream_name_len; return stream_name_len;
memset(stbuf, 0, sizeof(struct stat)); memset(stbuf, 0, sizeof(struct stat));
ni = ntfs_pathname_to_inode(vol, NULL, path); ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
@ -630,15 +636,13 @@ static int ntfs_fuse_readdir(const char *path, void *buf,
struct fuse_file_info *fi __attribute__((unused))) struct fuse_file_info *fi __attribute__((unused)))
{ {
ntfs_fuse_fill_context_t fill_ctx; ntfs_fuse_fill_context_t fill_ctx;
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
s64 pos = 0; s64 pos = 0;
int err = 0; int err = 0;
vol = ctx->vol;
fill_ctx.filler = filler; fill_ctx.filler = filler;
fill_ctx.buf = buf; fill_ctx.buf = buf;
ni = ntfs_pathname_to_inode(vol, NULL, path); ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
if (ntfs_readdir(ni, &pos, &fill_ctx, if (ntfs_readdir(ni, &pos, &fill_ctx,
@ -653,7 +657,6 @@ static int ntfs_fuse_readdir(const char *path, void *buf,
static int ntfs_fuse_open(const char *org_path, static int ntfs_fuse_open(const char *org_path,
struct fuse_file_info *fi) struct fuse_file_info *fi)
{ {
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
ntfs_attr *na; ntfs_attr *na;
int res = 0; int res = 0;
@ -666,8 +669,7 @@ static int ntfs_fuse_open(const char *org_path,
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
if (stream_name_len < 0) if (stream_name_len < 0)
return stream_name_len; return stream_name_len;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (ni) { if (ni) {
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (na) { if (na) {
@ -765,7 +767,6 @@ exit:
static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size, static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi __attribute__((unused))) off_t offset, struct fuse_file_info *fi __attribute__((unused)))
{ {
ntfs_volume *vol;
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
char *path = NULL; char *path = NULL;
@ -777,8 +778,7 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,
res = stream_name_len; res = stream_name_len;
goto out; goto out;
} }
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) { if (!ni) {
res = -errno; res = -errno;
goto exit; goto exit;
@ -789,17 +789,18 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,
goto exit; goto exit;
} }
while (size) { while (size) {
res = ntfs_attr_pwrite(na, offset, size, buf); s64 ret = ntfs_attr_pwrite(na, offset, size, buf);
if (res < (s64)size) if (0 <= ret && ret < (s64)size)
ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: " ntfs_log_perror("ntfs_attr_pwrite partial write to '%s'"
"%lld <> %d)", (long long)offset, (long long)size, res); " (%lld: %lld <> %lld)", path, (long long)offset,
if (res <= 0) { (long long)size, ret);
if (ret <= 0) {
res = -errno; res = -errno;
goto exit; goto exit;
} }
size -= res; size -= ret;
offset += res; offset += ret;
total += res; total += ret;
} }
res = total; res = total;
if (res > 0) if (res > 0)
@ -822,7 +823,6 @@ out:
static int ntfs_fuse_trunc(const char *org_path, off_t size, BOOL chkwrite) static int ntfs_fuse_trunc(const char *org_path, off_t size, BOOL chkwrite)
{ {
ntfs_volume *vol;
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
int res; int res;
@ -834,8 +834,7 @@ static int ntfs_fuse_trunc(const char *org_path, off_t size, BOOL chkwrite)
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
if (stream_name_len < 0) if (stream_name_len < 0)
return stream_name_len; return stream_name_len;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
goto exit; goto exit;
@ -1166,29 +1165,7 @@ static int ntfs_fuse_create_stream(const char *path,
return res; return res;
} }
static int ntfs_fuse_create_file(const char *org_path, mode_t mode, static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev)
struct fuse_file_info *fi __attribute__((unused)))
{
char *path = NULL;
ntfschar *stream_name;
int stream_name_len;
int res;
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
if (stream_name_len < 0)
return stream_name_len;
if (!stream_name_len)
res = ntfs_fuse_create(path, mode, 0, NULL);
else
res = ntfs_fuse_create_stream(path, stream_name,
stream_name_len);
free(path);
if (stream_name_len)
free(stream_name);
return res;
}
static int ntfs_fuse_mknod(const char *org_path, mode_t mode, dev_t dev)
{ {
char *path = NULL; char *path = NULL;
ntfschar *stream_name; ntfschar *stream_name;
@ -1214,6 +1191,17 @@ exit:
return res; return res;
} }
static int ntfs_fuse_mknod(const char *path, mode_t mode, dev_t dev)
{
return ntfs_fuse_mknod_common(path, mode, dev);
}
static int ntfs_fuse_create_file(const char *path, mode_t mode,
struct fuse_file_info *fi __attribute__((unused)))
{
return ntfs_fuse_mknod_common(path, mode, 0);
}
static int ntfs_fuse_symlink(const char *to, const char *from) static int ntfs_fuse_symlink(const char *to, const char *from)
{ {
if (ntfs_fuse_is_named_data_stream(from)) if (ntfs_fuse_is_named_data_stream(from))
@ -1616,17 +1604,13 @@ static const int nf_ns_xattr_preffix_len = 5;
static int ntfs_fuse_listxattr(const char *path, char *list, size_t size) static int ntfs_fuse_listxattr(const char *path, char *list, size_t size)
{ {
ntfs_attr_search_ctx *actx = NULL; ntfs_attr_search_ctx *actx = NULL;
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
char *to = list; char *to = list;
int ret = 0; int ret = 0;
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR) if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
return -EOPNOTSUPP; return -EOPNOTSUPP;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!vol)
return -ENODEV;
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
actx = ntfs_attr_get_search_ctx(ni, NULL); actx = ntfs_attr_get_search_ctx(ni, NULL);
@ -1680,17 +1664,13 @@ static int ntfs_fuse_getxattr_windows(const char *path, const char *name,
char *value, size_t size) char *value, size_t size)
{ {
ntfs_attr_search_ctx *actx = NULL; ntfs_attr_search_ctx *actx = NULL;
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
char *to = value; char *to = value;
int ret = 0; int ret = 0;
if (strcmp(name, "ntfs.streams.list")) if (strcmp(name, "ntfs.streams.list"))
return -EOPNOTSUPP; return -EOPNOTSUPP;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!vol)
return -ENODEV;
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
actx = ntfs_attr_get_search_ctx(ni, NULL); actx = ntfs_attr_get_search_ctx(ni, NULL);
@ -1746,7 +1726,6 @@ exit:
static int ntfs_fuse_getxattr(const char *path, const char *name, static int ntfs_fuse_getxattr(const char *path, const char *name,
char *value, size_t size) char *value, size_t size)
{ {
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
ntfschar *lename = NULL; ntfschar *lename = NULL;
@ -1759,10 +1738,7 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
strlen(name) == (size_t)nf_ns_xattr_preffix_len) strlen(name) == (size_t)nf_ns_xattr_preffix_len)
return -ENODATA; return -ENODATA;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!vol)
return -ENODEV;
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename);
@ -1796,7 +1772,6 @@ exit:
static int ntfs_fuse_setxattr(const char *path, const char *name, static int ntfs_fuse_setxattr(const char *path, const char *name,
const char *value, size_t size, int flags) const char *value, size_t size, int flags)
{ {
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
ntfschar *lename = NULL; ntfschar *lename = NULL;
@ -1807,10 +1782,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
strlen(name) == (size_t)nf_ns_xattr_preffix_len) strlen(name) == (size_t)nf_ns_xattr_preffix_len)
return -EACCES; return -EACCES;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!vol)
return -ENODEV;
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename);
@ -1854,7 +1826,6 @@ exit:
static int ntfs_fuse_removexattr(const char *path, const char *name) static int ntfs_fuse_removexattr(const char *path, const char *name)
{ {
ntfs_volume *vol;
ntfs_inode *ni; ntfs_inode *ni;
ntfschar *lename = NULL; ntfschar *lename = NULL;
int res = 0, lename_len; int res = 0, lename_len;
@ -1865,10 +1836,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
strlen(name) == (size_t)nf_ns_xattr_preffix_len) strlen(name) == (size_t)nf_ns_xattr_preffix_len)
return -ENODATA; return -ENODATA;
vol = ctx->vol; ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!vol)
return -ENODEV;
ni = ntfs_pathname_to_inode(vol, NULL, path);
if (!ni) if (!ni)
return -errno; return -errno;
lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename);
@ -2579,7 +2547,7 @@ static void setup_logging(char *parsed_options)
opts.device, (ctx->ro) ? "Read-Only" : "Read-Write", opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
ctx->vol->vol_name, ctx->vol->major_ver, ctx->vol->vol_name, ctx->vol->major_ver,
ctx->vol->minor_ver); ctx->vol->minor_ver);
ntfs_log_info("Cmdline options: %s\n", opts.options); ntfs_log_info("Cmdline options: %s\n", opts.options ? opts.options : "");
ntfs_log_info("Mount options: %s\n", parsed_options); ntfs_log_info("Mount options: %s\n", parsed_options);
} }
@ -2645,15 +2613,17 @@ int main(int argc, char *argv[])
if (drop_privs()) if (drop_privs())
goto err_out; goto err_out;
#endif #endif
if (stat(opts.device, &sbuf)) { if (stat(opts.device, &sbuf)) {
ntfs_log_perror("Failed to access '%s'", opts.device); ntfs_log_perror("Failed to access '%s'", opts.device);
err = NTFS_VOLUME_NO_PRIVILEGE; err = NTFS_VOLUME_NO_PRIVILEGE;
goto err_out; goto err_out;
} }
#if !(defined(__sun) && defined (__SVR4))
/* Always use fuseblk for block devices unless it's surely missing. */ /* Always use fuseblk for block devices unless it's surely missing. */
if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE)) if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
ctx->blkdev = TRUE; ctx->blkdev = TRUE;
#endif
#ifndef FUSE_INTERNAL #ifndef FUSE_INTERNAL
if (getuid() && ctx->blkdev) { if (getuid() && ctx->blkdev) {