]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
Report progress for capture symlink fixups
[wimlib] / src / mount_image.c
index 06890dbca45cc7c2294683e041f2997a082ff400..168ee8523bc9bc038a9c678bdbf9c2f50fce62e9 100644 (file)
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
 #include "wimlib/paths.h"
+#include "wimlib/progress.h"
 #include "wimlib/reparse.h"
 #include "wimlib/resource.h"
 #include "wimlib/timestamp.h"
+#include "wimlib/unix_data.h"
 #include "wimlib/version.h"
 #include "wimlib/write.h"
 #include "wimlib/xml.h"
@@ -313,7 +315,8 @@ fuse_mask_mode(mode_t mode, struct fuse_context *fuse_ctx)
  */
 static int
 create_dentry(struct fuse_context *fuse_ctx, const char *path,
-             mode_t mode, int attributes, struct wim_dentry **dentry_ret)
+             mode_t mode, dev_t rdev, int attributes,
+             struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *parent;
        struct wim_dentry *new;
@@ -341,9 +344,19 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
        new->d_inode->i_attributes = attributes;
 
        if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
-               new->d_inode->i_unix_data.uid = fuse_ctx->uid;
-               new->d_inode->i_unix_data.gid = fuse_ctx->gid;
-               new->d_inode->i_unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
+               struct wimlib_unix_data unix_data;
+
+               unix_data.uid = fuse_ctx->uid;
+               unix_data.gid = fuse_ctx->gid;
+               unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
+               unix_data.rdev = rdev;
+
+               if (!inode_set_unix_data(new->d_inode, &unix_data,
+                                        UNIX_DATA_ALL))
+               {
+                       free_dentry(new);
+                       return -ENOMEM;
+               }
        }
        dentry_add_child(parent, new);
        list_add_tail(&new->d_inode->i_list, wimfs_ctx->image_inode_list);
@@ -409,18 +422,21 @@ inode_to_stbuf(const struct wim_inode *inode,
               struct stat *stbuf)
 {
        const struct wimfs_context *ctx = wimfs_get_context();
+       struct wimlib_unix_data unix_data;
 
        memset(stbuf, 0, sizeof(struct stat));
        if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) &&
-           inode_has_unix_data(inode))
+           inode_get_unix_data(inode, &unix_data))
        {
-               stbuf->st_uid = inode->i_unix_data.uid;
-               stbuf->st_gid = inode->i_unix_data.gid;
-               stbuf->st_mode = inode->i_unix_data.mode;
+               stbuf->st_uid = unix_data.uid;
+               stbuf->st_gid = unix_data.gid;
+               stbuf->st_mode = unix_data.mode;
+               stbuf->st_rdev = unix_data.rdev;
        } else {
                stbuf->st_uid = ctx->default_uid;
                stbuf->st_gid = ctx->default_gid;
                stbuf->st_mode = inode_default_unix_mode(inode);
+               stbuf->st_rdev = 0;
        }
        stbuf->st_ino = (ino_t)inode->i_ino;
        stbuf->st_nlink = inode->i_nlink;
@@ -798,8 +814,7 @@ inode_close_fds(struct wim_inode *inode)
 
 /* Overwrites the WIM file, with changes saved. */
 static int
-rebuild_wim(struct wimfs_context *ctx, int write_flags,
-           wimlib_progress_func_t progress_func)
+rebuild_wim(struct wimfs_context *ctx, int write_flags)
 {
        int ret;
        struct wim_lookup_table_entry *lte, *tmp;
@@ -826,7 +841,7 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
        }
 
        xml_update_image_info(wim, wim->current_image);
-       ret = wimlib_overwrite(wim, write_flags, 0, progress_func);
+       ret = wimlib_overwrite(wim, write_flags, 0);
        if (ret)
                ERROR("Failed to commit changes to mounted WIM image");
        return ret;
