]> wimlib.net Git - wimlib/blobdiff - src/mount_image.c
Initial update functionality (library only)
[wimlib] / src / mount_image.c
index a2e09b435e43a60a72db289e0839c747315ceeaa..0538fbc9a9da1d65dbc54e9306ad35e6b57e53aa 100644 (file)
@@ -299,6 +299,15 @@ close_wimfs_fd(struct wimfs_fd *fd)
        return 0;
 }
 
+static mode_t
+fuse_mask_mode(mode_t mode, struct fuse_context *fuse_ctx)
+{
+#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
+       mode &= ~fuse_ctx->umask;
+#endif
+       return mode;
+}
+
 /*
  * Add a new dentry with a new inode to a WIM image.
  *
@@ -337,7 +346,7 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path,
                if (inode_set_unix_data(new->d_inode,
                                        fuse_ctx->uid,
                                        fuse_ctx->gid,
-                                       mode & ~fuse_ctx->umask,
+                                       fuse_mask_mode(mode, fuse_ctx),
                                        wimfs_ctx->wim->lookup_table,
                                        UNIX_DATA_ALL | UNIX_DATA_CREATE))
                {
@@ -649,6 +658,7 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
 
        lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte,
                                     inode, stream_id);
+       *retrieve_lte_pointer(new_lte) = new_lte;
        *lte = new_lte;
        return 0;
 out_revert_fd_changes:
@@ -804,7 +814,6 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
        image_for_each_unhashed_stream_safe(lte, tmp, imd) {
                wimlib_assert(lte->unhashed);
                if (wim_resource_size(lte) == 0) {
-                       print_lookup_table_entry(lte, stderr);
                        struct wim_lookup_table_entry **back_ptr;
                        back_ptr = retrieve_lte_pointer(lte);
                        *back_ptr = NULL;
@@ -1493,13 +1502,6 @@ execute_fusermount(const char *dir)
        return 0;
 }
 
-#if 0
-static int wimfs_access(const char *path, int mask)
-{
-       return -ENOSYS;
-}
-#endif
-
 static int
 wimfs_chmod(const char *path, mode_t mask)
 {
@@ -1561,17 +1563,6 @@ wimfs_destroy(void *p)
        }
 }
 
-#if 0
-static int wimfs_fallocate(const char *path, int mode,
-                          off_t offset, off_t len, struct fuse_file_info *fi)
-{
-       struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
-       wimlib_assert(fd->staging_fd != -1);
-       return fallocate(fd->staging_fd, mode, offset, len);
-}
-
-#endif
-
 static int
 wimfs_fgetattr(const char *path, struct stat *stbuf,
               struct fuse_file_info *fi)
@@ -1648,8 +1639,8 @@ wimfs_getxattr(const char *path, const char *name, char *value,
        if (res_size > size)
                return -ERANGE;
 
-       ret = read_full_resource_into_buf(lte, value, true);
-       if (ret != 0)
+       ret = read_full_resource_into_buf(lte, value);
+       if (ret)
                return -EIO;
 
        return res_size;
@@ -1809,7 +1800,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
 
        ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
                              &dentry, &lte, &stream_idx);
-       if (ret != 0)
+       if (ret)
                return ret;
 
        inode = dentry->d_inode;
@@ -1834,15 +1825,14 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
                u64 size = (lte) ? wim_resource_size(lte) : 0;
                ret = extract_resource_to_staging_dir(inode, stream_id,
                                                      &lte, size, ctx);
-               if (ret != 0)
+               if (ret)
                        return ret;
                *back_ptr = lte;
        }
-       print_lookup_table_entry(lte, stderr);
 
        ret = alloc_wimfs_fd(inode, stream_id, lte, &fd,
                             wimfs_ctx_readonly(ctx));
-       if (ret != 0)
+       if (ret)
                return ret;
 
        if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
@@ -1892,26 +1882,33 @@ wimfs_read(const char *path, char *buf, size_t size,
        if (!fd)
                return -EBADF;
 
-       if (!fd->f_lte) /* Empty stream with no lookup table entry */
+       if (size == 0)
                return 0;
 
-       res_size = wim_resource_size(fd->f_lte);
+       if (fd->f_lte)
+               res_size = wim_resource_size(fd->f_lte);
+       else
+               res_size = 0;
+
        if (offset > res_size)
                return -EOVERFLOW;
-       size = min(size, INT_MAX);
+
        size = min(size, res_size - offset);
+       if (size == 0)
+               return 0;
 
        switch (fd->f_lte->resource_location) {
        case RESOURCE_IN_STAGING_FILE:
-               ret = pread(fd->staging_fd, buf, size, offset);
-               if (ret < 0)
+               ret = full_pread(fd->staging_fd, buf, size, offset);
+               if (ret != size)
                        ret = -errno;
                break;
        case RESOURCE_IN_WIM:
                if (read_partial_wim_resource_into_buf(fd->f_lte, size,
-                                                      offset, buf, true))
+                                                      offset, buf))
                        ret = -errno;
-               ret = size;
+               else
+                       ret = size;
                break;
        case RESOURCE_IN_ATTACHED_BUFFER:
                memcpy(buf, fd->f_lte->attached_buffer + offset, size);
@@ -1988,10 +1985,16 @@ wimfs_readlink(const char *path, char *buf, size_t buf_len)
                return -errno;
        if (!inode_is_symlink(inode))
                return -EINVAL;
