]> wimlib.net Git - wimlib/blobdiff - src/mount.c
Use __builtin_bswap64() only if supported
[wimlib] / src / mount.c
index d5f43718d85833311514481feaa08897893aeab4..fa30aaeae255a0e9aa885cea62e59a629e16e914 100644 (file)
@@ -54,7 +54,7 @@
 /* File descriptor to a file open on the WIM filesystem. */
 struct wimlib_fd {
        struct inode *f_inode;
-       struct lookup_table_entry *lte;
+       struct lookup_table_entry *f_lte;
        int staging_fd;
        u16 idx;
        u32 stream_id;
@@ -130,7 +130,7 @@ static int alloc_wimlib_fd(struct inode *inode,
                        return -EMFILE;
                num_new_fds = min(fds_per_alloc,
                                  max_fds - inode->num_allocated_fds);
-               
+
                fds = REALLOC(inode->fds,
                              (inode->num_allocated_fds + num_new_fds) *
                                sizeof(inode->fds[0]));
@@ -147,7 +147,7 @@ static int alloc_wimlib_fd(struct inode *inode,
                        if (!fd)
                                return -ENOMEM;
                        fd->f_inode    = inode;
-                       fd->lte        = lte;
+                       fd->f_lte      = lte;
                        fd->staging_fd = -1;
                        fd->idx        = i;
                        fd->stream_id  = stream_id;
@@ -180,17 +180,16 @@ static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd)
 static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd)
 {
        wimlib_assert(fd);
-       wimlib_assert(fd->lte == lte);
+       wimlib_assert(fd->f_lte == lte);
 
        if (!lte) /* Empty stream with no lookup table entry */
                return 0;
 
        /* Close staging file descriptor if needed. */
-       wimlib_assert(lte->num_opened_fds);
 
-       if (lte->resource_location == RESOURCE_IN_STAGING_FILE) {
-               wimlib_assert(lte->staging_file_name);
-               wimlib_assert(fd->staging_fd != -1);
+       if (lte->resource_location == RESOURCE_IN_STAGING_FILE
+            && fd->staging_fd != -1)
+       {
                if (close(fd->staging_fd) != 0) {
                        ERROR_WITH_ERRNO("Failed to close staging file");
                        return -errno;
@@ -208,7 +207,7 @@ static int close_wimlib_fd(struct wimlib_fd *fd)
        DEBUG("Closing fd (inode = %lu, opened = %u, allocated = %u)",
              fd->f_inode->ino, fd->f_inode->num_opened_fds,
              fd->f_inode->num_allocated_fds);
-       ret = lte_put_fd(fd->lte, fd);
+       ret = lte_put_fd(fd->f_lte, fd);
        if (ret != 0)
                return ret;
 
@@ -287,7 +286,7 @@ static int create_staging_file(char **name_ret, int open_flags)
 
        DEBUG("Creating staging file `%s'", name);
 
-       fd = open(name, open_flags | O_CREAT | O_TRUNC, 0600); 
+       fd = open(name, open_flags | O_CREAT | O_TRUNC, 0600);
        if (fd == -1) {
                errno_save = errno;
                FREE(name);
@@ -298,7 +297,7 @@ static int create_staging_file(char **name_ret, int open_flags)
        return fd;
 }
 
-/* 
+/*
  * Extract a WIM resource to the staging directory.
  *
  * @inode:  Inode that contains the stream we are extracting
@@ -322,6 +321,9 @@ static int extract_resource_to_staging_dir(struct inode *inode,
        int fd;
        struct lookup_table_entry *old_lte, *new_lte;
 
+       DEBUG("Extracting resource to staging dir: inode %"PRIu64", "
+             "stream id %"PRIu32, inode->ino, stream_id);
+
        old_lte = *lte;
        fd = create_staging_file(&staging_file_name, O_WRONLY);
        if (fd == -1)
@@ -375,7 +377,7 @@ static int extract_resource_to_staging_dir(struct inode *inode,
                 * opening it read-write.  Identify those file descriptors and
                 * change their lookup table entry pointers to point to the new
                 * lookup table entry, and open staging file descriptors for
-                * them. 
+                * them.
                 *
                 * At the same time, we need to count the number of these opened
                 * file descriptors to the new lookup table entry.  If there's
@@ -385,8 +387,9 @@ static int extract_resource_to_staging_dir(struct inode *inode,
                        struct wimlib_fd *fd = inode->fds[i];
                        if (fd) {
                                if (fd->stream_id == stream_id) {
-                                       wimlib_assert(fd->lte == old_lte);
-                                       fd->lte = new_lte;
+                                       wimlib_assert(fd->f_lte == old_lte);
+                                       wimlib_assert(fd->staging_fd == -1);
+                                       fd->f_lte = new_lte;
                                        new_lte->num_opened_fds++;
                                        fd->staging_fd = open(staging_file_name, O_RDONLY);
                                        if (fd->staging_fd == -1) {
@@ -407,9 +410,9 @@ static int extract_resource_to_staging_dir(struct inode *inode,
 
        new_lte->resource_entry.original_size = size;
        new_lte->refcnt                       = inode->link_count;
-       new_lte->staging_file_name            = staging_file_name;
        new_lte->resource_location            = RESOURCE_IN_STAGING_FILE;
-       new_lte->lte_inode                        = inode;
+       new_lte->staging_file_name            = staging_file_name;
+       new_lte->lte_inode                    = inode;
        random_hash(new_lte->hash);
 
        if (stream_id == 0)
@@ -426,8 +429,8 @@ static int extract_resource_to_staging_dir(struct inode *inode,
 out_revert_fd_changes:
        for (u16 i = 0, j = 0; j < new_lte->num_opened_fds; i++) {
                struct wimlib_fd *fd = inode->fds[i];
-               if (fd && fd->stream_id == stream_id && fd->lte == new_lte) {
-                       fd->lte = old_lte;
+               if (fd && fd->stream_id == stream_id && fd->f_lte == new_lte) {
+                       fd->f_lte = old_lte;
                        if (fd->staging_fd != -1) {
                                close(fd->staging_fd);
                                fd->staging_fd = -1;
@@ -443,7 +446,7 @@ out_delete_staging_file:
        return ret;
 }
 
-/* 
+/*
  * Creates a randomly named staging directory and returns its name into the
  * static variable staging_dir_name.
  *
@@ -492,13 +495,13 @@ static int remove_file_or_directory(const char *fpath, const struct stat *sb,
 }
 
 
-/* 
- * Deletes the staging directory and all the files contained in it. 
+/*
+ * Deletes the staging directory and all the files contained in it.
  */
 static int delete_staging_dir()
 {
        int ret;
-       
+
        ret = nftw(staging_dir_name, remove_file_or_directory,10, FTW_DEPTH);
        staging_dir_name = NULL;
        return ret;
@@ -516,7 +519,7 @@ static mqd_t unmount_to_daemon_mq;
 static mqd_t daemon_to_unmount_mq;
 
 /* Simple function that returns the concatenation of 4 strings. */
-static char *strcat_dup(const char *s1, const char *s2, const char *s3, 
+static char *strcat_dup(const char *s1, const char *s2, const char *s3,
                        const char *s4)
 {
        size_t len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4) + 1;
@@ -551,7 +554,7 @@ static void s_slashes_underscores_g(char *s)
        }
 }
 
-/* 
+/*
  * Opens two POSIX message queue: one for sending messages from the unmount
  * process to the daemon process, and one to go the other way.  The names of the
  * message queues, which must be system-wide unique, are be based on the mount
@@ -596,7 +599,7 @@ static int open_message_queues(bool daemon)
        else
                flags = O_WRONLY | O_CREAT;
 
-       unmount_to_daemon_mq = mq_open(unmount_to_daemon_mq_name, flags, 
+       unmount_to_daemon_mq = mq_open(unmount_to_daemon_mq_name, flags,
                                       0700, NULL);
 
        if (unmount_to_daemon_mq == (mqd_t)-1) {
@@ -610,7 +613,7 @@ static int open_message_queues(bool daemon)
        else
                flags = O_RDONLY | O_CREAT;
 
-       daemon_to_unmount_mq = mq_open(daemon_to_unmount_mq_name, flags, 
+       daemon_to_unmount_mq = mq_open(daemon_to_unmount_mq_name, flags,
                                       0700, NULL);
 
        if (daemon_to_unmount_mq == (mqd_t)-1) {
@@ -673,6 +676,22 @@ static int wimfs_access(const char *path, int mask)
        return 0;
 }
 
+static void inode_update_lte_ptr(struct inode *inode,
+                                struct lookup_table_entry *old_lte,
+                                struct lookup_table_entry *new_lte)
+{
+       if (inode->lte == old_lte) {
+               inode->lte = new_lte;
+       } else {
+               for (unsigned i = 0; i < inode->num_ads; i++) {
+                       if (inode->ads_entries[i].lte == old_lte) {
+                               inode->ads_entries[i].lte = new_lte;
+                               break;
+                       }
+               }
+       }
+}
+
 static int update_lte_of_staging_file(struct lookup_table_entry *lte,
                                      struct lookup_table *table)
 {
@@ -696,27 +715,34 @@ static int update_lte_of_staging_file(struct lookup_table_entry *lte,
                /* Merge duplicate lookup table entries */
                duplicate_lte->refcnt += lte->refcnt;
                list_del(&lte->staging_list);
+               inode_update_lte_ptr(lte->lte_inode, lte, duplicate_lte);
                free_lookup_table_entry(lte);
        } else {
                if (stat(lte->staging_file_name, &stbuf) != 0) {
                        ERROR_WITH_ERRNO("Failed to stat `%s'", lte->staging_file_name);
                        return WIMLIB_ERR_STAT;
                }
-               wimlib_assert(&lte->file_on_disk == &lte->staging_file_name);
-               lte->resource_location = RESOURCE_IN_FILE_ON_DISK;
-               copy_hash(lte->hash, hash);
-               lte->resource_entry.original_size = stbuf.st_size;
-               lte->resource_entry.size = stbuf.st_size;
-               lte->lte_inode = NULL;
-               lookup_table_insert(table, lte);
+               if (stbuf.st_size == 0) {
+                       /* Zero-length stream.  No lookup table entry needed. */
+                       inode_update_lte_ptr(lte->lte_inode, lte, NULL);
+                       free_lookup_table_entry(lte);
+               } else {
+                       wimlib_assert(&lte->file_on_disk == &lte->staging_file_name);
+                       lte->resource_entry.original_size = stbuf.st_size;
+                       lte->resource_entry.size = stbuf.st_size;
+                       lte->resource_location = RESOURCE_IN_FILE_ON_DISK;
+                       lte->lte_inode = NULL;
+                       copy_hash(lte->hash, hash);
+                       lookup_table_insert(table, lte);
+               }
        }
-
        return 0;
 }
 
 static int inode_close_fds(struct inode *inode)
 {
-       for (u16 i = 0, j = 0; j < inode->num_opened_fds; i++) {
+       u16 num_opened_fds = inode->num_opened_fds;
+       for (u16 i = 0, j = 0; j < num_opened_fds; i++) {
                struct wimlib_fd *fd = inode->fds[i];
                if (fd) {
                        wimlib_assert(fd->f_inode == inode);
@@ -729,11 +755,6 @@ static int inode_close_fds(struct inode *inode)
        return 0;
 }
 
-/*static int dentry_close_fds(struct dentry *dentry, void *ignore)*/
-/*{*/
-       /*return inode_close_fds(dentry->d_inode);*/
-/*}*/
-
 /* Overwrites the WIM file, with changes saved. */
 static int rebuild_wim(WIMStruct *w, bool check_integrity)
 {
@@ -747,9 +768,6 @@ static int rebuild_wim(WIMStruct *w, bool check_integrity)
                if (ret != 0)
                        return ret;
        }
-       /*ret = for_dentry_in_tree(wim_root_dentry(w), dentry_close_fds, NULL);*/
-       /*if (ret != 0)*/
-               /*return ret;*/
 
        DEBUG("Calculating SHA1 checksums for all new staging files.");
        list_for_each_entry_safe(lte, tmp, &staging_list, staging_list) {
@@ -802,7 +820,7 @@ static void wimfs_destroy(void *p)
        DEBUG("Waiting for message telling us whether to commit or not, and "
              "whether to include integrity checks.");
 
-       bytes_received = mq_timedreceive(unmount_to_daemon_mq, msg, 
+       bytes_received = mq_timedreceive(unmount_to_daemon_mq, msg,
                                         msgsize, NULL, &timeout);
        commit = msg[0];
        check_integrity = msg[1];
@@ -861,7 +879,7 @@ static int wimfs_fgetattr(const char *path, struct stat *stbuf,
                          struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
-       return inode_to_stbuf(fd->f_inode, fd->lte, stbuf);
+       return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
 }
 
 static int wimfs_ftruncate(const char *path, off_t size,
@@ -871,8 +889,8 @@ static int wimfs_ftruncate(const char *path, off_t size,
        int ret = ftruncate(fd->staging_fd, size);
        if (ret != 0)
                return ret;
-       if (fd->lte && size < fd->lte->resource_entry.original_size)
-               fd->lte->resource_entry.original_size = size;
+       if (fd->f_lte && size < fd->f_lte->resource_entry.original_size)
+               fd->f_lte->resource_entry.original_size = size;
        return 0;
 }
 
@@ -899,7 +917,7 @@ static int wimfs_getxattr(const char *path, const char *name, char *value,
                          size_t size)
 {
        int ret;
-       struct dentry *dentry;
+       struct inode *inode;
        struct ads_entry *ads_entry;
        size_t res_size;
        struct lookup_table_entry *lte;
@@ -911,10 +929,11 @@ static int wimfs_getxattr(const char *path, const char *name, char *value,
                return -ENOATTR;
        name += 5;
 
-       dentry = get_dentry(w, path);
-       if (!dentry)
+       inode = wim_pathname_to_inode(w, path);
+       if (!inode)
                return -ENOENT;
-       ads_entry = inode_get_ads_entry(dentry->d_inode, name, NULL);
+
+       ads_entry = inode_get_ads_entry(inode, name, NULL);
        if (!ads_entry)
                return -ENOATTR;
 
@@ -923,11 +942,14 @@ static int wimfs_getxattr(const char *path, const char *name, char *value,
 
        if (size == 0)
                return res_size;
+
        if (res_size > size)
                return -ERANGE;
+
        ret = read_full_wim_resource(lte, (u8*)value);
        if (ret != 0)
                return -EIO;
+
        return res_size;
 }
 #endif
@@ -978,21 +1000,19 @@ static int wimfs_link(const char *to, const char *from)
 #ifdef ENABLE_XATTR
 static int wimfs_listxattr(const char *path, char *list, size_t size)
 {
-       struct dentry *dentry;
        int ret;
-       char *p = list;
        size_t needed_size;
        unsigned i;
        struct inode *inode;
+
        if (!(mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
                return -ENOTSUP;
 
        /* List alternate data streams, or get the list size */
 
-       ret = lookup_resource(w, path, get_lookup_flags(), &dentry, NULL, NULL);
-       if (ret != 0)
-               return ret;
-       inode = dentry->d_inode;
+       inode = wim_pathname_to_inode(w, path);
+       if (!inode)
+               return -ENOENT;
 
        if (size == 0) {
                needed_size = 0;
@@ -1000,6 +1020,7 @@ static int wimfs_listxattr(const char *path, char *list, size_t size)
                        needed_size += inode->ads_entries[i].stream_name_utf8_len + 6;
                return needed_size;
        } else {
+               char *p = list;
                for (i = 0; i < inode->num_ads; i++) {
                        needed_size = inode->ads_entries[i].stream_name_utf8_len + 6;
                        if (needed_size > size)
@@ -1013,8 +1034,8 @@ static int wimfs_listxattr(const char *path, char *list, size_t size)
 }
 #endif
 
-/* 
- * Create a directory in the WIM.  
+/*
+ * Create a directory in the WIM.
  * @mode is currently ignored.
  */
 static int wimfs_mkdir(const char *path, mode_t mode)
@@ -1022,7 +1043,7 @@ static int wimfs_mkdir(const char *path, mode_t mode)
        struct dentry *parent;
        struct dentry *newdir;
        const char *basename;
-       
+
        parent = get_parent_dentry(w, path);
        if (!parent)
                return -ENOENT;
@@ -1042,7 +1063,6 @@ static int wimfs_mkdir(const char *path, mode_t mode)
        return 0;
 }
 
-
 /* Creates a regular file. */
 static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
 {
@@ -1051,20 +1071,22 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
             && (stream_name = path_stream_name(path))) {
                /* Make an alternate data stream */
                struct ads_entry *new_entry;
-               struct dentry *dentry;
+               struct inode *inode;
 
                char *p = (char*)stream_name - 1;
                wimlib_assert(*p == ':');
                *p = '\0';
 
-               dentry = get_dentry(w, path);
-               if (!dentry || !dentry_is_regular_file(dentry))
+               inode = wim_pathname_to_inode(w, path);
+               if (!inode)
                        return -ENOENT;
-               if (inode_get_ads_entry(dentry->d_inode, stream_name, NULL))
+               if (!inode_is_regular_file(inode))
+                       return -ENOENT;
+               if (inode_get_ads_entry(inode, stream_name, NULL))
                        return -EEXIST;
-               new_entry = inode_add_ads(dentry->d_inode, stream_name);
+               new_entry = inode_add_ads(inode, stream_name);
                if (!new_entry)
-                       return -ENOENT;
+                       return -ENOMEM;
        } else {
                struct dentry *dentry, *parent;
                const char *basename;
@@ -1154,7 +1176,7 @@ static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
        struct inode *inode;
        int ret;
        struct wimlib_fd *fd = NULL;
-       
+
        inode = wim_pathname_to_inode(w, path);
        if (!inode)
                return -ENOENT;
@@ -1167,9 +1189,9 @@ static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
 
 
 /*
- * Read data from a file in the WIM or in the staging directory. 
+ * Read data from a file in the WIM or in the staging directory.
  */
-static int wimfs_read(const char *path, char *buf, size_t size, 
+static int wimfs_read(const char *path, char *buf, size_t size,
                      off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1177,13 +1199,13 @@ static int wimfs_read(const char *path, char *buf, size_t size,
        if (!fd)
                return -EBADF;
 
-       if (!fd->lte) /* Empty stream with no lookup table entry */
+       if (!fd->f_lte) /* Empty stream with no lookup table entry */
                return 0;
 
-       if (fd->lte->resource_location == RESOURCE_IN_STAGING_FILE) {
+       if (fd->f_lte->resource_location == RESOURCE_IN_STAGING_FILE) {
                /* Read from staging file */
 
-               wimlib_assert(fd->lte->staging_file_name);
+               wimlib_assert(fd->f_lte->staging_file_name);
                wimlib_assert(fd->staging_fd != -1);
 
                ssize_t ret;
@@ -1198,14 +1220,14 @@ static int wimfs_read(const char *path, char *buf, size_t size,
        } else {
                /* Read from WIM */
 
-               u64 res_size = wim_resource_size(fd->lte);
-               
+               u64 res_size = wim_resource_size(fd->f_lte);
+
                if (offset > res_size)
                        return -EOVERFLOW;
 
                size = min(size, res_size - offset);
 
-               if (read_wim_resource(fd->lte, (u8*)buf,
+               if (read_wim_resource(fd->f_lte, (u8*)buf,
                                      size, offset, false) != 0)
                        return -EIO;
                return size;
@@ -1214,7 +1236,7 @@ static int wimfs_read(const char *path, char *buf, size_t size,
 
 /* Fills in the entries of the directory specified by @path using the
  * FUSE-provided function @filler.  */
-static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 
+static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                         off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1245,14 +1267,14 @@ static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 
 static int wimfs_readlink(const char *path, char *buf, size_t buf_len)
 {
-       struct dentry *dentry = get_dentry(w, path);
+       struct inode *inode = wim_pathname_to_inode(w, path);
        int ret;
-       if (!dentry)
+       if (!inode)
                return -ENOENT;
-       if (!dentry_is_symlink(dentry))
+       if (!inode_is_symlink(inode))
                return -EINVAL;
 
-       ret = inode_readlink(dentry->d_inode, buf, buf_len, w);
+       ret = inode_readlink(inode, buf, buf_len, w);
        if (ret > 0)
                ret = 0;
        return ret;
@@ -1276,7 +1298,7 @@ static int wimfs_releasedir(const char *path, struct fuse_file_info *fi)
 /* Remove an alternate data stream through the XATTR interface */
 static int wimfs_removexattr(const char *path, const char *name)
 {
-       struct dentry *dentry;
+       struct inode *inode;
        struct ads_entry *ads_entry;
        u16 ads_idx;
        if (!(mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
@@ -1286,14 +1308,14 @@ static int wimfs_removexattr(const char *path, const char *name)
                return -ENOATTR;
        name += 5;
 
-       dentry = get_dentry(w, path);
-       if (!dentry)
+       inode = wim_pathname_to_inode(w, path);
+       if (!inode)
                return -ENOENT;
 
-       ads_entry = inode_get_ads_entry(dentry->d_inode, name, &ads_idx);
+       ads_entry = inode_get_ads_entry(inode, name, &ads_idx);
        if (!ads_entry)
                return -ENOATTR;
-       inode_remove_ads(dentry->d_inode, ads_idx, w->lookup_table);
+       inode_remove_ads(inode, ads_idx, w->lookup_table);
        return 0;
 }
 #endif
@@ -1310,7 +1332,7 @@ static int wimfs_rename(const char *from, const char *to)
 
        /* This rename() implementation currently only supports actual files
         * (not alternate data streams) */
-       
+
        src = get_dentry(w, from);
        if (!src)
                return -ENOENT;
@@ -1370,7 +1392,7 @@ static int wimfs_rename(const char *from, const char *to)
 static int wimfs_rmdir(const char *path)
 {
        struct dentry *dentry;
-       
+
        dentry = get_dentry(w, path);
        if (!dentry)
                return -ENOENT;
@@ -1455,7 +1477,7 @@ static int wimfs_symlink(const char *to, const char *from)
        struct dentry *dentry_parent, *dentry;
        const char *link_name;
        struct inode *inode;
-       
+
        dentry_parent = get_parent_dentry(w, from);
        if (!dentry_parent)
                return -ENOENT;
@@ -1496,7 +1518,7 @@ static int wimfs_truncate(const char *path, off_t size)
        u16 stream_idx;
        u32 stream_id;
        struct inode *inode;
-       
+
        ret = lookup_resource(w, path, get_lookup_flags(), &dentry,
                              &lte, &stream_idx);
 
@@ -1538,7 +1560,7 @@ static int wimfs_unlink(const char *path)
        int ret;
        u16 stream_idx;
        unsigned i;
-       
+
        ret = lookup_resource(w, path, get_lookup_flags(), &dentry,
                              &lte, &stream_idx);
 
@@ -1553,8 +1575,8 @@ static int wimfs_unlink(const char *path)
 }
 
 #ifdef HAVE_UTIMENSAT
-/* 
- * Change the timestamp on a file dentry. 
+/*
+ * Change the timestamp on a file dentry.
  *
  * Note that alternate data streams do not have their own timestamps.
  */
@@ -1597,10 +1619,10 @@ static int wimfs_utime(const char *path, struct utimbuf *times)
 }
 #endif
 
-/* Writes to a file in the WIM filesystem. 
+/* Writes to a file in the WIM filesystem.
  * It may be an alternate data stream, but here we don't even notice because we
  * just get a lookup table entry. */
-static int wimfs_write(const char *path, const char *buf, size_t size, 
+static int wimfs_write(const char *path, const char *buf, size_t size,
                       off_t offset, struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
@@ -1610,8 +1632,8 @@ static int wimfs_write(const char *path, const char *buf, size_t size,
        if (!fd)
                return -EBADF;
 
-       wimlib_assert(fd->lte);
-       wimlib_assert(fd->lte->staging_file_name);
+       wimlib_assert(fd->f_lte);
+       wimlib_assert(fd->f_lte->staging_file_name);
        wimlib_assert(fd->staging_fd != -1);
        wimlib_assert(fd->f_inode);
 
@@ -1676,7 +1698,7 @@ static struct fuse_operations wimfs_operations = {
 
 
 /* Mounts a WIM file. */
-WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, 
+WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                           int flags, WIMStruct **additional_swms,
                           unsigned num_additional_swms)
 {
@@ -1707,7 +1729,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                wim->lookup_table = joined_tab;
        }
 
-       ret = wimlib_select_image(wim, image);
+       ret = select_wim_image(wim, image);
 
        if (ret != 0)
                goto out;
@@ -1716,6 +1738,12 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
 
        DEBUG("Selected image %d", image);
 
+       if (imd->root_dentry->refcnt != 1) {
+               ERROR("Cannot mount image that was just exported with "
+                     "wimlib_export()");
+               return WIMLIB_ERR_INVALID_PARAM;
+       }
+
        next_ino = assign_inode_numbers(&imd->inode_list);
 
        DEBUG("(next_ino = %"PRIu64")", next_ino);
@@ -1768,7 +1796,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        if (flags & WIMLIB_MOUNT_FLAG_DEBUG)
                argv[argc++] = "-d";
 
-       /* 
+       /*
         * We provide the use_ino option because we are going to assign inode
         * numbers oursides.  We've already numbered the inodes with unique
         * numbers in the assign_inode_numbers() function, and the static
@@ -1820,7 +1848,7 @@ out:
 }
 
 
-/* 
+/*
  * Unmounts the WIM file that was previously mounted on @dir by using
  * wimlib_mount().
  */
@@ -1848,7 +1876,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        msg[0] = (flags & WIMLIB_UNMOUNT_FLAG_COMMIT) ? 1 : 0;
        msg[1] = (flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY) ? 1 : 0;
 
-       DEBUG("Sending message: %s, %s", 
+       DEBUG("Sending message: %s, %s",
                        (msg[0] == 0) ? "don't commit" : "commit",
                        (msg[1] == 0) ? "don't check"  : "check");
        ret = mq_send(unmount_to_daemon_mq, msg, 2, 1);
@@ -1868,7 +1896,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
         * send a message from this process to the filesystem daemon telling
         * whether --commit was specified or not.  However, after that, the
         * unmount process must wait for the filesystem daemon to finish writing
-        * the WIM file. 
+        * the WIM file.
         */
 
 
@@ -1930,7 +1958,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
         * filesystem daemon has crashed or failed for some reason.
         *
         * XXX come up with some method to determine if the filesystem
-        * daemon has really crashed or not. 
+        * daemon has really crashed or not.
         *
         * XXX Idea: have mount daemon write its PID into the WIM file header?
         * */
@@ -1983,7 +2011,7 @@ WIMLIBAPI int wimlib_unmount(const char *dir, int flags)
        return mount_unsupported_error();
 }
 
-WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir, 
+WIMLIBAPI int wimlib_mount(WIMStruct *wim_p, int image, const char *dir,
                           int flags, WIMStruct **additional_swms,
                           unsigned num_additional_swms)
 {