Compare commits

...

30 Commits

Author SHA1 Message Date
Jean-Pierre André 0e875d3039 Translated the junctions to lower case when ignore_case is set 2011-04-13 17:46:47 +02:00
Jean-Pierre André 860cddd4db Fixed a false detection of bad memory release in secaudit 2011-04-13 17:45:02 +02:00
Jean-Pierre André e9e3b18711 Fixed inconsistent interface to ntfs_initialize_file_security() 2011-04-13 17:02:51 +02:00
Jean-Pierre André 3c30a0e798 Fixed type of argument (same value) 2011-04-13 17:00:22 +02:00
Jean-Pierre André a165aca342 Removed duplicated code 2011-04-13 16:59:41 +02:00
Jean-Pierre André 097a681932 Fixed getting space for making an index non resident
In rare situations there is not enough space in the base inode entry
to make an index non resident. The index has to be moved to an extent
first. This happens when not using permissions and inserting a file
whose name has 60 chars into a directory whose name has 184 chars.
(bug reported by Vito Caputo)
2011-03-23 10:48:07 +01:00
Jean-Pierre André 54e49e77f1 Fixed cluster mapping ahead of mapped runlist
A corner case was wrong and could cause aborted writes with error
"Run lists overlap. Cannot merge" when the clusters required by the
write are described in different MFT extents.
This can only happen in very fragmented files when the cluster size
is smaller than 4096 bytes. It does not cause any metadata corruption.
2011-03-01 12:06:26 +01:00
Jean-Pierre André 29190c9394 Enabled getting the sector size from an ioctl on FreeBSD and MacOSX (Erik Larsson)
The sector size is needed for formatting a volume unless forced through
an option or using the traditional sector size.
2011-03-01 12:04:43 +01:00
Jean-Pierre André 285668105c Fixed dealing with holes when expanding an attribute 2011-02-16 12:17:07 +01:00
Jean-Pierre André 6c71d84ef8 Defined option acl to request the use of Posix ACLs 2011-02-08 11:45:55 +01:00
Jean-Pierre André eeabab767f Moved global options parsing to ntfs-3g_common.c 2011-02-08 11:45:55 +01:00
Jean-Pierre André 3ae68884f7 Moved mount options parsing to ntfs-3g_common.c 2011-02-08 11:45:55 +01:00
Jean-Pierre André 453a8aa501 Updated copyright notices 2011-02-08 11:45:54 +01:00
Jean-Pierre André 1df8ddc199 Moved the knowledge of default upcase size to unistr.c 2011-02-08 11:45:54 +01:00
Jean-Pierre André 1192e02fef Improved appending data to a long hole 2011-02-08 11:45:54 +01:00
Jean-Pierre André aabda06ffd Merged sparse testing when appending with ntfsprogs requirement 2011-02-08 11:45:54 +01:00
Jean-Pierre André e7daa6c72f Restricted listxattr() to environments with extended attributes 2011-02-08 11:45:54 +01:00
Jean-Pierre André 9efb8b60a4 Fixed possible wrong hole size when overwriting compressed data 2011-02-08 11:45:54 +01:00
Jean-Pierre André 6ebb79f251 Denied modifications to metadata files 2011-02-08 11:45:54 +01:00
Jean-Pierre André 13641ad4d6 Switched to the same Upcase table as Vista 2011-02-08 11:45:54 +01:00
Jean-Pierre André 53be5fa9b2 Enabled expanding an attribute without creating a hole 2011-02-08 11:45:54 +01:00
Jean-Pierre André fc20bbb5b8 Enabled forensic mounting 2011-02-08 11:45:53 +01:00
Jean-Pierre André f5d0ab51c6 Moved the definition of leMFT_REF to layout.h 2011-02-08 11:45:53 +01:00
Jean-Pierre André 2e7f889a72 Moved listxattr() to a specific source module 2011-01-17 15:33:17 +01:00
Szabolcs Szakacsits 4f03663c55 release 2011.1.15 2011-01-15 12:43:27 +02:00
Jean-Pierre André c7f958c8ed Fixed allocated size when an attribute update causes unnamed data to be expelled 2011-01-10 10:53:26 +01:00
Jean-Pierre André df8d045340 Do not record inode open when failed (debug only) 2011-01-10 10:51:21 +01:00
Jean-Pierre André 17c9f839d5 Fixed deleting files using ignore_case option 2010-12-14 10:46:24 +01:00
Jean-Pierre André 58be44ebc5 Updated the README file (tests without installing) 2010-12-14 10:43:10 +01:00
Jean-Pierre André 19bfa135e7 Added descriptions of options recover/norecover to the manual 2010-12-14 10:38:59 +01:00
26 changed files with 1277 additions and 1248 deletions

24
README
View File

@ -38,14 +38,15 @@ the FUSE kernel module. Then unpack the source tarball and type:
make
make install # or 'sudo make install' if you aren't root.
Please note that NTFS-3G doesn't require the FUSE user space package.
Please note that NTFS-3G doesn't require the FUSE user space package any
more.
Non-Linux: Please see
http://www.tuxera.com/community/ntfs-3g-download/
for OS specific installation and source packages.
for known OS specific installation and source packages, but generally
the same procedures apply.
USAGE
=====
@ -66,3 +67,20 @@ line at the END(!) of the /etc/fstab file:
/dev/sda1 /mnt/windows ntfs-3g defaults 0 0
TESTING WITHOUT INSTALLING
=========================
Newer versions of ntfs-3g can be tested without installing anything and
without disturbing an existing installation. Just configure and make as
shown previously. This will create the scripts ntfs-3g and lowntfs-3g
in the src directory, which you may activate for testing :
./configure
make
then, as root :
src/ntfs-3g [-o mount-options] /dev/sda1 /mnt/windows
And, to end the test, unmount the usual way :
umount /dev/sda1

View File

@ -23,7 +23,7 @@
# Autoconf
AC_PREREQ(2.59)
AC_INIT([ntfs-3g],[2010.10.2],[ntfs-3g-devel@lists.sf.net])
AC_INIT([ntfs-3g],[2011.1.15],[ntfs-3g-devel@lists.sf.net])
LIBNTFS_3G_VERSION="80"
AC_CONFIG_SRCDIR([src/ntfs-3g.c])
@ -261,10 +261,10 @@ AC_HEADER_STDC
AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h limits.h locale.h \
mntent.h stddef.h stdint.h stdlib.h stdio.h stdarg.h string.h \
strings.h errno.h time.h unistd.h utime.h wchar.h getopt.h features.h \
endian.h byteswap.h sys/byteorder.h sys/endian.h sys/param.h \
sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h sys/vfs.h \
sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h linux/hdreg.h \
machine/endian.h windows.h syslog.h])
endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \
sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \
linux/hdreg.h machine/endian.h windows.h syslog.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL

View File

@ -58,6 +58,12 @@ typedef enum {
LCN_EIO = -5,
} ntfs_lcn_special_values;
typedef enum { /* ways of processing holes when expanding */
HOLES_NO,
HOLES_OK,
HOLES_DELAY
} hole_type;
/**
* struct ntfs_attr_search_ctx - search context used in attribute search functions
* @mrec: buffer containing mft record to search
@ -203,7 +209,6 @@ typedef enum {
NA_BeingNonResident, /* 1: Attribute is being made not resident. */
NA_FullyMapped, /* 1: Attribute has been fully mapped */
NA_DataAppending, /* 1: Attribute is being appended to */
NA_DelaySparsing, /* 1: Delay checking attribute being sparse */
NA_ComprClosing, /* 1: Compressed attribute is being closed */
} ntfs_attr_state_bits;
@ -231,10 +236,6 @@ typedef enum {
#define NAttrSetDataAppending(na) set_nattr_flag(na, DataAppending)
#define NAttrClearDataAppending(na) clear_nattr_flag(na, DataAppending)
#define NAttrDelaySparsing(na) test_nattr_flag(na, DelaySparsing)
#define NAttrSetDelaySparsing(na) set_nattr_flag(na, DelaySparsing)
#define NAttrClearDelaySparsing(na) clear_nattr_flag(na, DelaySparsing)
#define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing)
#define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing)
#define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing)
@ -343,6 +344,7 @@ extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra);
extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn);
extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
extern int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize);
/**
* get_attribute_value_length - return the length of the value of an attribute

View File

@ -311,6 +311,7 @@ typedef enum {
#define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU)
typedef u64 MFT_REF;
typedef le64 leMFT_REF; /* a little-endian MFT_MREF */
#define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \
((MFT_REF)(m) & MFT_REF_MASK_CPU)))

View File

@ -137,6 +137,7 @@ struct PERMISSIONS_CACHE {
enum {
SECURITY_DEFAULT, /* rely on fuse for permissions checking */
SECURITY_RAW, /* force same ownership/permissions on files */
SECURITY_ACL, /* enable Posix ACLs (when compiled in) */
SECURITY_ADDSECURIDS, /* upgrade old security descriptors */
SECURITY_STATICGRPS, /* use static groups for access control */
SECURITY_WANTED /* a security related option was present */
@ -349,7 +350,7 @@ INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi,
INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi,
INDEX_ENTRY *entry);
struct SECURITY_API *ntfs_initialize_file_security(const char *device,
int flags);
unsigned long flags);
BOOL ntfs_leave_file_security(struct SECURITY_API *scx);
int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf);

View File

@ -61,6 +61,7 @@ extern char *ntfs_uppercase_mbs(const char *low,
const ntfschar *upcase, u32 upcase_len);
extern void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len);
extern u32 ntfs_upcase_build_default(ntfschar **upcase);
extern ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt);
extern ntfschar *ntfs_str2ucs(const char *s, int *len);

View File

@ -58,6 +58,7 @@
#endif
#define MS_IGNORE_HIBERFILE 0x20000000
#define MS_FORENSIC 0x04000000 /* No modification during mount */
/* Forward declaration */
typedef struct _ntfs_volume ntfs_volume;

View File

@ -59,8 +59,6 @@ void ntfs_xattr_free_mapping(struct XATTRMAPPING*);
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
ntfs_volume *vol);
int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing);
int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,

View File

