#include "wimlib/paths.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
-#include "wimlib/swm.h"
#include "wimlib/timestamp.h"
#include "wimlib/version.h"
#include "wimlib/write.h"
/* Name and message queue descriptors for message queues between the
* filesystem daemon process and the unmount process. These are used
* when the filesystem is unmounted and the process running
- * wimlib_unmount_image() (i.e. the `imagex unmount' command) needs to
- * communicate with the filesystem daemon running fuse_main() (i.e. the
- * daemon created by the `imagex mount' or `imagex mountrw' commands */
+ * wimlib_unmount_image() needs to communicate with the filesystem
+ * daemon running fuse_main() (i.e. the process created by a call to
+ * wimlib_mount_image(). */
char *unmount_to_daemon_mq_name;
char *daemon_to_unmount_mq_name;
mqd_t unmount_to_daemon_mq;
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
int ret;
- parent = get_parent_dentry(wimfs_ctx->wim, path);
+ parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
if (!parent)
return -errno;
return -ENOTDIR;
basename = path_basename(path);
- if (get_dentry_child_with_name(parent, basename))
+ if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
return -EEXIST;
ret = new_dentry_with_inode(basename, &new);
return 0;
}
+static struct wim_inode *
+wim_pathname_to_inode(WIMStruct *wim, const tchar *path)
+{
+ struct wim_dentry *dentry;
+ dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
+ if (dentry)
+ return dentry->d_inode;
+ else
+ return NULL;
+}
+
/* Remove a dentry from a mounted WIM image; i.e. remove an alias for the
* corresponding inode.
*
stbuf->st_ino = (ino_t)inode->i_ino;
stbuf->st_nlink = inode->i_nlink;
if (lte)
- stbuf->st_size = wim_resource_size(lte);
+ stbuf->st_size = lte->size;
else
stbuf->st_size = 0;
#ifdef HAVE_STAT_NANOSECOND_PRECISION
static const size_t STAGING_FILE_NAME_LEN = 20;
name_len = ctx->staging_dir_name_len + 1 + STAGING_FILE_NAME_LEN;
- name = MALLOC(name_len + 1);
+ name = MALLOC(name_len + 1);
if (!name) {
errno = ENOMEM;
return -1;
/* Extract the stream to the staging file (possibly truncated) */
if (old_lte) {
- struct filedes wimlib_fd = {.fd = fd};
- extract_size = min(wim_resource_size(old_lte), size);
- ret = extract_wim_resource_to_fd(old_lte, &wimlib_fd,
- extract_size);
+ struct filedes wimlib_fd;
+ filedes_init(&wimlib_fd, fd);
+ extract_size = min(old_lte->size, size);
+ ret = extract_stream_to_fd(old_lte, &wimlib_fd, extract_size);
} else {
ret = 0;
extract_size = 0;
}
}
- new_lte->refcnt = inode->i_nlink;
- new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
- new_lte->staging_file_name = staging_file_name;
- new_lte->resource_entry.original_size = size;
+ new_lte->refcnt = inode->i_nlink;
+ new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
+ new_lte->staging_file_name = staging_file_name;
+ new_lte->size = size;
lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte,
inode, stream_id);
DEBUG("Freeing entries for zero-length streams");
image_for_each_unhashed_stream_safe(lte, tmp, imd) {
wimlib_assert(lte->unhashed);
- if (wim_resource_size(lte) == 0) {
+ if (lte->size == 0) {
struct wim_lookup_table_entry **back_ptr;
back_ptr = retrieve_lte_pointer(lte);
*back_ptr = NULL;
char *p;
int ret;
- dir_path = realpath(mount_dir, NULL);
+ dir_path = realpath(mount_dir, NULL);
if (!dir_path) {
ERROR_WITH_ERRNO("Failed to resolve path \"%s\"", mount_dir);
if (errno == ENOMEM)
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
return -EPERM;
- ret = lookup_resource(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
- &dentry, NULL, NULL);
+ ret = wim_pathname_to_stream(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
+ &dentry, NULL, NULL);
if (ret)
return ret;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
return -EPERM;
- ret = lookup_resource(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
- &dentry, NULL, NULL);
+ ret = wim_pathname_to_stream(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
+ &dentry, NULL, NULL);
if (ret)
return ret;
if (ret)
return -errno;
touch_inode(fd->f_inode);
- fd->f_lte->resource_entry.original_size = size;
+ fd->f_lte->size = size;
return 0;
}
int ret;
struct wimfs_context *ctx = wimfs_get_context();
- ret = lookup_resource(ctx->wim, path,
- get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
- &dentry, <e, NULL);
+ ret = wim_pathname_to_stream(ctx->wim, path,
+ get_lookup_flags(ctx) |
+ LOOKUP_FLAG_DIRECTORY_OK,
+ &dentry, <e, NULL);
if (ret != 0)
return ret;
return inode_to_stbuf(dentry->d_inode, lte, stbuf);
int ret;
struct wim_inode *inode;
struct wim_ads_entry *ads_entry;
- size_t res_size;
+ u64 stream_size;
struct wim_lookup_table_entry *lte;
struct wimfs_context *ctx = wimfs_get_context();
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
- if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
+ if (strlen(name) <= 5 || memcmp(name, "user.", 5) != 0)
return -ENOATTR;
name += 5;
return -ENOATTR;
lte = ads_entry->lte;
- res_size = wim_resource_size(lte);
+ stream_size = lte->size;
if (size == 0)
- return res_size;
+ return stream_size;
- if (res_size > size)
+ if (stream_size > size)
return -ERANGE;
- ret = read_full_resource_into_buf(lte, value);
- if (ret)
- return -errno;
-
- return res_size;
+ ret = read_full_stream_into_buf(lte, value);
+ if (ret) {
+ if (errno)
+ return -errno;
+ else
+ return -EIO;
+ }
+ return stream_size;
}
#endif
FILE_ATTRIBUTE_REPARSE_POINT))
return -EPERM;
- from_dentry_parent = get_parent_dentry(wim, from);
+ from_dentry_parent = get_parent_dentry(wim, from, WIMLIB_CASE_SENSITIVE);
if (!from_dentry_parent)
return -errno;
if (!dentry_is_directory(from_dentry_parent))
return -ENOTDIR;
link_name = path_basename(from);
- if (get_dentry_child_with_name(from_dentry_parent, link_name))
+ if (get_dentry_child_with_name(from_dentry_parent, link_name,
+ WIMLIB_CASE_SENSITIVE))
return -EEXIST;
ret = new_dentry(link_name, &from_dentry);
p = list;
for (i = 0; i < inode->i_num_ads; i++) {
+
+ if (!ads_entry_is_named_stream(&inode->i_ads_entries[i]))
+ continue;
+
char *stream_name_mbs;
size_t stream_name_mbs_nbytes;
int ret;
struct wimfs_context *ctx = wimfs_get_context();
struct wim_lookup_table_entry **back_ptr;
- ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
- &dentry, <e, &stream_idx);
+ ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+ &dentry, <e, &stream_idx);
if (ret)
return ret;
if (flags_writable(fi->flags) &&
(!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
- u64 size = (lte) ? wim_resource_size(lte) : 0;
+ u64 size = (lte) ? lte->size : 0;
ret = extract_resource_to_staging_dir(inode, stream_id,
<e, size, ctx);
if (ret)
{
struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
ssize_t ret;
- u64 res_size;
+ u64 stream_size;
if (!fd)
return -EBADF;
return 0;
if (fd->f_lte)
- res_size = wim_resource_size(fd->f_lte);
+ stream_size = fd->f_lte->size;
else
- res_size = 0;
+ stream_size = 0;
- if (offset > res_size)
+ if (offset > stream_size)
return -EOVERFLOW;
- size = min(size, res_size - offset);
+ size = min(size, stream_size - offset);
if (size == 0)
return 0;
ret = -errno;
break;
case RESOURCE_IN_WIM:
- if (read_partial_wim_resource_into_buf(fd->f_lte, size,
- offset, buf))
- ret = -errno;
+ if (read_partial_wim_stream_into_buf(fd->f_lte, size,
+ offset, buf))
+ ret = errno ? -errno : -EIO;
else
ret = size;
break;
static int
wimfs_rename(const char *from, const char *to)
{
- return rename_wim_path(wimfs_get_WIMStruct(), from, to);
+ return rename_wim_path(wimfs_get_WIMStruct(), from, to,
+ WIMLIB_CASE_SENSITIVE);
}
/* Remove a directory */
struct wim_dentry *dentry;
WIMStruct *wim = wimfs_get_WIMStruct();
- dentry = get_dentry(wim, path);
+ dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (!dentry)
return -errno;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
- if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
+ if (strlen(name) <= 5 || memcmp(name, "user.", 5) != 0)
return -ENOATTR;
name += 5;
struct wim_inode *inode;
struct wimfs_context *ctx = wimfs_get_context();
- ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
- &dentry, <e, &stream_idx);
+ ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+ &dentry, <e, &stream_idx);
if (ret != 0)
return ret;
if (lte == NULL && size == 0)
return 0;
- if (lte->resource_location == RESOURCE_IN_STAGING_FILE) {
+ if (lte != NULL && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
ret = truncate(lte->staging_file_name, size);
if (ret)
ret = -errno;
else
- lte->resource_entry.original_size = size;
+ lte->size = size;
} else {
/* File in WIM. Extract it to the staging directory, but only
* the first @size bytes of it. */
u16 stream_idx;
struct wimfs_context *ctx = wimfs_get_context();
- ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
- &dentry, <e, &stream_idx);
+ ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+ &dentry, <e, &stream_idx);
if (ret != 0)
return ret;
- if (stream_idx == 0)
+ if (inode_stream_name_nbytes(dentry->d_inode, stream_idx) == 0)
remove_dentry(dentry, ctx->wim->lookup_table);
else
inode_remove_ads(dentry->d_inode, stream_idx - 1,
struct wim_inode *inode;
WIMStruct *wim = wimfs_get_WIMStruct();
- dentry = get_dentry(wim, path);
+ dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (!dentry)
return -errno;
inode = dentry->d_inode;
struct wim_inode *inode;
WIMStruct *wim = wimfs_get_WIMStruct();
- dentry = get_dentry(wim, path);
+ dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (!dentry)
return -errno;
inode = dentry->d_inode;
return -errno;
/* Update file size */
- if (offset + size > fd->f_lte->resource_entry.original_size) {
+ if (offset + size > fd->f_lte->size) {
DEBUG("Update file size %"PRIu64 " => %"PRIu64"",
- fd->f_lte->resource_entry.original_size,
- offset + size);
- fd->f_lte->resource_entry.original_size = offset + size;
+ fd->f_lte->size, offset + size);
+ fd->f_lte->size = offset + size;
}
/* Update timestamps */
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
- int mount_flags, WIMStruct **additional_swms,
- unsigned num_additional_swms,
- const char *staging_dir)
+ int mount_flags, const char *staging_dir)
{
int argc;
char *argv[16];
DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
wim, image, dir, mount_flags);
- if (!wim || !dir) {
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out;
- }
-
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- goto out;
+ if (!wim || !dir)
+ return WIMLIB_ERR_INVALID_PARAM;
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = can_delete_from_wim(wim);
if (ret)
- goto out;
+ return ret;
}
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
-
ret = select_wim_image(wim, image);
if (ret)
- goto out_restore_lookup_table;
+ return ret;
DEBUG("Selected image %d", image);
if (imd->refcnt != 1) {
ERROR("Cannot mount image that was just exported with "
"wimlib_export_image()");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out_restore_lookup_table;
+ return WIMLIB_ERR_INVALID_PARAM;
}
if (imd->modified) {
ERROR("Cannot mount image that was added "
"with wimlib_add_image()");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out_restore_lookup_table;
+ return WIMLIB_ERR_INVALID_PARAM;
}
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = lock_wim(wim, wim->in_fd.fd);
if (ret)
- goto out_restore_lookup_table;
+ return ret;
}
/* Use default stream interface if one was not specified */
goto out_free_message_queue_names;
argc = 0;
- argv[argc++] = IMAGEX_PROGNAME;
+ argv[argc++] = "wimlib";
argv[argc++] = dir_copy;
/* disable multi-threaded operation */
wim->wim_locked = 0;
out_free_message_queue_names:
free_message_queue_names(&ctx);
-out_restore_lookup_table:
- if (num_additional_swms)
- unmerge_lookup_table(wim);
-out:
return ret;
}
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
- int mount_flags, WIMStruct **additional_swms,
- unsigned num_additional_swms,
- const tchar *staging_dir)
+ int mount_flags, const tchar *staging_dir)
{
return mount_unsupported_error();
}