#define FUSE_USE_VERSION 26
+#include <sys/types.h> /* sometimes required before <attr/xattr.h> */
+
#include <attr/xattr.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
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;
}
}
- list_add_tail(&new_inode->i_list,
- &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
+ hlist_add_head(&new_inode->i_hlist,
+ &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
dentry_add_child(parent, new_dentry);
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.
*
}
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);
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;
}
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;
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:
close(ctx->parent_dir_fd);
}
-/* Number the inodes in the mounted image sequentially. */
static void
-reassign_inode_numbers(struct wimfs_context *ctx)
+prepare_inodes(struct wimfs_context *ctx)
{
struct wim_image_metadata *imd;
struct wim_inode *inode;
ctx->next_ino = 1;
imd = wim_get_current_image_metadata(ctx->wim);
- image_for_each_inode(inode, imd)
+ image_for_each_inode(inode, imd) {
inode->i_ino = ctx->next_ino++;
+ inode->i_num_opened_fds = 0;
+ inode->i_num_allocated_fds = 0;
+ inode->i_fds = NULL;
+ }
}
static void
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
static void
close_all_fds(struct wimfs_context *ctx)
{
- struct wim_inode *inode, *tmp;
+ struct wim_inode *inode;
+ struct hlist_node *tmp;
struct wim_image_metadata *imd;
imd = wim_get_current_image_metadata(ctx->wim);
- list_for_each_entry_safe(inode, tmp, &imd->inode_list, i_list)
+ image_for_each_inode_safe(inode, tmp, imd)
inode_close_fds(inode);
}
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
(!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;
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);
{
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;
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;
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);
return ret;
}
+ if (wim_has_solid_resources(wim)) {
+ WARNING("Mounting a WIM file containing solid-compressed data; "
+ "file access may be slow.");
+ }
+
/* If the user did not specify an interface for accessing named
* data streams, use the default (extended attributes). */
if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
}
}
- /* Assign new inode numbers. */
- reassign_inode_numbers(&ctx);
+ /* Number the inodes in the mounted image sequentially and initialize
+ * the file descriptor arrays */
+ prepare_inodes(&ctx);
/* If a read-write mount, mark the image as modified. */
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)