+ DEBUG("Exiting message loop");
+ return ret;
+}
+
+/* Execute `fusermount -u', which is installed setuid root, to unmount the WIM.
+ *
+ * FUSE does not yet implement synchronous unmounts. This means that fusermount
+ * -u will return before the filesystem daemon returns from wimfs_destroy().
+ * This is partly what we want, because we need to 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.
+ */
+static int
+execute_fusermount(const char *dir, bool lazy)
+{
+ pid_t pid;
+ int ret;
+ int status;
+
+ pid = fork();
+ if (pid == -1) {
+ ERROR_WITH_ERRNO("Failed to fork()");
+ return WIMLIB_ERR_FORK;
+ }
+ if (pid == 0) {
+ /* Child */
+ 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);
+ }
+
+ /* Parent */
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
+ "terminate");
+ return WIMLIB_ERR_FUSERMOUNT;
+ }
+
+ if (!WIFEXITED(status)) {
+ ERROR("'fusermount' did not terminate normally!");
+ return WIMLIB_ERR_FUSERMOUNT;
+ }
+
+ status = WEXITSTATUS(status);
+
+ if (status == 0)
+ return 0;
+
+ 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 */
+ 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);
+ }
+
+ /* 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 (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ ERROR("`umount' did not successfully complete");
+ return WIMLIB_ERR_FUSERMOUNT;
+ }
+
+ return 0;