]> wimlib.net Git - wimlib/blobdiff - src/mount.c
Cleanup wimlib_mount() preparations
[wimlib] / src / mount.c
index f2dad8d3714d945726d4e9c35f4d767cdfa06a4e..6096319688e1cd8f03ca5359091864287aecb15b 100644 (file)
@@ -64,7 +64,7 @@ struct wimlib_fd {
 static WIMStruct *w;
 
 /* Working directory when `imagex mount' is run. */
-static const char *working_directory;
+static 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
@@ -77,9 +77,6 @@ static size_t staging_dir_name_len;
 /* Flags passed to wimlib_mount(). */
 static int mount_flags;
 
-/* Name of the directory on which the WIM file is mounted. */
-static const char *mount_dir;
-
 /* Next inode number to be assigned. */
 static u64 next_ino;
 
@@ -130,7 +127,7 @@ static int alloc_wimlib_fd(struct inode *inode,
                        return -EMFILE;
                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]));
@@ -286,7 +283,7 @@ static int create_staging_file(char **name_ret, int open_flags)
 
        DEBUG("Creating staging file `%s'", name);
 
-       fd = open(name, open_flags | O_CREAT | O_TRUNC, 0600); 
+       fd = open(name, open_flags | O_CREAT | O_TRUNC, 0600);
        if (fd == -1) {
                errno_save = errno;
                FREE(name);
@@ -297,7 +294,7 @@ static int create_staging_file(char **name_ret, int open_flags)
        return fd;
 }
 
-/* 
+/*
  * Extract a WIM resource to the staging directory.
  *
  * @inode:  Inode that contains the stream we are extracting
@@ -377,7 +374,7 @@ static int extract_resource_to_staging_dir(struct inode *inode,
                 * opening it read-write.  Identify those file descriptors and
                 * change their lookup table entry pointers to point to the new
                 * lookup table entry, and open staging file descriptors for
-                * them. 
+                * them.
                 *
                 * At the same time, we need to count the number of these opened
                 * file descriptors to the new lookup table entry.  If there's
@@ -446,7 +443,7 @@ out_delete_staging_file:
        return ret;
 }
 
-/* 
+/*
  * Creates a randomly named staging directory and returns its name into the
  * static variable staging_dir_name.
  *
@@ -495,13 +492,13 @@ static int remove_file_or_directory(const char *fpath, const struct stat *sb,
 }
 
 
-/* 
- * Deletes the staging directory and all the files contained in it. 
+/*
+ * Deletes the staging directory and all the files contained in it.
  */
 static int delete_staging_dir()
 {
        int ret;
-       
+
        ret = nftw(staging_dir_name, remove_file_or_directory,10, FTW_DEPTH);
        staging_dir_name = NULL;
        return ret;
@@ -519,7 +516,7 @@ static mqd_t unmount_to_daemon_mq;
 static mqd_t daemon_to_unmount_mq;
 
 /* Simple function that returns the concatenation of 4 strings. */
-static char *strcat_dup(const char *s1, const char *s2, const char *s3, 
+static char *strcat_dup(const char *s1, const char *s2, const char *s3,
                        const char *s4)
 {
        size_t len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4) + 1;
@@ -554,17 +551,7 @@ static void s_slashes_underscores_g(char *s)
        }
 }
 
-/* 
- * Opens two POSIX message queue: one for sending messages from the unmount
- * process to the daemon process, and one to go the other way.  The names of the
- * message queues, which must be system-wide unique, are be based on the mount
- * point.  (There of course is still a possibility of a collision if one were to
- * unmount two identically named directories simultaneously...)
- *
- * @daemon specifies whether the calling process is the filesystem daemon or the
- * unmount process.
- */
-static int open_message_queues(bool daemon)
+static int set_message_queue_names(const char *mount_dir)
 {
        static const char *slash = "/";
        static const char *prefix = "wimlib-";
@@ -572,8 +559,6 @@ static int open_message_queues(bool daemon)
        static const char *d2u_suffix = "daemon-to-unmount-mq";
 
        const char *mount_dir_basename = path_basename(mount_dir);
-       int flags;
-       int ret;
 
        unmount_to_daemon_mq_name = strcat_dup(slash, mount_dir_basename,
                                                prefix, u2d_suffix);
@@ -585,27 +570,56 @@ static int open_message_queues(bool daemon)
                                                prefix, d2u_suffix);
        if (!daemon_to_unmount_mq_name) {
                ERROR("Out of memory");
-               ret = WIMLIB_ERR_NOMEM;
-               goto err1;
+               FREE(unmount_to_daemon_mq_name);
+               unmount_to_daemon_mq_name = NULL;
+               return WIMLIB_ERR_NOMEM;
        }
 
        remove_trailing_slashes(unmount_to_daemon_mq_name);
        remove_trailing_slashes(daemon_to_unmount_mq_name);
        s_slashes_underscores_g(unmount_to_daemon_mq_name + 1);
        s_slashes_underscores_g(daemon_to_unmount_mq_name + 1);
