X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fmodify.c;h=d5553dc8a2ba1838608f0df89fa2d897724a84fe;hp=fbbf1bf2abcc77502723ef7f50c6060b49cbd56c;hb=942bf22cf6306daf53df4b59ec589f8e294a57d0;hpb=e86f9f34e67c89123b747524d7e67dd70175d3d4 diff --git a/src/modify.c b/src/modify.c index fbbf1bf2..d5553dc8 100644 --- a/src/modify.c +++ b/src/modify.c @@ -236,7 +236,7 @@ static int build_dentry_tree(struct dentry **root_ret, inode->attributes = FILE_ATTRIBUTE_DIRECTORY; DIR *dir; - struct dirent *p; + struct dirent entry, *result; struct dentry *child; dir = opendir(root_disk_path); @@ -257,20 +257,20 @@ static int build_dentry_tree(struct dentry **root_ret, * to any subdirectories. */ while (1) { errno = 0; - p = readdir(dir); - if (p == NULL) { - if (errno) { - ret = WIMLIB_ERR_READ; - ERROR_WITH_ERRNO("Error reading the " - "directory `%s'", - root_disk_path); - } + ret = readdir_r(dir, &entry, &result); + if (ret != 0) { + ret = WIMLIB_ERR_READ; + ERROR_WITH_ERRNO("Error reading the " + "directory `%s'", + root_disk_path); break; } - if (p->d_name[0] == '.' && (p->d_name[1] == '\0' - || (p->d_name[1] == '.' && p->d_name[2] == '\0'))) + if (result == NULL) + break; + if (result->d_name[0] == '.' && (result->d_name[1] == '\0' + || (result->d_name[1] == '.' && result->d_name[2] == '\0'))) continue; - strcpy(name + len + 1, p->d_name); + strcpy(name + len + 1, result->d_name); ret = build_dentry_tree(&child, name, lookup_table, NULL, config, add_image_flags, progress_func, NULL); @@ -511,9 +511,6 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, struct wim_security_data *sd; struct lookup_table *joined_tab, *src_wim_tab_save; - if (!src_wim || !dest_wim) - return WIMLIB_ERR_INVALID_PARAM; - if (dest_wim->hdr.total_parts != 1) { ERROR("Exporting an image to a split WIM is " "unsupported"); @@ -667,6 +664,58 @@ out: return ret; } +static int image_run_full_verifications(WIMStruct *w) +{ + return for_dentry_in_tree(wim_root_dentry(w), verify_dentry, w); +} + +static int lte_fix_refcnt(struct lookup_table_entry *lte, void *ctr) +{ + if (lte->refcnt != lte->real_refcnt) { + WARNING("The following lookup table entry has a reference " + "count of %u, but", lte->refcnt); + WARNING("We found %u references to it", + lte->real_refcnt); + print_lookup_table_entry(lte); + lte->refcnt = lte->real_refcnt; + ++*(unsigned long *)ctr; + } + return 0; +} + +/* Ideally this would be unnecessary... however, the WIMs for Windows 8 are + * screwed up because some lookup table entries are referenced more times than + * their stated reference counts. So theoretically, if we do the delete all the + * references to a stream and then remove it, it might still be referenced + * somewhere else... So, work around this problem by looking at ALL the images + * to re-calculate the reference count of EVERY lookup table entry. */ +int wim_run_full_verifications(WIMStruct *w) +{ + int ret; + + for_lookup_table_entry(w->lookup_table, lte_zero_real_refcnt, NULL); + w->all_images_verified = true; + w->full_verification_in_progress = true; + ret = for_image(w, WIMLIB_ALL_IMAGES, image_run_full_verifications); + w->full_verification_in_progress = false; + if (ret == 0) { + unsigned long num_ltes_with_bogus_refcnt = 0; + for (int i = 0; i < w->hdr.image_count; i++) + w->image_metadata[i].metadata_lte->real_refcnt++; + for_lookup_table_entry(w->lookup_table, lte_fix_refcnt, + &num_ltes_with_bogus_refcnt); + if (num_ltes_with_bogus_refcnt != 0) { + WARNING("A total of %lu entries in the WIM's stream " + "lookup table had to have\n" + " their reference counts fixed.", + num_ltes_with_bogus_refcnt); + } + } else { + w->all_images_verified = false; + } + return ret; +} + /* * Deletes an image from the WIM. */ @@ -689,6 +738,12 @@ WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image) return 0; } + if (!w->all_images_verified) { + ret = wim_run_full_verifications(w); + if (ret != 0) + return ret; + } + DEBUG("Deleting image %d", image); /* Even if the dentry tree is not allocated, we must select it (and @@ -998,7 +1053,7 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *source, extra_arg = NULL; } - DEBUG("Adding dentry tree from directory or NTFS volume `%s'.", dir); + DEBUG("Adding dentry tree from directory or NTFS volume `%s'.", source); if (!name || !*name) { ERROR("Must specify a non-empty string for the image name");