@@ -1078,7 +1093,8 @@ struct unmount_msg_handler_context {
        pid_t daemon_pid;
        int mount_flags;
        int status;
-       wimlib_progress_func_t progress_func;
+       wimlib_progress_func_t progfunc;
+       void *progctx;
 };
 
 struct daemon_msg_handler_context {
@@ -1150,9 +1166,9 @@ send_unmount_finished_msg(mqd_t mq, int status)
                ERROR_WITH_ERRNO("Failed to send status to unmount process");
 }
 
-static int
+static enum wimlib_progress_status
 unmount_progress_func(enum wimlib_progress_msg msg,
-                     const union wimlib_progress_info *info)
+                     union wimlib_progress_info *info, void *_ignored_context)
 {
        if (msg == WIMLIB_PROGRESS_MSG_WRITE_STREAMS) {
                struct msg_write_streams_progress msg = {
@@ -1171,7 +1187,7 @@ unmount_progress_func(enum wimlib_progress_msg msg,
                                         "to unmount process");
                }
        }
-       return 0;
+       return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
 static void
@@ -1257,7 +1273,6 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
        int status = 0;
        int ret;
        int unmount_flags;
-       wimlib_progress_func_t progress_func;
 
        DEBUG("Handling unmount request msg");
 
@@ -1268,10 +1283,11 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
        }
 
        unmount_flags = msg->unmount_flags;
-       if (msg->want_progress_messages)
-               progress_func = unmount_progress_func;
-       else
-               progress_func = NULL;
+
+       wimlib_register_progress_function(wimfs_ctx->wim,
+                                         (msg->want_progress_messages ?
+                                          unmount_progress_func : NULL),
+                                         NULL);
 
        ret = send_daemon_info_msg(wimfs_ctx->daemon_to_unmount_mq, getpid(),
                                   wimfs_ctx->mount_flags);
@@ -1301,8 +1317,7 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
                                write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
                        if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
                                write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
-                       status = rebuild_wim(wimfs_ctx, write_flags,
-                                            progress_func);
+                       status = rebuild_wim(wimfs_ctx, write_flags);
                }
        } else {
                DEBUG("Read-only mount");
@@ -1349,11 +1364,10 @@ msg_write_streams_progress_handler(const void *_msg, void *_handler_ctx)
 
        if (msg->hdr.msg_size < sizeof(*msg))
                return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
-       if (handler_ctx->progress_func) {
-               handler_ctx->progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
-                                          &msg->info);
-       }
-       return 0;
+       return call_progress(handler_ctx->progfunc,
+                            WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                            (union wimlib_progress_info *)&msg->info,
+                            handler_ctx->progctx);
 }
 
 static int
@@ -1610,6 +1624,7 @@ wimfs_chmod(const char *path, mode_t mask)
        struct wim_dentry *dentry;
        struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
+       struct wimlib_unix_data unix_data;
        int ret;
 
        if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
@@ -1622,11 +1637,13 @@ wimfs_chmod(const char *path, mode_t mask)
 
        inode = dentry->d_inode;
 
-       if (!inode_has_unix_data(inode)) {
-               inode->i_unix_data.uid = ctx->default_uid;
-               inode->i_unix_data.gid = ctx->default_gid;
-       }
-       inode->i_unix_data.mode = mask;
+       unix_data.uid = ctx->default_uid;
+       unix_data.gid = ctx->default_gid;
+       unix_data.mode = mask;
+       unix_data.rdev = 0;
+       if (!inode_set_unix_data(inode, &unix_data, UNIX_DATA_MODE))
+               return -ENOMEM;
+
        return 0;
 }
 
@@ -1636,6 +1653,8 @@ wimfs_chown(const char *path, uid_t uid, gid_t gid)
        struct wim_dentry *dentry;
        struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
+       int which;
+       struct wimlib_unix_data unix_data;
        int ret;
 
        if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
@@ -1648,10 +1667,26 @@ wimfs_chown(const char *path, uid_t uid, gid_t gid)
 
        inode = dentry->d_inode;
 