@ -5,7 +5,7 @@
* Copyright (c) 2002-2005 Richard Russon
* Copyright (c) 2002-2008 Szabolcs Szakacsits
* Copyright (c) 2004-2007 Yura Pakhuchiy
* Copyright (c) 2007-2010 Jean-Pierre Andre
* Copyright (c) 2007-2011 Jean-Pierre Andre
* Copyright (c) 2010 Erik Larsson
*
* This program/include file is free software; you can redistribute it and/or
@ -603,6 +603,7 @@ static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
VCN last_vcn;
VCN highest_vcn;
VCN needed;
VCN existing_vcn;
runlist_element *rl;
ATTR_RECORD *a;
BOOL startseen;
@ -612,6 +613,8 @@ static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
return 0;
existing_vcn = (na->rl ? na->rl->vcn : -1);
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
if (!ctx)
return -1;
@ -643,6 +646,11 @@ static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
needed = highest_vcn + 1;
if (!a->lowest_vcn)
startseen = TRUE;
/* reaching a previously allocated part ? */
if ((existing_vcn >= 0)
&& (needed >= existing_vcn)) {
needed = last_vcn;
}
}
} else
rl = (runlist_element*)NULL;
@ -1182,12 +1190,27 @@ static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count)
rli++;
}
size = min(end - pos, NTFS_BUF_SIZE);
written = ntfs_rl_pwrite(vol, rli, ofsi, pos, size, buf);
if (written <= 0) {
ntfs_log_perror("Failed to zero space");
goto err_free;
/*
* If the zeroed block is fully within a hole,
* we need not write anything, so advance as far
* as possible within the hole.
*/
if ((rli->lcn == (LCN)LCN_HOLE)
&& (ofsi <= pos)
&& (ofsi + (rli->length << vol->cluster_size_bits)
>= (pos + size))) {
size = min(end - pos, ofsi - pos
+ (rli->length << vol->cluster_size_bits));
pos += size;
} else {
written = ntfs_rl_pwrite(vol, rli, ofsi, pos,
size, buf);
if (written <= 0) {
ntfs_log_perror("Failed to zero space");
goto err_free;
}
pos += written;
}
pos += written;
}
ret = 0;
@ -1711,6 +1734,9 @@ static int borrow_from_hole(ntfs_attr *na, runlist_element **prl,
return (compressed_part);
}
static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
hole_type holes);
/**
* ntfs_attr_pwrite - positioned write to an ntfs attribute
* @na: ntfs attribute to write to
@ -1815,20 +1841,20 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
* attribute to be made temporarily sparse, which
* implies reformating the inode and reorganizing the
* full runlist. To avoid unnecessary reorganization,
* we delay sparse testing until the data is filled in.
*
* Note : should add a specific argument to truncate()
* instead of the hackish test of a flag...
* we avoid sparse testing until the data is filled in.
*/
if (NAttrDataAppending(na))
NAttrSetDelaySparsing(na);
#endif
if (ntfs_attr_truncate(na, pos + count)) {
NAttrClearDelaySparsing(na);
if (ntfs_attr_truncate_i(na, pos + count,
(NAttrDataAppending(na) ?
HOLES_DELAY : HOLES_OK))) {
ntfs_log_perror("Failed to enlarge attribute");
goto errno_set;
}
NAttrClearDelaySparsing(na);
#else
if (ntfs_attr_truncate(na, pos + count)) {
ntfs_log_perror("Failed to enlarge attribute");
goto errno_set;
}
#endif
/* resizing may change the compression mode */
compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
!= const_cpu_to_le16(0);
@ -5011,6 +5037,15 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
ntfs_attr_close(tna);
continue;
}
if ((tna->type == AT_DATA) && !tna->name_len) {
/*
* If we had to make the unnamed data attribute
* non-resident, propagate its new allocated size
* to all name attributes and directory indexes
*/
tna->ni->allocated_size = tna->allocated_size;
NInoFileNameSetDirty(tna->ni);
}
if (((tna->data_flags & ATTR_COMPRESSION_MASK)
== ATTR_IS_COMPRESSED)
&& ntfs_attr_pclose(tna)) {
@ -5339,7 +5374,7 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
* update allocated and compressed size.
*/
static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
ntfs_attr_search_ctx *ctx)
hole_type holes, ntfs_attr_search_ctx *ctx)
{
int sparse, ret = 0;
@ -5352,7 +5387,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
a->allocated_size = cpu_to_sle64(na->allocated_size);
/* Update sparse bit, unless this is an intermediate state */
if (NAttrDelaySparsing(na))
if (holes == HOLES_DELAY)
sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
else {
sparse = ntfs_rl_sparse(na->rl);
@ -5363,7 +5398,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
}
/* Check whether attribute becomes sparse, unless check is delayed. */
if (!NAttrDelaySparsing(na)
if ((holes != HOLES_DELAY)
&& sparse
&& !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) {
/*
@ -5465,7 +5500,8 @@ error: ret = -3; goto out;
/**
* ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs
*/
static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn)
static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn,
hole_type holes)
{
ntfs_attr_search_ctx *ctx;
ntfs_inode *ni, *base_ni;
@ -5501,7 +5537,7 @@ retry:
* Same if the file was sparse and is not any more.
* Note : not needed if the full runlist is to be processed
*/
if (!NAttrDelaySparsing(na)
if ((holes != HOLES_DELAY)
&& (!NAttrFullyMapped(na) || from_vcn)
&& !(na->data_flags & ATTR_IS_COMPRESSED)) {
BOOL changed;
@ -5607,7 +5643,7 @@ retry:
continue;
}
switch (ntfs_attr_update_meta(a, na, m, ctx)) {
switch (ntfs_attr_update_meta(a, na, m, holes, ctx)) {
case -1: return -1;
case -2: goto retry;
case -3: goto put_err_out;
@ -5742,34 +5778,6 @@ retry:
goto put_err_out;
}
}
/*
* If the base extent was skipped in the above process,
* we still may have to update the sizes.
*/
if (!first_updated) {
le16 spcomp;
ntfs_attr_reinit_search_ctx(ctx);
if (!ntfs_attr_lookup(na->type, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
a = ctx->attr;
a->allocated_size = cpu_to_sle64(na->allocated_size);
spcomp = na->data_flags
& (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
if (spcomp)
a->compressed_size = cpu_to_sle64(na->compressed_size);
if ((na->type == AT_DATA) && (na->name == AT_UNNAMED)) {
na->ni->allocated_size
= (spcomp
? na->compressed_size
: na->allocated_size);
NInoFileNameSetDirty(na->ni);
}
} else {
ntfs_log_error("Failed to update sizes in base extent\n");
goto put_err_out;
}
}
/* Deallocate not used attribute extents and return with success. */
if (finished_build) {
@ -5903,7 +5911,7 @@ int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
int ret;
ntfs_log_enter("Entering\n");
ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn);
ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn, HOLES_OK);
ntfs_log_leave("\n");
return ret;
}
@ -6073,7 +6081,8 @@ put_err_out:
* ERANGE - @newsize is not valid for the attribute type of @na.
* ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
*/
static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
hole_type holes)
{
LCN lcn_seek_from;
VCN first_free_vcn;
@ -6137,7 +6146,8 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
* If we extend $DATA attribute on NTFS 3+ volume, we can add
* sparse runs instead of real allocation of clusters.
*/
if (na->type == AT_DATA && vol->major_ver >= 3) {
if ((na->type == AT_DATA) && (vol->major_ver >= 3)
&& (holes != HOLES_NO)) {
rl = ntfs_malloc(0x1000);
if (!rl)
return -1;
@ -6208,7 +6218,7 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
na->allocated_size = first_free_vcn << vol->cluster_size_bits;
/* Write mapping pairs for new runlist. */
#if PARTIAL_RUNLIST_UPDATING
if (ntfs_attr_update_mapping_pairs(na, start_update)) {
if (ntfs_attr_update_mapping_pairs_i(na, start_update, holes)) {
#else
if (ntfs_attr_update_mapping_pairs(na, 0)) {
#endif
@ -6297,12 +6307,13 @@ put_err_out:
}
static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
hole_type holes)
{
int ret;
ntfs_log_enter("Entering\n");
ret = ntfs_non_resident_attr_expand_i(na, newsize);
ret = ntfs_non_resident_attr_expand_i(na, newsize, holes);
ntfs_log_leave("\n");
return ret;
}
@ -6311,6 +6322,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
* ntfs_attr_truncate - resize an ntfs attribute
* @na: open ntfs attribute to resize
* @newsize: new size (in bytes) to which to resize the attribute
* @holes: how to create a hole if expanding
*
* Change the size of an open ntfs attribute @na to @newsize bytes. If the
* attribute is made bigger and the attribute is resident the newly
@ -6327,7 +6339,8 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
* EOPNOTSUPP - The desired resize is not implemented yet.
* EACCES - Encrypted attribute.
*/
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
hole_type holes)
{
int ret = STATUS_ERROR;
s64 fullsize;
@ -6392,7 +6405,8 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
else
fullsize = newsize;
if (fullsize > na->data_size)
ret = ntfs_non_resident_attr_expand(na, fullsize);
ret = ntfs_non_resident_attr_expand(na, fullsize,
holes);
else
ret = ntfs_non_resident_attr_shrink(na, fullsize);
} else
@ -6401,7 +6415,25 @@ out:
ntfs_log_leave("Return status %d\n", ret);
return ret;
}
/*
* Resize an attribute, creating a hole if relevant
*/
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{
return (ntfs_attr_truncate_i(na, newsize, HOLES_OK));
}
/*
* Resize an attribute, avoiding hole creation
*/
int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize)
{
return (ntfs_attr_truncate_i(na, newsize, HOLES_NO));
}
/*
* Stuff a hole in a compressed file
*
@ -6462,7 +6494,7 @@ static int stuff_hole(ntfs_attr *na, const s64 pos)
if (!ret
&& ((na->initialized_size + end_size) < pos)
&& ntfs_non_resident_attr_expand(na,
pos - end_size))
pos - end_size, HOLES_OK))
ret = -1;
else
na->initialized_size

View File

@ -5,7 +5,7 @@
* Copyright (c) 2004-2005 Anton Altaparmakov
* Copyright (c) 2004-2006 Szabolcs Szakacsits
* Copyright (c) 2005 Yura Pakhuchiy
* Copyright (c) 2009-2010 Jean-Pierre Andre
* Copyright (c) 2009-2011 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -1251,6 +1251,7 @@ static int ntfs_compress_overwr_free(ntfs_attr *na, runlist_element *rl,
case 1 :
/* there is a single hole, may have to merge */
freerl->vcn = freevcn;
freerl->length = freecnt;
if (freerl[1].lcn == LCN_HOLE) {
freerl->length += freerl[1].length;
erl = freerl;

View File

@ -58,6 +58,9 @@
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_DISK_H
#include <sys/disk.h>
#endif
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
#endif
@ -556,6 +559,36 @@ s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
return (s64)this_floppy.size * 512 / block_size;
}
}
#endif
#ifdef DIOCGMEDIASIZE
{
/* FreeBSD */
off_t size;
if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) {
ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n",
(unsigned long long)size,
(unsigned long long)size);
return (s64)size / block_size;
}
}
#endif
#ifdef DKIOCGETBLOCKCOUNT
{
/* Mac OS X */
uint64_t blocks;
int sector_size;
sector_size = ntfs_device_sector_size_get(dev);
if (sector_size >= 0 && dev->d_ops->ioctl(dev,
DKIOCGETBLOCKCOUNT, &blocks) >= 0)
{
ntfs_log_debug("DKIOCGETBLOCKCOUNT nr blocks = %llu (0x%llx)\n",
(unsigned long long) blocks,
(unsigned long long) blocks);
return blocks * sector_size / block_size;
}
}
#endif
/*
* We couldn't figure it out by using a specialized ioctl,
@ -705,6 +738,28 @@ int ntfs_device_sector_size_get(struct ntfs_device *dev)
return sect_size;
}
}
#elif defined(DIOCGSECTORSIZE)
{
/* FreeBSD */
size_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, &sect_size)) {
ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#elif defined(DKIOCGETBLOCKSIZE)
{
/* Mac OS X */
uint32_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, &sect_size)) {
ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#else
errno = EOPNOTSUPP;
#endif

View File

@ -1812,7 +1812,7 @@ search:
while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, actx)) {
char *s;
BOOL case_sensitive = IGNORE_CASE;
IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
errno = 0;
fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
@ -1844,8 +1844,9 @@ search:
(long long unsigned)MREF_LE(fn->parent_directory));
continue;
}
if (fn->file_name_type == FILE_NAME_POSIX || case_sensitive_match)
if (case_sensitive_match
|| ((fn->file_name_type == FILE_NAME_POSIX)
&& NVolCaseSensitive(ni->vol)))
case_sensitive = CASE_SENSITIVE;
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,

View File

@ -1121,6 +1121,7 @@ static int ntfs_ir_reparent(ntfs_index_context *icx)
INDEX_ENTRY *ie;
INDEX_BLOCK *ib = NULL;
VCN new_ib_vcn;
int ix_root_size;
int ret = STATUS_ERROR;
ntfs_log_trace("Entering\n");
@ -1150,6 +1151,7 @@ static int ntfs_ir_reparent(ntfs_index_context *icx)
if (ntfs_ib_write(icx, ib))
goto clear_bmp;
retry :
ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, &ctx);
if (!ir)
goto clear_bmp;
@ -1164,12 +1166,32 @@ static int ntfs_ir_reparent(ntfs_index_context *icx)
ir->index.index_length = cpu_to_le32(le32_to_cpu(ir->index.entries_offset)
+ le16_to_cpu(ie->length));
ir->index.allocated_size = ir->index.index_length;
ix_root_size = sizeof(INDEX_ROOT) - sizeof(INDEX_HEADER)
+ le32_to_cpu(ir->index.allocated_size);
if (ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
sizeof(INDEX_ROOT) - sizeof(INDEX_HEADER) +
le32_to_cpu(ir->index.allocated_size)))
ix_root_size)) {
/*
* When there is no space to build a non-resident
* index, we may have to move the root to an extent
*/
if ((errno == ENOSPC)
&& !ctx->al_entry
&& !ntfs_inode_add_attrlist(icx->ni)) {
ntfs_attr_put_search_ctx(ctx);
ctx = (ntfs_attr_search_ctx*)NULL;
ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len,
&ctx);
if (ir
&& !ntfs_attr_record_move_away(ctx, ix_root_size
- le32_to_cpu(ctx->attr->value_length))) {
ntfs_attr_put_search_ctx(ctx);
ctx = (ntfs_attr_search_ctx*)NULL;
goto retry;
}
}
/* FIXME: revert index root */
goto clear_bmp;
}
/*
* FIXME: do it earlier if we have enough space in IR (should always),
* so in error case we wouldn't lose the IB.

View File

@ -481,6 +481,9 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
} else {
ni = ntfs_inode_real_open(vol, mref);
}
if (!ni) {
debug_double_inode(item.inum, 0);
}
#else
ni = ntfs_inode_real_open(vol, mref);
#endif
@ -842,6 +845,12 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
else {
fnx->allocated_size = cpu_to_sle64(ni->allocated_size);
fnx->data_size = cpu_to_sle64(ni->data_size);
/*
* The file name record has also to be fixed if some
* attribute update implied the unnamed data to be
* made non-resident
*/
fn->allocated_size = fnx->allocated_size;
}
/* update or clear the reparse tag in the index */
fnx->reparse_point_tag = reparse_tag;

View File

@ -200,8 +200,13 @@ static u64 ntfs_fix_file_name(ntfs_inode *dir_ni, ntfschar *uname,
*/
lemref = entry->indexed_file;
mref = le64_to_cpu(lemref);
for (i=0; i<found->file_name_length; i++)
uname[i] = found->file_name[i];
if (NVolCaseSensitive(vol) || !vol->locase) {
for (i=0; i<found->file_name_length; i++)
uname[i] = found->file_name[i];
} else {
for (i=0; i<found->file_name_length; i++)
uname[i] = vol->locase[found->file_name[i]];
}
}
}
ntfs_index_ctx_put(icx);

View File

