]> wimlib.net Git - wimlib/blobdiff - src/mount.c
LZX LRU queue array_to_le32() fix
[wimlib] / src / mount.c
index 1a5500d2449e9e8fd239694dd035aab26226eaa5..abc7fb938df074395860795554fa99bb203acee2 100644 (file)
@@ -186,11 +186,10 @@ static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd)
                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;
@@ -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)
@@ -386,6 +388,7 @@ static int extract_resource_to_staging_dir(struct inode *inode,
                        if (fd) {
                                if (fd->stream_id == stream_id) {
                                        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);
@@ -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)
@@ -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) {
@@ -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)
@@ -1050,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_is_regular_file(inode))
                        return -ENOENT;
-               if (inode_get_ads_entry(dentry->d_inode, stream_name, NULL))
+               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;
@@ -1275,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))
@@ -1285,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