-       if (!inode_has_unix_data(inode))
-               inode->i_unix_data.mode = inode_default_unix_mode(inode);
-       inode->i_unix_data.uid = uid;
-       inode->i_unix_data.gid = gid;
+       which = 0;
+
+       if (uid != (uid_t)-1)
+               which |= UNIX_DATA_UID;
+       else
+               uid = ctx->default_uid;
+
+       if (gid != (gid_t)-1)
+               which |= UNIX_DATA_GID;
+       else
+               gid = ctx->default_gid;
+
+
+       unix_data.uid = uid;
+       unix_data.gid = gid;
+       unix_data.mode = inode_default_unix_mode(inode);
+       unix_data.rdev = 0;
+       if (!inode_set_unix_data(inode, &unix_data, which))
+               return -ENOMEM;
+
        return 0;
 }
 
@@ -1860,11 +1895,12 @@ wimfs_listxattr(const char *path, char *list, size_t size)
 static int
 wimfs_mkdir(const char *path, mode_t mode)
 {
-       return create_dentry(fuse_get_context(), path, mode | S_IFDIR,
+       return create_dentry(fuse_get_context(), path, mode | S_IFDIR, 0,
                             FILE_ATTRIBUTE_DIRECTORY, NULL);
 }
 
-/* Create a regular file or alternate data stream in the WIM image. */
+/* Create a non-directory, non-symbolic-link file or alternate data stream in
+ * the WIM image.  */
 static int
 wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
 {
@@ -1872,11 +1908,12 @@ wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
        struct fuse_context *fuse_ctx = fuse_get_context();
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
 
-       if (!S_ISREG(mode))
-               return -EPERM;
-
        if ((wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
             && (stream_name = path_stream_name(path))) {
+
+               if (!S_ISREG(mode))
+                       return -EPERM;
+
                /* Make an alternate data stream */
                struct wim_ads_entry *new_entry;
                struct wim_inode *inode;
@@ -1897,8 +1934,12 @@ wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
                        return -ENOMEM;
                return 0;
        } else {
-               /* Make a normal file (not an alternate data stream) */
-               return create_dentry(fuse_ctx, path, mode | S_IFREG,
+               if (!S_ISREG(mode) &&
+                   !(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
+                       return -EPERM;
+
+               /* Make a regular file, device node, named pipe, or socket.  */
+               return create_dentry(fuse_ctx, path, mode, rdev,
                                     FILE_ATTRIBUTE_NORMAL, NULL);
        }
 }
@@ -2235,7 +2276,7 @@ wimfs_symlink(const char *to, const char *from)
        struct wim_dentry *dentry;
        int ret;
 
-       ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777,
+       ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777, 0,
                            FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
        if (ret == 0) {
                dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
@@ -2675,8 +2716,8 @@ out_free_message_queue_names:
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
-wimlib_unmount_image(const char *dir, int unmount_flags,
-                    wimlib_progress_func_t progress_func)
+wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
+                                  wimlib_progress_func_t progfunc, void *progctx)
 {
        int ret;
        struct wimfs_context wimfs_ctx;
@@ -2701,7 +2742,7 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
 
        ret = send_unmount_request_msg(wimfs_ctx.unmount_to_daemon_mq,
                                       unmount_flags,
-                                      progress_func != NULL);
+                                      progfunc != NULL);
        if (ret != 0)
                goto out_close_message_queues;
 
@@ -2714,7 +2755,8 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
                        .timeout_seconds = 5,
                },
                .daemon_pid = 0,
-               .progress_func = progress_func,
+               .progfunc = progfunc,
+               .progctx = progctx,
        };
 
        ret = message_loop(wimfs_ctx.daemon_to_unmount_mq,
@@ -2746,8 +2788,8 @@ mount_unsupported_error(void)
 }
 
 WIMLIBAPI int
-wimlib_unmount_image(const tchar *dir, int unmount_flags,
-                    wimlib_progress_func_t progress_func)
+wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
+                                  wimlib_progress_func_t progfunc, void *progctx)
 {
        return mount_unsupported_error();
 }
@@ -2760,3 +2802,10 @@ wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
 }
 
 #endif /* !WITH_FUSE */
+
+
+WIMLIBAPI int
+wimlib_unmount_image(const tchar *dir, int unmount_flags)
+{
+       return wimlib_unmount_image_with_progress(dir, unmount_flags, NULL, NULL);
+}