@ -5030,7 +5030,7 @@ int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid)
*/
struct SECURITY_API *ntfs_initialize_file_security(const char *device,
int flags)
unsigned long flags)
{
ntfs_volume *vol;
unsigned long mntflag;

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2002-2009 Szabolcs Szakacsits
* Copyright (c) 2008-2010 Jean-Pierre Andre
* Copyright (c) 2008-2011 Jean-Pierre Andre
* Copyright (c) 2008 Bernhard Kaindl
*
* This program/include file is free software; you can redistribute it and/or
@ -1128,6 +1128,69 @@ char *ntfs_uppercase_mbs(const char *low,
*/
void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
{
#if 1 /* Vista */
/*
* This is the table as defined by Vista
*/
/*
* "Start" is inclusive and "End" is exclusive, every value has the
* value of "Add" added to it.
*/
static int uc_run_table[][3] = { /* Start, End, Add */
{0x0061, 0x007b, -32}, {0x00e0, 0x00f7, -32}, {0x00f8, 0x00ff, -32},
{0x0256, 0x0258, -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130},
{0x03ac, 0x03ad, -38}, {0x03ad, 0x03b0, -37}, {0x03b1, 0x03c2, -32},
{0x03c2, 0x03c3, -31}, {0x03c3, 0x03cc, -32}, {0x03cc, 0x03cd, -64},
{0x03cd, 0x03cf, -63}, {0x0430, 0x0450, -32}, {0x0450, 0x0460, -80},
{0x0561, 0x0587, -48}, {0x1f00, 0x1f08, 8}, {0x1f10, 0x1f16, 8},
{0x1f20, 0x1f28, 8}, {0x1f30, 0x1f38, 8}, {0x1f40, 0x1f46, 8},
{0x1f51, 0x1f52, 8}, {0x1f53, 0x1f54, 8}, {0x1f55, 0x1f56, 8},
{0x1f57, 0x1f58, 8}, {0x1f60, 0x1f68, 8}, {0x1f70, 0x1f72, 74},
{0x1f72, 0x1f76, 86}, {0x1f76, 0x1f78, 100}, {0x1f78, 0x1f7a, 128},
{0x1f7a, 0x1f7c, 112}, {0x1f7c, 0x1f7e, 126}, {0x1f80, 0x1f88, 8},
{0x1f90, 0x1f98, 8}, {0x1fa0, 0x1fa8, 8}, {0x1fb0, 0x1fb2, 8},
{0x1fb3, 0x1fb4, 9}, {0x1fcc, 0x1fcd, -9}, {0x1fd0, 0x1fd2, 8},
{0x1fe0, 0x1fe2, 8}, {0x1fe5, 0x1fe6, 7}, {0x1ffc, 0x1ffd, -9},
{0x2170, 0x2180, -16}, {0x24d0, 0x24ea, -26}, {0x2c30, 0x2c5f, -48},
{0x2d00, 0x2d26, -7264}, {0xff41, 0xff5b, -32}, {0}
};
/*
* "Start" is exclusive and "End" is inclusive, every second value is
* decremented by one.
*/
static int uc_dup_table[][2] = { /* Start, End */
{0x0100, 0x012f}, {0x0132, 0x0137}, {0x0139, 0x0149}, {0x014a, 0x0178},
{0x0179, 0x017e}, {0x01a0, 0x01a6}, {0x01b3, 0x01b7}, {0x01cd, 0x01dd},
{0x01de, 0x01ef}, {0x01f4, 0x01f5}, {0x01f8, 0x01f9}, {0x01fa, 0x0220},
{0x0222, 0x0234}, {0x023b, 0x023c}, {0x0241, 0x0242}, {0x0246, 0x024f},
{0x03d8, 0x03ef}, {0x03f7, 0x03f8}, {0x03fa, 0x03fb}, {0x0460, 0x0481},
{0x048a, 0x04bf}, {0x04c1, 0x04c4}, {0x04c5, 0x04c8}, {0x04c9, 0x04ce},
{0x04ec, 0x04ed}, {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x04f6, 0x0513},
{0x1e00, 0x1e95}, {0x1ea0, 0x1ef9}, {0x2183, 0x2184}, {0x2c60, 0x2c61},
{0x2c67, 0x2c6c}, {0x2c75, 0x2c76}, {0x2c80, 0x2ce3}, {0}
};
/*
* Set the Unicode character at offset "Offset" to "Value". Note,
* "Value" is host endian.
*/
static int uc_byte_table[][2] = { /* Offset, Value */
{0x00ff, 0x0178}, {0x0180, 0x0243}, {0x0183, 0x0182}, {0x0185, 0x0184},
{0x0188, 0x0187}, {0x018c, 0x018b}, {0x0192, 0x0191}, {0x0195, 0x01f6},
{0x0199, 0x0198}, {0x019a, 0x023d}, {0x019e, 0x0220}, {0x01a8, 0x01a7},
{0x01ad, 0x01ac}, {0x01b0, 0x01af}, {0x01b9, 0x01b8}, {0x01bd, 0x01bc},
{0x01bf, 0x01f7}, {0x01c6, 0x01c4}, {0x01c9, 0x01c7}, {0x01cc, 0x01ca},
{0x01dd, 0x018e}, {0x01f3, 0x01f1}, {0x023a, 0x2c65}, {0x023e, 0x2c66},
{0x0253, 0x0181}, {0x0254, 0x0186}, {0x0259, 0x018f}, {0x025b, 0x0190},
{0x0260, 0x0193}, {0x0263, 0x0194}, {0x0268, 0x0197}, {0x0269, 0x0196},
{0x026b, 0x2c62}, {0x026f, 0x019c}, {0x0272, 0x019d}, {0x0275, 0x019f},
{0x027d, 0x2c64}, {0x0280, 0x01a6}, {0x0283, 0x01a9}, {0x0288, 0x01ae},
{0x0289, 0x0244}, {0x028c, 0x0245}, {0x0292, 0x01b7}, {0x03f2, 0x03f9},
{0x04cf, 0x04c0}, {0x1d7d, 0x2c63}, {0x214e, 0x2132}, {0}
};
#else /* Vista */
/*
* This is the table as defined by Windows XP
*/
static int uc_run_table[][3] = { /* Start, End, Add */
{0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74},
{0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86},
@ -1164,6 +1227,7 @@ void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
{0x01A8, 0x01A7}, {0x01DD, 0x018E}, {0x0268, 0x0197},
{0}
};
#endif /* Vista */
int i, r;
int k, off;
@ -1187,6 +1251,27 @@ void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
}
}
/*
* Allocate and build the default upcase table
*
* Returns the number of entries
* 0 if failed
*/
#define UPCASE_LEN 65536 /* default number of entries in upcase */
u32 ntfs_upcase_build_default(ntfschar **upcase)
{
u32 upcase_len;
*upcase = (ntfschar*)ntfs_malloc(UPCASE_LEN*2);
if (*upcase) {
ntfs_upcase_table_build(*upcase, UPCASE_LEN*2);
upcase_len = UPCASE_LEN;
}
return (upcase_len);
}
/*
* Build a table for converting to lower case
*

View File

@ -482,13 +482,10 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags)
goto error_exit;
/* Create the default upcase table. */
vol->upcase_len = 65536;
vol->upcase = ntfs_malloc(vol->upcase_len * sizeof(ntfschar));
if (!vol->upcase)
vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
if (!vol->upcase_len || !vol->upcase)
goto error_exit;
ntfs_upcase_table_build(vol->upcase,
vol->upcase_len * sizeof(ntfschar));
/* Default with no locase table and case sensitive file names */
vol->locase = (ntfschar*)NULL;
NVolSetCaseSensitive(vol);
@ -1184,7 +1181,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
* Check for dirty logfile and hibernated Windows.
* We care only about read-write mounts.
*/
if (!(flags & MS_RDONLY)) {
if (!(flags & (MS_RDONLY | MS_FORENSIC))) {
if (!(flags & MS_IGNORE_HIBERFILE) &&
ntfs_volume_check_hiberfile(vol, 1) < 0)
goto error_exit;
@ -1196,10 +1193,10 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
if (ntfs_logfile_reset(vol))
goto error_exit;
}
}
/* make $TXF_DATA resident if present on the root directory */
if (!NVolReadOnly(vol) && fix_txf_data(vol))
goto error_exit;
if (fix_txf_data(vol))
goto error_exit;
}
return vol;
io_error_exit:

View File

@ -473,110 +473,6 @@ void ntfs_xattr_free_mapping(struct XATTRMAPPING *mapping)
#endif /* XATTR_MAPPINGS */
int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing)
{
int ret = 0;
char *to = list;
#ifdef XATTR_MAPPINGS
BOOL accepted;
const struct XATTRMAPPING *item;
#endif /* XATTR_MAPPINGS */
/* first list the regular user attributes (ADS) */
while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
0, NULL, 0, actx)) {
char *tmp_name = NULL;
int tmp_name_len;
if (!actx->attr->name_length)
continue;
tmp_name_len = ntfs_ucstombs(
(ntfschar *)((u8*)actx->attr +
le16_to_cpu(actx->attr->name_offset)),
actx->attr->name_length, &tmp_name, 0);
if (tmp_name_len < 0) {
ret = -errno;
goto exit;
}
/*
* When using name spaces, do not return
* security, trusted or system attributes
* (filtered elsewhere anyway)
* otherwise insert "user." prefix
*/
if (prefixing) {
if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g))
&& !strncmp(tmp_name,xattr_ntfs_3g,
sizeof(xattr_ntfs_3g)-1))
tmp_name_len = 0;
else
ret += tmp_name_len
+ nf_ns_user_prefix_len + 1;
} else
ret += tmp_name_len + 1;
if (size && tmp_name_len) {
if ((size_t)ret <= size) {
if (prefixing) {
strcpy(to, nf_ns_user_prefix);
to += nf_ns_user_prefix_len;
}
strncpy(to, tmp_name, tmp_name_len);
to += tmp_name_len;
*to = 0;
to++;
} else {
free(tmp_name);
ret = -ERANGE;
goto exit;
}
}
free(tmp_name);
}
#ifdef XATTR_MAPPINGS
/* now append the system attributes mapped to user space */
for (item=ni->vol->xattr_mapping; item; item=item->next) {
switch (item->xattr) {
case XATTR_NTFS_EFSINFO :
accepted = ni->vol->efs_raw
&& (ni->flags & FILE_ATTR_ENCRYPTED);
break;
case XATTR_NTFS_REPARSE_DATA :
accepted = (ni->flags & FILE_ATTR_REPARSE_POINT)
!= const_cpu_to_le32(0);
break;
// TODO : we are supposed to only return xattrs which are set
// this is more complex for OBJECT_ID and DOS_NAME
default : accepted = TRUE;
break;
}
if (accepted) {
ret += strlen(item->name) + 1;
if (size) {
if ((size_t)ret <= size) {
strcpy(to, item->name);
to += strlen(item->name);
*to++ = 0;
} else {
ret = -ERANGE;
goto exit;
}
}
#else /* XATTR_MAPPINGS */
/* List efs info xattr for encrypted files */
if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) {
ret += sizeof(nf_ns_alt_xattr_efsinfo);
if ((size_t)ret <= size) {
memcpy(to, nf_ns_alt_xattr_efsinfo,
sizeof(nf_ns_alt_xattr_efsinfo));
to += sizeof(nf_ns_alt_xattr_efsinfo);
#endif /* XATTR_MAPPINGS */
}
}
exit :
return (ret);
}
int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,

View File

@ -1,5 +1,5 @@
EXTRA_DIST = secaudit.h
EXTRA_DIST = secaudit.h ntfs-3g_common.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
@ -29,7 +29,7 @@ ntfs_3g_CFLAGS = \
-DFUSE_USE_VERSION=26 \
$(FUSE_CFLAGS) \
-I$(top_srcdir)/include/ntfs-3g
ntfs_3g_SOURCES = ntfs-3g.c
ntfs_3g_SOURCES = ntfs-3g.c ntfs-3g_common.c
lowntfs_3g_LDADD = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la
if REALLYSTATIC
@ -40,7 +40,7 @@ lowntfs_3g_CFLAGS = \
-DFUSE_USE_VERSION=26 \
$(FUSE_CFLAGS) \
-I$(top_srcdir)/include/ntfs-3g
lowntfs_3g_SOURCES = lowntfs-3g.c
lowntfs_3g_SOURCES = lowntfs-3g.c ntfs-3g_common.c
ntfs_3g_probe_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la
ntfs_3g_usermap_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la

View File

