X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Ftemplate.c;h=ed1dd19eaa20282e2efec2985e2f815489718b5a;hp=6b21015a0aedf6e7b5000cc962213870f74d74ee;hb=ee547cc83f231d727e4d9984c23e86d96d3da769;hpb=668c363a59c521f48eecbc4dd549c07a3e36179e diff --git a/src/template.c b/src/template.c index 6b21015a..ed1dd19e 100644 --- a/src/template.c +++ b/src/template.c @@ -5,22 +5,20 @@ */ /* - * Copyright (C) 2013 Eric Biggers + * Copyright (C) 2013, 2015 Eric Biggers * - * This file is part of wimlib, a library for working with WIM files. + * This file is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. * - * wimlib is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) - * any later version. - * - * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * - * You should have received a copy of the GNU General Public License - * along with wimlib; if not, see http://www.gnu.org/licenses/. + * You should have received a copy of the GNU Lesser General Public License + * along with this file; if not, see http://www.gnu.org/licenses/. */ #ifdef HAVE_CONFIG_H @@ -28,18 +26,32 @@ #endif #include "wimlib.h" +#include "wimlib/blob_table.h" +#include "wimlib/assert.h" #include "wimlib/dentry.h" #include "wimlib/error.h" -#include "wimlib/lookup_table.h" #include "wimlib/metadata.h" #include "wimlib/util.h" +static u64 +stream_size(const struct wim_inode_stream *strm, + const struct blob_table *blob_table) +{ + const struct blob_descriptor *blob; + + blob = stream_blob(strm, blob_table); + if (!blob) + return 0; + return blob->size; +} + /* Returns %true iff the metadata of @inode and @template_inode are reasonably * consistent with them being the same, unmodified file. */ static bool inode_metadata_consistent(const struct wim_inode *inode, const struct wim_inode *template_inode, - const struct wim_lookup_table *template_lookup_table) + const struct blob_table *blob_table, + const struct blob_table *template_blob_table) { /* Must have exact same creation time and last write time. */ if (inode->i_creation_time != template_inode->i_creation_time || @@ -51,111 +63,60 @@ inode_metadata_consistent(const struct wim_inode *inode, if (inode->i_last_access_time < template_inode->i_last_access_time) return false; - /* Must have same number of alternate data stream entries. */ - if (inode->i_num_ads != template_inode->i_num_ads) - return false; - - /* If the stream entries for the inode are for some reason not resolved, - * then the hashes are already available and the point of this function - * is defeated. */ - if (!inode->i_resolved) - return false; - - /* Iterate through each stream and do some more checks. */ - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - const struct wim_lookup_table_entry *lte, *template_lte; + /* All stream sizes must match. */ + for (unsigned i = 0; i < inode->i_num_streams; i++) { + const struct wim_inode_stream *strm, *template_strm; - lte = inode_stream_lte_resolved(inode, i); - template_lte = inode_stream_lte(template_inode, i, - template_lookup_table); - - /* Compare stream sizes. */ - if (lte && template_lte) { - if (lte->size != template_lte->size) - return false; - - /* If hash happens to be available, compare with template. */ - if (!lte->unhashed && !template_lte->unhashed && - !hashes_equal(lte->hash, template_lte->hash)) - return false; - - } else if (lte && lte->size) { + strm = &inode->i_streams[i]; + template_strm = inode_get_stream(template_inode, + strm->stream_type, + strm->stream_name); + if (!template_strm) return false; - } else if (template_lte && template_lte->size) { + + if (stream_size(strm, blob_table) != + stream_size(template_strm, template_blob_table)) return false; - } } - /* All right, barring a full checksum and given that the inodes share a - * path and the user isn't trying to trick us, these inodes most likely - * refer to the same file. */ return true; } /** * Given an inode @inode that has been determined to be "the same" as another - * inode @template_inode in either the same WIM or another WIM, retrieve some - * useful stream information (e.g. checksums) from @template_inode. - * - * This assumes that the streams for @inode have been resolved (to point - * directly to the appropriate `struct wim_lookup_table_entry's) but do not - * necessarily have checksum information filled in. + * inode @template_inode in either the same WIM or another WIM, copy stream + * checksums from @template_inode to @inode. */ -static int +static void inode_copy_checksums(struct wim_inode *inode, struct wim_inode *template_inode, - WIMStruct *wim, - WIMStruct *template_wim) + struct blob_table *blob_table, + struct blob_table *template_blob_table) { - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - struct wim_lookup_table_entry *lte, *template_lte; - struct wim_lookup_table_entry *replace_lte; - - lte = inode_stream_lte_resolved(inode, i); - template_lte = inode_stream_lte(template_inode, i, - template_wim->lookup_table); - - /* Only take action if both entries exist, the entry for @inode - * has no checksum calculated, but the entry for @template_inode - * does. */ - if (lte == NULL || template_lte == NULL || - !lte->unhashed || template_lte->unhashed) + for (unsigned i = 0; i < inode->i_num_streams; i++) { + const struct wim_inode_stream *strm, *template_strm; + struct blob_descriptor *blob, *template_blob, **back_ptr; + + strm = &inode->i_streams[i]; + template_strm = inode_get_stream(template_inode, + strm->stream_type, + strm->stream_name); + + blob = stream_blob(strm, blob_table); + template_blob = stream_blob(template_strm, template_blob_table); + + /* To copy hashes: both blobs must exist, the blob for @inode + * must be unhashed, and the blob for @template_inode must be + * hashed. */ + if (!blob || !template_blob || + !blob->unhashed || template_blob->unhashed) continue; - wimlib_assert(lte->refcnt == inode->i_nlink); - - /* If the WIM of the template image is the same as the WIM of - * the new image, then @template_lte can be used directly. - * - * Otherwise, look for a stream with the same hash in the WIM of - * the new image. If found, use it; otherwise re-use the entry - * being discarded, filling in the hash. */ - - if (wim == template_wim) - replace_lte = template_lte; - else - replace_lte = lookup_stream(wim->lookup_table, - template_lte->hash); - - list_del(<e->unhashed_list); - if (replace_lte) { - free_lookup_table_entry(lte); - } else { - copy_hash(lte->hash, template_lte->hash); - lte->unhashed = 0; - lookup_table_insert(wim->lookup_table, lte); - lte->refcnt = 0; - replace_lte = lte; - } - - if (i == 0) - inode->i_lte = replace_lte; - else - inode->i_ads_entries[i - 1].lte = replace_lte; - - replace_lte->refcnt += inode->i_nlink; + back_ptr = retrieve_pointer_to_unhashed_blob(blob); + copy_hash(blob->hash, template_blob->hash); + if (after_blob_hashed(blob, back_ptr, blob_table) != blob) + free_blob_descriptor(blob); } - return 0; } struct reference_template_args { @@ -180,34 +141,34 @@ dentry_reference_template(struct wim_dentry *dentry, void *_args) if (ret) return ret; - template_dentry = get_dentry(template_wim, dentry->_full_path, + template_dentry = get_dentry(template_wim, dentry->d_full_path, WIMLIB_CASE_SENSITIVE); if (template_dentry == NULL) { - DEBUG("\"%"TS"\": newly added file", dentry->_full_path); + DEBUG("\"%"TS"\": newly added file", dentry->d_full_path); return 0; } inode = dentry->d_inode; template_inode = template_dentry->d_inode; - if (inode_metadata_consistent(inode, template_inode, - template_wim->lookup_table)) { - /*DEBUG("\"%"TS"\": No change detected", dentry->_full_path);*/ - ret = inode_copy_checksums(inode, template_inode, - wim, template_wim); + if (inode_metadata_consistent(inode, template_inode, wim->blob_table, + template_wim->blob_table)) + { + DEBUG("\"%"TS"\": No change detected", dentry->d_full_path); + inode_copy_checksums(inode, template_inode, wim->blob_table, + template_wim->blob_table); inode->i_visited = 1; } else { - DEBUG("\"%"TS"\": change detected!", dentry->_full_path); - ret = 0; + DEBUG("\"%"TS"\": change detected!", dentry->d_full_path); } - return ret; + return 0; } /* API function documented in wimlib.h */ WIMLIBAPI int wimlib_reference_template_image(WIMStruct *wim, int new_image, WIMStruct *template_wim, int template_image, - int flags, wimlib_progress_func_t progress_func) + int flags) { int ret; struct wim_image_metadata *new_imd;