]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
wimfs_write(), dentry_to_stbuf()
[wimlib] / src / dentry.c
index 76ec2decbe82fffa81c14f38bff25697baa047c1..ea21e07b57e90540adfccd65fb0485adeab3e39e 100644 (file)
@@ -80,8 +80,8 @@ void stbuf_to_dentry(const struct stat *stbuf, struct dentry *dentry)
 }
 
 /* Transfers file attributes from a struct dentry to a `stat' buffer. */
-void dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf, 
-                    const struct lookup_table *table)
+int dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf, 
+                   const struct lookup_table *table)
 {
        struct lookup_table_entry *lte;
 
@@ -92,11 +92,18 @@ void dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf,
        else
                stbuf->st_mode = S_IFREG | 0644;
 
+       stbuf->st_ino = (ino_t)dentry->hard_link;
+
+       stbuf->st_nlink = dentry_link_group_size(dentry);
+       stbuf->st_uid   = getuid();
+       stbuf->st_gid   = getgid();
+
        /* Use the size of the unnamed (default) file stream. */
        if (table && (lte = __lookup_resource(table, dentry_hash(dentry)))) {
                if (lte->staging_file_name) {
                        struct stat native_stat;
-                       stat(lte->staging_file_name, &native_stat);
+                       if (stat(lte->staging_file_name, &native_stat) != 0)
+                               return -errno;
                        stbuf->st_size = native_stat.st_size;
                } else {
                        stbuf->st_size = lte->resource_entry.original_size;
@@ -105,14 +112,11 @@ void dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf,
                stbuf->st_size = 0;
        }
 
-       stbuf->st_nlink   = dentry_link_group_size(dentry);
-       stbuf->st_ino     = dentry->hard_link;
-       stbuf->st_uid     = getuid();
-       stbuf->st_gid     = getgid();
        stbuf->st_atime   = ms_timestamp_to_unix(dentry->last_access_time);
        stbuf->st_mtime   = ms_timestamp_to_unix(dentry->last_write_time);
        stbuf->st_ctime   = ms_timestamp_to_unix(dentry->creation_time);
        stbuf->st_blocks  = (stbuf->st_size + 511) / 512;
+       return 0;
 }
 
 /* Makes all timestamp fields for the dentry be the current time. */
@@ -553,7 +557,11 @@ void put_dentry(struct dentry *dentry)
                        }
                }
        }
+       struct list_head *next;
+       next = dentry->link_group_list.next;
        list_del(&dentry->link_group_list);
+       /*if (next->next == next)*/
+               /*container_of(next, struct dentry, link_group_list)->hard_link = 0;*/
        free_dentry(dentry);
 }
 
@@ -583,6 +591,11 @@ int share_dentry_ads(struct dentry *master, struct dentry *slave)
                mismatch_type = "attributes";
                goto mismatch;
        }
+       if (master->attributes & FILE_ATTRIBUTE_DIRECTORY) {
+               ERROR("`%s' is hard-linked to `%s', which is a directory ",
+                     slave->full_path_utf8, master->full_path_utf8);
+               return WIMLIB_ERR_INVALID_DENTRY;
+       }
        if (master->security_id != slave->security_id) {
                mismatch_type = "security ID";
                goto mismatch;
@@ -745,9 +758,9 @@ int get_names(char **name_utf16_ret, char **name_utf8_ret,
 
        utf8_len = strlen(name);
 
-       name_utf8 = utf8_to_utf16(name, utf8_len, &utf16_len);
+       name_utf16 = utf8_to_utf16(name, utf8_len, &utf16_len);
 
-       if (!name_utf8)
+       if (!name_utf16)
                return WIMLIB_ERR_NOMEM;
 
        name_utf8 = MALLOC(utf8_len + 1);
@@ -1163,8 +1176,13 @@ static u8 *write_dentry(const struct dentry *dentry, u8 *p)
                p = put_u32(p, dentry->reparse_tag);
                p = put_zeroes(p, 4);
        } else {
+               u64 hard_link;
                p = put_u32(p, dentry->reparse_tag);
-               p = put_u64(p, dentry->hard_link);
+               if (dentry->link_group_list.next == &dentry->link_group_list)
+                       hard_link = 0;
+               else
+                       hard_link = dentry->hard_link;
+               p = put_u64(p, hard_link);
        }
        p = put_u16(p, dentry->num_ads);
        p = put_u16(p, dentry->short_name_len);