-/* Wait for a message from the filesytem daemon indicating whether the
- * filesystem was unmounted successfully. This may
- * take a long time if a big WIM file needs to be rewritten.
- *
- * Wait at most 600??? seconds before giving up and returning an error. Either
- * it's a really big WIM file, or (more likely) the 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.
- *
- * XXX Idea: have mount daemon write its PID into the WIM file header? No, this
- * wouldn't work because we know the directory but not the WIM file...
- */
-static int receive_unmount_response(struct wimfs_context *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->status = msg->status;
+ DEBUG("status is %d", handler_ctx->status);
+ return MSG_BREAK_LOOP;
+}
+
+static int
+unmount_timed_out_cb(void *_handler_ctx)
+{
+ const struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
+
+ if (handler_ctx->daemon_pid == 0 ||
+ (kill(handler_ctx->daemon_pid, 0) != 0 && errno == ESRCH))
+ {
+ ERROR("The filesystem daemon has crashed! Changes to the "
+ "WIM may not have been commited.");
+ return WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED;
+ }
+
+ DEBUG("Filesystem daemon is still alive... "
+ "Waiting another %d seconds", handler_ctx->hdr.timeout_seconds);
+ return 0;
+}
+
+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, void *_handler_ctx);
+
+struct msg_handler_callbacks {
+ int (*timed_out)(void * _handler_ctx);
+ msg_handler_t msg_handlers[MSG_TYPE_MAX];
+};
+
+static const struct msg_handler_callbacks unmount_msg_handler_callbacks = {
+ .timed_out = unmount_timed_out_cb,
+ .msg_handlers = {
+ [MSG_TYPE_DAEMON_INFO] = msg_daemon_info_handler,
+ [MSG_TYPE_WRITE_STREAMS_PROGRESS] = msg_write_streams_progress_handler,
+ [MSG_TYPE_UNMOUNT_FINISHED] = msg_unmount_finished_handler,
+ },
+};
+
+static const struct msg_handler_callbacks daemon_msg_handler_callbacks = {
+ .timed_out = daemon_timed_out_cb,
+ .msg_handlers = {
+ [MSG_TYPE_UNMOUNT_REQUEST] = msg_unmount_request_handler,
+ },
+};
+
+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)