]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
Update version to 1.4.2
[wimlib] / src / mount_image.c
index b00a2a686c28bcb7cebb67f97f4d18d562bb8187..f1baebba1338516e788d5edc00b539aa1ffa4723 100644 (file)
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
-#include "wimlib_internal.h"
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "wimlib.h"
+#include "wimlib/error.h"
 
 #ifdef WITH_FUSE
 
 #  error "FUSE mount not supported on Win32!  Please configure --without-fuse"
 #endif
 
-#include "buffer_io.h"
-#include "lookup_table.h"
-#include "sha1.h"
-#include "timestamp.h"
-#include "xml.h"
+#include "wimlib/encoding.h"
+#include "wimlib/file_io.h"
+#include "wimlib/lookup_table.h"
+#include "wimlib/metadata.h"
+#include "wimlib/paths.h"
+#include "wimlib/reparse.h"
+#include "wimlib/resource.h"
+#include "wimlib/swm.h"
+#include "wimlib/timestamp.h"
+#include "wimlib/version.h"
+#include "wimlib/write.h"
+#include "wimlib/xml.h"
 
 #include <errno.h>
 #include <ftw.h>
@@ -130,13 +142,13 @@ init_wimfs_context(struct wimfs_context *ctx)
 #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
 
 static inline struct wimfs_context *
-wimfs_get_context()
+wimfs_get_context(void)
 {
        return WIMFS_CTX(fuse_get_context());
 }
 
 static inline WIMStruct *
-wimfs_get_WIMStruct()
+wimfs_get_WIMStruct(void)
 {
        return wimfs_get_context()->wim;
 }
@@ -160,54 +172,6 @@ flags_writable(int open_flags)
        return open_flags & (O_RDWR | O_WRONLY);
 }
 
