From: Eric Biggers Date: Sun, 19 Aug 2012 18:07:37 +0000 (-0500) Subject: use_ino mount option X-Git-Tag: v1.0.0~131 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=81a608ecc78f13a32a69c6185fdacdcf30177ddd use_ino mount option --- diff --git a/src/dentry.c b/src/dentry.c index 76ec2dec..0c607e0b 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -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); diff --git a/src/hardlink.c b/src/hardlink.c index 9a128d46..e3f30b45 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -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; } diff --git a/src/mount.c b/src/mount.c index b8fe5278..7817c58e 100644 --- a/src/mount.c +++ b/src/mount.c @@ -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 { diff --git a/src/resource.c b/src/resource.c index 4b71cb3f..6ca59c91 100644 --- a/src/resource.c +++ b/src/resource.c @@ -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;