/*
* Copyright (C) 2012, 2013, 2014 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
if (new == NULL)
return NULL;
- new->extracted_file = NULL;
switch (new->resource_location) {
case RESOURCE_IN_WIM:
list_add(&new->rspec_node, &new->rspec->stream_list);
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
#ifdef WITH_FUSE
break;
case RESOURCE_IN_FILE_ON_DISK:
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
#ifdef WITH_FUSE
}
/*
- * Decrements the reference count for the lookup table entry @lte, which must be
- * inserted in the stream lookup table @table.
+ * Decrements the reference count of the single-instance stream @lte, which must
+ * be inserted in the stream lookup table @table.
+ *
+ * If the stream's reference count reaches 0, we may unlink it from @table and
+ * free it. However, we retain streams with 0 reference count that originated
+ * from WIM files (RESOURCE_IN_WIM). We do this for two reasons:
+ *
+ * 1. This prevents information about valid streams in a WIM file --- streams
+ * which will continue to be present after appending to the WIM file --- from
+ * being lost merely because we dropped all references to them.
+ *
+ * 2. Stream reference counts we read from WIM files can't be trusted. It's
+ * possible that a WIM has reference counts that are too low; WIMGAPI
+ * sometimes creates WIMs where this is the case. It's also possible that
+ * streams have been referenced from an external WIM; those streams can
+ * potentially have any reference count at all, either lower or higher than
+ * would be expected for this WIM ("this WIM" meaning the owner of @table) if
+ * it were a standalone WIM.
*
- * If the reference count reaches 0, this may cause @lte to be destroyed.
- * However, we may retain entries with 0 reference count. This does not affect
- * correctness, but it prevents the entries for valid streams in a WIM archive,
- * which will continue to be present after appending to the file, from being
- * lost merely because we dropped all references to them.
+ * So we can't take the reference counts too seriously. But at least, we do
+ * recalculate by default when writing a new WIM file.
*/
void
lte_decrement_refcnt(struct wim_lookup_table_entry *lte,
struct wim_lookup_table *table)
{
- wimlib_assert(lte->refcnt != 0);
+ if (unlikely(lte->refcnt == 0)) /* See comment above */
+ return;
if (--lte->refcnt == 0) {
if (lte->unhashed) {
* that there still may be open file descriptors to it.)
* */
if (lte->resource_location == RESOURCE_IN_STAGING_FILE)
- unlink(lte->staging_file_name);
+ unlinkat(lte->staging_dir_fd,
+ lte->staging_file_name, 0);
#endif
} else {
if (!should_retain_lte(lte))
case RESOURCE_IN_STAGING_FILE:
#endif
#ifdef __WIN32__
+ case RESOURCE_IN_WINNT_FILE_ON_DISK:
case RESOURCE_WIN32_ENCRYPTED:
#endif
/* Compare files by path: just a heuristic that will place files
/* Which part of the split WIM this stream is in; indexed from 1. */
le16 part_number;
- /* Reference count of this stream over all WIM images. */
+ /* Reference count of this stream over all WIM images. (But see comment
+ * above lte_decrement_refcnt().) */
le32 refcnt;
/* SHA1 message digest of the uncompressed data of this stream, or
return ret;
}
-int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *_ignore)
-{
- lte->real_refcnt = 0;
- return 0;
-}
-
int
lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *_ignore)
{
return 0;
}
-int
-lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *_ignore)
-{
- if (lte->extracted_file != NULL) {
- FREE(lte->extracted_file);
- lte->extracted_file = NULL;
- }
- return 0;
-}
-
/* Allocate a stream entry for the contents of the buffer, or re-use an existing
* entry in @lookup_table for the same stream. */
struct wim_lookup_table_entry *