]> wimlib.net Git - wimlib/blobdiff - src/mount.c
Extract WIM hard links correctly
[wimlib] / src / mount.c
index 7817c58e0a980b9e88b22a538d1b4c07c5e2b3ef..5a2b6b73441d091e1062a6ca03c93a62dbb949d6 100644 (file)
@@ -73,6 +73,10 @@ static int mount_flags;
 /* Name of the directory on which the WIM file is mounted. */
 static const char *mount_dir;
 
+/* Next hard link group ID to be assigned.  These are also used as the inode
+ * numbers. */
+static u64 next_link_group_id;
+
 
 static inline int get_lookup_flags()
 {
@@ -139,8 +143,11 @@ static int close_wimlib_fd(struct wimlib_fd *fd)
                if (close(fd->staging_fd) != 0)
                        return -errno;
        }
-       if (--lte->num_opened_fds == 0 && lte->refcnt == 0)
+       if (--lte->num_opened_fds == 0 && lte->refcnt == 0) {
+               if (lte->staging_file_name)
+                       unlink(lte->staging_file_name);
                free_lookup_table_entry(lte);
+       }
        lte->fds[fd->idx] = NULL;
        FREE(fd);
        return 0;
@@ -702,7 +709,6 @@ static int rebuild_wim(WIMStruct *w, bool check_integrity)
 /* Called when the filesystem is unmounted. */
 static void wimfs_destroy(void *p)
 {
-
        /* For read-write mounts, the `imagex unmount' command, which is
         * running in a separate process and is executing the
         * wimlib_unmount() function, will send this process a byte
@@ -775,12 +781,19 @@ done:
        close_message_queues();
 }
 
+static int wimfs_fallocate(const char *path, int mode,
+                          off_t offset, off_t len, struct fuse_file_info *fi)
+{
+       struct wimlib_fd *fd = (struct wimlib_fd*)fi->fh;
+       wimlib_assert(fd->staging_fd != -1);
+       return fallocate(fd->staging_fd, mode, offset, len);
+}
+
 static int wimfs_fgetattr(const char *path, struct stat *stbuf,
                          struct fuse_file_info *fi)
 {
        struct wimlib_fd *fd = (struct wimlib_fd*)fi->fh;
-       dentry_to_stbuf(fd->dentry, stbuf, w->lookup_table);
-       return 0;
+       return dentry_to_stbuf(fd->dentry, stbuf, w->lookup_table);
 }
 
 static int wimfs_ftruncate(const char *path, off_t size,
@@ -802,8 +815,14 @@ static int wimfs_getattr(const char *path, struct stat *stbuf)
        struct dentry *dentry = get_dentry(w, path);
        if (!dentry)
                return -ENOENT;
-       dentry_to_stbuf(dentry, stbuf, w->lookup_table);
-       return 0;
+       return dentry_to_stbuf(dentry, stbuf, w->lookup_table);
+}
+
+static int wimfs_getxattr(const char *path, const char *name, char *value,
+                         size_t size)
+{
+       /* XXX */
+       return -ENOTSUP;
 }
 
 /* Create a hard link */
@@ -841,6 +860,12 @@ static int wimfs_link(const char *to, const char *from)
        return 0;
 }
 
+static int wimfs_listxattr(const char *path, char *list, size_t size)
+{
+       /* XXX */
+       return -ENOTSUP;
+}
+
 /* 
  * Create a directory in the WIM.  
  * @mode is currently ignored.
@@ -905,6 +930,7 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
                dentry = new_dentry(basename);
                if (!dentry)
                        return -ENOMEM;
+               dentry->hard_link = next_link_group_id++;
                link_dentry(dentry, parent);
        }
        return 0;
@@ -1115,6 +1141,12 @@ static int wimfs_releasedir(const char *path, struct fuse_file_info *fi)
        return 0;
 }
 
+static int wimfs_removexattr(const char *path, const char *name)
+{
+       /* XXX */
+       return -ENOTSUP;
+}
+
 /* Renames a file or directory.  See rename (3) */
 static int wimfs_rename(const char *from, const char *to)
 {
@@ -1195,6 +1227,13 @@ static int wimfs_rmdir(const char *path)
        return 0;
 }
 
