use_ino mount option
authorEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 18:07:37 +0000 (13:07 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 18:07:37 +0000 (13:07 -0500)
src/dentry.c
src/hardlink.c
src/mount.c
src/resource.c

index 76ec2de..0c607e0 100644 (file)
@@ -85,6 +85,8 @@ void dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf,
 {
        struct lookup_table_entry *lte;
 
+
+
        if (dentry_is_symlink(dentry))
                stbuf->st_mode = S_IFLNK | 0777;
        else if (dentry_is_directory(dentry))
@@ -92,6 +94,11 @@ void dentry_to_stbuf(const struct dentry *dentry, struct stat *stbuf,
        else
                stbuf->st_mode = S_IFREG | 0644;
 
+       stbuf->st_ino   = 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) {
@@ -105,10 +112,6 @@ 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);
@@ -583,6 +586,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 +753,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);
index 9a128d4..e3f30b4 100644 (file)
@@ -156,6 +156,7 @@ static int link_group_free_duplicate_data(struct link_group *group)
                                                        link_group_list));
                if (ret != 0)
                        return ret;
+               head = head->next;
        }
        return 0;
 }
index b8fe527..7817c58 100644 (file)
@@ -261,6 +261,8 @@ static int extract_resource_to_staging_dir(struct dentry *dentry,
        struct lookup_table_entry *old_lte, *new_lte;
        size_t link_group_size;
 
+       DEBUG("Extracting resource `%s' to staging directory", dentry->full_path_utf8);
+
        old_lte = *lte;
        fd = create_staging_file(&staging_file_name, O_WRONLY);
        if (fd == -1)
@@ -286,9 +288,13 @@ static int extract_resource_to_staging_dir(struct dentry *dentry,
                if (link_group_size == old_lte->refcnt) {
                        /* This hard link group is the only user of the lookup
                         * table entry, so we can re-use it. */
+                       DEBUG("Re-using lookup table entry");
                        lookup_table_remove(w->lookup_table, old_lte);
                        new_lte = old_lte;
                } else {
+                       DEBUG("Splitting lookup table entry "
+                             "(link_group_size = %u, lte refcnt = %u)",
+                             link_group_size, old_lte->refcnt);
                        /* Split a hard link group away from the "lookup table
                         * entry" hard link group (i.e. we had two hard link
                         * groups that were identical, but now we are changing
@@ -317,15 +323,16 @@ static int extract_resource_to_staging_dir(struct dentry *dentry,
                                        num_transferred_fds++;
                                }
                        }
+                       DEBUG("Transferring %u file descriptors",
+                             num_transferred_fds);
                        new_lte->fds = MALLOC(num_transferred_fds *
                                              sizeof(new_lte->fds[0]));
                        if (!new_lte->fds) {
-                               free_lookup_table_entry(new_lte);
+                               FREE(new_lte);
                                ret = -ENOMEM;
                                goto out_delete_staging_file;
                        }
-                       u16 j = 0;
-                       for (u16 i = 0; i < old_lte->num_allocated_fds; i++) {
+                       for (u16 i = 0, j = 0; ; i++) {
                                if (old_lte->fds[i] &&
                                    old_lte->fds[i]->dentry->hard_link ==
                                      dentry->hard_link)
@@ -335,12 +342,14 @@ static int extract_resource_to_staging_dir(struct dentry *dentry,
                                        fd->lte = new_lte;
                                        fd->idx = j;
                                        new_lte->fds[j] = fd;
+                                       if (++j == num_transferred_fds)
+                                               break;
                                }
                        }
                        old_lte->refcnt -= link_group_size;
-                       old_lte->num_opened_fds -= j;
-                       new_lte->num_opened_fds = j;
-
+                       old_lte->num_opened_fds -= num_transferred_fds;
+                       new_lte->num_opened_fds = num_transferred_fds;
+                       new_lte->num_allocated_fds = num_transferred_fds;
                } 
        } else {
                new_lte = new_lookup_table_entry();
@@ -828,6 +837,7 @@ static int wimfs_link(const char *to, const char *from)
        list_add(&from_dentry->link_group_list, &to_dentry->link_group_list);
        link_dentry(from_dentry, from_dentry_parent);
        dentry_increment_lookup_table_refcnts(from_dentry, w->lookup_table);
+       from_dentry->link_group_master_status = GROUP_SLAVE;
        return 0;
 }
 
@@ -1356,7 +1366,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                           int flags)
 {
        int argc = 0;
-       char *argv[6];
+       char *argv[16];
        int ret;
        char *p;
 
@@ -1397,16 +1407,19 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
        if (flags & WIMLIB_MOUNT_FLAG_DEBUG) {
                argv[argc++] = "-d";
        }
-       if (!(flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
-               argv[argc++] = "-o";
-               argv[argc++] = "ro";
-       } else {
+       char optstring[256] = "use_ino";
+       argv[argc++] = "-o";
+       argv[argc++] = optstring;
+       if ((flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
                make_staging_dir();
                if (!staging_dir_name) {
                        FREE(p);
                        return WIMLIB_ERR_MKDIR;
                }
+       } else {
+               strcat(optstring, ",ro");
        }
+       argv[argc] = NULL;
 
 #ifdef ENABLE_DEBUG
        {
index 4b71cb3..6ca59c9 100644 (file)
@@ -991,16 +991,19 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd)
        if (ret != 0)
                goto out_free_dentry_tree;
 
+       DEBUG("Reading dentry tree");
        /* Now read the entire directory entry tree. */
        ret = read_dentry_tree(buf, res_entry->original_size, dentry);
        if (ret != 0)
                goto out_free_dentry_tree;
 
+       DEBUG("Calculating dentry full paths");
        /* Calculate the full paths in the dentry tree. */
        ret = for_dentry_in_tree(dentry, calculate_dentry_full_path, NULL);
        if (ret != 0)
                goto out_free_dentry_tree;
 
+       DEBUG("Building link group table");
        lgt = new_link_group_table(9001);
        if (!lgt)
                goto out_free_dentry_tree;
@@ -1008,6 +1011,7 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd)
        if (ret != 0)
                goto out_free_lgt;
 
+       DEBUG("Freeing duplicate ADS entries in link group table");
        ret = link_groups_free_duplicate_data(lgt);
        if (ret != 0)
                goto out_free_lgt;