+       return 0;
+}
+
+static void free_message_queue_names()
+{
+       FREE(unmount_to_daemon_mq_name);
+       FREE(daemon_to_unmount_mq_name);
+       unmount_to_daemon_mq_name = NULL;
+       daemon_to_unmount_mq_name = NULL;
+}
+
+/*
+ * Opens two POSIX message queue: one for sending messages from the unmount
+ * process to the daemon process, and one to go the other way.  The names of the
+ * message queues, which must be system-wide unique, are be based on the mount
+ * point.  (There of course is still a possibility of a collision if one were to
+ * unmount two identically named directories simultaneously...)
+ *
+ * @daemon specifies whether the calling process is the filesystem daemon or the
+ * unmount process.
+ */
+static int open_message_queues(bool daemon)
+{
+       int flags;
+       int ret;
+
+       wimlib_assert(unmount_to_daemon_mq_name != NULL &&
+                     daemon_to_unmount_mq_name != NULL);
 
        if (daemon)
                flags = O_RDONLY | O_CREAT;
        else
                flags = O_WRONLY | O_CREAT;
 
-       unmount_to_daemon_mq = mq_open(unmount_to_daemon_mq_name, flags, 
+       unmount_to_daemon_mq = mq_open(unmount_to_daemon_mq_name, flags,
                                       0700, NULL);
 
        if (unmount_to_daemon_mq == (mqd_t)-1) {
                ERROR_WITH_ERRNO("mq_open()");
                ret = WIMLIB_ERR_MQUEUE;
-               goto err2;
+               goto out;
        }
 
        if (daemon)
@@ -613,22 +627,21 @@ static int open_message_queues(bool daemon)
        else
                flags = O_RDONLY | O_CREAT;
 
-       daemon_to_unmount_mq = mq_open(daemon_to_unmount_mq_name, flags, 
+       daemon_to_unmount_mq = mq_open(daemon_to_unmount_mq_name, flags,
                                       0700, NULL);
 
        if (daemon_to_unmount_mq == (mqd_t)-1) {
                ERROR_WITH_ERRNO("mq_open()");
                ret = WIMLIB_ERR_MQUEUE;
-               goto err3;
+               goto out_close_unmount_to_daemon_mq;
        }
-       return 0;
-err3:
+       ret = 0;
+       goto out;
+out_close_unmount_to_daemon_mq:
        mq_close(unmount_to_daemon_mq);
        mq_unlink(unmount_to_daemon_mq_name);
-err2:
-       FREE(daemon_to_unmount_mq_name);
-err1:
-       FREE(unmount_to_daemon_mq_name);
+       unmount_to_daemon_mq = (mqd_t)-1;
+out:
        return ret;
 }
 
@@ -661,13 +674,20 @@ static int mq_get_msgsize(mqd_t mq)
        return msgsize;
 }
 
+static void unlink_message_queues()
+{
+       mq_unlink(unmount_to_daemon_mq_name);
+       mq_unlink(daemon_to_unmount_mq_name);
+}
+
 /* Closes the message queues, which are allocated in static variables */
 static void close_message_queues()
 {
        mq_close(unmount_to_daemon_mq);
+       unmount_to_daemon_mq = (mqd_t)(-1);
        mq_close(daemon_to_unmount_mq);
-       mq_unlink(unmount_to_daemon_mq_name);
-       mq_unlink(daemon_to_unmount_mq_name);
+       daemon_to_unmount_mq = (mqd_t)(-1);
+       unlink_message_queues();
 }
 
 static int wimfs_access(const char *path, int mask)
@@ -806,7 +826,7 @@ static void wimfs_destroy(void *p)
 
        ret = open_message_queues(true);
        if (ret != 0)
-               exit(1);
+               return;
 
        msgsize = mq_get_msgsize(unmount_to_daemon_mq);
        char msg[msgsize];
@@ -820,19 +840,20 @@ static void wimfs_destroy(void *p)
        DEBUG("Waiting for message telling us whether to commit or not, and "
              "whether to include integrity checks.");
 
-       bytes_received = mq_timedreceive(unmount_to_daemon_mq, msg, 
+       bytes_received = mq_timedreceive(unmount_to_daemon_mq, msg,
                                         msgsize, NULL, &timeout);
-       commit = msg[0];
-       check_integrity = msg[1];
        if (bytes_received == -1) {
-               if (errno == ETIMEDOUT) {
+               if (errno == ETIMEDOUT)
                        ERROR("Timed out.");
-               } else {
+               else
                        ERROR_WITH_ERRNO("mq_timedreceive()");
-               }
                ERROR("Not committing.");
+               commit = 0;
+               check_integrity = 0;
        } else {
                DEBUG("Received message: [%d %d]", msg[0], msg[1]);
+               commit = msg[0];
+               check_integrity = msg[1];
        }
 
        status = 0;
@@ -842,7 +863,7 @@ static void wimfs_destroy(void *p)
                        if (status != 0) {
                                ERROR_WITH_ERRNO("chdir()");
                                status = WIMLIB_ERR_NOTDIR;
-                               goto done;
+                               goto out;
                        }
                        status = rebuild_wim(w, (check_integrity != 0));
                }
@@ -856,8 +877,8 @@ static void wimfs_destroy(void *p)
        } else {
                DEBUG("Read-only mount");
        }