-/* Like pread(), but keep trying until everything has been read or we know for
- * sure that there was an error. */
-static ssize_t
-full_pread(int fd, void *buf, size_t count, off_t offset)
-{
-       ssize_t bytes_remaining = count;
-       ssize_t bytes_read;
-
-       while (bytes_remaining > 0) {
-               bytes_read = pread(fd, buf, bytes_remaining, offset);
-               if (bytes_read <= 0) {
-                       if (bytes_read < 0) {
-                               if (errno == EINTR)
-                                       continue;
-                       } else {
-                               errno = EIO;
-                       }
-                       break;
-               }
-               bytes_remaining -= bytes_read;
-               buf += bytes_read;
-               offset += bytes_read;
-       }
-       return count - bytes_remaining;
-}
-
-/* Like pwrite(), but keep trying until everything has been written or we know
- * for sure that there was an error. */
-static ssize_t
-full_pwrite(int fd, const void *buf, size_t count, off_t offset)
-{
-       ssize_t bytes_remaining = count;
-       ssize_t bytes_written;
-
-       while (bytes_remaining > 0) {
-               bytes_written = pwrite(fd, buf, bytes_remaining, offset);
-               if (bytes_written < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       break;
-               }
-               bytes_remaining -= bytes_written;
-               buf += bytes_written;
-               offset += bytes_written;
-       }
-       return count - bytes_remaining;
-}
-
 /*
  * Allocate a file descriptor for a stream.
  *
@@ -230,8 +194,6 @@ alloc_wimfs_fd(struct wim_inode *inode,
        static const u16 max_fds = 0xffff;
        int ret;
 
-       pthread_mutex_lock(&inode->i_mutex);
-
        DEBUG("Allocating fd for stream ID %u from inode %#"PRIx64" "
              "(open = %u, allocated = %u)",
              stream_id, inode->i_ino, inode->i_num_opened_fds,
@@ -283,7 +245,6 @@ alloc_wimfs_fd(struct wim_inode *inode,
                }
        }
 out:
-       pthread_mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
@@ -291,9 +252,6 @@ static void
 inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
 {
        wimlib_assert(inode != NULL);
-
-       pthread_mutex_lock(&inode->i_mutex);
-
        wimlib_assert(fd->f_inode == inode);
        wimlib_assert(inode->i_num_opened_fds != 0);
        wimlib_assert(fd->idx < inode->i_num_allocated_fds);
@@ -301,11 +259,12 @@ inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
 
        inode->i_fds[fd->idx] = NULL;
        FREE(fd);
-       if (--inode->i_num_opened_fds == 0 && inode->i_nlink == 0) {
-               pthread_mutex_unlock(&inode->i_mutex);
-               free_inode(inode);
-       } else {
-               pthread_mutex_unlock(&inode->i_mutex);
+       if (--inode->i_num_opened_fds == 0) {
+               FREE(inode->i_fds);
+               inode->i_fds = NULL;
+               inode->i_num_allocated_fds = 0;
+               if (inode->i_nlink == 0)
+                       free_inode(inode);
        }
 }
 
@@ -347,6 +306,15 @@ close_wimfs_fd(struct wimfs_fd *fd)
        return 0;
 }
 
+static mode_t
+fuse_mask_mode(mode_t mode, struct fuse_context *fuse_ctx)
+{
+#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
+       mode &= ~fuse_ctx->umask;
+#endif
+       return mode;
+}
+
 /*
  * Add a new dentry with a new inode to a WIM image.
  *
@@ -385,7 +353,7 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
                if (inode_set_unix_data(new->d_inode,
                                        fuse_ctx->uid,
                                        fuse_ctx->gid,
-                                       mode & ~fuse_ctx->umask,
+                                       fuse_mask_mode(mode, fuse_ctx),
                                        wimfs_ctx->wim->lookup_table,
                                        UNIX_DATA_ALL | UNIX_DATA_CREATE))
                {
@@ -839,7 +807,7 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
 {
        int ret;
        struct wim_lookup_table_entry *lte, *tmp;
-       WIMStruct *w = ctx->wim;
+       WIMStruct *wim = ctx->wim;
        struct wim_image_metadata *imd = wim_get_current_image_metadata(ctx->wim);
 
        DEBUG("Closing all staging file descriptors.");
@@ -861,8 +829,8 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
                }
        }
 
-       xml_update_image_info(w, w->current_image);
-       ret = wimlib_overwrite(w, write_flags, 0, progress_func);
+       xml_update_image_info(wim, wim->current_image);
+       ret = wimlib_overwrite(wim, write_flags, 0, progress_func);
        if (ret)
                ERROR("Failed to commit changes to mounted WIM image");
        return ret;
@@ -1073,29 +1041,29 @@ struct unmount_msg_hdr {
        u32 cur_version;
        u32 msg_type;
        u32 msg_size;
-} PACKED;
+} _packed_attribute;
 
 struct msg_unmount_request {
        struct unmount_msg_hdr hdr;
        u32 unmount_flags;
        u8 want_progress_messages;
-} PACKED;
+} _packed_attribute;
 
 struct msg_daemon_info {
        struct unmount_msg_hdr hdr;
        pid_t daemon_pid;
        u32 mount_flags;
-} PACKED;
+} _packed_attribute;
 
 struct msg_unmount_finished {
        struct unmount_msg_hdr hdr;
-       int32_t status;
-} PACKED;
+       s32 status;
+} _packed_attribute;
 
 struct msg_write_streams_progress {
        struct unmount_msg_hdr hdr;
        union wimlib_progress_info info;
-} PACKED;
+} _packed_attribute;
 
 enum {
        MSG_TYPE_UNMOUNT_REQUEST,
@@ -1471,7 +1439,7 @@ message_loop(mqd_t mq,
  *  daemon to finish writing the WIM file.
  */
 static int
-execute_fusermount(const char *dir)
+execute_fusermount(const char *dir, bool lazy)
 {
        pid_t pid;
        int ret;
@@ -1484,7 +1452,15 @@ execute_fusermount(const char *dir)
        }
        if (pid == 0) {
                /* Child */
-               execlp("fusermount", "fusermount", "-u", dir, NULL);
+               char *argv[10];
+               char **argp = argv;
+               *argp++ = "fusermount";
+               if (lazy)
+                       *argp++ = "-z";
+               *argp++ = "-u";
+               *argp++ = (char*)dir;
+               *argp = NULL;
+               execvp("fusermount", argv);
                ERROR_WITH_ERRNO("Failed to execute `fusermount'");
                exit(WIMLIB_ERR_FUSERMOUNT);
        }