@ -4,7 +4,7 @@
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2007-2010 Jean-Pierre Andre
* Copyright (c) 2007-2011 Jean-Pierre Andre
* Copyright (c) 2009 Erik Larsson
*
* This file is originated from the Linux-NTFS project.
@ -38,12 +38,6 @@
#error "***********************************************************"
#endif
#ifdef FUSE_INTERNAL
#define FUSE_TYPE "integrated FUSE low"
#else
#define FUSE_TYPE "external FUSE low"
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
@ -69,7 +63,6 @@
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <getopt.h>
#include <syslog.h>
#include <sys/wait.h>
@ -105,6 +98,8 @@
#include "xattrs.h"
#include "misc.h"
#include "ntfs-3g_common.h"
/*
* The following permission checking modes are governed by
* the LPERMSCONFIG value in param.h
@ -157,12 +152,6 @@ typedef enum {
FSTYPE_FUSEBLK
} fuse_fstype;
typedef enum {
ATIME_ENABLED,
ATIME_DISABLED,
ATIME_RELATIVE
} ntfs_atime_t;
typedef struct fill_item {
struct fill_item *next;
size_t bufsize;
@ -187,66 +176,16 @@ struct open_file {
int state;
} ;
typedef enum {
NF_STREAMS_INTERFACE_NONE, /* No access to named data streams. */
NF_STREAMS_INTERFACE_XATTR, /* Map named data streams to xattrs. */
NF_STREAMS_INTERFACE_OPENXATTR, /* Same, not limited to "user." */
} ntfs_fuse_streams_interface;
enum {
CLOSE_GHOST = 1,
CLOSE_COMPRESSED = 2,
CLOSE_ENCRYPTED = 4
};
typedef struct {
ntfs_volume *vol;
unsigned int uid;
unsigned int gid;
unsigned int fmask;
unsigned int dmask;
ntfs_fuse_streams_interface streams;
ntfs_atime_t atime;
BOOL ro;
BOOL show_sys_files;
BOOL hide_hid_files;
BOOL hide_dot_files;
BOOL ignore_case;
BOOL windows_names;
BOOL compression;
BOOL silent;
BOOL recover;
BOOL hiberfile;
BOOL sync;
BOOL debug;
BOOL no_detach;
BOOL blkdev;
BOOL mounted;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
BOOL efs_raw;
#ifdef XATTR_MAPPINGS
char *xattrmap_path;
#endif /* XATTR_MAPPINGS */
#endif /* HAVE_SETXATTR */
struct fuse_chan *fc;
BOOL inherit;
unsigned int secure_flags;
char *usermap_path;
char *abs_mnt_point;
struct PERMISSIONS_CACHE *seccache;
struct SECURITY_CONTEXT security;
struct open_file *open_files;
u64 latest_ghost;
} ntfs_fuse_context_t;
static struct ntfs_options opts;
static struct options {
char *mnt_point; /* Mount point */
char *options; /* Mount options */
char *device; /* Device to mount */
} opts;
const char *EXEC_NAME = "lowntfs-3g";
static const char *EXEC_NAME = "ntfs-3g";
static char def_opts[] = "allow_other,nonempty,";
static ntfs_fuse_context_t *ctx;
static u32 ntfs_sequence;
static const char ghostformat[] = ".ghost-ntfs-3g-%020llu";
@ -268,7 +207,7 @@ static const char *usage_msg =
"\n"
"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
"Copyright (C) 2007-2010 Jean-Pierre Andre\n"
"Copyright (C) 2007-2011 Jean-Pierre Andre\n"
"Copyright (C) 2009 Erik Larsson\n"
"\n"
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
@ -1272,6 +1211,9 @@ static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino,
&& (ni->flags & FILE_ATTR_ENCRYPTED))
state |= CLOSE_ENCRYPTED;
#endif /* HAVE_SETXATTR */
/* deny opening metadata files for writing */
if (ino < FILE_first_user)
res = -EPERM;
}
ntfs_attr_close(na);
} else
@ -1549,6 +1491,11 @@ static int ntfs_fuse_trunc(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
if (!ni)
goto exit;
/* deny truncating metadata files */
if (ino < FILE_first_user) {
errno = EPERM;
goto exit;
}
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na)
goto exit;
@ -2156,6 +2103,11 @@ static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name)
res = -errno;
goto exit;
}
/* deny unlinking metadata files */
if (MREF(iref) < FILE_first_user) {
res = -EPERM;
goto exit;
}
of = ctx->open_files;
ino = (fuse_ino_t)MREF(iref);
@ -2572,17 +2524,6 @@ enum {
XATTRNS_OPEN
} ;
static const char nf_ns_user_prefix[] = "user.";
static const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
static const char nf_ns_system_prefix[] = "system.";
static const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1;
static const char nf_ns_security_prefix[] = "security.";
static const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1;
static const char nf_ns_trusted_prefix[] = "trusted.";
static const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1;
static const char xattr_ntfs_3g[] = "ntfs-3g.";
/*
* Check whether access to internal data as an extended
* attribute in system name space is allowed
@ -2771,7 +2712,7 @@ static void ntfs_fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
|| (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
ret = ntfs_xattr_listxattr(ni, actx, list, size,
ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
ctx->streams == NF_STREAMS_INTERFACE_XATTR);
if (ret < 0)
goto exit;
@ -3508,350 +3449,6 @@ err_out:
}
#define STRAPPEND_MAX_INSIZE 8192
#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)
static int strappend(char **dest, const char *append)
{
char *p;
size_t size_append, size_dest = 0;
if (!dest)
return -1;
if (!append)
return 0;
size_append = strlen(append);
if (*dest)
size_dest = strlen(*dest);
if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
errno = EOVERFLOW;
ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
return -1;
}
p = (char*)realloc(*dest, size_dest + size_append + 1);
if (!p) {
ntfs_log_perror("%s: Memory reallocation failed", EXEC_NAME);
return -1;
}
*dest = p;
strcpy(*dest + size_dest, append);
return 0;
}
static int bogus_option_value(char *val, const char *s)
{
if (val) {
ntfs_log_error("'%s' option shouldn't have value.\n", s);
return -1;
}
return 0;
}
static int missing_option_value(char *val, const char *s)
{
if (!val) {
ntfs_log_error("'%s' option should have a value.\n", s);
return -1;
}
return 0;
}
static char *parse_mount_options(const char *orig_opts)
{
char *options, *s, *opt, *val, *ret = NULL;
BOOL no_def_opts = FALSE;
int default_permissions = 0;
int permissions = 0;
int want_permissions = 0;
ctx->secure_flags = 0;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
ctx->efs_raw = FALSE;
#endif /* HAVE_SETXATTR */
ctx->compression = DEFAULT_COMPRESSION;
options = strdup(orig_opts ? orig_opts : "");
if (!options) {
ntfs_log_perror("%s: strdup failed", EXEC_NAME);
return NULL;
}
s = options;
while (s && *s && (val = strsep(&s, ","))) {
opt = strsep(&val, "=");
if (!strcmp(opt, "ro")) { /* Read-only mount. */
if (bogus_option_value(val, "ro"))
goto err_exit;
ctx->ro = TRUE;
if (strappend(&ret, "ro,"))
goto err_exit;
} else if (!strcmp(opt, "noatime")) {
if (bogus_option_value(val, "noatime"))
goto err_exit;
ctx->atime = ATIME_DISABLED;
} else if (!strcmp(opt, "atime")) {
if (bogus_option_value(val, "atime"))
goto err_exit;
ctx->atime = ATIME_ENABLED;
} else if (!strcmp(opt, "relatime")) {
if (bogus_option_value(val, "relatime"))
goto err_exit;
ctx->atime = ATIME_RELATIVE;
} else if (!strcmp(opt, "fake_rw")) {
if (bogus_option_value(val, "fake_rw"))
goto err_exit;
ctx->ro = TRUE;
} else if (!strcmp(opt, "fsname")) { /* Filesystem name. */
/*
* We need this to be able to check whether filesystem
* mounted or not.
*/
ntfs_log_error("'fsname' is unsupported option.\n");
goto err_exit;
} else if (!strcmp(opt, "no_def_opts")) {
if (bogus_option_value(val, "no_def_opts"))
goto err_exit;
no_def_opts = TRUE; /* Don't add default options. */
ctx->silent = FALSE; /* cancel default silent */
} else if (!strcmp(opt, "default_permissions")) {
default_permissions = 1;
} else if (!strcmp(opt, "permissions")) {
permissions = 1;
} else if (!strcmp(opt, "umask")) {
if (missing_option_value(val, "umask"))
goto err_exit;
sscanf(val, "%o", &ctx->fmask);
ctx->dmask = ctx->fmask;
want_permissions = 1;
} else if (!strcmp(opt, "fmask")) {
if (missing_option_value(val, "fmask"))
goto err_exit;
sscanf(val, "%o", &ctx->fmask);
want_permissions = 1;
} else if (!strcmp(opt, "dmask")) {
if (missing_option_value(val, "dmask"))
goto err_exit;
sscanf(val, "%o", &ctx->dmask);
want_permissions = 1;
} else if (!strcmp(opt, "uid")) {
if (missing_option_value(val, "uid"))
goto err_exit;
sscanf(val, "%i", &ctx->uid);
want_permissions = 1;
} else if (!strcmp(opt, "gid")) {
if (missing_option_value(val, "gid"))
goto err_exit;
sscanf(val, "%i", &ctx->gid);
want_permissions = 1;
} else if (!strcmp(opt, "show_sys_files")) {
if (bogus_option_value(val, "show_sys_files"))
goto err_exit;
ctx->show_sys_files = TRUE;
} else if (!strcmp(opt, "hide_hid_files")) {
if (bogus_option_value(val, "hide_hid_files"))
goto err_exit;
ctx->hide_hid_files = TRUE;
} else if (!strcmp(opt, "hide_dot_files")) {
if (bogus_option_value(val, "hide_dot_files"))
goto err_exit;
ctx->hide_dot_files = TRUE;
} else if (!strcmp(opt, "ignore_case")) {
if (bogus_option_value(val, "ignore_case"))
goto err_exit;
ctx->ignore_case = TRUE;
} else if (!strcmp(opt, "windows_names")) {
if (bogus_option_value(val, "windows_names"))
goto err_exit;
ctx->windows_names = TRUE;
} else if (!strcmp(opt, "compression")) {
if (bogus_option_value(val, "compression"))
goto err_exit;
ctx->compression = TRUE;
} else if (!strcmp(opt, "nocompression")) {
if (bogus_option_value(val, "nocompression"))
goto err_exit;
ctx->compression = FALSE;
} else if (!strcmp(opt, "silent")) {
if (bogus_option_value(val, "silent"))
goto err_exit;
ctx->silent = TRUE;
} else if (!strcmp(opt, "recover")) {
if (bogus_option_value(val, "recover"))
goto err_exit;
ctx->recover = TRUE;
} else if (!strcmp(opt, "norecover")) {
if (bogus_option_value(val, "norecover"))
goto err_exit;
ctx->recover = FALSE;
} else if (!strcmp(opt, "remove_hiberfile")) {
if (bogus_option_value(val, "remove_hiberfile"))
goto err_exit;
ctx->hiberfile = TRUE;
} else if (!strcmp(opt, "sync")) {
if (bogus_option_value(val, "sync"))
goto err_exit;
ctx->sync = TRUE;
if (strappend(&ret, "sync,"))
goto err_exit;
} else if (!strcmp(opt, "locale")) {
if (missing_option_value(val, "locale"))
goto err_exit;
ntfs_set_char_encoding(val);
#if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV
} else if (!strcmp(opt, "nfconv")) {
if (bogus_option_value(val, "nfconv"))
goto err_exit;
if (ntfs_macosx_normalize_filenames(1)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n");
goto err_exit;
}
} else if (!strcmp(opt, "nonfconv")) {
if (bogus_option_value(val, "nonfconv"))
goto err_exit;
if (ntfs_macosx_normalize_filenames(0)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n");
goto err_exit;
}
#endif /* ENABLE_NFCONV */
#endif /* defined(__APPLE__) || defined(__DARWIN__) */
} else if (!strcmp(opt, "streams_interface")) {
if (missing_option_value(val, "streams_interface"))
goto err_exit;
if (!strcmp(val, "none"))
ctx->streams = NF_STREAMS_INTERFACE_NONE;
else if (!strcmp(val, "xattr"))
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
else if (!strcmp(val, "openxattr"))
ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR;
else {
ntfs_log_error("Invalid named data streams "
"access interface.\n");
goto err_exit;
}
} else if (!strcmp(opt, "user_xattr")) {
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
} else if (!strcmp(opt, "noauto")) {
/* Don't pass noauto option to fuse. */
} else if (!strcmp(opt, "debug")) {
if (bogus_option_value(val, "debug"))
goto err_exit;
ctx->debug = TRUE;
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
} else if (!strcmp(opt, "no_detach")) {
if (bogus_option_value(val, "no_detach"))
goto err_exit;
ctx->no_detach = TRUE;
} else if (!strcmp(opt, "remount")) {
ntfs_log_error("Remounting is not supported at present."
" You have to umount volume and then "
"mount it once again.\n");
goto err_exit;
} else if (!strcmp(opt, "blksize")) {
ntfs_log_info("WARNING: blksize option is ignored "
"because ntfs-3g must calculate it.\n");
} else if (!strcmp(opt, "inherit")) {
/*
* JPA do not overwrite inherited permissions
* in create()
*/
ctx->inherit = TRUE;
} else if (!strcmp(opt, "addsecurids")) {
/*
* JPA create security ids for files being read
* with an individual security attribute
*/
ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS);
} else if (!strcmp(opt, "staticgrps")) {
/*
* JPA use static definition of groups
* for file access control
*/
ctx->secure_flags |= (1 << SECURITY_STATICGRPS);
} else if (!strcmp(opt, "usermapping")) {
if (!val) {
ntfs_log_error("'usermapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->usermap_path = strdup(val);
if (!ctx->usermap_path) {
ntfs_log_error("no more memory to store "
"'usermapping' option.\n");
goto err_exit;
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
#ifdef XATTR_MAPPINGS
} else if (!strcmp(opt, "xattrmapping")) {
if (!val) {
ntfs_log_error("'xattrmapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->xattrmap_path = strdup(val);
if (!ctx->xattrmap_path) {
ntfs_log_error("no more memory to store "
"'xattrmapping' option.\n");
goto err_exit;
}
#endif /* XATTR_MAPPINGS */
} else if (!strcmp(opt, "efs_raw")) {
if (bogus_option_value(val, "efs_raw"))
goto err_exit;
ctx->efs_raw = TRUE;
#endif /* HAVE_SETXATTR */
} else { /* Probably FUSE option. */
if (strappend(&ret, opt))
goto err_exit;
if (val) {
if (strappend(&ret, "="))
goto err_exit;
if (strappend(&ret, val))
goto err_exit;
}
if (strappend(&ret, ","))
goto err_exit;
}
}
if (!no_def_opts && strappend(&ret, def_opts))
goto err_exit;
#if KERNELPERMS
if ((default_permissions || permissions)
&& strappend(&ret, "default_permissions,"))
goto err_exit;
#endif
if (ctx->atime == ATIME_RELATIVE && strappend(&ret, "relatime,"))
goto err_exit;
else if (ctx->atime == ATIME_ENABLED && strappend(&ret, "atime,"))
goto err_exit;
else if (ctx->atime == ATIME_DISABLED && strappend(&ret, "noatime,"))
goto err_exit;
if (strappend(&ret, "fsname="))
goto err_exit;
if (strappend(&ret, opts.device))
goto err_exit;
if (permissions)
ctx->secure_flags |= (1 << SECURITY_DEFAULT);
if (want_permissions)
ctx->secure_flags |= (1 << SECURITY_WANTED);
if (ctx->ro)
ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS);
exit:
free(options);
return ret;
err_exit:
free(ret);
ret = NULL;
goto exit;
}
static void usage(void)
{
ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
@ -3869,97 +3466,6 @@ static char *realpath(const char *path, char *resolved_path)
}
#endif
/**
* parse_options - Read and validate the programs command line
* Read the command line, verify the syntax and parse the options.
*
* Return: 0 success, -1 error.
*/
static int parse_options(int argc, char *argv[])
{
int c;
static const char *sopt = "-o:hnvV";
static const struct option lopt[] = {
{ "options", required_argument, NULL, 'o' },
{ "help", no_argument, NULL, 'h' },
{ "no-mtab", no_argument, NULL, 'n' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
opterr = 0; /* We'll handle the errors, thank you. */
while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
switch (c) {
case 1: /* A non-option argument */
if (!opts.device) {
opts.device = (char*)ntfs_malloc(PATH_MAX + 1);
if (!opts.device)
return -1;
/* Canonicalize device name (mtab, etc) */
if (!realpath(optarg, opts.device)) {
ntfs_log_perror("%s: Failed to access "
"volume '%s'", EXEC_NAME, optarg);
free(opts.device);
opts.device = NULL;
return -1;
}
} else if (!opts.mnt_point) {
opts.mnt_point = optarg;
} else {
ntfs_log_error("%s: You must specify exactly one "
"device and exactly one mount "
"point.\n", EXEC_NAME);
return -1;
}
break;
case 'o':
if (opts.options)
if (strappend(&opts.options, ","))
return -1;
if (strappend(&opts.options, optarg))
return -1;
break;
case 'h':
usage();
exit(9);
case 'n':
/*
* no effect - automount passes it, meaning 'no-mtab'
*/
break;
case 'v':
/*
* We must handle the 'verbose' option even if
* we don't use it because mount(8) passes it.
*/
break;
case 'V':
ntfs_log_info("%s %s %s %d\n", EXEC_NAME, VERSION,
FUSE_TYPE, fuse_version());
exit(0);
default:
ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
argv[optind - 1]);
return -1;
}
}
if (!opts.device) {
ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);
return -1;
}
if (!opts.mnt_point) {
ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);
return -1;
}
return 0;
}
#if defined(linux) || defined(__uClinux__)
static const char *dev_fuse_msg =
@ -4105,7 +3611,7 @@ static int set_fuseblk_options(char **parsed_options)
blksize = pagesize;
snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
if (strappend(parsed_options, options))
if (ntfs_strappend(parsed_options, options))
return -1;
return 0;
}
@ -4207,7 +3713,7 @@ int main(int argc, char *argv[])
ntfs_set_locale();
ntfs_log_set_handler(ntfs_log_handler_stderr);
if (parse_options(argc, argv)) {
if (ntfs_parse_options(&opts, usage, argc, argv)) {
usage();
return NTFS_VOLUME_SYNTAX_ERROR;
}
@ -4217,7 +3723,7 @@ int main(int argc, char *argv[])
goto err2;
}
parsed_options = parse_mount_options(opts.options);
parsed_options = parse_mount_options(ctx, &opts, TRUE);
if (!parsed_options) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
@ -4306,15 +3812,17 @@ int main(int argc, char *argv[])
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,
(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
(ctx->vol->secure_flags
& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
#if POSIXACLS
/* use basic permissions if requested */
if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
permissions_mode = "User mapping built, Posix ACLs not used";
else {
permissions_mode = "User mapping built, Posix ACLs in use";
#if KERNELACLS
if (strappend(&parsed_options,
if (ntfs_strappend(&parsed_options,
",default_permissions,acl")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
@ -4322,14 +3830,15 @@ int main(int argc, char *argv[])
#endif /* KERNELACLS */
}
#else /* POSIXACLS */
if (!(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
if (!(ctx->vol->secure_flags
& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
/*
* No explicit option but user mapping found
* force default security
*/
#if KERNELPERMS
ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
if (strappend(&parsed_options, ",default_permissions")) {
if (ntfs_strappend(&parsed_options, ",default_permissions")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
}
@ -4346,7 +3855,7 @@ int main(int argc, char *argv[])
if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
&& !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
if (strappend(&parsed_options, ",default_permissions")) {
if (ntfs_strappend(&parsed_options, ",default_permissions")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
}

View File

@ -128,6 +128,13 @@ When a user mapping file is defined, the options \fBuid=\fP, \fBgid=\fP,
Set standard permissions on created files and use standard access control.
This option is set by default when a user mapping file is present.
.TP
.B acl
Enable setting Posix ACLs on created files and use them for access control.
This option is only available on specific builds. It is set by default
when a user mapping file is present and the
.B permissions
mount option is not set.
.TP
.B inherit
When creating a new file, set its initial ownership and protections
according to inheritance rules defined in parent directory. These rules
@ -147,6 +154,14 @@ to not be visible.
This option is obsolete. It has been superseded by the \fBrecover\fR and
\fBnorecover\fR options.
.TP
.B recover
Recover and try to mount a partition which was not unmounted properly by
Windows. The Windows logfile is cleared, which may cause inconsistencies.
Currently this is the default option.
.TP
.B norecover
Do not try to mount a partition which was not unmounted properly by Windows.
.TP
.B ignore_case \fP(only with lowntfs-3g)
Ignore character case when accessing a file (\fBFOO\fR, \fBFoo\fR, \fBfoo\fR,
etc. designate the same file). All files are displayed with lower case in
@ -157,7 +172,7 @@ Unlike in case of read-only mount, the read-write mount is denied if
the NTFS volume is hibernated. One needs either to resume Windows and
shutdown it properly, or use this option which will remove the Windows
hibernation file. Please note, this means that the saved Windows
session will be completely lost. Use this option for your own
session will be completely lost. Use this option under your own
responsibility.
.TP
.B atime, noatime, relatime

View File

@ -4,7 +4,7 @@
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2007-2010 Jean-Pierre Andre
* Copyright (c) 2007-2011 Jean-Pierre Andre
* Copyright (c) 2009 Erik Larsson
*
* This file is originated from the Linux-NTFS project.
@ -37,12 +37,6 @@
#error "***********************************************************"
#endif
#ifdef FUSE_INTERNAL
#define FUSE_TYPE "integrated FUSE"
#else
#define FUSE_TYPE "external FUSE"
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
@ -68,7 +62,6 @@
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <getopt.h>
#include <syslog.h>
#include <sys/wait.h>
@ -104,6 +97,8 @@
#include "xattrs.h"
#include "misc.h"
#include "ntfs-3g_common.h"
/*
* The following permission checking modes are governed by
* the HPERMSCONFIG value in param.h
@ -138,74 +133,20 @@ typedef enum {
FSTYPE_FUSEBLK
} fuse_fstype;
typedef enum {
ATIME_ENABLED,
ATIME_DISABLED,
ATIME_RELATIVE
} ntfs_atime_t;
typedef struct {
fuse_fill_dir_t filler;
void *buf;
} ntfs_fuse_fill_context_t;
typedef enum {
NF_STREAMS_INTERFACE_NONE, /* No access to named data streams. */
NF_STREAMS_INTERFACE_XATTR, /* Map named data streams to xattrs. */
NF_STREAMS_INTERFACE_OPENXATTR, /* Same, not limited to "user." */
NF_STREAMS_INTERFACE_WINDOWS, /* "file:stream" interface. */
} ntfs_fuse_streams_interface;
enum {
CLOSE_COMPRESSED = 1,
CLOSE_ENCRYPTED = 2
};
typedef struct {
ntfs_volume *vol;
unsigned int uid;
unsigned int gid;
unsigned int fmask;
unsigned int dmask;
ntfs_fuse_streams_interface streams;
ntfs_atime_t atime;
BOOL ro;
BOOL show_sys_files;
BOOL hide_hid_files;
BOOL hide_dot_files;
BOOL windows_names;
BOOL compression;
BOOL silent;
BOOL recover;
BOOL hiberfile;
BOOL sync;
BOOL debug;
BOOL no_detach;
BOOL blkdev;
BOOL mounted;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
BOOL efs_raw;
#ifdef XATTR_MAPPINGS
char *xattrmap_path;
#endif /* XATTR_MAPPINGS */
#endif /* HAVE_SETXATTR */
struct fuse_chan *fc;
BOOL inherit;
unsigned int secure_flags;
char *usermap_path;
char *abs_mnt_point;
struct PERMISSIONS_CACHE *seccache;
struct SECURITY_CONTEXT security;
} ntfs_fuse_context_t;
static struct ntfs_options opts;
static struct options {
char *mnt_point; /* Mount point */
char *options; /* Mount options */
char *device; /* Device to mount */
} opts;
const char *EXEC_NAME = "ntfs-3g";
static const char *EXEC_NAME = "ntfs-3g";
static char def_opts[] = "allow_other,nonempty,";
static ntfs_fuse_context_t *ctx;
static u32 ntfs_sequence;
@ -226,7 +167,7 @@ static const char *usage_msg =
"\n"
"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
"Copyright (C) 2007-2010 Jean-Pierre Andre\n"
"Copyright (C) 2007-2011 Jean-Pierre Andre\n"
"Copyright (C) 2009 Erik Larsson\n"
"\n"
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
@ -1218,6 +1159,9 @@ static int ntfs_fuse_open(const char *org_path,
&& (ni->flags & FILE_ATTR_ENCRYPTED))
fi->fh |= CLOSE_ENCRYPTED;
#endif /* HAVE_SETXATTR */
/* deny opening metadata files for writing */
if (ni->mft_no < FILE_first_user)
res = -EPERM;
}
ntfs_attr_close(na);
} else
@ -1429,6 +1373,11 @@ static int ntfs_fuse_trunc(const char *org_path, off_t size,
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
if (!ni)
goto exit;
/* deny truncating metadata files */
if (ni->mft_no < FILE_first_user) {
errno = EPERM;
goto exit;
}
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na)
@ -1981,6 +1930,13 @@ static int ntfs_fuse_rm(const char *org_path)
res = -errno;
goto exit;
}
/* deny unlinking metadata files */
if (ni->mft_no < FILE_first_user) {
errno = EPERM;
res = -errno;
goto exit;
}
/* Generate unicode filename. */
name = strrchr(path, '/');
name++;
@ -2471,17 +2427,6 @@ enum {
XATTRNS_OPEN
} ;
static const char nf_ns_user_prefix[] = "user.";
static const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
static const char nf_ns_system_prefix[] = "system.";
static const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1;
static const char nf_ns_security_prefix[] = "security.";
static const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1;
static const char nf_ns_trusted_prefix[] = "trusted.";
static const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1;
static const char xattr_ntfs_3g[] = "ntfs-3g.";
/*
* Check whether access to internal data as an extended
* attribute in system name space is allowed
@ -2648,7 +2593,7 @@ static int ntfs_fuse_listxattr(const char *path, char *list, size_t size)
if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
|| (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
ret = ntfs_xattr_listxattr(ni, actx, list, size,
ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
ctx->streams == NF_STREAMS_INTERFACE_XATTR);
if (ret < 0)
goto exit;
@ -3419,346 +3364,6 @@ err_out:
}
#define STRAPPEND_MAX_INSIZE 8192
#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)
static int strappend(char **dest, const char *append)
{
char *p;
size_t size_append, size_dest = 0;
if (!dest)
return -1;
if (!append)
return 0;
size_append = strlen(append);
if (*dest)
size_dest = strlen(*dest);
if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
errno = EOVERFLOW;
ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
return -1;
}
p = realloc(*dest, size_dest + size_append + 1);
if (!p) {
ntfs_log_perror("%s: Memory realloction failed", EXEC_NAME);
return -1;
}
*dest = p;
strcpy(*dest + size_dest, append);
return 0;
}
static int bogus_option_value(char *val, const char *s)
{
if (val) {
ntfs_log_error("'%s' option shouldn't have value.\n", s);
return -1;
}
return 0;
}
static int missing_option_value(char *val, const char *s)
{
if (!val) {
ntfs_log_error("'%s' option should have a value.\n", s);
return -1;
}
return 0;
}
static char *parse_mount_options(const char *orig_opts)
{
char *options, *s, *opt, *val, *ret = NULL;
BOOL no_def_opts = FALSE;
int default_permissions = 0;
int permissions = 0;
int want_permissions = 0;
ctx->secure_flags = 0;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
ctx->efs_raw = FALSE;
#endif /* HAVE_SETXATTR */
ctx->compression = DEFAULT_COMPRESSION;
options = strdup(orig_opts ? orig_opts : "");
if (!options) {
ntfs_log_perror("%s: strdup failed", EXEC_NAME);
return NULL;
}
s = options;
while (s && *s && (val = strsep(&s, ","))) {
opt = strsep(&val, "=");
if (!strcmp(opt, "ro")) { /* Read-only mount. */
if (bogus_option_value(val, "ro"))
goto err_exit;
ctx->ro = TRUE;
if (strappend(&ret, "ro,"))
goto err_exit;
} else if (!strcmp(opt, "noatime")) {
if (bogus_option_value(val, "noatime"))
goto err_exit;
ctx->atime = ATIME_DISABLED;
} else if (!strcmp(opt, "atime")) {
if (bogus_option_value(val, "atime"))
goto err_exit;
ctx->atime = ATIME_ENABLED;
} else if (!strcmp(opt, "relatime")) {
if (bogus_option_value(val, "relatime"))
goto err_exit;
ctx->atime = ATIME_RELATIVE;
} else if (!strcmp(opt, "fake_rw")) {
if (bogus_option_value(val, "fake_rw"))
goto err_exit;
ctx->ro = TRUE;
} else if (!strcmp(opt, "fsname")) { /* Filesystem name. */
/*
* We need this to be able to check whether filesystem
* mounted or not.
*/
ntfs_log_error("'fsname' is unsupported option.\n");
goto err_exit;
} else if (!strcmp(opt, "no_def_opts")) {
if (bogus_option_value(val, "no_def_opts"))
goto err_exit;
no_def_opts = TRUE; /* Don't add default options. */
ctx->silent = FALSE; /* cancel default silent */
} else if (!strcmp(opt, "default_permissions")) {
default_permissions = 1;
} else if (!strcmp(opt, "permissions")) {
permissions = 1;
} else if (!strcmp(opt, "umask")) {
if (missing_option_value(val, "umask"))
goto err_exit;
sscanf(val, "%o", &ctx->fmask);
ctx->dmask = ctx->fmask;
want_permissions = 1;
} else if (!strcmp(opt, "fmask")) {
if (missing_option_value(val, "fmask"))
goto err_exit;
sscanf(val, "%o", &ctx->fmask);
want_permissions = 1;
} else if (!strcmp(opt, "dmask")) {
if (missing_option_value(val, "dmask"))
goto err_exit;
sscanf(val, "%o", &ctx->dmask);
want_permissions = 1;
} else if (!strcmp(opt, "uid")) {
if (missing_option_value(val, "uid"))
goto err_exit;
sscanf(val, "%i", &ctx->uid);
want_permissions = 1;
} else if (!strcmp(opt, "gid")) {
if (missing_option_value(val, "gid"))
goto err_exit;
sscanf(val, "%i", &ctx->gid);
want_permissions = 1;
} else if (!strcmp(opt, "show_sys_files")) {
if (bogus_option_value(val, "show_sys_files"))
goto err_exit;
ctx->show_sys_files = TRUE;
} else if (!strcmp(opt, "hide_hid_files")) {
if (bogus_option_value(val, "hide_hid_files"))
goto err_exit;
ctx->hide_hid_files = TRUE;
} else if (!strcmp(opt, "hide_dot_files")) {
if (bogus_option_value(val, "hide_dot_files"))
goto err_exit;
ctx->hide_dot_files = TRUE;
} else if (!strcmp(opt, "windows_names")) {
if (bogus_option_value(val, "windows_names"))
goto err_exit;
ctx->windows_names = TRUE;
} else if (!strcmp(opt, "compression")) {
if (bogus_option_value(val, "compression"))
goto err_exit;
ctx->compression = TRUE;
} else if (!strcmp(opt, "nocompression")) {
if (bogus_option_value(val, "nocompression"))
goto err_exit;
ctx->compression = FALSE;
} else if (!strcmp(opt, "silent")) {
if (bogus_option_value(val, "silent"))
goto err_exit;
ctx->silent = TRUE;
} else if (!strcmp(opt, "recover")) {
if (bogus_option_value(val, "recover"))
goto err_exit;
ctx->recover = TRUE;
} else if (!strcmp(opt, "norecover")) {
if (bogus_option_value(val, "norecover"))
goto err_exit;
ctx->recover = FALSE;
} else if (!strcmp(opt, "remove_hiberfile")) {
if (bogus_option_value(val, "remove_hiberfile"))
goto err_exit;
ctx->hiberfile = TRUE;
} else if (!strcmp(opt, "sync")) {
if (bogus_option_value(val, "sync"))
goto err_exit;
ctx->sync = TRUE;
if (strappend(&ret, "sync,"))
goto err_exit;
} else if (!strcmp(opt, "locale")) {
if (missing_option_value(val, "locale"))
goto err_exit;
ntfs_set_char_encoding(val);
#if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV
} else if (!strcmp(opt, "nfconv")) {
if (bogus_option_value(val, "nfconv"))
goto err_exit;
if (ntfs_macosx_normalize_filenames(1)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n");
goto err_exit;
}
} else if (!strcmp(opt, "nonfconv")) {
if (bogus_option_value(val, "nonfconv"))
goto err_exit;
if (ntfs_macosx_normalize_filenames(0)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n");
goto err_exit;
}
#endif /* ENABLE_NFCONV */
#endif /* defined(__APPLE__) || defined(__DARWIN__) */
} else if (!strcmp(opt, "streams_interface")) {
if (missing_option_value(val, "streams_interface"))
goto err_exit;
if (!strcmp(val, "none"))
ctx->streams = NF_STREAMS_INTERFACE_NONE;
else if (!strcmp(val, "xattr"))
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
else if (!strcmp(val, "openxattr"))
ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR;
else if (!strcmp(val, "windows"))
ctx->streams = NF_STREAMS_INTERFACE_WINDOWS;
else {
ntfs_log_error("Invalid named data streams "
"access interface.\n");
goto err_exit;
}
} else if (!strcmp(opt, "user_xattr")) {
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
} else if (!strcmp(opt, "noauto")) {
/* Don't pass noauto option to fuse. */
} else if (!strcmp(opt, "debug")) {
if (bogus_option_value(val, "debug"))
goto err_exit;
ctx->debug = TRUE;
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
} else if (!strcmp(opt, "no_detach")) {
if (bogus_option_value(val, "no_detach"))
goto err_exit;
ctx->no_detach = TRUE;
} else if (!strcmp(opt, "remount")) {
ntfs_log_error("Remounting is not supported at present."
" You have to umount volume and then "
"mount it once again.\n");
goto err_exit;
} else if (!strcmp(opt, "blksize")) {
ntfs_log_info("WARNING: blksize option is ignored "
"because ntfs-3g must calculate it.\n");
} else if (!strcmp(opt, "inherit")) {
/*
* JPA do not overwrite inherited permissions
* in create()
*/
ctx->inherit = TRUE;
} else if (!strcmp(opt, "addsecurids")) {
/*
* JPA create security ids for files being read
* with an individual security attribute
*/
ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS);
} else if (!strcmp(opt, "staticgrps")) {
/*
* JPA use static definition of groups
* for file access control
*/
ctx->secure_flags |= (1 << SECURITY_STATICGRPS);
} else if (!strcmp(opt, "usermapping")) {
if (!val) {
ntfs_log_error("'usermapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->usermap_path = strdup(val);
if (!ctx->usermap_path) {
ntfs_log_error("no more memory to store "
"'usermapping' option.\n");
goto err_exit;
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
#ifdef XATTR_MAPPINGS
} else if (!strcmp(opt, "xattrmapping")) {
if (!val) {
ntfs_log_error("'xattrmapping' option should have "
"a value.\n");
goto err_exit;
}
ctx->xattrmap_path = strdup(val);
if (!ctx->xattrmap_path) {
ntfs_log_error("no more memory to store "
"'xattrmapping' option.\n");
goto err_exit;
}
#endif /* XATTR_MAPPINGS */
} else if (!strcmp(opt, "efs_raw")) {
if (bogus_option_value(val, "efs_raw"))
goto err_exit;
ctx->efs_raw = TRUE;
#endif /* HAVE_SETXATTR */
} else { /* Probably FUSE option. */
if (strappend(&ret, opt))
goto err_exit;
if (val) {
if (strappend(&ret, "="))
goto err_exit;
if (strappend(&ret, val))
goto err_exit;
}
if (strappend(&ret, ","))
goto err_exit;
}
}
if (!no_def_opts && strappend(&ret, def_opts))
goto err_exit;
if ((default_permissions || permissions)
&& strappend(&ret, "default_permissions,"))
goto err_exit;
if (ctx->atime == ATIME_RELATIVE && strappend(&ret, "relatime,"))
goto err_exit;
else if (ctx->atime == ATIME_ENABLED && strappend(&ret, "atime,"))
goto err_exit;
else if (ctx->atime == ATIME_DISABLED && strappend(&ret, "noatime,"))
goto err_exit;
if (strappend(&ret, "fsname="))
goto err_exit;
if (strappend(&ret, opts.device))
goto err_exit;
if (permissions)
ctx->secure_flags |= (1 << SECURITY_DEFAULT);
if (want_permissions)
ctx->secure_flags |= (1 << SECURITY_WANTED);
if (ctx->ro)
ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS);
exit:
free(options);
return ret;
err_exit:
free(ret);
ret = NULL;
goto exit;
}
static void usage(void)
{
ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
@ -3776,97 +3381,6 @@ static char *realpath(const char *path, char *resolved_path)
}
#endif
/**
* parse_options - Read and validate the programs command line
* Read the command line, verify the syntax and parse the options.
*
* Return: 0 success, -1 error.
*/
static int parse_options(int argc, char *argv[])
{
int c;
static const char *sopt = "-o:hnvV";
static const struct option lopt[] = {
{ "options", required_argument, NULL, 'o' },
{ "help", no_argument, NULL, 'h' },
{ "no-mtab", no_argument, NULL, 'n' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
opterr = 0; /* We'll handle the errors, thank you. */
while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
switch (c) {
case 1: /* A non-option argument */
if (!opts.device) {
opts.device = ntfs_malloc(PATH_MAX + 1);
if (!opts.device)
return -1;
/* Canonicalize device name (mtab, etc) */
if (!realpath(optarg, opts.device)) {
ntfs_log_perror("%s: Failed to access "
"volume '%s'", EXEC_NAME, optarg);
free(opts.device);
opts.device = NULL;
return -1;
}
} else if (!opts.mnt_point) {
opts.mnt_point = optarg;
} else {
ntfs_log_error("%s: You must specify exactly one "
"device and exactly one mount "
"point.\n", EXEC_NAME);
return -1;
}
break;
case 'o':
if (opts.options)
if (strappend(&opts.options, ","))
return -1;
if (strappend(&opts.options, optarg))
return -1;
break;
case 'h':
usage();
exit(9);
case 'n':
/*
* no effect - automount passes it, meaning 'no-mtab'
*/
break;
case 'v':
/*
* We must handle the 'verbose' option even if
* we don't use it because mount(8) passes it.
*/
break;
case 'V':
ntfs_log_info("%s %s %s %d\n", EXEC_NAME, VERSION,
FUSE_TYPE, fuse_version());
exit(0);
default:
ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
argv[optind - 1]);
return -1;
}
}
if (!opts.device) {
ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);
return -1;
}
if (!opts.mnt_point) {
ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);
return -1;
}
return 0;
}
#if defined(linux) || defined(__uClinux__)
static const char *dev_fuse_msg =
@ -4012,7 +3526,7 @@ static int set_fuseblk_options(char **parsed_options)
blksize = pagesize;
snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
if (strappend(parsed_options, options))
if (ntfs_strappend(parsed_options, options))
return -1;
return 0;
}
@ -4119,7 +3633,7 @@ int main(int argc, char *argv[])
ntfs_set_locale();
ntfs_log_set_handler(ntfs_log_handler_stderr);
if (parse_options(argc, argv)) {
if (ntfs_parse_options(&opts, usage, argc, argv)) {
usage();
return NTFS_VOLUME_SYNTAX_ERROR;
}
@ -4129,7 +3643,7 @@ int main(int argc, char *argv[])
goto err2;
}
parsed_options = parse_mount_options(opts.options);
parsed_options = parse_mount_options(ctx, &opts, FALSE);
if (!parsed_options) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
@ -4218,15 +3732,17 @@ int main(int argc, char *argv[])
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,
(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
(ctx->vol->secure_flags
& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
#if POSIXACLS
/* use basic permissions if requested */
if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
permissions_mode = "User mapping built, Posix ACLs not used";
else {
permissions_mode = "User mapping built, Posix ACLs in use";
#if KERNELACLS
if (strappend(&parsed_options, ",default_permissions,acl")) {
if (ntfs_strappend(&parsed_options, ",default_permissions,acl")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
}
@ -4234,13 +3750,14 @@ int main(int argc, char *argv[])
}
#else /* POSIXACLS */
#if KERNELPERMS
if (!(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
if (!(ctx->vol->secure_flags
& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
/*
* No explicit option but user mapping found
* force default security
*/
ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
if (strappend(&parsed_options, ",default_permissions")) {
if (ntfs_strappend(&parsed_options, ",default_permissions")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
}
@ -4257,7 +3774,7 @@ int main(int argc, char *argv[])
if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
&& !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
if (strappend(&parsed_options, ",default_permissions")) {
if (ntfs_strappend(&parsed_options, ",default_permissions")) {
err = NTFS_VOLUME_SYNTAX_ERROR;
goto err_out;
}

View File

@ -0,0 +1,674 @@
/**
* ntfs-3g_common.c - Common definitions for ntfs-3g and lowntfs-3g.
*
* Copyright (c) 2010-2011 Jean-Pierre Andre
* Copyright (c) 2010 Erik Larsson
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <getopt.h>
#include <fuse.h>
#include "inode.h"
#include "security.h"
#include "xattrs.h"
#include "ntfs-3g_common.h"
#include "misc.h"
const char xattr_ntfs_3g[] = "ntfs-3g.";
const char nf_ns_user_prefix[] = "user.";
const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
const char nf_ns_system_prefix[] = "system.";
const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1;
const char nf_ns_security_prefix[] = "security.";
const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1;
const char nf_ns_trusted_prefix[] = "trusted.";
const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1;
static const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
#ifdef HAVE_SETXATTR
static const char def_opts[] = "allow_other,nonempty,";
/*
* Table of recognized options
* Their order may be significant
* The options invalid in some configuration should still
* be present, so that an error can be returned
*/
const struct DEFOPTION optionlist[] = {
{ "ro", OPT_RO, FLGOPT_APPEND | FLGOPT_BOGUS },
{ "noatime", OPT_NOATIME, FLGOPT_BOGUS },
{ "atime", OPT_ATIME, FLGOPT_BOGUS },
{ "relatime", OPT_RELATIME, FLGOPT_BOGUS },
{ "fake_rw", OPT_FAKE_RW, FLGOPT_BOGUS },
{ "fsname", OPT_FSNAME, FLGOPT_NOSUPPORT },
{ "no_def_opts", OPT_NO_DEF_OPTS, FLGOPT_BOGUS },
{ "default_permissions", OPT_DEFAULT_PERMISSIONS, FLGOPT_BOGUS },
{ "permissions", OPT_PERMISSIONS, FLGOPT_BOGUS },
{ "acl", OPT_ACL, FLGOPT_BOGUS },
{ "umask", OPT_UMASK, FLGOPT_OCTAL },
{ "fmask", OPT_FMASK, FLGOPT_OCTAL },
{ "dmask", OPT_DMASK, FLGOPT_OCTAL },
{ "uid", OPT_UID, FLGOPT_DECIMAL },
{ "gid", OPT_GID, FLGOPT_DECIMAL },
{ "show_sys_files", OPT_SHOW_SYS_FILES, FLGOPT_BOGUS },
{ "hide_hid_files", OPT_HIDE_HID_FILES, FLGOPT_BOGUS },
{ "hide_dot_files", OPT_HIDE_DOT_FILES, FLGOPT_BOGUS },
{ "ignore_case", OPT_IGNORE_CASE, FLGOPT_BOGUS },
{ "windows_names", OPT_WINDOWS_NAMES, FLGOPT_BOGUS },
{ "compression", OPT_COMPRESSION, FLGOPT_BOGUS },
{ "nocompression", OPT_NOCOMPRESSION, FLGOPT_BOGUS },
{ "silent", OPT_SILENT, FLGOPT_BOGUS },
{ "recover", OPT_RECOVER, FLGOPT_BOGUS },
{ "norecover", OPT_NORECOVER, FLGOPT_BOGUS },
{ "remove_hiberfile", OPT_REMOVE_HIBERFILE, FLGOPT_BOGUS },
{ "sync", OPT_SYNC, FLGOPT_BOGUS | FLGOPT_APPEND },
{ "locale", OPT_LOCALE, FLGOPT_STRING },
{ "nfconv", OPT_NFCONV, FLGOPT_BOGUS },
{ "nonfconv", OPT_NONFCONV, FLGOPT_BOGUS },
{ "streams_interface", OPT_STREAMS_INTERFACE, FLGOPT_STRING },
{ "user_xattr", OPT_USER_XATTR, FLGOPT_BOGUS },
{ "noauto", OPT_NOAUTO, FLGOPT_BOGUS },
{ "debug", OPT_DEBUG, FLGOPT_BOGUS },
{ "no_detach", OPT_NO_DETACH, FLGOPT_BOGUS },
{ "remount", OPT_REMOUNT, FLGOPT_BOGUS },
{ "blksize", OPT_BLKSIZE, FLGOPT_STRING },
{ "inherit", OPT_INHERIT, FLGOPT_BOGUS },
{ "addsecurids", OPT_ADDSECURIDS, FLGOPT_BOGUS },
{ "staticgrps", OPT_STATICGRPS, FLGOPT_BOGUS },
{ "usermapping", OPT_USERMAPPING, FLGOPT_STRING },
{ "xattrmapping", OPT_XATTRMAPPING, FLGOPT_STRING },
{ "efs_raw", OPT_EFS_RAW, FLGOPT_BOGUS },
{ (const char*)NULL, 0, 0 } /* end marker */
} ;
#define STRAPPEND_MAX_INSIZE 8192
#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)
int ntfs_strappend(char **dest, const char *append)
{
char *p;
size_t size_append, size_dest = 0;
if (!dest)
return -1;
if (!append)
return 0;
size_append = strlen(append);
if (*dest)
size_dest = strlen(*dest);
if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
errno = EOVERFLOW;
ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
return -1;
}
p = (char*)realloc(*dest, size_dest + size_append + 1);
if (!p) {
ntfs_log_perror("%s: Memory realloction failed", EXEC_NAME);
return -1;
}
*dest = p;
strcpy(*dest + size_dest, append);
return 0;
}
static int bogus_option_value(char *val, const char *s)
{
if (val) {
ntfs_log_error("'%s' option shouldn't have value.\n", s);
return -1;
}
return 0;
}
static int missing_option_value(char *val, const char *s)
{
if (!val) {
ntfs_log_error("'%s' option should have a value.\n", s);
return -1;
}
return 0;
}
char *parse_mount_options(ntfs_fuse_context_t *ctx,
const struct ntfs_options *popts, BOOL low_fuse)
{
char *options, *s, *opt, *val, *ret = NULL;
const char *orig_opts = popts->options;
BOOL no_def_opts = FALSE;
int default_permissions = 0;
int permissions = 0;
int acl = 0;
int want_permissions = 0;
int intarg;
const struct DEFOPTION *poptl;
ctx->secure_flags = 0;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
ctx->efs_raw = FALSE;
#endif /* HAVE_SETXATTR */
ctx->compression = DEFAULT_COMPRESSION;
ctx->atime = ATIME_ENABLED;
options = strdup(orig_opts ? orig_opts : "");
if (!options) {
ntfs_log_perror("%s: strdup failed", EXEC_NAME);
return NULL;
}
s = options;
while (s && *s && (val = strsep(&s, ","))) {
opt = strsep(&val, "=");
poptl = optionlist;
while (poptl->name && strcmp(poptl->name,opt))
poptl++;
if (poptl->name) {
if ((poptl->flags & FLGOPT_BOGUS)
&& bogus_option_value(val, opt))
goto err_exit;
if ((poptl->flags & FLGOPT_OCTAL)
&& (!val
|| !sscanf(val, "%o", &intarg))) {
ntfs_log_error("'%s' option needs an octal value\n",
opt);
goto err_exit;
}
if ((poptl->flags & FLGOPT_DECIMAL)
&& (!val
|| !sscanf(val, "%i", &intarg))) {
ntfs_log_error("'%s' option needs a decimal value\n",
opt);
goto err_exit;
}
if ((poptl->flags & FLGOPT_STRING)
&& missing_option_value(val, opt))
goto err_exit;
switch (poptl->type) {
case OPT_RO :
case OPT_FAKE_RW :
ctx->ro = TRUE;
break;
case OPT_NOATIME :
ctx->atime = ATIME_DISABLED;
break;
case OPT_ATIME :
ctx->atime = ATIME_ENABLED;
break;
case OPT_RELATIME :
ctx->atime = ATIME_RELATIVE;
break;
case OPT_NO_DEF_OPTS :
no_def_opts = TRUE; /* Don't add default options. */
ctx->silent = FALSE; /* cancel default silent */
break;
case OPT_DEFAULT_PERMISSIONS :
default_permissions = 1;
break;
case OPT_PERMISSIONS :
permissions = 1;
break;
#if POSIXACLS
case OPT_ACL :
acl = 1;
break;
#endif
case OPT_UMASK :
ctx->dmask = ctx->fmask = intarg;
want_permissions = 1;
break;
case OPT_FMASK :
ctx->fmask = intarg;
want_permissions = 1;
break;
case OPT_DMASK :
ctx->dmask = intarg;
want_permissions = 1;
break;
case OPT_UID :
ctx->uid = intarg;
want_permissions = 1;
break;
case OPT_GID :
ctx->gid = intarg;
want_permissions = 1;
break;
case OPT_SHOW_SYS_FILES :
ctx->show_sys_files = TRUE;
break;
case OPT_HIDE_HID_FILES :
ctx->hide_hid_files = TRUE;
break;
case OPT_HIDE_DOT_FILES :
ctx->hide_dot_files = TRUE;
break;
case OPT_WINDOWS_NAMES :
ctx->windows_names = TRUE;
break;
case OPT_IGNORE_CASE :
if (low_fuse)
ctx->ignore_case = TRUE;
else {
ntfs_log_error("'%s' is an unsupported option.\n",
poptl->name);
goto err_exit;
}
break;
case OPT_COMPRESSION :
ctx->compression = TRUE;
break;
case OPT_NOCOMPRESSION :
ctx->compression = FALSE;
break;
case OPT_SILENT :
ctx->silent = TRUE;
break;
case OPT_RECOVER :
ctx->recover = TRUE;
break;
case OPT_NORECOVER :
ctx->recover = FALSE;
break;
case OPT_REMOVE_HIBERFILE :
ctx->hiberfile = TRUE;
break;
case OPT_SYNC :
ctx->sync = TRUE;
break;
case OPT_LOCALE :
ntfs_set_char_encoding(val);
break;
#if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV
case OPT_NFCONV :
if (ntfs_macosx_normalize_filenames(1)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n");
goto err_exit;
}
break;
case OPT_NONFCONV :
if (ntfs_macosx_normalize_filenames(0)) {
ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n");
goto err_exit;
}
break;
#endif /* ENABLE_NFCONV */
#endif /* defined(__APPLE__) || defined(__DARWIN__) */
case OPT_STREAMS_INTERFACE :
if (!strcmp(val, "none"))
ctx->streams = NF_STREAMS_INTERFACE_NONE;
else if (!strcmp(val, "xattr"))
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
else if (!strcmp(val, "openxattr"))
ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR;
else if (!low_fuse && !strcmp(val, "windows"))
ctx->streams = NF_STREAMS_INTERFACE_WINDOWS;
else {
ntfs_log_error("Invalid named data streams "
"access interface.\n");
goto err_exit;
}
break;
case OPT_USER_XATTR :
ctx->streams = NF_STREAMS_INTERFACE_XATTR;
break;
case OPT_NOAUTO :
/* Don't pass noauto option to fuse. */
break;
case OPT_DEBUG :
ctx->debug = TRUE;
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
break;
case OPT_NO_DETACH :
ctx->no_detach = TRUE;
break;
case OPT_REMOUNT :
ntfs_log_error("Remounting is not supported at present."
" You have to umount volume and then "
"mount it once again.\n");
goto err_exit;
case OPT_BLKSIZE :
ntfs_log_info("WARNING: blksize option is ignored "
"because ntfs-3g must calculate it.\n");
break;
case OPT_INHERIT :
/*
* do not overwrite inherited permissions
* in create()
*/
ctx->inherit = TRUE;
break;
case OPT_ADDSECURIDS :
/*
* create security ids for files being read
* with an individual security attribute
*/
ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS);
break;
case OPT_STATICGRPS :
/*
* use static definition of groups
* for file access control
*/
ctx->secure_flags |= (1 << SECURITY_STATICGRPS);
break;
case OPT_USERMAPPING :
ctx->usermap_path = strdup(val);
if (!ctx->usermap_path) {
ntfs_log_error("no more memory to store "
"'usermapping' option.\n");
goto err_exit;
}
break;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
#ifdef XATTR_MAPPINGS
case OPT_XATTRMAPPING :
ctx->xattrmap_path = strdup(val);
if (!ctx->xattrmap_path) {
ntfs_log_error("no more memory to store "
"'xattrmapping' option.\n");
goto err_exit;
}
break;
#endif /* XATTR_MAPPINGS */
case OPT_EFS_RAW :
ctx->efs_raw = TRUE;
break;
#endif /* HAVE_SETXATTR */
case OPT_FSNAME : /* Filesystem name. */
/*
* We need this to be able to check whether filesystem
* mounted or not.
* (falling through to default)
*/
default :
ntfs_log_error("'%s' is an unsupported option.\n",
poptl->name);
goto err_exit;
}
if ((poptl->flags & FLGOPT_APPEND)
&& (ntfs_strappend(&ret, poptl->name)
|| ntfs_strappend(&ret, ",")))
goto err_exit;
} else { /* Probably FUSE option. */
if (ntfs_strappend(&ret, opt))
goto err_exit;
if (val) {
if (ntfs_strappend(&ret, "="))
goto err_exit;
if (ntfs_strappend(&ret, val))
goto err_exit;
}
if (ntfs_strappend(&ret, ","))
goto err_exit;
}
}
if (!no_def_opts && ntfs_strappend(&ret, def_opts))
goto err_exit;
if ((default_permissions || (permissions && !acl))
&& ntfs_strappend(&ret, "default_permissions,"))
goto err_exit;
/* The atime options exclude each other */
if (ctx->atime == ATIME_RELATIVE && ntfs_strappend(&ret, "relatime,"))
goto err_exit;
else if (ctx->atime == ATIME_ENABLED && ntfs_strappend(&ret, "atime,"))
goto err_exit;
else if (ctx->atime == ATIME_DISABLED && ntfs_strappend(&ret, "noatime,"))
goto err_exit;
if (ntfs_strappend(&ret, "fsname="))
goto err_exit;
if (ntfs_strappend(&ret, popts->device))
goto err_exit;
if (permissions && !acl)
ctx->secure_flags |= (1 << SECURITY_DEFAULT);
if (acl)
ctx->secure_flags |= (1 << SECURITY_ACL);
if (want_permissions)
ctx->secure_flags |= (1 << SECURITY_WANTED);
if (ctx->ro)
ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS);
exit:
free(options);
return ret;
err_exit:
free(ret);
ret = NULL;
goto exit;
}
/**
* parse_options - Read and validate the programs command line
* Read the command line, verify the syntax and parse the options.
*
* Return: 0 success, -1 error.
*/
int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
int argc, char *argv[])
{
int c;
static const char *sopt = "-o:hnvV";
static const struct option lopt[] = {
{ "options", required_argument, NULL, 'o' },
{ "help", no_argument, NULL, 'h' },
{ "no-mtab", no_argument, NULL, 'n' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
opterr = 0; /* We'll handle the errors, thank you. */
while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
switch (c) {
case 1: /* A non-option argument */
if (!popts->device) {
popts->device = ntfs_malloc(PATH_MAX + 1);
if (!popts->device)
return -1;
/* Canonicalize device name (mtab, etc) */
if (!realpath(optarg, popts->device)) {
ntfs_log_perror("%s: Failed to access "
"volume '%s'", EXEC_NAME, optarg);
free(popts->device);
popts->device = NULL;
return -1;
}
} else if (!popts->mnt_point) {
popts->mnt_point = optarg;
} else {
ntfs_log_error("%s: You must specify exactly one "
"device and exactly one mount "
"point.\n", EXEC_NAME);
return -1;
}
break;
case 'o':
if (popts->options)
if (ntfs_strappend(&popts->options, ","))
return -1;
if (ntfs_strappend(&popts->options, optarg))
return -1;
break;
case 'h':
usage();
exit(9);
case 'n':
/*
* no effect - automount passes it, meaning 'no-mtab'
*/
break;
case 'v':
/*
* We must handle the 'verbose' option even if
* we don't use it because mount(8) passes it.
*/
break;
case 'V':
ntfs_log_info("%s %s %s %d\n", EXEC_NAME, VERSION,
FUSE_TYPE, fuse_version());
exit(0);
default:
ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
argv[optind - 1]);
return -1;
}
}
if (!popts->device) {
ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);
return -1;
}
if (!popts->mnt_point) {
ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);
return -1;
}
return 0;
}
int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing)
{
int ret = 0;
char *to = list;
#ifdef XATTR_MAPPINGS
BOOL accepted;
const struct XATTRMAPPING *item;
#endif /* XATTR_MAPPINGS */
/* first list the regular user attributes (ADS) */
while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
0, NULL, 0, actx)) {
char *tmp_name = NULL;
int tmp_name_len;
if (!actx->attr->name_length)
continue;
tmp_name_len = ntfs_ucstombs(
(ntfschar *)((u8*)actx->attr +
le16_to_cpu(actx->attr->name_offset)),
actx->attr->name_length, &tmp_name, 0);
if (tmp_name_len < 0) {
ret = -errno;
goto exit;
}
/*
* When using name spaces, do not return
* security, trusted or system attributes
* (filtered elsewhere anyway)
* otherwise insert "user." prefix
*/
if (prefixing) {
if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g))
&& !strncmp(tmp_name,xattr_ntfs_3g,
sizeof(xattr_ntfs_3g)-1))
tmp_name_len = 0;
else
ret += tmp_name_len
+ nf_ns_user_prefix_len + 1;
} else
ret += tmp_name_len + 1;
if (size && tmp_name_len) {
if ((size_t)ret <= size) {
if (prefixing) {
strcpy(to, nf_ns_user_prefix);
to += nf_ns_user_prefix_len;
}
strncpy(to, tmp_name, tmp_name_len);
to += tmp_name_len;
*to = 0;
to++;
} else {
free(tmp_name);
ret = -ERANGE;
goto exit;
}
}
free(tmp_name);
}
#ifdef XATTR_MAPPINGS
/* now append the system attributes mapped to user space */
for (item=ni->vol->xattr_mapping; item; item=item->next) {
switch (item->xattr) {
case XATTR_NTFS_EFSINFO :
accepted = ni->vol->efs_raw
&& (ni->flags & FILE_ATTR_ENCRYPTED);
break;
case XATTR_NTFS_REPARSE_DATA :
accepted = (ni->flags & FILE_ATTR_REPARSE_POINT)
!= const_cpu_to_le32(0);
break;
// TODO : we are supposed to only return xattrs which are set
// this is more complex for OBJECT_ID and DOS_NAME
default : accepted = TRUE;
break;
}
if (accepted) {
ret += strlen(item->name) + 1;
if (size) {
if ((size_t)ret <= size) {
strcpy(to, item->name);
to += strlen(item->name);
*to++ = 0;
} else {
ret = -ERANGE;
goto exit;
}
}
#else /* XATTR_MAPPINGS */
/* List efs info xattr for encrypted files */
if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) {
ret += sizeof(nf_ns_alt_xattr_efsinfo);
if ((size_t)ret <= size) {
memcpy(to, nf_ns_alt_xattr_efsinfo,
sizeof(nf_ns_alt_xattr_efsinfo));
to += sizeof(nf_ns_alt_xattr_efsinfo);
#endif /* XATTR_MAPPINGS */
}
}
exit :
return (ret);
}
#endif /* HAVE_SETXATTR */

View File

@ -0,0 +1,178 @@
/*
* ntfs-3g_common.h - Common declarations for ntfs-3g and lowntfs-3g.
*
* Copyright (c) 2010-2011 Jean-Pierre Andre
* Copyright (c) 2010 Erik Larsson
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_3G_COMMON_H
#define _NTFS_3G_COMMON_H
#include "inode.h"
struct ntfs_options {
char *mnt_point; /* Mount point */
char *options; /* Mount options */
char *device; /* Device to mount */
} ;
typedef enum {
NF_STREAMS_INTERFACE_NONE, /* No access to named data streams. */
NF_STREAMS_INTERFACE_XATTR, /* Map named data streams to xattrs. */
NF_STREAMS_INTERFACE_OPENXATTR, /* Same, not limited to "user." */
NF_STREAMS_INTERFACE_WINDOWS, /* "file:stream" interface. */
} ntfs_fuse_streams_interface;
struct DEFOPTION {
const char *name;
int type;
int flags;
} ;
/* Options, order not significant */
enum {
OPT_RO,
OPT_NOATIME,
OPT_ATIME,
OPT_RELATIME,
OPT_FAKE_RW,
OPT_FSNAME,
OPT_NO_DEF_OPTS,
OPT_DEFAULT_PERMISSIONS,
OPT_PERMISSIONS,
OPT_ACL,
OPT_UMASK,
OPT_FMASK,
OPT_DMASK,
OPT_UID,
OPT_GID,
OPT_SHOW_SYS_FILES,
OPT_HIDE_HID_FILES,
OPT_HIDE_DOT_FILES,
OPT_IGNORE_CASE,
OPT_WINDOWS_NAMES,
OPT_COMPRESSION,
OPT_NOCOMPRESSION,
OPT_SILENT,
OPT_RECOVER,
OPT_NORECOVER,
OPT_REMOVE_HIBERFILE,
OPT_SYNC,
OPT_LOCALE,
OPT_NFCONV,
OPT_NONFCONV,
OPT_STREAMS_INTERFACE,
OPT_USER_XATTR,
OPT_NOAUTO,
OPT_DEBUG,
OPT_NO_DETACH,
OPT_REMOUNT,
OPT_BLKSIZE,
OPT_INHERIT,
OPT_ADDSECURIDS,
OPT_STATICGRPS,
OPT_USERMAPPING,
OPT_XATTRMAPPING,
OPT_EFS_RAW,
} ;
/* Option flags */
enum {
FLGOPT_BOGUS = 1,
FLGOPT_STRING = 2,
FLGOPT_OCTAL = 4,
FLGOPT_DECIMAL = 8,
FLGOPT_APPEND = 16,
FLGOPT_NOSUPPORT = 32
} ;
typedef enum {
ATIME_ENABLED,
ATIME_DISABLED,
ATIME_RELATIVE
} ntfs_atime_t;
typedef struct {
ntfs_volume *vol;
unsigned int uid;
unsigned int gid;
unsigned int fmask;
unsigned int dmask;
ntfs_fuse_streams_interface streams;
ntfs_atime_t atime;
BOOL ro;
BOOL show_sys_files;
BOOL hide_hid_files;
BOOL hide_dot_files;
BOOL windows_names;
BOOL ignore_case;
BOOL compression;
BOOL acl;
BOOL silent;
BOOL recover;
BOOL hiberfile;
BOOL sync;
BOOL debug;
BOOL no_detach;
BOOL blkdev;
BOOL mounted;
#ifdef HAVE_SETXATTR /* extended attributes interface required */
BOOL efs_raw;
#ifdef XATTR_MAPPINGS
char *xattrmap_path;
#endif /* XATTR_MAPPINGS */
#endif /* HAVE_SETXATTR */
struct fuse_chan *fc;
BOOL inherit;
unsigned int secure_flags;
char *usermap_path;
char *abs_mnt_point;
struct PERMISSIONS_CACHE *seccache;
struct SECURITY_CONTEXT security;
struct open_file *open_files; /* only defined in lowntfs-3g */
u64 latest_ghost;
} ntfs_fuse_context_t;
extern const char *EXEC_NAME;
#ifdef FUSE_INTERNAL
#define FUSE_TYPE "integrated FUSE"
#else
#define FUSE_TYPE "external FUSE"
#endif
extern const char xattr_ntfs_3g[];
extern const char nf_ns_user_prefix[];
extern const int nf_ns_user_prefix_len;
extern const char nf_ns_system_prefix[];
extern const int nf_ns_system_prefix_len;
extern const char nf_ns_security_prefix[];
extern const int nf_ns_security_prefix_len;
extern const char nf_ns_trusted_prefix[];
extern const int nf_ns_trusted_prefix_len;
int ntfs_strappend(char **dest, const char *append);
char *parse_mount_options(ntfs_fuse_context_t *ctx,
const struct ntfs_options *popts, BOOL low_fuse);
int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
int argc, char *argv[]);
int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing);
#endif /* _NTFS_3G_COMMON_H */

