libwim_la_SOURCES = \
src/add_image.c \
+ src/buffer_io.h \
src/compress.c \
src/compress.h \
src/decompress.c \
src/hardlink.c \
src/header.c \
src/integrity.c \
- src/io.h \
src/join.c \
src/list.h \
src/lookup_table.c \
src/timestamp.h \
src/util.c \
src/util.h \
+ src/verify.c \
src/wim.c \
src/wimlib.h \
src/wimlib_internal.h \
/*
- * io.h
+ * buffer_io.h
*
* A few endianness-aware macros for reading and writing data from in-memory
* buffers.
*/
-#ifndef _WIMLIB_IO_H
-#define _WIMLIB_IO_H
+#ifndef _WIMLIB_BUFFER_IO_H
+#define _WIMLIB_BUFFER_IO_H
#include "util.h"
#include "endianness.h"
{
return (u8*)memcpy(p, input, num_bytes) + num_bytes;
}
-#endif /* _WIMLIB_IO_H */
+#endif /* _WIMLIB_BUFFER_IO_H */
#include <unistd.h>
#include "dentry.h"
-#include "io.h"
+#include "buffer_io.h"
#include "lookup_table.h"
#include "sha1.h"
#include "timestamp.h"
}
#endif
-static inline struct dentry *inode_first_dentry(struct inode *inode)
-{
- wimlib_assert(inode->dentry_list.next != &inode->dentry_list);
- return container_of(inode->dentry_list.next, struct dentry,
- inode_dentry_list);
-}
-
-static int verify_inode(struct inode *inode, const WIMStruct *w)
-{
- const struct lookup_table *table = w->lookup_table;
- const struct wim_security_data *sd = wim_const_security_data(w);
- const struct dentry *first_dentry = inode_first_dentry(inode);
- int ret = WIMLIB_ERR_INVALID_DENTRY;
-
- /* Check the security ID */
- if (inode->security_id < -1) {
- ERROR("Dentry `%s' has an invalid security ID (%d)",
- first_dentry->full_path_utf8, inode->security_id);
- goto out;
- }
- if (inode->security_id >= sd->num_entries) {
- ERROR("Dentry `%s' has an invalid security ID (%d) "
- "(there are only %u entries in the security table)",
- first_dentry->full_path_utf8, inode->security_id,
- sd->num_entries);
- goto out;
- }
-
- /* Check that lookup table entries for all the resources exist, except
- * if the SHA1 message digest is all 0's, which indicates there is
- * intentionally no resource there. */
- if (w->hdr.total_parts == 1) {
- for (unsigned i = 0; i <= inode->num_ads; i++) {
- struct lookup_table_entry *lte;
- const u8 *hash;
- hash = inode_stream_hash_unresolved(inode, i);
- lte = __lookup_resource(table, hash);
- if (!lte && !is_zero_hash(hash)) {
- ERROR("Could not find lookup table entry for stream "
- "%u of dentry `%s'", i, first_dentry->full_path_utf8);
- goto out;
- }
- if (lte)
- lte->real_refcnt += inode->link_count;
-
- /* The following is now done when required by
- * wim_run_full_verifications(). */
-
- #if 0
- if (lte && !w->full_verification_in_progress &&
- lte->real_refcnt > lte->refcnt)
- {
- #ifdef ENABLE_ERROR_MESSAGES
- 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);
- WARNING("(One dentry referencing it is at `%s')",
- first_dentry->full_path_utf8);
-
- print_lookup_table_entry(lte);
- #endif
- /* Guess what! install.wim for Windows 8
- * contains many streams referenced by more
- * dentries than the refcnt stated in the lookup
- * table entry. So we will need to handle this
- * case and not just make it be an error... I'm
- * just setting the reference count to the
- * number of references we found.
- * (Unfortunately, even after doing this, the
- * reference count could be too low if it's also
- * referenced in other WIM images) */
-
- #if 1
- lte->refcnt = lte->real_refcnt;
- WARNING("Fixing reference count");
- #else
- goto out;
- #endif
- }
- #endif
- }
- }
-
- /* Make sure there is only one un-named stream. */
- unsigned num_unnamed_streams = 0;
- for (unsigned i = 0; i <= inode->num_ads; i++) {
- const u8 *hash;
- hash = inode_stream_hash_unresolved(inode, i);
- if (!inode_stream_name_len(inode, i) && !is_zero_hash(hash))
- num_unnamed_streams++;
- }
- if (num_unnamed_streams > 1) {
- ERROR("Dentry `%s' has multiple (%u) un-named streams",
- first_dentry->full_path_utf8, num_unnamed_streams);
- goto out;
- }
- inode->verified = true;
- ret = 0;
-out:
- return ret;
-}
-
-/* Run some miscellaneous verifications on a WIM dentry */
-int verify_dentry(struct dentry *dentry, void *wim)
-{
- int ret;
-
- if (!dentry->d_inode->verified) {
- ret = verify_inode(dentry->d_inode, wim);
- if (ret != 0)
- return ret;
- }
-
- /* Cannot have a short name but no long name */
- if (dentry->short_name_len && !dentry->file_name_len) {
- ERROR("Dentry `%s' has a short name but no long name",
- dentry->full_path_utf8);
- return WIMLIB_ERR_INVALID_DENTRY;
- }
-
- /* Make sure root dentry is unnamed */
- if (dentry_is_root(dentry)) {
- if (dentry->file_name_len) {
- ERROR("The root dentry is named `%s', but it must "
- "be unnamed", dentry->file_name_utf8);
- return WIMLIB_ERR_INVALID_DENTRY;
- }
- }
-
-#if 0
- /* Check timestamps */
- if (inode->last_access_time < inode->creation_time ||
- inode->last_write_time < inode->creation_time) {
- WARNING("Dentry `%s' was created after it was last accessed or "
- "written to", dentry->full_path_utf8);
- }
-#endif
-
- return 0;
-}
-
-
#ifdef WITH_FUSE
/* Returns the alternate data stream entry belonging to @inode that has the
* stream name @stream_name. */
extern bool dentry_add_child(struct dentry * restrict parent,
struct dentry * restrict child);
-extern int verify_dentry(struct dentry *dentry, void *wim);
-
-
extern struct ads_entry *inode_get_ads_entry(struct inode *inode,
const char *stream_name,
u16 *idx_ret);
inode->reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT);
}
-static inline bool dentry_is_symlink(const struct dentry *dentry)
-{
- return inode_is_symlink(dentry->d_inode);
-}
-
static inline bool inode_is_regular_file(const struct inode *inode)
{
return !inode_is_directory(inode) && !inode_is_symlink(inode);
}
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 delete all the
- * references to a stream and then remove it, it might still be referenced
- * somewhere else, making a file be missing from the WIM... So, work around this
- * problem by looking at ALL the images to re-calculate the reference count of
- * EVERY lookup table entry. This only absolutely has to be done before an image
- * is deleted or before an image is mounted read-write. */
-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;
-}
* along with wimlib; if not, see http://www.gnu.org/licenses/.
*/
-
#include "config.h"
#include <dirent.h>
*/
/*
- * Copyright (C) 2010 Carl Thijssen
* Copyright (C) 2012 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*/
#include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
#include <limits.h>
/* First 8 bytes in every WIM file. */
*/
#include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
#include "sha1.h"
/* Size, in bytes, of each SHA1-summed chunk, when wimlib writes integrity
return for_lookup_table_entry(new, move_lte_to_table, table);
}
-/*
- * Sanity checks to make sure a set of WIMs correctly correspond to a spanned
- * set.
- *
- * @w:
- * Part 1 of the set.
- *
- * @additional_swms:
- * All parts of the set other than part 1.
- *
- * @num_additional_swms:
- * Number of WIMStructs in @additional_swms. Or, the total number of parts
- * in the set minus 1.
- *
- * @return:
- * 0 on success; WIMLIB_ERR_SPLIT_INVALID if the set is not valid.
- */
-int verify_swm_set(WIMStruct *w, WIMStruct **additional_swms,
- unsigned num_additional_swms)
-{
- unsigned total_parts = w->hdr.total_parts;
- int ctype;
- const u8 *guid;
-
- if (total_parts != num_additional_swms + 1) {
- ERROR("`%s' says there are %u parts in the spanned set, "
- "but %s%u part%s provided",
- w->filename, total_parts,
- (num_additional_swms + 1 < total_parts) ? "only " : "",
- num_additional_swms + 1,
- (num_additional_swms) ? "s were" : " was");
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (w->hdr.part_number != 1) {
- ERROR("WIM `%s' is not the first part of the split WIM.",
- w->filename);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- for (unsigned i = 0; i < num_additional_swms; i++) {
- if (additional_swms[i]->hdr.total_parts != total_parts) {
- ERROR("WIM `%s' says there are %u parts in the spanned set, "
- "but %u parts were provided",
- additional_swms[i]->filename,
- additional_swms[i]->hdr.total_parts,
- total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- }
-
- /* keep track of ctype and guid just to make sure they are the same for
- * all the WIMs. */
- ctype = wimlib_get_compression_type(w);
- guid = w->hdr.guid;
-
- WIMStruct *parts_to_swms[num_additional_swms];
- ZERO_ARRAY(parts_to_swms);
- for (unsigned i = 0; i < num_additional_swms; i++) {
-
- WIMStruct *swm = additional_swms[i];
-
- if (wimlib_get_compression_type(swm) != ctype) {
- ERROR("The split WIMs do not all have the same "
- "compression type");
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (memcmp(guid, swm->hdr.guid, WIM_GID_LEN) != 0) {
- ERROR("The split WIMs do not all have the same "
- "GUID");
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (swm->hdr.part_number == 1) {
- ERROR("WIMs `%s' and `%s' both are marked as the "
- "first WIM in the spanned set",
- w->filename, swm->filename);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (swm->hdr.part_number == 0 ||
- swm->hdr.part_number > total_parts)
- {
- ERROR("WIM `%s' says it is part %u in the spanned set, "
- "but the part number must be in the range "
- "[1, %u]",
- swm->filename, swm->hdr.part_number, total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- }
- if (parts_to_swms[swm->hdr.part_number - 2])
- {
- ERROR("`%s' and `%s' are both marked as part %u of %u "
- "in the spanned set",
- parts_to_swms[swm->hdr.part_number - 2]->filename,
- swm->filename,
- swm->hdr.part_number,
- total_parts);
- return WIMLIB_ERR_SPLIT_INVALID;
- } else {
- parts_to_swms[swm->hdr.part_number - 2] = swm;
- }
- }
- return 0;
-}
-
/*
* Joins lookup tables from the parts of a split WIM.
*
#include "wimlib_internal.h"
#include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
#include <errno.h>
#ifdef WITH_FUSE
int R2;
};
-extern int lzx_decompress(const void *compressed_data, uint compressed_len,
- void *uncompressed_data, uint uncompressed_len);
+extern int lzx_decompress(const void *compressed_data, unsigned compressed_len,
+ void *uncompressed_data, unsigned uncompressed_len);
-extern int lzx_compress(const void *uncompressed_data, uint uncompressed_len,
- void *compressed_data, uint *compressed_len_ret);
+extern int lzx_compress(const void *uncompressed_data, unsigned uncompressed_len,
+ void *compressed_data, unsigned *compressed_len_ret);
#endif /* _WIMLIB_LZX_H */
#include "sha1.h"
#include "lookup_table.h"
#include "xml.h"
-#include "io.h"
+#include "buffer_io.h"
#include "timestamp.h"
#include <limits.h>
#include <stdlib.h>
#include "wimlib_internal.h"
#include "dentry.h"
#include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
#include <ntfs-3g/layout.h>
#include <ntfs-3g/acls.h>
#include <ntfs-3g/attrib.h>
#include "dentry.h"
#include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
#include <ntfs-3g/layout.h>
#include <ntfs-3g/acls.h>
#include <ntfs-3g/attrib.h>
#include "wimlib_internal.h"
#include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
#include "lzx.h"
#include "xpress.h"
#include "sha1.h"
if (len == 0)
return 0;
- int (*decompress)(const void *, uint, void *, uint);
+ int (*decompress)(const void *, unsigned, void *, unsigned);
/* Set the appropriate decompress function. */
if (resource_ctype == WIMLIB_COMPRESSION_TYPE_LZX)
decompress = lzx_decompress;
/* Calculate the sizes of the compressed chunk and of the
* uncompressed chunk. */
- uint compressed_chunk_size, uncompressed_chunk_size;
+ unsigned compressed_chunk_size;
+ unsigned uncompressed_chunk_size;
if (i != num_chunks - 1) {
/* All the chunks except the last one in the resource
* expand to WIM_CHUNK_SIZE uncompressed, and the amount
/* Get the lookup table entry for the metadata resource so we can update
* it. */
- lte = wim_metadata_lookup_table_entry(w);
+ lte = w->image_metadata[w->current_image - 1].metadata_lte;
/* Write the metadata resource to the output WIM using the proper
* compression type. The lookup table entry for the metadata resource
*/
#include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
#include "security.h"
/*
printf(" ACE Count = %u\n", ace_count);
p += sizeof(ACL);
- for (uint i = 0; i < acl->ace_count; i++) {
+ for (u16 i = 0; i < ace_count; i++) {
const ACEHeader *hdr = (const ACEHeader*)p;
printf(" [ACE]\n");
printf(" ACE type = %d\n", hdr->type);
print_byte_field(sid->identifier_authority,
sizeof(sid->identifier_authority));
putchar('\n');
- for (uint i = 0; i < sid->sub_authority_count; i++)
+ for (u8 i = 0; i < sid->sub_authority_count; i++)
printf(" Subauthority %u = %u\n",
i, le32_to_cpu(sid->sub_authority[i]));
putchar('\n');
#include "wimlib_internal.h"
#include "lookup_table.h"
#include "xml.h"
-#include "io.h"
+#include "buffer_io.h"
struct split_args {
WIMStruct *w;
*/
#include "dentry.h"
-#include "io.h"
+#include "buffer_io.h"
#include "lookup_table.h"
#include "sha1.h"
#include <errno.h>
return ret;
}
-void *make_symlink_reparse_data_buf(const char *symlink_target, size_t *len_ret)
+static void *make_symlink_reparse_data_buf(const char *symlink_target,
+ size_t *len_ret)
{
size_t utf8_len = strlen(symlink_target);
size_t utf16_len;
--- /dev/null
+/*
+ * verify.c
+ *
+ * Some functions to verify that stuff in the WIM is valid. Of course, not
+ * *all* the verifications of the input data are in this file.
+ */
+
+/*
+ * Copyright (C) 2012 Eric Biggers
+ *
+ * wimlib - Library for working with WIM files
+ *
+ * This file is part of wimlib, a library for working with WIM files.
+ *
+ * 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
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ */
+
+#include "wimlib_internal.h"
+#include "dentry.h"
+#include "lookup_table.h"
+
+static inline struct dentry *inode_first_dentry(struct inode *inode)
+{
+ wimlib_assert(inode->dentry_list.next != &inode->dentry_list);
+ return container_of(inode->dentry_list.next, struct dentry,
+ inode_dentry_list);
+}
+
+static int verify_inode(struct inode *inode, const WIMStruct *w)
+{
+ const struct lookup_table *table = w->lookup_table;
+ const struct wim_security_data *sd = wim_const_security_data(w);
+ const struct dentry *first_dentry = inode_first_dentry(inode);
+ int ret = WIMLIB_ERR_INVALID_DENTRY;
+
+ /* Check the security ID */
+ if (inode->security_id < -1) {
+ ERROR("Dentry `%s' has an invalid security ID (%d)",
+ first_dentry->full_path_utf8, inode->security_id);
+ goto out;
+ }
+ if (inode->security_id >= sd->num_entries) {
+ ERROR("Dentry `%s' has an invalid security ID (%d) "
+ "(there are only %u entries in the security table)",
+ first_dentry->full_path_utf8, inode->security_id,
+ sd->num_entries);
+ goto out;
+ }
+
+ /* Check that lookup table entries for all the resources exist, except
+ * if the SHA1 message digest is all 0's, which indicates there is
+ * intentionally no resource there. */
+ if (w->hdr.total_parts == 1) {
+ for (unsigned i = 0; i <= inode->num_ads; i++) {
+ struct lookup_table_entry *lte;
+ const u8 *hash;
+ hash = inode_stream_hash_unresolved(inode, i);
+ lte = __lookup_resource(table, hash);
+ if (!lte && !is_zero_hash(hash)) {
+ ERROR("Could not find lookup table entry for stream "
+ "%u of dentry `%s'", i, first_dentry->full_path_utf8);
+ goto out;
+ }
+ if (lte)
+ lte->real_refcnt += inode->link_count;
+
+ /* The following is now done when required by
+ * wim_run_full_verifications(). */
+
+ #if 0
+ if (lte && !w->full_verification_in_progress &&
+ lte->real_refcnt > lte->refcnt)
+ {
+ #ifdef ENABLE_ERROR_MESSAGES
+ 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);
+ WARNING("(One dentry referencing it is at `%s')",
+ first_dentry->full_path_utf8);
+
+ print_lookup_table_entry(lte);
+ #endif
+ /* Guess what! install.wim for Windows 8
+ * contains many streams referenced by more
+ * dentries than the refcnt stated in the lookup
+ * table entry. So we will need to handle this
+ * case and not just make it be an error... I'm
+ * just setting the reference count to the
+ * number of references we found.
+ * (Unfortunately, even after doing this, the
+ * reference count could be too low if it's also
+ * referenced in other WIM images) */
+
+ #if 1
+ lte->refcnt = lte->real_refcnt;
+ WARNING("Fixing reference count");
+ #else
+ goto out;
+ #endif
+ }
+ #endif
+ }
+ }
+
+ /* Make sure there is only one un-named stream. */
+ unsigned num_unnamed_streams = 0;
+ for (unsigned i = 0; i <= inode->num_ads; i++) {
+ const u8 *hash;
+ hash = inode_stream_hash_unresolved(inode, i);
+ if (!inode_stream_name_len(inode, i) && !is_zero_hash(hash))
+ num_unnamed_streams++;
+ }
+ if (num_unnamed_streams > 1) {
+ ERROR("Dentry `%s' has multiple (%u) un-named streams",
+ first_dentry->full_path_utf8, num_unnamed_streams);
+ goto out;
+ }
+ inode->verified = true;
+ ret = 0;
+out:
+ return ret;
+}
+
+/* Run some miscellaneous verifications on a WIM dentry */
+int verify_dentry(struct dentry *dentry, void *wim)
+{
+ int ret;
+
+ if (!dentry->d_inode->verified) {
+ ret = verify_inode(dentry->d_inode, wim);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* Cannot have a short name but no long name */
+ if (dentry->short_name_len && !dentry->file_name_len) {
+ ERROR("Dentry `%s' has a short name but no long name",
+ dentry->full_path_utf8);
+ return WIMLIB_ERR_INVALID_DENTRY;
+ }
+
+ /* Make sure root dentry is unnamed */
+ if (dentry_is_root(dentry)) {
+ if (dentry->file_name_len) {
+ ERROR("The root dentry is named `%s', but it must "
+ "be unnamed", dentry->file_name_utf8);
+ return WIMLIB_ERR_INVALID_DENTRY;
+ }
+ }
+
+#if 0
+ /* Check timestamps */
+ if (inode->last_access_time < inode->creation_time ||
+ inode->last_write_time < inode->creation_time) {
+ WARNING("Dentry `%s' was created after it was last accessed or "
+ "written to", dentry->full_path_utf8);
+ }
+#endif
+
+ return 0;
+}
+
+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 delete all the
+ * references to a stream and then remove it, it might still be referenced
+ * somewhere else, making a file be missing from the WIM... So, work around this
+ * problem by looking at ALL the images to re-calculate the reference count of
+ * EVERY lookup table entry. This only absolutely has to be done before an image
+ * is deleted or before an image is mounted read-write. */
+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 = 1;
+ w->full_verification_in_progress = 1;
+ ret = for_image(w, WIMLIB_ALL_IMAGES, image_run_full_verifications);
+ w->full_verification_in_progress = 0;
+ 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 = 0;
+ }
+ return ret;
+}
+
+/*
+ * Sanity checks to make sure a set of WIMs correctly correspond to a spanned
+ * set.
+ *
+ * @w:
+ * Part 1 of the set.
+ *
+ * @additional_swms:
+ * All parts of the set other than part 1.
+ *
+ * @num_additional_swms:
+ * Number of WIMStructs in @additional_swms. Or, the total number of parts
+ * in the set minus 1.
+ *
+ * @return:
+ * 0 on success; WIMLIB_ERR_SPLIT_INVALID if the set is not valid.
+ */
+int verify_swm_set(WIMStruct *w, WIMStruct **additional_swms,
+ unsigned num_additional_swms)
+{
+ unsigned total_parts = w->hdr.total_parts;
+ int ctype;
+ const u8 *guid;
+
+ if (total_parts != num_additional_swms + 1) {
+ ERROR("`%s' says there are %u parts in the spanned set, "
+ "but %s%u part%s provided",
+ w->filename, total_parts,
+ (num_additional_swms + 1 < total_parts) ? "only " : "",
+ num_additional_swms + 1,
+ (num_additional_swms) ? "s were" : " was");
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (w->hdr.part_number != 1) {
+ ERROR("WIM `%s' is not the first part of the split WIM.",
+ w->filename);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ for (unsigned i = 0; i < num_additional_swms; i++) {
+ if (additional_swms[i]->hdr.total_parts != total_parts) {
+ ERROR("WIM `%s' says there are %u parts in the spanned set, "
+ "but %u parts were provided",
+ additional_swms[i]->filename,
+ additional_swms[i]->hdr.total_parts,
+ total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ }
+
+ /* keep track of ctype and guid just to make sure they are the same for
+ * all the WIMs. */
+ ctype = wimlib_get_compression_type(w);
+ guid = w->hdr.guid;
+
+ WIMStruct *parts_to_swms[num_additional_swms];
+ ZERO_ARRAY(parts_to_swms);
+ for (unsigned i = 0; i < num_additional_swms; i++) {
+
+ WIMStruct *swm = additional_swms[i];
+
+ if (wimlib_get_compression_type(swm) != ctype) {
+ ERROR("The split WIMs do not all have the same "
+ "compression type");
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (memcmp(guid, swm->hdr.guid, WIM_GID_LEN) != 0) {
+ ERROR("The split WIMs do not all have the same "
+ "GUID");
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (swm->hdr.part_number == 1) {
+ ERROR("WIMs `%s' and `%s' both are marked as the "
+ "first WIM in the spanned set",
+ w->filename, swm->filename);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (swm->hdr.part_number == 0 ||
+ swm->hdr.part_number > total_parts)
+ {
+ ERROR("WIM `%s' says it is part %u in the spanned set, "
+ "but the part number must be in the range "
+ "[1, %u]",
+ swm->filename, swm->hdr.part_number, total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ }
+ if (parts_to_swms[swm->hdr.part_number - 2])
+ {
+ ERROR("`%s' and `%s' are both marked as part %u of %u "
+ "in the spanned set",
+ parts_to_swms[swm->hdr.part_number - 2]->filename,
+ swm->filename,
+ swm->hdr.part_number,
+ total_parts);
+ return WIMLIB_ERR_SPLIT_INVALID;
+ } else {
+ parts_to_swms[swm->hdr.part_number - 2] = swm;
+ }
+ }
+ return 0;
+}
+
*/
/*
- * Copyright (C) 2010 Carl Thijssen
* Copyright (C) 2012 Eric Biggers
*
* wimlib - Library for working with WIM files
#endif
#include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
#include "lookup_table.h"
#include "xml.h"
+static inline struct image_metadata *
+wim_get_current_image_metadata(WIMStruct *w)
+{
+ return &w->image_metadata[w->current_image - 1];
+}
+
static int print_metadata(WIMStruct *w)
{
DEBUG("Printing metadata for image %d", w->current_image);
NULL);
}
-WIMStruct *new_wim_struct()
+static WIMStruct *new_wim_struct()
{
WIMStruct *w = CALLOC(1, sizeof(WIMStruct));
#ifdef WITH_FUSE
}
/* Returns the compression type given in the flags of a WIM header. */
-int wim_hdr_flags_compression_type(int wim_hdr_flags)
+static int wim_hdr_flags_compression_type(int wim_hdr_flags)
{
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESSION) {
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESS_LZX)
*/
/*
- * Copyright (C) 2010 Carl Thijssen
* Copyright (C) 2012 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
#include "config.h"
#include "util.h"
#include "list.h"
-
#include "wimlib.h"
#ifdef WITH_FUSE
#define WIM_GID_LEN 16
#define WIM_UNUSED_LEN 60
-
/* Length of the WIM header on disk. */
#define WIM_HEADER_DISK_SIZE (148 + WIM_UNUSED_LEN)
* yet. The differences between the versions are undocumented. */
#define WIM_VERSION 0x10d00
-#define WIM_INTEGRITY_OK 0
-#define WIM_INTEGRITY_NOT_OK -1
-#define WIM_INTEGRITY_NONEXISTENT -2
-
/* Metadata for a resource in a WIM file. */
struct resource_entry {
/* Size, in bytes, of the resource in the WIM file. */
* Either way, we don't actually use this flag for anything. */
#define WIM_RESHDR_FLAG_SPANNED 0x08
-
/* Header at the very beginning of the WIM file. */
struct wim_header {
/* Identifies the file as WIM file. Must be exactly
//u32 chunk_size;
/* A unique identifier for the WIM file. */
- u8 guid[WIM_GID_LEN];
+ u8 guid[WIM_GID_LEN];
/* Part number of the WIM file in a spanned set. */
u16 part_number;
u8 has_been_mounted_rw : 1;
};
-#define WIMLIB_RESOURCE_FLAG_RAW 0x1
-#define WIMLIB_RESOURCE_FLAG_MULTITHREADED 0x2
-#define WIMLIB_RESOURCE_FLAG_RECOMPRESS 0x4
-
/* The opaque structure exposed to the wimlib API. */
struct WIMStruct {
* image_metadata array. */
int current_image;
- /* %true iff any images have been deleted from this WIM. */
- bool deletion_occurred;
-
- bool all_images_verified;
- bool full_verification_in_progress;
+ u8 deletion_occurred : 1;
+ u8 all_images_verified : 1;
+ u8 full_verification_in_progress : 1;
};
-
/* Inline utility functions for WIMStructs. */
static inline struct dentry *wim_root_dentry(WIMStruct *w)
return w->image_metadata[w->current_image - 1].security_data;
}
-static inline struct lookup_table_entry*
-wim_metadata_lookup_table_entry(WIMStruct *w)
-{
- return w->image_metadata[w->current_image - 1].metadata_lte;
-}
-
/* Nonzero if a struct resource_entry indicates a compressed resource. */
static inline int resource_is_compressed(const struct resource_entry *entry)
{
return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED);
}
-static inline struct image_metadata *
-wim_get_current_image_metadata(WIMStruct *w)
-{
- return &w->image_metadata[w->current_image - 1];
-}
+/* add_image.c */
struct pattern_list {
const char **pats;
char *prefix;
size_t prefix_len;
};
-
-/* add_image.c */
extern bool exclude_path(const char *path,
const struct capture_config *config,
bool exclude_prefix);
extern int add_new_dentry_tree(WIMStruct *dest_wim, struct dentry *root,
struct wim_security_data *sd);
+/* extract_image.c */
+
+/* Internal use only */
+#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000
+#define WIMLIB_EXTRACT_FLAG_NO_STREAMS 0x40000000
+#define WIMLIB_EXTRACT_MASK_PUBLIC 0x3fffffff
+
/* hardlink.c */
/* Hash table to find inodes, identified by their inode ID.
extern int init_header(struct wim_header *hdr, int ctype);
/* integrity.c */
+
+#define WIM_INTEGRITY_OK 0
+#define WIM_INTEGRITY_NOT_OK -1
+#define WIM_INTEGRITY_NONEXISTENT -2
+
extern int write_integrity_table(FILE *out,
struct resource_entry *integrity_res_entry,
off_t new_lookup_table_end,
unsigned num_additional_swms,
struct lookup_table **table_ret);
-extern int verify_swm_set(WIMStruct *w,
- WIMStruct **additional_swms,
- unsigned num_additional_swms);
-extern int wim_run_full_verifications(WIMStruct *w);
-
/* ntfs-apply.c */
struct apply_args {
void *extra_arg);
/* resource.c */
+
+#define WIMLIB_RESOURCE_FLAG_RAW 0x1
+#define WIMLIB_RESOURCE_FLAG_MULTITHREADED 0x2
+#define WIMLIB_RESOURCE_FLAG_RECOMPRESS 0x4
+
extern const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry);
extern u8 *put_resource_entry(u8 *p, const struct resource_entry *entry);
/* security.c */
-int read_security_data(const u8 metadata_resource[],
- u64 metadata_resource_len, struct wim_security_data **sd_p);
-
-void print_security_data(const struct wim_security_data *sd);
-u8 *write_security_data(const struct wim_security_data *sd, u8 *p);
-void free_security_data(struct wim_security_data *sd);
+extern int read_security_data(const u8 metadata_resource[],
+ u64 metadata_resource_len,
+ struct wim_security_data **sd_p);
+extern void print_security_data(const struct wim_security_data *sd);
+extern u8 *write_security_data(const struct wim_security_data *sd, u8 *p);
+extern void free_security_data(struct wim_security_data *sd);
/* symlink.c */
ssize_t inode_readlink(const struct inode *inode, char *buf, size_t buf_len,
const WIMStruct *w, int read_resource_flags);
-extern void *make_symlink_reparse_data_buf(const char *symlink_target,
- size_t *len_ret);
extern int inode_set_symlink(struct inode *inode,
const char *target,
struct lookup_table *lookup_table,
struct lookup_table_entry **lte_ret);
+/* verify.c */
+extern int verify_dentry(struct dentry *dentry, void *wim);
+extern int wim_run_full_verifications(WIMStruct *w);
+extern int verify_swm_set(WIMStruct *w,
+ WIMStruct **additional_swms,
+ unsigned num_additional_swms);
+
/* wim.c */
-extern WIMStruct *new_wim_struct();
extern int select_wim_image(WIMStruct *w, int image);
-extern int wim_hdr_flags_compression_type(int wim_hdr_flags);
extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *));
extern void destroy_image_metadata(struct image_metadata *imd,
struct lookup_table *lt);
+
+/* write.c */
+
/* Internal use only */
#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000
#define WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE 0x40000000
#define WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML 0x20000000
#define WIMLIB_WRITE_MASK_PUBLIC 0x1fffffff
-/* Internal use only */
-#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000
-#define WIMLIB_EXTRACT_FLAG_NO_STREAMS 0x40000000
-#define WIMLIB_EXTRACT_MASK_PUBLIC 0x3fffffff
-
-
-/* write.c */
extern int begin_write(WIMStruct *w, const char *path, int write_flags);
extern void close_wim_writable(WIMStruct *w);
*/
/*
- * Copyright (C) 2010 Carl Thijssen
* Copyright (C) 2012 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
#include "list.h"
#include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
#include "dentry.h"
#include "lookup_table.h"
#include "xml.h"
#define XPRESS_MIN_MATCH 3
#define XPRESS_MAX_MATCH 65538
-extern int xpress_decompress(const void *__compressed_data, uint compressed_len,
- void *__uncompressed_data, uint uncompressed_len);
+extern int xpress_decompress(const void *__compressed_data, unsigned compressed_len,
+ void *__uncompressed_data, unsigned uncompressed_len);
-extern int xpress_compress(const void *uncompressed_data, uint uncompressed_len,
- void *compressed_data, uint *compressed_len_ret);
+extern int xpress_compress(const void *uncompressed_data, unsigned uncompressed_len,
+ void *compressed_data, unsigned *compressed_len_ret);
#endif /* _WIMLIB_XPRESS_H */