Moved mount options parsing to ntfs-3g_common.c

PERMISSION_HANDLING_BRANCH
Jean-Pierre André 2011-02-08 11:45:55 +01:00
parent 453a8aa501
commit 3ae68884f7
4 changed files with 551 additions and 812 deletions

View File

@ -159,12 +159,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;
@ -189,66 +183,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";
@ -3512,350 +3456,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(),
@ -3922,9 +3522,9 @@ static int parse_options(int argc, char *argv[])
break;
case 'o':
if (opts.options)
if (strappend(&opts.options, ","))
if (ntfs_strappend(&opts.options, ","))
return -1;
if (strappend(&opts.options, optarg))
if (ntfs_strappend(&opts.options, optarg))
return -1;
break;
case 'h':
@ -4109,7 +3709,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;
}
@ -4221,7 +3821,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;
@ -4318,7 +3918,7 @@ int main(int argc, char *argv[])
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;
@ -4333,7 +3933,7 @@ int main(int argc, char *argv[])
*/
#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;
}
@ -4350,7 +3950,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

@ -140,74 +140,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;
@ -3425,346 +3371,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(),
@ -3831,9 +3437,9 @@ static int parse_options(int argc, char *argv[])
break;
case 'o':
if (opts.options)
if (strappend(&opts.options, ","))
if (ntfs_strappend(&opts.options, ","))
return -1;
if (strappend(&opts.options, optarg))
if (ntfs_strappend(&opts.options, optarg))
return -1;
break;
case 'h':
@ -4018,7 +3624,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;
}
@ -4135,7 +3741,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;
@ -4232,7 +3838,7 @@ int main(int argc, char *argv[])
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;
}
@ -4246,7 +3852,7 @@ int main(int argc, char *argv[])
* 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;
}
@ -4263,7 +3869,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

@ -40,6 +40,7 @@
#include "security.h"
#include "xattrs.h"
#include "ntfs-3g_common.h"
#include "misc.h"
const char xattr_ntfs_3g[] = "ntfs-3g.";
@ -56,6 +57,412 @@ 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 },
{ "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 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;
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)
&& 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)
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;
}
int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing)
{

View File

@ -25,6 +25,128 @@
#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_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 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;
extern const char xattr_ntfs_3g[];
extern const char nf_ns_user_prefix[];
@ -36,6 +158,10 @@ 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_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing);