X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract.c;h=14accdac3119c6d4241ca6d86b4c9a0934d4b69e;hb=597e700af87a07ec12f2bd10690954473cf1ca93;hp=26164028ee9d6dc5f73d2af2f1987f445abbd29d;hpb=67f45cecd793345416d5d85fbe37ec54b1bb6ef8;p=wimlib diff --git a/src/extract.c b/src/extract.c index 26164028..14accdac 100644 --- a/src/extract.c +++ b/src/extract.c @@ -48,7 +48,7 @@ /* Internal */ #define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000 -static int extract_regular_file_linked(const struct dentry *dentry, +static int extract_regular_file_linked(const struct dentry *dentry, const char *output_dir, const char *output_path, int extract_flags, @@ -77,7 +77,7 @@ static int extract_regular_file_linked(const struct dentry *dentry, wimlib_assert(extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK); - num_path_components = + num_path_components = get_num_path_components(dentry->full_path_utf8) - 1; num_output_dir_path_components = get_num_path_components(output_dir); @@ -114,7 +114,7 @@ static int extract_regular_file_linked(const struct dentry *dentry, } static int extract_regular_file_unlinked(WIMStruct *w, - struct dentry *dentry, + struct dentry *dentry, const char *output_path, int extract_flags, struct lookup_table_entry *lte) @@ -124,29 +124,31 @@ static int extract_regular_file_unlinked(WIMStruct *w, int out_fd; int ret; - struct inode *inode = dentry->inode; - - if (!(extract_flags & WIMLIB_EXTRACT_FLAG_MULTI_IMAGE)) { - /* This dentry is one of a hard link set of at least 2 dentries. - * If one of the other dentries has already been extracted, make - * a hard link to the file corresponding to this - * already-extracted directory. Otherwise, extract the - * file, and set the dentry->extracted_file field so that other + struct inode *inode = dentry->d_inode; + + if (!((extract_flags & WIMLIB_EXTRACT_FLAG_MULTI_IMAGE) + && (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | + WIMLIB_EXTRACT_FLAG_HARDLINK)))) + { + /* If the dentry is one of a hard link set of at least 2 + * dentries and one of the other dentries has already been + * extracted, make a hard link to the file corresponding to this + * already-extracted directory. Otherwise, extract the file, + * and set the inode->extracted_file field so that other * dentries in the hard link group can link to it. */ - struct dentry *other; - if (inode->extracted_file) { - DEBUG("Extracting hard link `%s' => `%s'", - output_path, inode->extracted_file); - if (link(inode->extracted_file, output_path) != 0) { - ERROR_WITH_ERRNO("Failed to hard link " - "`%s' to `%s'", - output_path, - inode->extracted_file); - return WIMLIB_ERR_LINK; - } - return 0; - } if (inode->link_count > 1) { + if (inode->extracted_file) { + DEBUG("Extracting hard link `%s' => `%s'", + output_path, inode->extracted_file); + if (link(inode->extracted_file, output_path) != 0) { + ERROR_WITH_ERRNO("Failed to hard link " + "`%s' to `%s'", + output_path, + inode->extracted_file); + return WIMLIB_ERR_LINK; + } + return 0; + } FREE(inode->extracted_file); inode->extracted_file = STRDUP(output_path); if (!inode->extracted_file) { @@ -169,16 +171,16 @@ static int extract_regular_file_unlinked(WIMStruct *w, /* Empty file with no lookup table entry */ DEBUG("Empty file `%s'.", output_path); ret = 0; - goto done; + goto out; } ret = extract_full_wim_resource_to_fd(lte, out_fd); if (ret != 0) { ERROR("Failed to extract resource to `%s'", output_path); - goto done; + goto out; } -done: +out: if (close(out_fd) != 0) { ERROR_WITH_ERRNO("Failed to close file `%s'", output_path); ret = WIMLIB_ERR_WRITE; @@ -186,29 +188,31 @@ done: return ret; } -/* - * Extracts a regular file from the WIM archive. +/* + * Extracts a regular file from the WIM archive. */ -static int extract_regular_file(WIMStruct *w, - struct dentry *dentry, +static int extract_regular_file(WIMStruct *w, + struct dentry *dentry, const char *output_dir, const char *output_path, int extract_flags) { struct lookup_table_entry *lte; - const struct inode *inode = dentry->inode; + const struct inode *inode = dentry->d_inode; lte = inode_unnamed_lte(inode, w->lookup_table); if ((extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) && lte) { - if (++lte->out_refcnt != 1) + if (lte->extracted_file) { return extract_regular_file_linked(dentry, output_dir, output_path, extract_flags, lte); - lte->extracted_file = STRDUP(output_path); - if (!lte->extracted_file) - return WIMLIB_ERR_NOMEM; + } else { + lte->extracted_file = STRDUP(output_path); + if (!lte->extracted_file) + return WIMLIB_ERR_NOMEM; + } } return extract_regular_file_unlinked(w, dentry, output_path, @@ -220,7 +224,7 @@ static int extract_symlink(const struct dentry *dentry, const char *output_path, const WIMStruct *w) { char target[4096]; - ssize_t ret = inode_readlink(dentry->inode, target, sizeof(target), w); + ssize_t ret = inode_readlink(dentry->d_inode, target, sizeof(target), w); if (ret <= 0) { ERROR("Could not read the symbolic link from dentry `%s'", dentry->full_path_utf8); @@ -235,12 +239,12 @@ static int extract_symlink(const struct dentry *dentry, const char *output_path, return 0; } -/* - * Extracts a directory from the WIM archive. +/* + * Extracts a directory from the WIM archive. * * @dentry: The directory entry for the directory. * @output_path: The path to which the directory is to be extracted to. - * @return: True on success, false on failure. + * @return: True on success, false on failure. */ static int extract_directory(const char *output_path, bool is_root) { @@ -278,7 +282,7 @@ struct extract_args { const char *output_dir; }; -/* +/* * Extracts a file, directory, or symbolic link from the WIM archive. For use * in for_dentry_in_tree(). */ @@ -320,8 +324,8 @@ static int apply_dentry_timestamps(struct dentry *dentry, void *arg) output_path[len + dentry->full_path_utf8_len] = '\0'; struct timeval tv[2]; - wim_timestamp_to_timeval(dentry->inode->last_access_time, &tv[0]); - wim_timestamp_to_timeval(dentry->inode->last_write_time, &tv[1]); + wim_timestamp_to_timeval(dentry->d_inode->last_access_time, &tv[0]); + wim_timestamp_to_timeval(dentry->d_inode->last_write_time, &tv[1]); if (lutimes(output_path, tv) != 0) { WARNING("Failed to set timestamp on file `%s': %s", output_path, strerror(errno)); @@ -336,7 +340,7 @@ static int extract_single_image(WIMStruct *w, int image, DEBUG("Extracting image %d", image); int ret; - ret = wimlib_select_image(w, image); + ret = select_wim_image(w, image); if (ret != 0) return ret; @@ -377,7 +381,7 @@ static int extract_all_images(WIMStruct *w, const char *output_dir, memcpy(buf, output_dir, output_path_len); buf[output_path_len] = '/'; for (image = 1; image <= w->hdr.image_count; image++) { - + image_name = wimlib_get_image_name(w, image); if (*image_name) { strcpy(buf + output_path_len + 1, image_name); @@ -426,8 +430,7 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, w->lookup_table = joined_tab; } - - for_lookup_table_entry(w->lookup_table, zero_out_refcnts, NULL); + for_lookup_table_entry(w->lookup_table, lte_free_extracted_file, NULL); if (image == WIM_ALL_IMAGES) { flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;