-
-       ret = inode_readlink(inode, buf, buf_len, ctx->wim, true);
-       if (ret > 0)
+       if (buf_len == 0)
+               return -ENAMETOOLONG;
+       ret = wim_inode_readlink(inode, buf, buf_len - 1);
+       if (ret >= 0) {
+               wimlib_assert(ret <= buf_len - 1);
+               buf[ret] = '\0';
                ret = 0;
+       } else if (ret == -ENAMETOOLONG) {
+               buf[buf_len - 1] = '\0';
+       }
        return ret;
 }
 
@@ -2044,58 +2047,7 @@ wimfs_removexattr(const char *path, const char *name)
 static int
 wimfs_rename(const char *from, const char *to)
 {
-       struct wim_dentry *src;
-       struct wim_dentry *dst;
-       struct wim_dentry *parent_of_dst;
-       WIMStruct *w = wimfs_get_WIMStruct();
-       int ret;
-
-       /* This rename() implementation currently only supports actual files
-        * (not alternate data streams) */
-
-       src = get_dentry(w, from);
-       if (!src)
-               return -errno;
-
-       dst = get_dentry(w, to);
-
-       if (dst) {
-               /* Destination file exists */
-
-               if (src == dst) /* Same file */
-                       return 0;
-
-               if (!dentry_is_directory(src)) {
-                       /* Cannot rename non-directory to directory. */
-                       if (dentry_is_directory(dst))
-                               return -EISDIR;
-               } else {
-                       /* Cannot rename directory to a non-directory or a non-empty
-                        * directory */
-                       if (!dentry_is_directory(dst))
-                               return -ENOTDIR;
-                       if (inode_has_children(dst->d_inode))
-                               return -ENOTEMPTY;
-               }
-               parent_of_dst = dst->parent;
-       } else {
-               /* Destination does not exist */
-               parent_of_dst = get_parent_dentry(w, to);
-               if (!parent_of_dst)
-                       return -errno;
-
-               if (!dentry_is_directory(parent_of_dst))
-                       return -ENOTDIR;
-       }
-
-       ret = set_dentry_name(src, path_basename(to));
-       if (ret != 0)
-               return -ENOMEM;
-       if (dst)
-               remove_dentry(dst, w->lookup_table);
-       unlink_dentry(src);
-       dentry_add_child(parent_of_dst, src);
-       return 0;
+       return rename_wim_path(wimfs_get_WIMStruct(), from, to);
 }
 
 /* Remove a directory */
@@ -2175,11 +2127,14 @@ wimfs_symlink(const char *to, const char *from)
                            FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
        if (ret == 0) {
                dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
-               if (inode_set_symlink(dentry->d_inode, to,
-                                     wimfs_ctx->wim->lookup_table, NULL))
-               {
+               ret = wim_inode_set_symlink(dentry->d_inode, to,
+                                           wimfs_ctx->wim->lookup_table);
+               if (ret) {
                        remove_dentry(dentry, wimfs_ctx->wim->lookup_table);
-                       ret = -ENOMEM;
+                       if (ret == WIMLIB_ERR_NOMEM)
+                               ret = -ENOMEM;
+                       else
+                               ret = -EIO;
                }
        }
        return ret;
@@ -2216,13 +2171,19 @@ wimfs_truncate(const char *path, off_t size)
        } else {
                /* File in WIM.  Extract it to the staging directory, but only
                 * the first @size bytes of it. */
+               struct wim_lookup_table_entry **back_ptr;
+
                inode = dentry->d_inode;
-               if (stream_idx == 0)
+               if (stream_idx == 0) {
                        stream_id = 0;
-               else
+                       back_ptr = &inode->i_lte;
+               } else {
                        stream_id = inode->i_ads_entries[stream_idx - 1].stream_id;
+                       back_ptr = &inode->i_ads_entries[stream_idx - 1].lte;
+               }
                ret = extract_resource_to_staging_dir(inode, stream_id,
                                                      &lte, size, ctx);
+               *back_ptr = lte;
        }
        return ret;
 }
@@ -2321,8 +2282,8 @@ wimfs_write(const char *path, const char *buf, size_t size,
        wimlib_assert(fd->f_inode != NULL);
 
        /* Write the data. */
-       ret = pwrite(fd->staging_fd, buf, size, offset);
-       if (ret == -1)
+       ret = full_pwrite(fd->staging_fd, buf, size, offset);
+       if (ret != size)
                return -errno;
 
        /* Update file size */
@@ -2339,15 +2300,9 @@ wimfs_write(const char *path, const char *buf, size_t size,
 }
 
 static struct fuse_operations wimfs_operations = {
-#if 0
-       .access      = wimfs_access,
-#endif
        .chmod       = wimfs_chmod,
        .chown       = wimfs_chown,
        .destroy     = wimfs_destroy,
-#if 0
-       .fallocate   = wimfs_fallocate,
-#endif
        .fgetattr    = wimfs_fgetattr,
        .ftruncate   = wimfs_ftruncate,
        .getattr     = wimfs_getattr,
@@ -2472,7 +2427,7 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        }
 
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
-               ret = lock_wim(wim, wim->fp);
+               ret = lock_wim(wim, wim->in_fd);
                if (ret)
                        goto out;
        }
@@ -2559,10 +2514,8 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
 #endif
 
        /* Mark dentry tree as modified if read-write mount. */
-       if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
+       if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
                imd->modified = 1;
-               imd->has_been_mounted_rw = 1;
-       }
 
        /* Resolve the lookup table entries for every inode in the image, and
         * assign inode numbers */