wimlib_mount_image(): Correctly return NOMEM in one case
[wimlib] / src / mount_image.c
index 5829e6a..41478d9 100644 (file)
@@ -41,6 +41,8 @@
 
 #include "wimlib/encoding.h"
 #include "wimlib/file_io.h"
+#include "wimlib/dentry.h"
+#include "wimlib/inode.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
 #include "wimlib/paths.h"
@@ -152,12 +154,6 @@ wimfs_get_WIMStruct(void)
        return wimfs_get_context()->wim;
 }
 
-static inline bool
-wimfs_ctx_readonly(const struct wimfs_context *ctx)
-{
-       return (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) == 0;
-}
-
 static inline int
 get_lookup_flags(const struct wimfs_context *ctx)
 {
@@ -168,7 +164,8 @@ get_lookup_flags(const struct wimfs_context *ctx)
 static inline int
 flags_writable(int open_flags)
 {
-       return open_flags & (O_RDWR | O_WRONLY);
+       int accmode = (open_flags & O_ACCMODE);
+       return (accmode == O_RDWR || accmode == O_WRONLY);
 }
 
 /*
@@ -178,7 +175,6 @@ flags_writable(int open_flags)
  * @stream_id: ID of the stream we're opening
  * @lte:       Lookup table entry for the stream (may be NULL)
  * @fd_ret:    Return the allocated file descriptor if successful.
- * @readonly:  True if this is a read-only mount.
  *
  * Return 0 iff successful or error code if unsuccessful.
  */
@@ -186,8 +182,7 @@ static int
 alloc_wimfs_fd(struct wim_inode *inode,
               u32 stream_id,
               struct wim_lookup_table_entry *lte,
-              struct wimfs_fd **fd_ret,
-              bool readonly)
+              struct wimfs_fd **fd_ret)
 {
        static const u16 fds_per_alloc = 8;
        static const u16 max_fds = 0xffff;
@@ -236,7 +231,7 @@ alloc_wimfs_fd(struct wim_inode *inode,
                        *fd_ret         = fd;
                        inode->i_fds[i] = fd;
                        inode->i_num_opened_fds++;
-                       if (lte && !readonly)
+                       if (lte)
                                lte->num_opened_fds++;
                        DEBUG("Allocated fd (idx = %u)", fd->idx);
                        ret = 0;
@@ -673,13 +668,14 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
                }
        }
 
+       lte_put_resource(new_lte);
        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);
+       add_unhashed_stream(new_lte, inode, stream_id,
+                           &wim_get_current_image_metadata(ctx->wim)->unhashed_streams);
        *retrieve_lte_pointer(new_lte) = new_lte;
        *lte = new_lte;
        return 0;
@@ -1526,10 +1522,12 @@ execute_fusermount(const char *dir, bool lazy)
                                 "terminate");
                return WIMLIB_ERR_FUSERMOUNT;
        }
-       if (status != 0) {
+
+       if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
                ERROR("`umount' did not successfully complete");
                return WIMLIB_ERR_FUSERMOUNT;
        }
+
        return 0;
 }
 
@@ -1870,8 +1868,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
                *back_ptr = lte;
        }
 
-       ret = alloc_wimfs_fd(inode, stream_id, lte, &fd,
-                            wimfs_ctx_readonly(ctx));
+       ret = alloc_wimfs_fd(inode, stream_id, lte, &fd);
        if (ret)
                return ret;
 
@@ -1905,7 +1902,7 @@ wimfs_opendir(const char *path, struct fuse_file_info *fi)
                return -errno;
        if (!inode_is_directory(inode))
                return -ENOTDIR;
-       ret = alloc_wimfs_fd(inode, 0, NULL, &fd, wimfs_ctx_readonly(ctx));
+       ret = alloc_wimfs_fd(inode, 0, NULL, &fd);
        fi->fh = (uintptr_t)fd;
        return ret;
 }
@@ -2029,7 +2026,7 @@ wimfs_readlink(const char *path, char *buf, size_t buf_len)
        if (!inode_is_symlink(inode))
                return -EINVAL;
        if (buf_len == 0)
-               return -ENAMETOOLONG;
+               return -EINVAL;
        ret = wim_inode_readlink(inode, buf, buf_len - 1, NULL);
        if (ret >= 0) {
                wimlib_assert(ret <= buf_len - 1);
@@ -2415,6 +2412,15 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        if (!wim || !dir)
                return WIMLIB_ERR_INVALID_PARAM;
 
+       if (mount_flags & ~(WIMLIB_MOUNT_FLAG_READWRITE |
+                           WIMLIB_MOUNT_FLAG_DEBUG |
+                           WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
+                           WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
+                           WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS |
+                           WIMLIB_MOUNT_FLAG_UNIX_DATA |
+                           WIMLIB_MOUNT_FLAG_ALLOW_OTHER))
+               return WIMLIB_ERR_INVALID_PARAM;
+
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
                ret = can_delete_from_wim(wim);
                if (ret)
@@ -2429,15 +2435,12 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
 
        imd = wim_get_current_image_metadata(wim);
 
-       if (imd->refcnt != 1) {
-               ERROR("Cannot mount image that was just exported with "
-                     "wimlib_export_image()");
-               return WIMLIB_ERR_INVALID_PARAM;
-       }
-
        if (imd->modified) {
-               ERROR("Cannot mount image that was added "
-                     "with wimlib_add_image()");
+               /* wimfs_read() only supports a limited number of stream
+                * locations, not including RESOURCE_IN_FILE_ON_DISK,
+                * RESOURCE_IN_NTFS_VOLUME, etc. that might appear if files were
+                * added to the WIM image.  */
+               ERROR("Cannot mount an image with newly added files!");
                return WIMLIB_ERR_INVALID_PARAM;
        }
 
@@ -2461,7 +2464,6 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        ctx.default_uid = getuid();
        ctx.default_gid = getgid();
        wimlib_assert(list_empty(&imd->unhashed_streams));
-       ctx.wim->lookup_table->unhashed_streams = &imd->unhashed_streams;
        if (mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
                ctx.default_lookup_flags = LOOKUP_FLAG_ADS_OK;
 
@@ -2474,8 +2476,10 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        DEBUG("Preparing arguments to fuse_main()");
 
        dir_copy = STRDUP(dir);
-       if (!dir_copy)
+       if (!dir_copy) {
+               ret = WIMLIB_ERR_NOMEM;
                goto out_free_message_queue_names;
+       }
 
        argc = 0;
        argv[argc++] = "wimlib";
@@ -2579,6 +2583,13 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
        int ret;
        struct wimfs_context wimfs_ctx;
 
+       if (unmount_flags & ~(WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY |
+                             WIMLIB_UNMOUNT_FLAG_COMMIT |
+                             WIMLIB_UNMOUNT_FLAG_REBUILD |
+                             WIMLIB_UNMOUNT_FLAG_RECOMPRESS |
+                             WIMLIB_UNMOUNT_FLAG_LAZY))
+               return WIMLIB_ERR_INVALID_PARAM;
+
        init_wimfs_context(&wimfs_ctx);
 
        ret = set_message_queue_names(&wimfs_ctx, dir);