Make WIM mounting work on FreeBSD v1.0.1
authorEric Biggers <ebiggers3@gmail.com>
Sun, 2 Sep 2012 19:33:26 +0000 (14:33 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 2 Sep 2012 19:33:26 +0000 (14:33 -0500)
- Fallback to `umount' if `fusermount' is not available.
- Place message in message queue before executing `umount'.  This is needed in
  case the unmount occurs synchronously.

README
src/list.h
src/mount.c

diff --git a/README b/README
index 640432bbe9bd23ff1ca8e6074f837dabe378fae5..2fa925e981eaa548b4d547b773f262ffaacfe04b 100644 (file)
--- a/README
+++ b/README
@@ -184,13 +184,11 @@ wimlib has mostly been developed and tested on x86_64 (64-bit) GNU/Linux.
 
 It has been tested on x86 (32-bit) GNU/Linux occasionally.
 
 
 It has been tested on x86 (32-bit) GNU/Linux occasionally.
 
-wimlib may work on FreeBSD.  However, this not well tested.  If you do not have
-libntfs-3g 2011-4-12 or later available, you may have to configure with
+wimlib may work on FreeBSD.  However, this is not well tested.  If you do not
+have libntfs-3g 2011-4-12 or later available, you must configure with
 --without-ntfs-3g.  Also, GNU coreutils is needed to run the test suite.  Before
 mounting a WIM you need to load the POSIX message queue module (run `kldload
 --without-ntfs-3g.  Also, GNU coreutils is needed to run the test suite.  Before
 mounting a WIM you need to load the POSIX message queue module (run `kldload
-mqueuefs').  There is no `fusermount' command on FreeBSD, so you must use
-`umount' rather than `imagex unmount' to unmount a mounted WIM, but this won't
-allow you to commit changes to a read-write mounted WIM...
+mqueuefs').  
 
 wimlib should work on big endian machines but it has not been tested.
 
 
 wimlib should work on big endian machines but it has not been tested.
 
index ffce657076653d9e85878e933139b61ee584b2cd..e21f6d17c33dc98f55722cde32e0697e4793ee56 100644 (file)
@@ -66,6 +66,10 @@ struct stream_list_head {
 
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
 
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
+#ifdef LIST_HEAD /* BSD sys/queue.h defines this... */
+#undef LIST_HEAD
+#endif
+
 #define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)
 
 #define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)
 
index f152fcd726d4d7e7f1e7dc287f566cf66fdc17ce..6efe84c6a375468654f246b3313b055d5782f682 100644 (file)
@@ -29,6 +29,7 @@
 #include "wimlib_internal.h"
 
 #ifdef WITH_FUSE
 #include "wimlib_internal.h"
 
 #ifdef WITH_FUSE
+
 #include "sha1.h"
 #include "lookup_table.h"
 #include "xml.h"
 #include "sha1.h"
 #include "lookup_table.h"
 #include "xml.h"
@@ -2030,6 +2031,30 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        int msgsize;
        int errno_save;
 
        int msgsize;
        int errno_save;
 
+       mount_dir = dir;
+
+       /* Open message queues between the unmount process and the
+        * filesystem daemon. */
+       ret = open_message_queues(false);
+       if (ret != 0)
+               return ret;
+
+       /* Send a message to the filesystem 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;
+
+       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);
+       if (ret == -1) {
+               ERROR("Failed to notify filesystem daemon whether we want to "
+                     "commit changes or not");
+               close_message_queues();
+               return WIMLIB_ERR_MQUEUE;
+       }
+
        /* Execute `fusermount -u', which is installed setuid root, to unmount
         * the WIM.
         *
        /* Execute `fusermount -u', which is installed setuid root, to unmount
         * the WIM.
         *
@@ -2042,7 +2067,6 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
         * the WIM file. 
         */
 
         * the WIM file. 
         */
 
-       mount_dir = dir;
 
        pid = fork();
        if (pid == -1) {
 
        pid = fork();
        if (pid == -1) {
@@ -2052,10 +2076,10 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        if (pid == 0) {
                execlp("fusermount", "fusermount", "-u", dir, NULL);
                ERROR_WITH_ERRNO("Failed to execute `fusermount'");
        if (pid == 0) {
                execlp("fusermount", "fusermount", "-u", dir, NULL);
                ERROR_WITH_ERRNO("Failed to execute `fusermount'");
-               return WIMLIB_ERR_FUSERMOUNT;
+               exit(WIMLIB_ERR_FUSERMOUNT);
        }
 
        }
 
-       ret = waitpid(pid, &status, 0);
+       ret = wait(&status);
        if (ret == -1) {
                ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
                                 "terminate");
        if (ret == -1) {
                ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
                                 "terminate");
@@ -2064,31 +2088,35 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
 
        if (status != 0) {
                ERROR("fusermount exited with status %d", status);
 
        if (status != 0) {
                ERROR("fusermount exited with status %d", status);
-               return WIMLIB_ERR_FUSERMOUNT;
-       }
 
 
-       /* Open message queues between the unmount process and the
-        * filesystem daemon. */
-       ret = open_message_queues(false);
-       if (ret != 0)
-               return ret;
+               /* 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. */
 
 
-       /* Send a message to the filesystem 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;
+               pid = fork();
+               if (pid == -1) {
+                       ERROR_WITH_ERRNO("Failed to fork()");
+                       return WIMLIB_ERR_FORK;
+               }
+               if (pid == 0) {
+                       execlp("umount", "umount", dir, NULL);
+                       ERROR_WITH_ERRNO("Failed to execute `umount'");
+                       exit(WIMLIB_ERR_FUSERMOUNT);
+               }
 
 
-       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);
-       if (ret == -1) {
-               ERROR("Failed to notify filesystem daemon whether we want to "
-                     "commit changes or not");
-               close_message_queues();
-               return WIMLIB_ERR_MQUEUE;
+               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;
+               }
        }
 
        }
 
+
        /* Wait for a message from the filesytem daemon indicating whether  the
         * filesystem was unmounted successfully (0) or an error occurred (1).
         * This may take a long time if a big WIM file needs to be rewritten. */
        /* Wait for a message from the filesytem daemon indicating whether  the
         * filesystem was unmounted successfully (0) or an error occurred (1).
         * This may take a long time if a big WIM file needs to be rewritten. */