]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
do_apply_dentry_ntfs(): Adjust inode closing
[wimlib] / src / mount_image.c
index 6a38dc33e8cabbfb7b0dce837052a18bc28650a9..090a828026e95e197180cf96bd8f4513125a9208 100644 (file)
@@ -291,7 +291,7 @@ static int create_dentry(struct wimfs_context *ctx, const char *path,
 
        new = new_dentry_with_inode(basename);
        if (!new)
-               return -ENOMEM;
+               return -errno;
 
        new->d_inode->resolved = 1;
        new->d_inode->ino = ctx->next_ino++;
@@ -1016,19 +1016,21 @@ enum {
        MSG_TYPE_MAX,
 };
 
-struct msg_handler_context {
+struct msg_handler_context_hdr {
        int timeout_seconds;
-       union {
-               struct {
-                       pid_t daemon_pid;
-                       int mount_flags;
-                       int status;
-                       wimlib_progress_func_t progress_func;
-               } unmount;
-               struct {
-                       struct wimfs_context *wimfs_ctx;
-               } daemon;
-       };
+};
+
+struct unmount_msg_handler_context {
+       struct msg_handler_context_hdr hdr;
+       pid_t daemon_pid;
+       int mount_flags;
+       int status;
+       wimlib_progress_func_t progress_func;
+};
+
+struct daemon_msg_handler_context {
+       struct msg_handler_context_hdr hdr;
+       struct wimfs_context *wimfs_ctx;
 };
 
 static int send_unmount_request_msg(mqd_t mq, int unmount_flags,
@@ -1037,7 +1039,7 @@ static int send_unmount_request_msg(mqd_t mq, int unmount_flags,
        DEBUG("Sending unmount request msg");
        struct msg_unmount_request msg = {
                .hdr = {
-                       .min_version = WIMLIB_MAKEVERSION(1, 2, 0),
+                       .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
                        .cur_version = WIMLIB_VERSION_CODE,
                        .msg_type    = MSG_TYPE_UNMOUNT_REQUEST,
                        .msg_size    = sizeof(msg),
@@ -1060,7 +1062,7 @@ static int send_daemon_info_msg(mqd_t mq, pid_t pid, int mount_flags)
 
        struct msg_daemon_info msg = {
                .hdr = {
-                       .min_version = WIMLIB_MAKEVERSION(1, 2, 0),
+                       .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
                        .cur_version = WIMLIB_VERSION_CODE,
                        .msg_type = MSG_TYPE_DAEMON_INFO,
                        .msg_size = sizeof(msg),
@@ -1080,7 +1082,7 @@ static void send_unmount_finished_msg(mqd_t mq, int status)
        DEBUG("Sending unmount finished msg");
        struct msg_unmount_finished msg = {
                .hdr = {
-                       .min_version = WIMLIB_MAKEVERSION(1, 2, 0),
+                       .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
                        .cur_version = WIMLIB_VERSION_CODE,
                        .msg_type = MSG_TYPE_UNMOUNT_FINISHED,
                        .msg_size = sizeof(msg),
@@ -1097,7 +1099,7 @@ static int unmount_progress_func(enum wimlib_progress_msg msg,
        if (msg == WIMLIB_PROGRESS_MSG_WRITE_STREAMS) {
                struct msg_write_streams_progress msg = {
                        .hdr = {
-                               .min_version = WIMLIB_MAKEVERSION(1, 2, 0),
+                               .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
                                .cur_version = WIMLIB_VERSION_CODE,
                                .msg_type = MSG_TYPE_WRITE_STREAMS_PROGRESS,
                                .msg_size = sizeof(msg),
@@ -1114,10 +1116,10 @@ static int unmount_progress_func(enum wimlib_progress_msg msg,
        return 0;
 }
 
-static int msg_unmount_request_handler(const void *_msg,
-                                      struct msg_handler_context *handler_ctx)
+static int msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
 {
-       const struct msg_unmount_request *msg;
+       const struct msg_unmount_request *msg = _msg;
+       struct daemon_msg_handler_context *handler_ctx = _handler_ctx;
        struct wimfs_context *wimfs_ctx;
        int status = 0;
        int ret;
@@ -1126,9 +1128,7 @@ static int msg_unmount_request_handler(const void *_msg,
 
        DEBUG("Handling unmount request msg");
 
-       msg = _msg;
-       wimfs_ctx = handler_ctx->daemon.wimfs_ctx;
-
+       wimfs_ctx = handler_ctx->wimfs_ctx;
        if (msg->hdr.msg_size < sizeof(*msg)) {
                status = WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
                goto out;
@@ -1177,59 +1177,65 @@ out:
        return MSG_BREAK_LOOP;
 }
 
-static int msg_daemon_info_handler(const void *_msg,
-                                  struct msg_handler_context *handler_ctx)
+static int msg_daemon_info_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_daemon_info *msg = _msg;
+       struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
+
        DEBUG("Handling daemon info msg");
        if (msg->hdr.msg_size < sizeof(*msg))
                return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
-       handler_ctx->unmount.daemon_pid = msg->daemon_pid;
-       handler_ctx->unmount.mount_flags = msg->mount_flags;
-       handler_ctx->timeout_seconds = 1;
+       handler_ctx->daemon_pid = msg->daemon_pid;
+       handler_ctx->mount_flags = msg->mount_flags;
+       handler_ctx->hdr.timeout_seconds = 1;
        DEBUG("pid of daemon is %d; mount flags were %#x",
-             handler_ctx->unmount.daemon_pid,
-             handler_ctx->unmount.mount_flags);
+             handler_ctx->daemon_pid,
+             handler_ctx->mount_flags);
        return 0;
 }
 
 static int msg_write_streams_progress_handler(const void *_msg,
-                                             struct msg_handler_context *handler_ctx)
+                                             void *_handler_ctx)
 {
        const struct msg_write_streams_progress *msg = _msg;
+       struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
+
        if (msg->hdr.msg_size < sizeof(*msg))
                return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
-       if (handler_ctx->unmount.progress_func) {
-               handler_ctx->unmount.progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
-                                                  &msg->info);
+       if (handler_ctx->progress_func) {
+               handler_ctx->progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                                          &msg->info);
        }
        return 0;
 }
 
-static int msg_unmount_finished_handler(const void *_msg,
-                                       struct msg_handler_context *handler_ctx)
+static int msg_unmount_finished_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_unmount_finished *msg = _msg;
+       struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
+
        DEBUG("Handling unmount finished message");
        if (msg->hdr.msg_size < sizeof(*msg))
                return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
-       handler_ctx->unmount.status = msg->status;
-       DEBUG("status is %d", handler_ctx->unmount.status);
+       handler_ctx->status = msg->status;
+       DEBUG("status is %d", handler_ctx->status);
        return MSG_BREAK_LOOP;
 }
 
-static int unmount_timed_out_cb(struct msg_handler_context *handler_ctx)
+static int unmount_timed_out_cb(void *_handler_ctx)
 {
-       if (handler_ctx->unmount.daemon_pid == 0) {
+       struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
+
+       if (handler_ctx->daemon_pid == 0) {
                goto out_crashed;
        } else {
-               kill(handler_ctx->unmount.daemon_pid, 0);
+               kill(handler_ctx->daemon_pid, 0);
                if (errno == ESRCH) {
                        goto out_crashed;
                } else {
                        DEBUG("Filesystem daemon is still alive... "
                              "Waiting another %d seconds\n",
-                             handler_ctx->timeout_seconds);
+                             handler_ctx->hdr.timeout_seconds);
                        return 0;
                }
        }
@@ -1239,18 +1245,17 @@ out_crashed:
        return WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED;
 }
 
-static int daemon_timed_out_cb(struct msg_handler_context *handler_ctx)
+static int daemon_timed_out_cb(void *_handler_ctx)
 {
        ERROR("Timed out waiting for unmount request! "
              "Changes to the mounted WIM will not be committed.");
        return WIMLIB_ERR_TIMEOUT;
 }
 
-typedef int (*msg_handler_t)(const void *_msg,
-                            struct msg_handler_context *handler_ctx);
+typedef int (*msg_handler_t)(const void *_msg, void *_handler_ctx);
 
 struct msg_handler_callbacks {
-       int (*timed_out)(struct msg_handler_context *);
+       int (*timed_out)(void * _handler_ctx);
        msg_handler_t msg_handlers[MSG_TYPE_MAX];
 };
 
@@ -1270,7 +1275,8 @@ static const struct msg_handler_callbacks daemon_msg_handler_callbacks = {
        },
 };
 
-static int receive_message(mqd_t mq, struct msg_handler_context *handler_ctx,
+static int receive_message(mqd_t mq,
+                          struct msg_handler_context_hdr *handler_ctx,
                           const msg_handler_t msg_handlers[],
                           long mailbox_size, void *mailbox)
 {
@@ -1316,7 +1322,7 @@ static int receive_message(mqd_t mq, struct msg_handler_context *handler_ctx,
 
 static int message_loop(mqd_t mq,
                        const struct msg_handler_callbacks *callbacks,
-                       struct msg_handler_context *handler_ctx)
+                       struct msg_handler_context_hdr *handler_ctx)
 {
        static const size_t MAX_MSG_SIZE = 512;
        long msgsize;
@@ -1383,46 +1389,53 @@ static int execute_fusermount(const char *dir)
        }
 
        /* Parent */
-       ret = wait(&status);
+       ret = waitpid(pid, &status, 0);
        if (ret == -1) {
                ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
                                 "terminate");
                return WIMLIB_ERR_FUSERMOUNT;
        }
 
-       if (status != 0) {
-               if (status == WIMLIB_ERR_FUSERMOUNT)
-                       ERROR("Could not find the `fusermount' program");
-               else
-                       ERROR("fusermount exited with status %d", status);
+       if (!WIFEXITED(status)) {
+               ERROR("'fusermount' did not terminate normally!");
+               return WIMLIB_ERR_FUSERMOUNT;
+       }
 
-               /* Try again, but with the `umount' program.  This is required
-                * on other FUSE implementations such as FreeBSD's that do not
-                * have a `fusermount' program. */
+       status = WEXITSTATUS(status);
 
-               pid = fork();
-               if (pid == -1) {
-                       ERROR_WITH_ERRNO("Failed to fork()");
-                       return WIMLIB_ERR_FORK;
-               }
-               if (pid == 0) {
-                       /* Child */
-                       execlp("umount", "umount", dir, NULL);
-                       ERROR_WITH_ERRNO("Failed to execute `umount'");
-                       exit(WIMLIB_ERR_FUSERMOUNT);
-               }
+       if (status == 0)
+               return 0;
 
-               /* Parent */
-               ret = wait(&status);
-               if (ret == -1) {
-                       ERROR_WITH_ERRNO("Failed to wait for `umount' process to "
-                                        "terminate");
-                       return WIMLIB_ERR_FUSERMOUNT;
-               }
-               if (status != 0) {
-                       ERROR("`umount' exited with failure status");
-                       return WIMLIB_ERR_FUSERMOUNT;
-               }
+       if (status != WIMLIB_ERR_FUSERMOUNT)
+               return WIMLIB_ERR_FUSERMOUNT;
+
+       /* Try again, but with the `umount' program.  This is required on other
+        * FUSE implementations such as FreeBSD's that do not have a
+        * `fusermount' program. */
+       ERROR("Falling back to 'umount'.  Note: you may need to be "
+             "root for this to work");
+       pid = fork();
+       if (pid == -1) {
+               ERROR_WITH_ERRNO("Failed to fork()");
+               return WIMLIB_ERR_FORK;
+       }
+       if (pid == 0) {
+               /* Child */
+               execlp("umount", "umount", dir, NULL);
+               ERROR_WITH_ERRNO("Failed to execute `umount'");
+               exit(WIMLIB_ERR_FUSERMOUNT);
+       }
+
+       /* Parent */
+       ret = waitpid(pid, &status, 0);
+       if (ret == -1) {
+               ERROR_WITH_ERRNO("Failed to wait for `umount' process to "
+                                "terminate");
+               return WIMLIB_ERR_FUSERMOUNT;
+       }
+       if (status != 0) {
+               ERROR("`umount' did not successfully complete");
+               return WIMLIB_ERR_FUSERMOUNT;
        }
        return 0;
 }
@@ -1459,15 +1472,15 @@ static void wimfs_destroy(void *p)
 {
        struct wimfs_context *wimfs_ctx = wimfs_get_context();
        if (open_message_queues(wimfs_ctx, true) == 0) {
-               struct msg_handler_context handler_ctx = {
-                       .timeout_seconds = 5,
-                       .daemon = {
-                               .wimfs_ctx = wimfs_ctx,
+               struct daemon_msg_handler_context handler_ctx = {
+                       .hdr = {
+                               .timeout_seconds = 5,
                        },
+                       .wimfs_ctx = wimfs_ctx,
                };
                message_loop(wimfs_ctx->unmount_to_daemon_mq,
                             &daemon_msg_handler_callbacks,
-                            &handler_ctx);
+                            &handler_ctx.hdr);
                close_message_queues(wimfs_ctx);
        }
 }
@@ -1596,7 +1609,7 @@ static int wimfs_link(const char *to, const char *from)
                return -EEXIST;
        from_dentry = new_dentry(link_name);
        if (!from_dentry)
-               return -ENOMEM;
+               return -errno;
 
        inode_add_dentry(from_dentry, inode);
        from_dentry->d_inode = inode;
@@ -2357,6 +2370,9 @@ WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
                goto out;
        }
 
+       if (imd->inode_list.first)
+               imd->inode_list.first->pprev = &imd->inode_list.first;
+
        if (imd->modified) {
                ERROR("Cannot mount image that was added "
                      "with wimlib_add_image()");
@@ -2516,19 +2532,19 @@ WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
        if (ret != 0)
                goto out_close_message_queues;
 
-       struct msg_handler_context handler_ctx = {
-               .timeout_seconds = 5,
-               .unmount = {
-                       .daemon_pid = 0,
-                       .progress_func = progress_func,
+       struct unmount_msg_handler_context handler_ctx = {
+               .hdr = {
+                       .timeout_seconds = 5,
                },
+               .daemon_pid = 0,
+               .progress_func = progress_func,
        };
 
        ret = message_loop(wimfs_ctx.daemon_to_unmount_mq,
                           &unmount_msg_handler_callbacks,
-                          &handler_ctx);
+                          &handler_ctx.hdr);
        if (ret == 0)
-               ret = handler_ctx.unmount.status;
+               ret = handler_ctx.status;
 out_close_message_queues:
        close_message_queues(&wimfs_ctx);
 out_free_message_queue_names: