#include "xml.h"
#include "io.h"
#include "timestamp.h"
+#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
/* The WIMStruct for the mounted WIM. */
WIMStruct *wim;
- /* Working directory when `imagex mount' is run. */
- char *working_directory;
-
/* Name of the staging directory for a read-write mount. Whenever a new file is
* created, it is done so in the staging directory. Furthermore, whenever a
* file in the WIM is modified, it is extracted to the staging directory. If
return wimfs_get_context()->wim;
}
+static inline bool wimfs_ctx_readonly(const struct wimfs_context *ctx)
+{
+ return (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) == 0;
+}
+
static inline int get_lookup_flags(const struct wimfs_context *ctx)
{
if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
* @stream_id: ID of the stream we're opening
* @lte: Lookup table entry for the stream (may be NULL)
* @fd_ret: Return the allocated file descriptor if successful.
+ * @readonly: True if this is a read-only mount.
*
* Return 0 iff successful or error code if unsuccessful.
*/
static int alloc_wimlib_fd(struct inode *inode,
u32 stream_id,
struct lookup_table_entry *lte,
- struct wimlib_fd **fd_ret)
+ struct wimlib_fd **fd_ret,
+ bool readonly)
{
static const u16 fds_per_alloc = 8;
static const u16 max_fds = 0xffff;
+ int ret;
+
+ pthread_mutex_lock(&inode->i_mutex);
DEBUG("Allocating fd for stream ID %u from inode %lx (open = %u, allocated = %u)",
stream_id, inode->ino, inode->num_opened_fds,
struct wimlib_fd **fds;
u16 num_new_fds;
- if (inode->num_allocated_fds == max_fds)
- return -EMFILE;
+ if (inode->num_allocated_fds == max_fds) {
+ ret = -EMFILE;
+ goto out;
+ }
num_new_fds = min(fds_per_alloc,
max_fds - inode->num_allocated_fds);
fds = REALLOC(inode->fds,
(inode->num_allocated_fds + num_new_fds) *
sizeof(inode->fds[0]));
- if (!fds)
- return -ENOMEM;
+ if (!fds) {
+ ret = -ENOMEM;
+ goto out;
+ }
memset(&fds[inode->num_allocated_fds], 0,
num_new_fds * sizeof(fds[0]));
inode->fds = fds;
for (u16 i = 0; ; i++) {
if (!inode->fds[i]) {
struct wimlib_fd *fd = CALLOC(1, sizeof(*fd));
- if (!fd)
- return -ENOMEM;
+ if (!fd) {
+ ret = -ENOMEM;
+ break;
+ }
fd->f_inode = inode;
fd->f_lte = lte;
fd->staging_fd = -1;
*fd_ret = fd;
inode->fds[i] = fd;
inode->num_opened_fds++;
- if (lte)
+ if (lte && !readonly)
lte->num_opened_fds++;
- DEBUG("Allocated fd");
- return 0;
+ DEBUG("Allocated fd (idx = %u)", fd->idx);
+ ret = 0;
+ break;
}
}
+out:
+ pthread_mutex_unlock(&inode->i_mutex);
+ return ret;
}
static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd)
{
- wimlib_assert(fd);
- wimlib_assert(inode);
+ wimlib_assert(fd != NULL);
+ wimlib_assert(inode != NULL);
+
+ pthread_mutex_lock(&inode->i_mutex);
+
wimlib_assert(fd->f_inode == inode);
- wimlib_assert(inode->num_opened_fds);
- wimlib_assert(fd->idx < inode->num_opened_fds);
+ wimlib_assert(inode->num_opened_fds != 0);
+ wimlib_assert(fd->idx < inode->num_allocated_fds);
wimlib_assert(inode->fds[fd->idx] == fd);
inode->fds[fd->idx] = NULL;
FREE(fd);
- if (--inode->num_opened_fds == 0 && inode->link_count == 0)
+ if (--inode->num_opened_fds == 0 && inode->link_count == 0) {
+ pthread_mutex_unlock(&inode->i_mutex);
free_inode(inode);
+ } else {
+ pthread_mutex_unlock(&inode->i_mutex);
+ }
}
static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd)
{
- wimlib_assert(fd);
+ wimlib_assert(fd != NULL);
wimlib_assert(fd->f_lte == lte);
if (!lte) /* Empty stream with no lookup table entry */
static int close_wimlib_fd(struct wimlib_fd *fd)
{
int ret;
- wimlib_assert(fd);
+ wimlib_assert(fd != NULL);
DEBUG("Closing fd (inode = %lu, opened = %u, allocated = %u)",
fd->f_inode->ino, fd->f_inode->num_opened_fds,
fd->f_inode->num_allocated_fds);
}
/*
- * Creates a randomly named staging directory and returns its name into the
- * static variable staging_dir_name.
- *
- * If the staging directory cannot be created, staging_dir_name is set to NULL.
- * */
-static int make_staging_dir(struct wimfs_context *ctx)
+ * Creates a randomly named staging directory and saves its name in the
+ * filesystem context structure.
+ */
+static int make_staging_dir(struct wimfs_context *ctx,
+ const char *user_prefix)
{
- /* XXX Give the user an option of where to stage files */
-
- static const char prefix[] = "wimlib-staging-";
- static const size_t prefix_len = sizeof(prefix) - 1;
static const size_t random_suffix_len = 10;
+ static const char *common_suffix = ".staging";
+ static const size_t common_suffix_len = 8;
+
+ char *staging_dir_name = NULL;
+ size_t staging_dir_name_len;
+ size_t prefix_len;
+ const char *wim_basename;
+ char *real_user_prefix = NULL;
+ int ret;
- size_t pwd_len = strlen(ctx->working_directory);
+ if (user_prefix) {
+ real_user_prefix = realpath(user_prefix, NULL);
+ if (!real_user_prefix) {
+ ERROR_WITH_ERRNO("Could not resolve `%s'",
+ real_user_prefix);
+ ret = WIMLIB_ERR_NOTDIR;
+ goto out;
+ }
+ wim_basename = path_basename(ctx->wim->filename);
+ prefix_len = strlen(real_user_prefix) + 1 + strlen(wim_basename);
+ } else {
+ prefix_len = strlen(ctx->wim->filename);
+ }
- ctx->staging_dir_name_len = pwd_len + 1 + prefix_len + random_suffix_len;
+ staging_dir_name_len = prefix_len + common_suffix_len + random_suffix_len;
- ctx->staging_dir_name = MALLOC(ctx->staging_dir_name_len + 1);
- if (!ctx->staging_dir_name)
- return WIMLIB_ERR_NOMEM;
+ staging_dir_name = MALLOC(staging_dir_name_len + 1);
+ if (!staging_dir_name) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out;
+ }
- memcpy(ctx->staging_dir_name, ctx->working_directory, pwd_len);
- ctx->staging_dir_name[pwd_len] = '/';
- memcpy(ctx->staging_dir_name + pwd_len + 1, prefix, prefix_len);
- randomize_char_array_with_alnum(ctx->staging_dir_name + pwd_len +
- 1 + prefix_len, random_suffix_len);
- ctx->staging_dir_name[ctx->staging_dir_name_len] = '\0';
+ if (real_user_prefix)
+ sprintf(staging_dir_name, "%s/%s", real_user_prefix, wim_basename);
+ else
+ strcpy(staging_dir_name, ctx->wim->filename);
+
+ strcat(staging_dir_name, common_suffix);
+
+ randomize_char_array_with_alnum(staging_dir_name + prefix_len + common_suffix_len,
+ random_suffix_len);
+
+ staging_dir_name[staging_dir_name_len] = '\0';
- if (mkdir(ctx->staging_dir_name, 0700) != 0) {
+ if (mkdir(staging_dir_name, 0700) != 0) {
ERROR_WITH_ERRNO("Failed to create temporary directory `%s'",
- ctx->staging_dir_name);
- FREE(ctx->staging_dir_name);
- ctx->staging_dir_name = NULL;
- return WIMLIB_ERR_MKDIR;
+ staging_dir_name);
+ ret = WIMLIB_ERR_MKDIR;
+ } else {
+ ret = 0;
}
- return 0;
+out:
+ FREE(real_user_prefix);
+ if (ret == 0) {
+ ctx->staging_dir_name = staging_dir_name;
+ ctx->staging_dir_name_len = staging_dir_name_len;
+ } else {
+ FREE(staging_dir_name);
+ }
+ return ret;
}
static int remove_file_or_directory(const char *fpath, const struct stat *sb,
}
-/* Simple function that returns the concatenation of 4 strings. */
-static char *strcat_dup(const char *s1, const char *s2, const char *s3,
- const char *s4)
+/* Simple function that returns the concatenation of 2 strings. */
+static char *strcat_dup(const char *s1, const char *s2, size_t max_len)
{
- size_t len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4) + 1;
- char *p = MALLOC(len);
+ size_t len = strlen(s1) + strlen(s2);
+ if (len > max_len)
+ len = max_len;
+ char *p = MALLOC(len + 1);
if (!p)
return NULL;
- p = strcpy(p, s1);
- p = strcat(p, s2);
- p = strcat(p, s3);
- return strcat(p, s4);
+ snprintf(p, len + 1, "%s%s", s1, s2);
+ return p;
}
-/* Removes trailing forward slashes in a string. */
-static void remove_trailing_slashes(char *s)
+static int set_message_queue_names(struct wimfs_context *ctx,
+ const char *mount_dir)
{
- long len = strlen(s);
- for (long i = len - 1; i >= 1; i--) {
- if (s[i] == '/')
- s[i] = '\0';
- else
- break;
- }
-}
+ static const char *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
+ static const char *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
+ char *dir_path;
+ char *p;
+ int ret;
-/* Changes forward slashes to underscores in a string. */
-static void s_slashes_underscores_g(char *s)
-{
- while (*s) {
- if (*s == '/')
- *s = '_';
- s++;
+ dir_path = realpath(mount_dir, NULL);
+ if (!dir_path) {
+ ERROR_WITH_ERRNO("Failed to resolve path \"%s\"", mount_dir);
+ return WIMLIB_ERR_NOTDIR;
}
-}
-static int set_message_queue_names(struct wimfs_context *ctx,
- const char *mount_dir)
-{
- static const char *slash = "/";
- static const char *prefix = "wimlib-";
- static const char *u2d_suffix = "unmount-to-daemon-mq";
- static const char *d2u_suffix = "daemon-to-unmount-mq";
+ DEBUG("Using absolute dir_path = `%s'", dir_path);
+
- const char *mount_dir_basename = path_basename(mount_dir);
+ p = dir_path;
+ while (*p) {
+ if (*p == '/')
+ *p = 0xff;
+ p++;
+ }
- ctx->unmount_to_daemon_mq_name = strcat_dup(slash, mount_dir_basename,
- prefix, u2d_suffix);
+ ctx->unmount_to_daemon_mq_name = strcat_dup(u2d_prefix, dir_path,
+ NAME_MAX);
if (!ctx->unmount_to_daemon_mq_name) {
- ERROR("Out of memory");
- return WIMLIB_ERR_NOMEM;
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_dir_path;
}
- ctx->daemon_to_unmount_mq_name = strcat_dup(slash, mount_dir_basename,
- prefix, d2u_suffix);
+ ctx->daemon_to_unmount_mq_name = strcat_dup(d2u_prefix, dir_path,
+ NAME_MAX);
if (!ctx->daemon_to_unmount_mq_name) {
- ERROR("Out of memory");
- FREE(ctx->unmount_to_daemon_mq_name);
- ctx->unmount_to_daemon_mq_name = NULL;
- return WIMLIB_ERR_NOMEM;
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_unmount_to_daemon_mq_name;
}
- remove_trailing_slashes(ctx->unmount_to_daemon_mq_name);
- remove_trailing_slashes(ctx->daemon_to_unmount_mq_name);
- s_slashes_underscores_g(ctx->unmount_to_daemon_mq_name + 1);
- s_slashes_underscores_g(ctx->daemon_to_unmount_mq_name + 1);
- return 0;
+ ret = 0;
+ goto out_free_dir_path;
+out_free_unmount_to_daemon_mq_name:
+ FREE(ctx->unmount_to_daemon_mq_name);
+ ctx->unmount_to_daemon_mq_name = NULL;
+out_free_dir_path:
+ FREE(dir_path);
+ return ret;
}
static void free_message_queue_names(struct wimfs_context *ctx)
else
flags = O_WRONLY | O_CREAT;
+ DEBUG("Opening message queue \"%s\"", ctx->unmount_to_daemon_mq_name);
ctx->unmount_to_daemon_mq = mq_open(ctx->unmount_to_daemon_mq_name,
flags, 0700, NULL);
else
flags = O_RDONLY | O_CREAT;
+ DEBUG("Opening message queue \"%s\"", ctx->daemon_to_unmount_mq_name);
ctx->daemon_to_unmount_mq = mq_open(ctx->daemon_to_unmount_mq_name,
flags, 0700, NULL);
return 0;
}
+static int wimfs_chmod(const char *path, mode_t mask)
+{
+ struct dentry *dentry;
+ struct wimfs_context *ctx = wimfs_get_context();
+ struct inode *inode;
+ struct stat stbuf;
+ int ret;
+
+ ret = lookup_resource(ctx->wim, path,
+ get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
+ &dentry, NULL, NULL);
+ if (ret != 0)
+ return ret;
+ inode = dentry->d_inode;
+ inode_to_stbuf(inode, NULL, &stbuf);
+ if (mask == stbuf.st_mode)
+ return 0;
+ else
+ return -EPERM;
+
+}
+
static void inode_update_lte_ptr(struct inode *inode,
struct lookup_table_entry *old_lte,
struct lookup_table_entry *new_lte)
}
/* Overwrites the WIM file, with changes saved. */
-static int rebuild_wim(struct wimfs_context *ctx, bool check_integrity)
+static int rebuild_wim(struct wimfs_context *ctx, int write_flags)
{
int ret;
struct lookup_table_entry *lte, *tmp;
DEBUG("Closing all staging file descriptors.");
- list_for_each_entry(lte, &ctx->staging_list, staging_list) {
+ list_for_each_entry_safe(lte, tmp, &ctx->staging_list, staging_list) {
ret = inode_close_fds(lte->lte_inode);
if (ret != 0)
return ret;
xml_update_image_info(w, w->current_image);
- ret = wimlib_overwrite(w, check_integrity);
+ ret = wimlib_overwrite(w, write_flags, 0, NULL);
if (ret != 0) {
ERROR("Failed to commit changes");
return ret;
char status;
char *mailbox;
struct wimfs_context *ctx = wimfs_get_context();
+ int write_flags;
if (open_message_queues(ctx, true))
return;
status = 0;
if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
if (commit) {
- ret = chdir(ctx->working_directory);
- if (ret == 0) {
- status = rebuild_wim(ctx, (check_integrity != 0));
- } else {
- ERROR_WITH_ERRNO("chdir()");
- status = WIMLIB_ERR_NOTDIR;
- }
+ if (check_integrity)
+ write_flags = WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
+ else
+ write_flags = 0;
+ status = rebuild_wim(ctx, write_flags);
}
ret = delete_staging_dir(ctx);
if (ret != 0) {
struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
int ret = ftruncate(fd->staging_fd, size);
if (ret != 0)
- return ret;
+ return -errno;
if (fd->f_lte && size < fd->f_lte->resource_entry.original_size)
fd->f_lte->resource_entry.original_size = size;
return 0;
if (res_size > size)
return -ERANGE;
- ret = read_full_wim_resource(lte, (u8*)value);
+ ret = read_full_wim_resource(lte, (u8*)value,
+ WIMLIB_RESOURCE_FLAG_MULTITHREADED);
if (ret != 0)
return -EIO;
lte->refcnt++;
}
- link_dentry(from_dentry, from_dentry_parent);
+ dentry_add_child(from_dentry_parent, from_dentry);
return 0;
}
newdir->d_inode->attributes |= FILE_ATTRIBUTE_DIRECTORY;
newdir->d_inode->resolved = true;
newdir->d_inode->ino = ctx->next_ino++;
- link_dentry(newdir, parent);
+ dentry_add_child(parent, newdir);
return 0;
}
return -ENOMEM;
dentry->d_inode->resolved = true;
dentry->d_inode->ino = ctx->next_ino++;
- link_dentry(dentry, parent);
+ dentry_add_child(parent, dentry);
}
return 0;
}
return ret;
}
- ret = alloc_wimlib_fd(inode, stream_id, lte, &fd);
+ ret = alloc_wimlib_fd(inode, stream_id, lte, &fd,
+ wimfs_ctx_readonly(ctx));
if (ret != 0)
return ret;
int ret;
struct wimlib_fd *fd = NULL;
struct wimfs_context *ctx = wimfs_get_context();
+ WIMStruct *w = ctx->wim;
- inode = wim_pathname_to_inode(ctx->wim, path);
+ inode = wim_pathname_to_inode(w, path);
if (!inode)
return -ENOENT;
if (!inode_is_directory(inode))
return -ENOTDIR;
- ret = alloc_wimlib_fd(inode, 0, NULL, &fd);
+ ret = alloc_wimlib_fd(inode, 0, NULL, &fd, wimfs_ctx_readonly(ctx));
fi->fh = (uintptr_t)fd;
return ret;
}
} else {
/* Read from WIM */
+ wimlib_assert(fd->f_lte->resource_location == RESOURCE_IN_WIM);
+
u64 res_size = wim_resource_size(fd->f_lte);
if (offset > res_size)
size = min(size, res_size - offset);
if (read_wim_resource(fd->f_lte, (u8*)buf,
- size, offset, false) != 0)
+ size, offset,
+ WIMLIB_RESOURCE_FLAG_MULTITHREADED) != 0)
return -EIO;
return size;
}
}
+struct fill_params {
+ void *buf;
+ fuse_fill_dir_t filler;
+};
+
+static int dentry_fuse_fill(struct dentry *dentry, void *arg)
+{
+ struct fill_params *fill_params = arg;
+ return fill_params->filler(fill_params->buf, dentry->file_name_utf8,
+ NULL, 0);
+}
+
/* Fills in the entries of the directory specified by @path using the
* FUSE-provided function @filler. */
static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
{
struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
struct inode *inode;
- struct dentry *child;
if (!fd)
return -EBADF;
inode = fd->f_inode;
+ struct fill_params fill_params = {
+ .buf = buf,
+ .filler = filler,
+ };
+
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
- child = inode->children;
-
- if (!child)
- return 0;
-
- do {
- if (filler(buf, child->file_name_utf8, NULL, 0))
- return 0;
- child = child->next;
- } while (child != inode->children);
- return 0;
+ return for_dentry_in_rbtree(inode->children.rb_node,
+ dentry_fuse_fill, &fill_params);
}
if (!inode_is_symlink(inode))
return -EINVAL;
- ret = inode_readlink(inode, buf, buf_len, ctx->wim);
+ ret = inode_readlink(inode, buf, buf_len, ctx->wim,
+ WIMLIB_RESOURCE_FLAG_MULTITHREADED);
if (ret > 0)
ret = 0;
return ret;
* directory */
if (!dentry_is_directory(dst))
return -ENOTDIR;
- if (dst->d_inode->children != NULL)
+ if (inode_has_children(dst->d_inode))
return -ENOTEMPTY;
}
parent_of_dst = dst->parent;
src->file_name_utf8_len = file_name_utf8_len;
unlink_dentry(src);
- link_dentry(src, parent_of_dst);
+ dentry_add_child(parent_of_dst, src);
return 0;
}
if (inode_set_symlink(inode, to, ctx->wim->lookup_table, NULL) != 0)
goto out_free_dentry;
- link_dentry(dentry, dentry_parent);
+ dentry_add_child(dentry_parent, dentry);
return 0;
out_free_dentry:
free_dentry(dentry);
{
struct dentry *dentry;
struct inode *inode;
+ WIMStruct *w = wimfs_get_WIMStruct();
+
dentry = get_dentry(w, path);
if (!dentry)
return -ENOENT;
static struct fuse_operations wimfs_operations = {
.access = wimfs_access,
+ .chmod = wimfs_chmod,
.destroy = wimfs_destroy,
#if 0
.fallocate = wimfs_fallocate,
.utime = wimfs_utime,
#endif
.write = wimfs_write,
+
+#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
+ .flag_nullpath_ok = 1,
+#endif
+#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 9)
+ .flag_nopath = 1,
+ .flag_utime_omit_ok = 1,
+#endif
};
-/* Mounts a WIM file. */
-WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
- int flags, WIMStruct **additional_swms,
- unsigned num_additional_swms)
+/* Mounts an image from a WIM file. */
+WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
+ int mount_flags, WIMStruct **additional_swms,
+ unsigned num_additional_swms,
+ const char *staging_dir)
{
int argc = 0;
char *argv[16];
struct wimfs_context ctx;
DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
- wim, image, dir, flags);
+ wim, image, dir, mount_flags);
if (!wim || !dir)
return WIMLIB_ERR_INVALID_PARAM;
if (ret != 0)
return ret;
+ if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) && (wim->hdr.total_parts != 1)) {
+ ERROR("Cannot mount a split WIM read-write");
+ return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+ }
+
if (num_additional_swms) {
ret = new_joined_lookup_table(wim, additional_swms,
num_additional_swms,
wim->lookup_table = joined_tab;
}
+ if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
+ ret = wim_run_full_verifications(wim);
+ if (ret != 0)
+ goto out;
+ }
+
ret = select_wim_image(wim, image);
if (ret != 0)
if (imd->root_dentry->refcnt != 1) {
ERROR("Cannot mount image that was just exported with "
- "wimlib_export()");
+ "wimlib_export_image()");
+ ret = WIMLIB_ERR_INVALID_PARAM;
+ goto out;
+ }
+
+ if (imd->modified) {
+ ERROR("Cannot mount image that was added "
+ "with wimlib_add_image()");
ret = WIMLIB_ERR_INVALID_PARAM;
goto out;
}
- if (!(flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
+ if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
+ ret = lock_wim(wim->fp, wim->filename);
+ if (ret != 0)
+ goto out;
+ }
+
+ if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
- flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
+ mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
DEBUG("Initializing struct wimfs_context");
init_wimfs_context(&ctx);
-
- DEBUG("Getting current directory");
- ctx.working_directory = getcwd(NULL, 0);
- if (!ctx.working_directory) {
- ERROR_WITH_ERRNO("Could not determine current directory");
- ret = WIMLIB_ERR_NOTDIR;
- goto out;
- }
+ ctx.wim = wim;
+ ctx.mount_flags = mount_flags;
DEBUG("Unlinking message queues in case they already exist");
ret = set_message_queue_names(&ctx, dir);
if (ret != 0)
- goto out_free_working_directory;
+ goto out;
unlink_message_queues(&ctx);
DEBUG("Preparing arguments to fuse_main()");
argv[argc++] = "imagex";
argv[argc++] = dir_copy;
- argv[argc++] = "-s"; /* disable multi-threaded operation */
- if (flags & WIMLIB_MOUNT_FLAG_DEBUG)
+ /* disable multi-threaded operation for read-write mounts */
+ if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
+ argv[argc++] = "-s";
+
+ if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
argv[argc++] = "-d";
/*
char optstring[256] = "use_ino,subtype=wimfs,attr_timeout=0";
argv[argc++] = "-o";
argv[argc++] = optstring;
- if ((flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
+ if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
/* Read-write mount. Make the staging directory */
- ret = make_staging_dir(&ctx);
+ ret = make_staging_dir(&ctx, staging_dir);
if (ret != 0)
goto out_free_dir_copy;
} else {
#endif
/* Mark dentry tree as modified if read-write mount. */
- if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
- imd->modified = true;
+ if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
+ imd->modified = 1;
+ imd->has_been_mounted_rw = 1;
+ }
/* Resolve all the lookup table entries of the dentry tree */
DEBUG("Resolving lookup table entries");
ctx.next_ino = assign_inode_numbers(&imd->inode_list);
DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
- /* Finish initializing the filesystem context. */
- ctx.wim = wim;
- ctx.mount_flags = flags;
+
+ DEBUG("Calling fuse_main()");
ret = fuse_main(argc, argv, &wimfs_operations, &ctx);
+
+ DEBUG("Returned from fuse_main() (ret = %d)", ret);
if (ret)
ret = WIMLIB_ERR_FUSE;
out_free_dir_copy:
FREE(dir_copy);
out_free_message_queue_names:
free_message_queue_names(&ctx);
-out_free_working_directory:
- FREE(ctx.working_directory);
- ctx.working_directory = NULL;
out:
if (num_additional_swms) {
free_lookup_table(wim->lookup_table);
/*
* Unmounts the WIM file that was previously mounted on @dir by using
- * wimlib_mount().
+ * wimlib_mount_image().
*/
-WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
+WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
+ wimlib_progress_func_t progress_func)
{
pid_t pid;
int status;
/* Send a message to the filesystem daemon saying whether to commit or
* not. */
- msg[0] = (flags & WIMLIB_UNMOUNT_FLAG_COMMIT) ? 1 : 0;
- msg[1] = (flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY) ? 1 : 0;
+ msg[0] = (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) ? 1 : 0;
+ msg[1] = (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY) ? 1 : 0;
DEBUG("Sending message: %scommit, %scheck",
(msg[0] ? "" : "don't "),
return WIMLIB_ERR_UNSUPPORTED;
}
-WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
+WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
+ wimlib_progress_func_t progress_func)
{
return mount_unsupported_error();
}
-WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir,
- int flags, WIMStruct **additional_swms,
- unsigned num_additional_swms)
+WIMLIBAPI int wimlib_mount_image(WIMStruct *wim_p, int image, const char *dir,
+ int mount_flags, WIMStruct **additional_swms,
+ unsigned num_additional_swms,
+ const char *staging_dir)
{
return mount_unsupported_error();
}