diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 7d07eb2a..f23a0dad 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -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; } diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index e80d31d6..6baf7021 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -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; } diff --git a/src/ntfs-3g_common.c b/src/ntfs-3g_common.c index 7c595b80..dc7201ed 100644 --- a/src/ntfs-3g_common.c +++ b/src/ntfs-3g_common.c @@ -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) { diff --git a/src/ntfs-3g_common.h b/src/ntfs-3g_common.h index 2ef6dbc2..8d165248 100644 --- a/src/ntfs-3g_common.h +++ b/src/ntfs-3g_common.h @@ -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);