View File

@ -178,6 +178,12 @@
*
* May 2010, version 1.3.18
* - redefined early error logging
*
* Mar 2011, version 1.3.19
* - fixed interface to ntfs_initialize_file_security()
*
* Apr 2011, version 1.3.20
* - fixed false memory leak detection
*/
/*
@ -201,7 +207,7 @@
* General parameters which may have to be adapted to needs
*/
#define AUDT_VERSION "1.3.18"
#define AUDT_VERSION "1.3.20"
#define GET_FILE_SECURITY "ntfs_get_file_security"
#define SET_FILE_SECURITY "ntfs_set_file_security"
@ -343,7 +349,7 @@ int ntfs_get_gsid(void *scapi, gid_t gid, char *buf);
int ntfs_get_user(void *scapi, const char *usid);
int ntfs_get_group(void *scapi, const char *gsid);
void *ntfs_initialize_file_security(const char *device, int flags);
void *ntfs_initialize_file_security(const char *device, unsigned long flags);
BOOL ntfs_leave_file_security(void *scapi);
#else
@ -369,7 +375,8 @@ typedef int (*type_get_gsid)(void *scapi, gid_t gid, char *buf);
typedef int (*type_get_user)(void *scapi, const char *usid);
typedef int (*type_get_group)(void *scapi, const char *gsid);
typedef void *(*type_initialize_file_security)(const char *device, int flags);
typedef void *(*type_initialize_file_security)(const char *device,
unsigned long flags);
typedef BOOL (*type_leave_file_security)(void *scapi);
type_get_file_security ntfs_get_file_security;
@ -400,7 +407,7 @@ type_leave_file_security ntfs_leave_file_security;
BOOL open_security_api(void);
BOOL close_security_api(void);
#ifndef WIN32
BOOL open_volume(const char*, int flags);
BOOL open_volume(const char*, unsigned long flags);
BOOL close_volume(const char*);
#endif
unsigned int get2l(const char*, int);
@ -707,7 +714,7 @@ BOOL close_security_api(void)
* Assumes a single volume is opened
*/
BOOL open_volume(const char *volume, int flags)
BOOL open_volume(const char *volume, unsigned long flags)
{
BOOL ok;
@ -5011,7 +5018,11 @@ void showfull(const char *fullname, BOOL isdir)
| POSIX_ACL_GROUP
| POSIX_ACL_MASK))))
showposix(pxdesc);
#if USESTUBS
stdfree(pxdesc); /* allocated within library */
#else
free(pxdesc);
#endif
}
#endif
if ((opt_r || opt_b) && (securindex < MAXSECURID)