-done:
-       DEBUG("Sending status %u", status);
+out:
+       DEBUG("Sending status %hhd", status);
        ret = mq_send(daemon_to_unmount_mq, &status, 1, 1);
        if (ret == -1)
                ERROR_WITH_ERRNO("Failed to send status to unmount process");
@@ -1034,8 +1055,8 @@ static int wimfs_listxattr(const char *path, char *list, size_t size)
 }
 #endif
 
-/* 
- * Create a directory in the WIM.  
+/*
+ * Create a directory in the WIM.
  * @mode is currently ignored.
  */
 static int wimfs_mkdir(const char *path, mode_t mode)
@@ -1043,7 +1064,7 @@ static int wimfs_mkdir(const char *path, mode_t mode)
        struct dentry *parent;
        struct dentry *newdir;
        const char *basename;
-       
+
        parent = get_parent_dentry(w, path);
        if (!parent)
                return -ENOENT;
@@ -1176,7 +1197,7 @@ static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
        struct inode *inode;
        int ret;
        struct wimlib_fd *fd = NULL;
-       
+
        inode = wim_pathname_to_inode(w, path);
        if (!inode)
                return -ENOENT;
@@ -1189,9 +1210,9 @@ static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
 
 
 /*
- * Read data from a file in the WIM or in the staging directory. 
+ * Read data from a file in the WIM or in the staging directory.
  */