@@ -1522,7 +1498,14 @@ execute_fusermount(const char *dir)
        }
        if (pid == 0) {
                /* Child */
-               execlp("umount", "umount", dir, NULL);
+               char *argv[10];
+               char **argp = argv;
+               *argp++ = "umount";
+               if (lazy)
+                       *argp++ = "-l";
+               *argp++ = (char*)dir;
+               *argp = NULL;
+               execvp("umount", argv);
                ERROR_WITH_ERRNO("Failed to execute `umount'");
                exit(WIMLIB_ERR_FUSERMOUNT);
        }
@@ -1678,8 +1661,8 @@ wimfs_getxattr(const char *path, const char *name, char *value,
        if (res_size > size)
                return -ERANGE;
 
-       ret = read_full_resource_into_buf(lte, value, true);
-       if (ret != 0)
+       ret = read_full_resource_into_buf(lte, value);
+       if (ret)
                return -EIO;
 
        return res_size;
@@ -1693,10 +1676,10 @@ wimfs_link(const char *to, const char *from)
        struct wim_dentry *from_dentry, *from_dentry_parent;
        const char *link_name;
        struct wim_inode *inode;
-       WIMStruct *w = wimfs_get_WIMStruct();
+       WIMStruct *wim = wimfs_get_WIMStruct();
        int ret;
 
-       inode = wim_pathname_to_inode(w, to);
+       inode = wim_pathname_to_inode(wim, to);
        if (!inode)
                return -errno;
 
@@ -1704,7 +1687,7 @@ wimfs_link(const char *to, const char *from)
                                   FILE_ATTRIBUTE_REPARSE_POINT))
                return -EPERM;
 
-       from_dentry_parent = get_parent_dentry(w, from);
+       from_dentry_parent = get_parent_dentry(wim, from);
        if (!from_dentry_parent)
                return -errno;
        if (!dentry_is_directory(from_dentry_parent))
@@ -1894,9 +1877,9 @@ wimfs_opendir(const char *path, struct fuse_file_info *fi)
        int ret;
        struct wimfs_fd *fd = NULL;
        struct wimfs_context *ctx = wimfs_get_context();
-       WIMStruct *w = ctx->wim;
+       WIMStruct *wim = ctx->wim;
 
-       inode = wim_pathname_to_inode(w, path);
+       inode = wim_pathname_to_inode(wim, path);
        if (!inode)
                return -errno;
        if (!inode_is_directory(inode))
@@ -1944,7 +1927,7 @@ wimfs_read(const char *path, char *buf, size_t size,
                break;
        case RESOURCE_IN_WIM:
                if (read_partial_wim_resource_into_buf(fd->f_lte, size,
-                                                      offset, buf, true))
+                                                      offset, buf))
                        ret = -errno;
                else
                        ret = size;
@@ -2026,7 +2009,7 @@ wimfs_readlink(const char *path, char *buf, size_t buf_len)
                return -EINVAL;
        if (buf_len == 0)
                return -ENAMETOOLONG;
-       ret = inode_readlink(inode, buf, buf_len - 1, ctx->wim, true);
+       ret = wim_inode_readlink(inode, buf, buf_len - 1);
        if (ret >= 0) {
                wimlib_assert(ret <= buf_len - 1);
                buf[ret] = '\0';
@@ -2086,58 +2069,7 @@ wimfs_removexattr(const char *path, const char *name)
 static int
 wimfs_rename(const char *from, const char *to)
 {
-       struct wim_dentry *src;
-       struct wim_dentry *dst;
-       struct wim_dentry *parent_of_dst;
-       WIMStruct *w = wimfs_get_WIMStruct();
-       int ret;
-
-       /* This rename() implementation currently only supports actual files
-        * (not alternate data streams) */
-
-       src = get_dentry(w, from);
-       if (!src)
-               return -errno;
-
-       dst = get_dentry(w, to);
-
-       if (dst) {
-               /* Destination file exists */
-
-               if (src == dst) /* Same file */
-                       return 0;
-
-               if (!dentry_is_directory(src)) {
-                       /* Cannot rename non-directory to directory. */
-                       if (dentry_is_directory(dst))
-                               return -EISDIR;
-               } else {
-                       /* Cannot rename directory to a non-directory or a non-empty
-                        * directory */
-                       if (!dentry_is_directory(dst))
-                               return -ENOTDIR;
-                       if (inode_has_children(dst->d_inode))
-                               return -ENOTEMPTY;
-               }
-               parent_of_dst = dst->parent;
-       } else {
-               /* Destination does not exist */
-               parent_of_dst = get_parent_dentry(w, to);
-               if (!parent_of_dst)
-                       return -errno;
-
-               if (!dentry_is_directory(parent_of_dst))
-                       return -ENOTDIR;
-       }
-
-       ret = set_dentry_name(src, path_basename(to));
-       if (ret != 0)
-               return -ENOMEM;
-       if (dst)
-               remove_dentry(dst, w->lookup_table);
-       unlink_dentry(src);
-       dentry_add_child(parent_of_dst, src);
-       return 0;
+       return rename_wim_path(wimfs_get_WIMStruct(), from, to);
 }
 
 /* Remove a directory */
@@ -2145,9 +2077,9 @@ static int
 wimfs_rmdir(const char *path)
 {
        struct wim_dentry *dentry;
-       WIMStruct *w = wimfs_get_WIMStruct();
+       WIMStruct *wim = wimfs_get_WIMStruct();
 
-       dentry = get_dentry(w, path);
+       dentry = get_dentry(wim, path);
        if (!dentry)
                return -errno;
 
@@ -2157,7 +2089,7 @@ wimfs_rmdir(const char *path)
        if (dentry_has_children(dentry))
                return -ENOTEMPTY;
 
-       remove_dentry(dentry, w->lookup_table);
+       remove_dentry(dentry, wim->lookup_table);
        return 0;
 }
 
@@ -2217,11 +2149,14 @@ wimfs_symlink(const char *to, const char *from)
                            FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
        if (ret == 0) {
                dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
-               if (inode_set_symlink(dentry->d_inode, to,
-                                     wimfs_ctx->wim->lookup_table, NULL))
-               {
+               ret = wim_inode_set_symlink(dentry->d_inode, to,
+                                           wimfs_ctx->wim->lookup_table);
+               if (ret) {
                        remove_dentry(dentry, wimfs_ctx->wim->lookup_table);
-                       ret = -ENOMEM;
+                       if (ret == WIMLIB_ERR_NOMEM)
+                               ret = -ENOMEM;
+                       else
+                               ret = -EIO;
                }
        }
        return ret;
@@ -2310,9 +2245,9 @@ wimfs_utimens(const char *path, const struct timespec tv[2])
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
-       WIMStruct *w = wimfs_get_WIMStruct();
+       WIMStruct *wim = wimfs_get_WIMStruct();
 
-       dentry = get_dentry(w, path);
+       dentry = get_dentry(wim, path);
        if (!dentry)
                return -errno;
        inode = dentry->d_inode;
@@ -2337,9 +2272,9 @@ wimfs_utime(const char *path, struct utimbuf *times)
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
-       WIMStruct *w = wimfs_get_WIMStruct();
+       WIMStruct *wim = wimfs_get_WIMStruct();
 
-       dentry = get_dentry(w, path);
+       dentry = get_dentry(wim, path);
        if (!dentry)
                return -errno;
        inode = dentry->d_inode;
@@ -2451,7 +2386,6 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        char *argv[16];
        int ret;
        char *dir_copy;
-       struct wim_lookup_table *joined_tab, *wim_tab_save;
        struct wim_image_metadata *imd;
        struct wimfs_context ctx;
        struct wim_inode *inode;
@@ -2459,41 +2393,27 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
              wim, image, dir, mount_flags);
 
-       if (!wim || !dir)
-               return WIMLIB_ERR_INVALID_PARAM;
+       if (!wim || !dir) {
+               ret = WIMLIB_ERR_INVALID_PARAM;
+               goto out;
+       }
 
        ret = verify_swm_set(wim, additional_swms, num_additional_swms);
        if (ret)
-               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,
-                                             &joined_tab);
-               if (ret)
-                       return ret;
-               wim_tab_save = wim->lookup_table;
-               wim->lookup_table = joined_tab;
-       }
+               goto out;
 
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
-               ret = wim_run_full_verifications(wim);
+               ret = can_delete_from_wim(wim);
                if (ret)
                        goto out;
        }
 
