]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
lz_sarray: Performance and memory usage optimizations
[wimlib] / src / mount_image.c
index 85c0dee4c88d6ae848e76258e8ab37ad5b6b83ad..02a863c9b6ac55b47e09e01080bad6f085eaaefc 100644 (file)
@@ -329,7 +329,7 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
        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;
 
@@ -337,7 +337,7 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
                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);
@@ -367,6 +367,17 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
        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.
  *
@@ -434,7 +445,7 @@ inode_to_stbuf(const struct wim_inode *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
@@ -482,7 +493,7 @@ create_staging_file(char **name_ret, struct wimfs_context *ctx)
        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;
@@ -568,9 +579,8 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
        if (old_lte) {
                struct filedes wimlib_fd;
                filedes_init(&wimlib_fd, fd);
-               extract_size = min(wim_resource_size(old_lte), size);
-               ret = extract_wim_resource_to_fd(old_lte, &wimlib_fd,
-                                                extract_size);
+               extract_size = min(old_lte->size, size);
+               ret = extract_stream_to_fd(old_lte, &wimlib_fd, extract_size);
        } else {
                ret = 0;
                extract_size = 0;
@@ -663,10 +673,10 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
                }
        }
 
-       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);
@@ -825,7 +835,7 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
        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;
@@ -864,7 +874,7 @@ set_message_queue_names(struct wimfs_context *ctx, const char *mount_dir)
        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)
@@ -1539,8 +1549,8 @@ wimfs_chmod(const char *path, mode_t mask)
        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;
 
@@ -1560,8 +1570,8 @@ wimfs_chown(const char *path, uid_t uid, gid_t gid)
        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;
 
@@ -1606,7 +1616,7 @@ wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
        if (ret)
                return -errno;
        touch_inode(fd->f_inode);
-       fd->f_lte->resource_entry.original_size = size;
+       fd->f_lte->size = size;
        return 0;
 }
 
@@ -1621,9 +1631,10 @@ wimfs_getattr(const char *path, struct stat *stbuf)
        int ret;
        struct wimfs_context *ctx = wimfs_get_context();
 
-       ret = lookup_resource(ctx->wim, path,
-                             get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
-                             &dentry, &lte, NULL);
+       ret = wim_pathname_to_stream(ctx->wim, path,
+                                    get_lookup_flags(ctx) |
+                                       LOOKUP_FLAG_DIRECTORY_OK,
+                                    &dentry, &lte, NULL);
        if (ret != 0)
                return ret;
        return inode_to_stbuf(dentry->d_inode, lte, stbuf);
@@ -1638,14 +1649,14 @@ wimfs_getxattr(const char *path, const char *name, char *value,
        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;
 
@@ -1658,22 +1669,22 @@ wimfs_getxattr(const char *path, const char *name, char *value,
                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);
+       ret = read_full_stream_into_buf(lte, value);
        if (ret) {
                if (errno)
                        return -errno;
                else
                        return -EIO;
        }
-       return res_size;
+       return stream_size;
 }
 #endif
 
@@ -1695,14 +1706,15 @@ wimfs_link(const char *to, const char *from)
                                   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);
@@ -1739,6 +1751,10 @@ wimfs_listxattr(const char *path, char *list, size_t size)
 
        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;
@@ -1828,8 +1844,8 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
        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, &lte, &stream_idx);
+       ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+                                    &dentry, &lte, &stream_idx);
        if (ret)
                return ret;
 
@@ -1852,7 +1868,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
 
        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,
                                                      &lte, size, ctx);
                if (ret)
@@ -1910,7 +1926,7 @@ wimfs_read(const char *path, char *buf, size_t size,
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        ssize_t ret;
-       u64 res_size;
+       u64 stream_size;
 
        if (!fd)
                return -EBADF;
@@ -1919,14 +1935,14 @@ wimfs_read(const char *path, char *buf, size_t size,
                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;
 
@@ -1937,9 +1953,9 @@ wimfs_read(const char *path, char *buf, size_t size,
                        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;
@@ -2080,7 +2096,8 @@ wimfs_removexattr(const char *path, const char *name)
 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 */
@@ -2090,7 +2107,7 @@ wimfs_rmdir(const char *path)
        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;
 
@@ -2119,7 +2136,7 @@ wimfs_setxattr(const char *path, const char *name,
        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;
 
@@ -2186,8 +2203,8 @@ wimfs_truncate(const char *path, off_t size)
        struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
 
-       ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
-                             &dentry, &lte, &stream_idx);
+       ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+                                    &dentry, &lte, &stream_idx);
 
        if (ret != 0)
                return ret;
@@ -2200,7 +2217,7 @@ wimfs_truncate(const char *path, off_t 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. */
@@ -2231,13 +2248,13 @@ wimfs_unlink(const char *path)
        u16 stream_idx;
        struct wimfs_context *ctx = wimfs_get_context();
 
-       ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
-                             &dentry, &lte, &stream_idx);
+       ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
+                                    &dentry, &lte, &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,
@@ -2258,7 +2275,7 @@ wimfs_utimens(const char *path, const struct timespec tv[2])
        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;
@@ -2285,7 +2302,7 @@ wimfs_utime(const char *path, struct utimbuf *times)
        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;
@@ -2320,11 +2337,10 @@ wimfs_write(const char *path, const char *buf, size_t size,
                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 */