X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fmount_image.c;h=87620defc68daf0daf2356fc2577afb4cee995bd;hp=10fc61cca03c07e5ce45d7b8a74e9ac171108e2b;hb=0b52336c9e67aa31c04af59867c2541384141a3d;hpb=43a26b833482fc019c7aeee95656b8f2f3077db7 diff --git a/src/mount_image.c b/src/mount_image.c index 10fc61cc..87620def 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -357,7 +357,7 @@ inode_get_data_stream_tstr(const struct wim_inode *inode, struct wim_inode_stream *strm; if (!stream_name || !*stream_name) { - strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA); + strm = inode_get_unnamed_data_stream(inode); } else { const utf16lechar *uname; @@ -458,9 +458,9 @@ wim_pathname_to_stream(const struct wimfs_context *ctx, * Returns 0 or a -errno code. */ static int -create_dentry(struct fuse_context *fuse_ctx, const char *path, - mode_t mode, dev_t rdev, u32 attributes, - struct wim_dentry **dentry_ret) +create_file(struct fuse_context *fuse_ctx, const char *path, + mode_t mode, dev_t rdev, u32 attributes, + struct wim_dentry **dentry_ret) { struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx); struct wim_dentry *parent; @@ -549,6 +549,25 @@ inode_default_unix_mode(const struct wim_inode *inode) return inode_unix_file_type(inode) | 0777; } +static u64 +blob_size(const struct blob_descriptor *blob) +{ + if (!blob) + return 0; + return blob->size; +} + +static u64 +blob_stored_size(const struct blob_descriptor *blob) +{ + if (!blob) + return 0; + if (blob->blob_location == BLOB_IN_WIM && + blob->size == blob->rdesc->uncompressed_size) + return blob->rdesc->size_in_wim; + return blob->size; +} + /* * Retrieve standard UNIX metadata ('struct stat') for a WIM inode. * @@ -586,8 +605,7 @@ inode_to_stbuf(const struct wim_inode *inode, } stbuf->st_ino = inode->i_ino; stbuf->st_nlink = inode->i_nlink; - if (blob) - stbuf->st_size = blob->size; + stbuf->st_size = blob_size(blob); #ifdef HAVE_STAT_NANOSECOND_PRECISION stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time); stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time); @@ -597,7 +615,7 @@ inode_to_stbuf(const struct wim_inode *inode, stbuf->st_mtime = wim_timestamp_to_time_t(inode->i_last_write_time); stbuf->st_ctime = stbuf->st_mtime; #endif - stbuf->st_blocks = DIV_ROUND_UP(stbuf->st_size, 512); + stbuf->st_blocks = DIV_ROUND_UP(blob_stored_size(blob), 512); return 0; } @@ -757,15 +775,9 @@ extract_blob_to_staging_dir(struct wim_inode *inode, filedes_init(&fd->f_staging_fd, raw_fd); } - /* Remove the appropriate count of file descriptors and stream - * references from the old blob. */ - if (old_blob) { + if (old_blob) old_blob->num_opened_fds -= new_blob->num_opened_fds; - for (u32 i = 0; i < inode->i_nlink; i++) - blob_decrement_refcnt(old_blob, ctx->wim->blob_table); - } - new_blob->refcnt = inode->i_nlink; new_blob->blob_location = BLOB_IN_STAGING_FILE; new_blob->staging_file_name = staging_file_name; new_blob->staging_dir_fd = ctx->staging_dir_fd; @@ -773,7 +785,7 @@ extract_blob_to_staging_dir(struct wim_inode *inode, prepare_unhashed_blob(new_blob, inode, strm->stream_id, &wim_get_current_image_metadata(ctx->wim)->unhashed_blobs); - stream_set_blob(strm, new_blob); + inode_replace_stream_blob(inode, strm, new_blob, ctx->wim->blob_table); return 0; out_revert_fd_changes: @@ -947,11 +959,8 @@ release_extra_refcnts(struct wimfs_context *ctx) struct blob_table *blob_table = ctx->wim->blob_table; struct blob_descriptor *blob, *tmp; - list_for_each_entry_safe(blob, tmp, list, orig_blob_list) { - u32 n = blob->out_refcnt; - while (n--) - blob_decrement_refcnt(blob, blob_table); - } + list_for_each_entry_safe(blob, tmp, list, orig_blob_list) + blob_subtract_refcnt(blob, blob_table, blob->out_refcnt); } /* Delete the 'struct blob_descriptor' for any stream that was modified @@ -1027,8 +1036,10 @@ renew_current_image(struct wimfs_context *ctx) new_blob = new_blob_descriptor(); if (!new_blob) goto err_put_replace_imd; - new_blob->flags = WIM_RESHDR_FLAG_METADATA; + + new_blob->refcnt = 1; new_blob->unhashed = 1; + new_blob->is_metadata = 1; /* Make the image being moved available at a new index. Increments the * WIM's image count, but does not increment the reference count of the @@ -1475,8 +1486,8 @@ wimfs_mkdir(const char *path, mode_t mode) int ret; /* Note: according to fuse.h, mode may not include S_IFDIR */ - ret = create_dentry(fuse_get_context(), path, mode | S_IFDIR, 0, - FILE_ATTRIBUTE_DIRECTORY, &dentry); + ret = create_file(fuse_get_context(), path, mode | S_IFDIR, 0, + FILE_ATTRIBUTE_DIRECTORY, &dentry); if (ret) return ret; touch_parent(dentry); @@ -1541,8 +1552,8 @@ wimfs_mknod(const char *path, mode_t mode, dev_t rdev) /* Note: we still use FILE_ATTRIBUTE_NORMAL for device nodes, * named pipes, and sockets. The real mode is in the UNIX * metadata. */ - ret = create_dentry(fuse_ctx, path, mode, rdev, - FILE_ATTRIBUTE_NORMAL, &dentry); + ret = create_file(fuse_ctx, path, mode, rdev, + FILE_ATTRIBUTE_NORMAL, &dentry); if (ret) return ret; touch_parent(dentry); @@ -1580,7 +1591,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi) (!blob || blob->blob_location != BLOB_IN_STAGING_FILE)) { ret = extract_blob_to_staging_dir(inode, strm, - blob ? blob->size : 0, + blob_size(blob), ctx); if (ret) return ret; @@ -1620,7 +1631,7 @@ wimfs_opendir(const char *path, struct fuse_file_info *fi) return -errno; if (!inode_is_directory(inode)) return -ENOTDIR; - strm = inode_get_unnamed_stream(inode, STREAM_TYPE_DATA); + strm = inode_get_unnamed_data_stream(inode); if (!strm) return -ENOTDIR; ret = alloc_wimfs_fd(inode, strm, &fd); @@ -1808,7 +1819,7 @@ wimfs_setxattr(const char *path, const char *name, { struct wimfs_context *ctx = wimfs_get_context(); struct wim_inode *inode; - struct wim_inode_stream *existing_strm; + struct wim_inode_stream *strm; const utf16lechar *uname; int ret; @@ -1850,8 +1861,8 @@ wimfs_setxattr(const char *path, const char *name, if (ret) return -errno; - existing_strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname); - if (existing_strm) { + strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname); + if (strm) { ret = -EEXIST; if (flags & XATTR_CREATE) goto out_put_uname; @@ -1861,14 +1872,22 @@ wimfs_setxattr(const char *path, const char *name, goto out_put_uname; } - if (!inode_add_stream_with_data(inode, STREAM_TYPE_DATA, uname, - value, size, ctx->wim->blob_table)) - { - ret = -errno; - goto out_put_uname; + if (strm) { + if (!inode_replace_stream_data(inode, strm, value, size, + ctx->wim->blob_table)) + { + ret = -errno; + goto out_put_uname; + } + } else { + if (!inode_add_stream_with_data(inode, STREAM_TYPE_DATA, uname, + value, size, ctx->wim->blob_table)) + { + ret = -errno; + goto out_put_uname; + } } - if (existing_strm) - inode_remove_stream(inode, existing_strm, ctx->wim->blob_table); + ret = 0; out_put_uname: tstr_put_utf16le(uname); @@ -1883,8 +1902,8 @@ wimfs_symlink(const char *to, const char *from) struct wim_dentry *dentry; int ret; - ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777, 0, - FILE_ATTRIBUTE_REPARSE_POINT, &dentry); + ret = create_file(fuse_ctx, from, S_IFLNK | 0777, 0, + FILE_ATTRIBUTE_REPARSE_POINT, &dentry); if (ret) return ret; dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;