+static int wimfs_setxattr(const char *path, const char *name,
+                         const char *value, size_t size, int flags)
+{
+       /* XXX */
+       return -ENOTSUP;
+}
+
 static int wimfs_symlink(const char *to, const char *from)
 {
        struct dentry *dentry_parent, *dentry;
@@ -1273,10 +1312,6 @@ static int wimfs_unlink(const char *path)
        if (ret != 0)
                return ret;
 
-       if (lte && lte->staging_file_name)
-               if (unlink(lte->staging_file_name) != 0)
-                       return -errno;
-
        if (dentry_hash == dentry->hash) {
                /* We are removing the full dentry including all alternate data
                 * streams. */
@@ -1326,6 +1361,10 @@ static int wimfs_write(const char *path, const char *buf, size_t size,
        wimlib_assert(fd->lte->staging_file_name);
        wimlib_assert(fd->staging_fd != -1);
 
+       /* Seek to the requested position */
+       if (lseek(fd->staging_fd, offset, SEEK_SET) == -1)
+               return -errno;
+
        /* Write the data. */
        ret = write(fd->staging_fd, buf, size);
        if (ret == -1)
@@ -1336,28 +1375,33 @@ static int wimfs_write(const char *path, const char *buf, size_t size,
 
 
 static struct fuse_operations wimfs_operations = {
-       .access     = wimfs_access,
-       .destroy    = wimfs_destroy,
-       .fgetattr   = wimfs_fgetattr,
-       .ftruncate  = wimfs_ftruncate,
-       .getattr    = wimfs_getattr,
-       .link       = wimfs_link,
-       .mkdir      = wimfs_mkdir,
-       .mknod      = wimfs_mknod,
-       .open       = wimfs_open,
-       .opendir    = wimfs_opendir,
-       .read       = wimfs_read,
-       .readdir    = wimfs_readdir,
-       .readlink   = wimfs_readlink,
-       .release    = wimfs_release,
-       .releasedir = wimfs_releasedir,
-       .rename     = wimfs_rename,
-       .rmdir      = wimfs_rmdir,
-       .symlink    = wimfs_symlink,
-       .truncate   = wimfs_truncate,
-       .unlink     = wimfs_unlink,
-       .utimens    = wimfs_utimens,
-       .write      = wimfs_write,
+       .access      = wimfs_access,
+       .destroy     = wimfs_destroy,
+       .fallocate   = wimfs_fallocate,
+       .fgetattr    = wimfs_fgetattr,
+       .ftruncate   = wimfs_ftruncate,
+       .getattr     = wimfs_getattr,
+       .getxattr    = wimfs_getxattr,
+       .link        = wimfs_link,
+       .listxattr   = wimfs_listxattr,
+       .mkdir       = wimfs_mkdir,
+       .mknod       = wimfs_mknod,
+       .open        = wimfs_open,
+       .opendir     = wimfs_opendir,
+       .read        = wimfs_read,
+       .readdir     = wimfs_readdir,
+       .readlink    = wimfs_readlink,
+       .release     = wimfs_release,
+       .releasedir  = wimfs_releasedir,
+       .removexattr = wimfs_removexattr,
+       .rename      = wimfs_rename,
+       .rmdir       = wimfs_rmdir,
+       .setxattr    = wimfs_setxattr,
+       .symlink     = wimfs_symlink,
+       .truncate    = wimfs_truncate,
+       .unlink      = wimfs_unlink,
+       .utimens     = wimfs_utimens,
+       .write       = wimfs_write,
 };
 
 
@@ -1381,6 +1425,10 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        if (ret != 0)
                return ret;
 
+       DEBUG("Selected image %d", image);
+
+       next_link_group_id = assign_link_groups(wim->image_metadata[image - 1].lgt);
+
        if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
                wim_get_current_image_metadata(wim)->modified = true;