-static int wimfs_read(const char *path, char *buf, size_t size, 
+static int wimfs_read(const char *path, char *buf, size_t size,
                      off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1221,7 +1242,7 @@ static int wimfs_read(const char *path, char *buf, size_t size,
                /* Read from WIM */
 
                u64 res_size = wim_resource_size(fd->f_lte);
-               
+
                if (offset > res_size)
                        return -EOVERFLOW;
 
@@ -1236,7 +1257,7 @@ static int wimfs_read(const char *path, char *buf, size_t size,
 
 /* 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, 
+static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                         off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1332,7 +1353,7 @@ static int wimfs_rename(const char *from, const char *to)
 
        /* This rename() implementation currently only supports actual files
         * (not alternate data streams) */
-       
+
        src = get_dentry(w, from);
        if (!src)
                return -ENOENT;
@@ -1392,7 +1413,7 @@ static int wimfs_rename(const char *from, const char *to)
 static int wimfs_rmdir(const char *path)
 {
        struct dentry *dentry;
-       
+
        dentry = get_dentry(w, path);
        if (!dentry)
                return -ENOENT;
@@ -1477,7 +1498,7 @@ static int wimfs_symlink(const char *to, const char *from)
        struct dentry *dentry_parent, *dentry;
        const char *link_name;
        struct inode *inode;
-       
+
        dentry_parent = get_parent_dentry(w, from);
        if (!dentry_parent)
                return -ENOENT;
@@ -1518,7 +1539,7 @@ static int wimfs_truncate(const char *path, off_t size)
        u16 stream_idx;
        u32 stream_id;
        struct inode *inode;
-       
+
        ret = lookup_resource(w, path, get_lookup_flags(), &dentry,
                              &lte, &stream_idx);
 
@@ -1560,7 +1581,7 @@ static int wimfs_unlink(const char *path)
        int ret;
        u16 stream_idx;
        unsigned i;
-       
+
        ret = lookup_resource(w, path, get_lookup_flags(), &dentry,
                              &lte, &stream_idx);
 
@@ -1575,8 +1596,8 @@ static int wimfs_unlink(const char *path)
 }
 
 #ifdef HAVE_UTIMENSAT
-/* 
- * Change the timestamp on a file dentry. 
+/*
+ * Change the timestamp on a file dentry.
  *
  * Note that alternate data streams do not have their own timestamps.
  */
@@ -1619,10 +1640,10 @@ static int wimfs_utime(const char *path, struct utimbuf *times)
 }
 #endif
 
-/* Writes to a file in the WIM filesystem. 
+/* Writes to a file in the WIM filesystem.
  * It may be an alternate data stream, but here we don't even notice because we
  * just get a lookup table entry. */
-static int wimfs_write(const char *path, const char *buf, size_t size, 
+static int wimfs_write(const char *path, const char *buf, size_t size,
                       off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1698,14 +1719,14 @@ static struct fuse_operations wimfs_operations = {
 
 
 /* Mounts a WIM file. */
-WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, 
+WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                           int flags, WIMStruct **additional_swms,
                           unsigned num_additional_swms)
 {
        int argc = 0;
        char *argv[16];
        int ret;
-       char *p;
+       char *dir_copy;
        struct lookup_table *joined_tab, *wim_tab_save;
        struct image_metadata *imd;
 
@@ -1741,21 +1762,10 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        if (imd->root_dentry->refcnt != 1) {
                ERROR("Cannot mount image that was just exported with "
                      "wimlib_export()");
-               return WIMLIB_ERR_INVALID_PARAM;
+               ret = WIMLIB_ERR_INVALID_PARAM;
+               goto out;
        }
 
-       next_ino = assign_inode_numbers(&imd->inode_list);
-
-       DEBUG("(next_ino = %"PRIu64")", next_ino);
-
-       /* Resolve all the lookup table entries of the dentry tree */
-       DEBUG("Resolving lookup table entries");
-       for_dentry_in_tree(imd->root_dentry, dentry_resolve_ltes,
-                          wim->lookup_table);
-
-       if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
-               imd->modified = true;
-
        if (!(flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
                       WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
                       WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
@@ -1763,7 +1773,6 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
 
        DEBUG("Getting current directory");
 
-       mount_dir = dir;
        working_directory = getcwd(NULL, 0);
        if (!working_directory) {
                ERROR_WITH_ERRNO("Could not determine current directory");
@@ -1771,36 +1780,30 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                goto out;
        }
 
-       DEBUG("Closing POSIX message queues");
-       /* XXX hack to get rid of the message queues if they already exist for
-        * some reason (maybe left over from a previous mount that wasn't
-        * unmounted correctly) */
-       ret = open_message_queues(true);
+       DEBUG("Unlinking message queues in case they already exist");
+       ret = set_message_queue_names(dir);
        if (ret != 0)
-               goto out;
-       close_message_queues();
+               goto out_free_working_directory;
+       unlink_message_queues();
 
        DEBUG("Preparing arguments to fuse_main()");
 
-
-       p = STRDUP(dir);
-       if (!p) {
-               ret = WIMLIB_ERR_NOMEM;
-               goto out;
-       }
+       dir_copy = STRDUP(dir);
+       if (!dir_copy)
+               goto out_free_message_queue_names;
 
        argv[argc++] = "imagex";
-       argv[argc++] = p;
+       argv[argc++] = dir_copy;
        argv[argc++] = "-s"; /* disable multi-threaded operation */
 
        if (flags & WIMLIB_MOUNT_FLAG_DEBUG)
                argv[argc++] = "-d";
 
-       /* 
+       /*
         * We provide the use_ino option because we are going to assign inode
-        * numbers oursides.  We've already numbered the inodes with unique
-        * numbers in the assign_inode_numbers() function, and the static
-        * variable next_ino is set to the next available inode number.
+        * numbers oursides.  The inodes will be given unique numbers in the
+        * assign_inode_numbers() function, and the static variable @next_ino is
+        * set to the next available inode number.
         */
        char optstring[256] = "use_ino,subtype=wimfs,attr_timeout=0";
        argv[argc++] = "-o";
@@ -1809,9 +1812,8 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                /* Read-write mount.  Make the staging directory */
                make_staging_dir();
                if (!staging_dir_name) {
-                       FREE(p);
                        ret = WIMLIB_ERR_MKDIR;
-                       goto out;
+                       goto out_free_dir_copy;
                }
        } else {
                /* Read-only mount */
@@ -1832,6 +1834,20 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        }
 #endif
 
+
+       /* Mark dentry tree as modified if read-write mount. */
+       if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
+               imd->modified = true;
+
+       next_ino = assign_inode_numbers(&imd->inode_list);
+
+       DEBUG("(next_ino = %"PRIu64")", next_ino);
+
+       /* Resolve all the lookup table entries of the dentry tree */
+       DEBUG("Resolving lookup table entries");
+       for_dentry_in_tree(imd->root_dentry, dentry_resolve_ltes,
+                          wim->lookup_table);
+
        /* Set static variables. */
        w = wim;
        mount_flags = flags;
@@ -1839,6 +1855,13 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        ret = fuse_main(argc, argv, &wimfs_operations, NULL);
        if (ret)
                ret = WIMLIB_ERR_FUSE;
+out_free_dir_copy:
+       FREE(dir_copy);
+out_free_message_queue_names:
+       free_message_queue_names();
+out_free_working_directory:
+       FREE(working_directory);
+       working_directory = NULL;
 out:
        if (num_additional_swms) {
                free_lookup_table(wim->lookup_table);
@@ -1848,7 +1871,7 @@ out:
 }
 
 
-/* 
+/*
  * Unmounts the WIM file that was previously mounted on @dir by using
  * wimlib_mount().
  */
@@ -1863,10 +1886,12 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        int msgsize;
        int errno_save;
 
-       mount_dir = dir;
-
        /* Open message queues between the unmount process and the
         * filesystem daemon. */
+       ret = set_message_queue_names(dir);
+       if (ret != 0)
+               return ret;
+
        ret = open_message_queues(false);
        if (ret != 0)
                return ret;
@@ -1876,7 +1901,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        msg[0] = (flags & WIMLIB_UNMOUNT_FLAG_COMMIT) ? 1 : 0;
        msg[1] = (flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY) ? 1 : 0;
 
-       DEBUG("Sending message: %s, %s", 
+       DEBUG("Sending message: %s, %s",
                        (msg[0] == 0) ? "don't commit" : "commit",
                        (msg[1] == 0) ? "don't check"  : "check");
        ret = mq_send(unmount_to_daemon_mq, msg, 2, 1);
@@ -1896,7 +1921,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
         * send a message from this process to the filesystem daemon telling
         * whether --commit was specified or not.  However, after that, the
         * unmount process must wait for the filesystem daemon to finish writing
-        * the WIM file. 
+        * the WIM file.
         */
 
 
@@ -1958,7 +1983,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
         * filesystem daemon has crashed or failed for some reason.
         *
         * XXX come up with some method to determine if the filesystem
-        * daemon has really crashed or not. 
+        * daemon has really crashed or not.
         *
         * XXX Idea: have mount daemon write its PID into the WIM file header?
         * */
@@ -2011,7 +2036,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        return mount_unsupported_error();
 }
 
-WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir, 
+WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir,
                           int flags, WIMStruct **additional_swms,
                           unsigned num_additional_swms)
 {