-       ret = wim_checksum_unhashed_streams(wim);
-       if (ret)
-               goto out;
+       if (num_additional_swms)
+               merge_lookup_tables(wim, additional_swms, num_additional_swms);
 
        ret = select_wim_image(wim, image);
        if (ret)
-               goto out;
+               goto out_restore_lookup_table;
 
        DEBUG("Selected image %d", image);
 
@@ -2503,20 +2423,20 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
                ERROR("Cannot mount image that was just exported with "
                      "wimlib_export_image()");
                ret = WIMLIB_ERR_INVALID_PARAM;
-               goto out;
+               goto out_restore_lookup_table;
        }
 
        if (imd->modified) {
                ERROR("Cannot mount image that was added "
                      "with wimlib_add_image()");
                ret = WIMLIB_ERR_INVALID_PARAM;
-               goto out;
+               goto out_restore_lookup_table;
        }
 
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
-               ret = lock_wim(wim, wim->fp);
+               ret = lock_wim(wim, wim->in_fd);
                if (ret)
-                       goto out;
+                       goto out_restore_lookup_table;
        }
 
        /* Use default stream interface if one was not specified */
@@ -2550,12 +2470,11 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
                goto out_free_message_queue_names;
 
        argc = 0;
-       argv[argc++] = "imagex";
+       argv[argc++] = IMAGEX_PROGNAME;
        argv[argc++] = dir_copy;
 
-       /* disable multi-threaded operation for read-write mounts */
-       if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
-               argv[argc++] = "-s";
+       /* disable multi-threaded operation */
+       argv[argc++] = "-s";
 
        if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
                argv[argc++] = "-d";
@@ -2608,10 +2527,8 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
         * assign inode numbers */
        DEBUG("Resolving lookup table entries and assigning inode numbers");
        ctx.next_ino = 1;
-       image_for_each_inode(inode, imd) {
-               inode_resolve_ltes(inode, wim->lookup_table);
+       image_for_each_inode(inode, imd)
                inode->i_ino = ctx.next_ino++;
-       }
        DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
 
        DEBUG("Calling fuse_main()");
@@ -2643,11 +2560,10 @@ out_unlock:
        wim->wim_locked = 0;
 out_free_message_queue_names:
        free_message_queue_names(&ctx);
+out_restore_lookup_table:
+       if (num_additional_swms)
+               unmerge_lookup_table(wim);
 out:
-       if (num_additional_swms) {
-               free_lookup_table(wim->lookup_table);
-               wim->lookup_table = wim_tab_save;
-       }
        return ret;
 }
 
@@ -2678,7 +2594,7 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
        if (ret != 0)
                goto out_close_message_queues;
 
-       ret = execute_fusermount(dir);
+       ret = execute_fusermount(dir, (unmount_flags & WIMLIB_UNMOUNT_FLAG_LAZY) != 0);
        if (ret != 0)
                goto out_close_message_queues;
 
@@ -2707,7 +2623,7 @@ out:
 
 
 static int
-mount_unsupported_error()
+mount_unsupported_error(void)
 {
 #if defined(__WIN32__)
        ERROR("Sorry-- Mounting WIM images is not supported on Windows!");