verify.c, buffer_io.h
authorEric Biggers <ebiggers3@gmail.com>
Sun, 16 Dec 2012 18:57:18 +0000 (12:57 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 16 Dec 2012 18:57:18 +0000 (12:57 -0600)
23 files changed:
Makefile.am
src/buffer_io.h [moved from src/io.h with 96% similarity]
src/dentry.c
src/dentry.h
src/export_image.c
src/extract_image.c
src/header.c
src/integrity.c
src/join.c
src/lookup_table.c
src/lzx.h
src/mount_image.c
src/ntfs-apply.c
src/ntfs-capture.c
src/resource.c
src/security.c
src/split.c
src/symlink.c
src/verify.c [new file with mode: 0644]
src/wim.c
src/wimlib_internal.h
src/write.c
src/xpress.h

index b032083..eae0a6f 100644 (file)
@@ -11,6 +11,7 @@ libwim_la_LDFLAGS = -version-info 1:0:0
 
 libwim_la_SOURCES =            \
        src/add_image.c         \
+       src/buffer_io.h         \
        src/compress.c          \
        src/compress.h          \
        src/decompress.c        \
@@ -24,7 +25,6 @@ libwim_la_SOURCES =           \
        src/hardlink.c          \
        src/header.c            \
        src/integrity.c         \
-       src/io.h                \
        src/join.c              \
        src/list.h              \
        src/lookup_table.c      \
@@ -48,6 +48,7 @@ libwim_la_SOURCES =           \
        src/timestamp.h         \
        src/util.c              \
        src/util.h              \
+       src/verify.c            \
        src/wim.c               \
        src/wimlib.h            \
        src/wimlib_internal.h   \
similarity index 96%
rename from src/io.h
rename to src/buffer_io.h
index 1a617e2..9dd88a0 100644 (file)
--- a/src/io.h
@@ -1,12 +1,12 @@
 /*
- * 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"
@@ -117,4 +117,4 @@ static inline u8 *put_bytes(u8 *p, size_t num_bytes, const u8 *input)
 {
        return (u8*)memcpy(p, input, num_bytes) + num_bytes;
 }
-#endif /* _WIMLIB_IO_H */
+#endif /* _WIMLIB_BUFFER_IO_H */
index 4ff8602..ae71c1d 100644 (file)
@@ -33,7 +33,7 @@
 #include <unistd.h>
 
 #include "dentry.h"
-#include "io.h"
+#include "buffer_io.h"
 #include "lookup_table.h"
 #include "sha1.h"
 #include "timestamp.h"
@@ -1080,150 +1080,6 @@ void unlink_dentry(struct dentry *dentry)
 }
 #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. */
index 64b6471..d03d42e 100644 (file)
@@ -381,9 +381,6 @@ extern void unlink_dentry(struct dentry *dentry);
 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);
@@ -427,11 +424,6 @@ static inline bool inode_is_symlink(const struct inode *inode)
                     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);
index 9b9304c..a019280 100644 (file)
@@ -290,57 +290,3 @@ 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 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;
-}
index 22b12ba..470469a 100644 (file)
@@ -28,7 +28,6 @@
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
-
 #include "config.h"
 
 #include <dirent.h>
index bb17209..5b4d0b9 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 /*
- * Copyright (C) 2010 Carl Thijssen
  * Copyright (C) 2012 Eric Biggers
  *
  * This file is part of wimlib, a library for working with WIM files.
@@ -25,7 +24,7 @@
  */
 
 #include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
 #include <limits.h>
 
 /* First 8 bytes in every WIM file. */
index b5fac79..837a1d8 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #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
index 34e5df9..054e347 100644 (file)
@@ -43,107 +43,6 @@ static int lookup_table_join(struct lookup_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.
  *
  * @w specifies the first part, while @additional_swms and @num_additional_swms
index 12ff12b..0a92006 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "wimlib_internal.h"
 #include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
 #include <errno.h>
 
 #ifdef WITH_FUSE
index 70872ab..42ae5ce 100644 (file)
--- a/src/lzx.h
+++ b/src/lzx.h
@@ -82,10 +82,10 @@ struct lru_queue {
        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 */
index ea44f22..6ab60d9 100644 (file)
@@ -33,7 +33,7 @@
 #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>
index 1113a83..dc732d8 100644 (file)
@@ -34,7 +34,7 @@
 #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>
index aa4458c..5b47b56 100644 (file)
@@ -35,7 +35,7 @@
 
 #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>
index 2576197..f8f4844 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "wimlib_internal.h"
 #include "lookup_table.h"
-#include "io.h"
+#include "buffer_io.h"
 #include "lzx.h"
 #include "xpress.h"
 #include "sha1.h"
@@ -81,7 +81,7 @@ static int read_compressed_resource(FILE *fp, u64 resource_compressed_size,
        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;
@@ -230,7 +230,8 @@ static int read_compressed_resource(FILE *fp, u64 resource_compressed_size,
 
                /* 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
@@ -946,7 +947,7 @@ int write_metadata_resource(WIMStruct *w)
 
        /* 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
index c915854..c084258 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
 #include "security.h"
 
 /*
@@ -250,7 +250,7 @@ static void print_acl(const u8 *p, const char *type)
        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);
@@ -274,7 +274,7 @@ static void print_sid(const u8 *p, const char *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');
index 50f15bf..59aedf7 100644 (file)
@@ -26,7 +26,7 @@
 #include "wimlib_internal.h"
 #include "lookup_table.h"
 #include "xml.h"
-#include "io.h"
+#include "buffer_io.h"
 
 struct split_args {
        WIMStruct *w;
index 6ef0dab..b90ebe5 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "dentry.h"
-#include "io.h"
+#include "buffer_io.h"
 #include "lookup_table.h"
 #include "sha1.h"
 #include <errno.h>
@@ -124,7 +124,8 @@ out:
        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;
diff --git a/src/verify.c b/src/verify.c
new file mode 100644 (file)
index 0000000..a4527fe
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * 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;
+}
+
index c726484..af5098c 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -3,7 +3,6 @@
  */
 
 /*
- * 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);
@@ -59,7 +64,7 @@ static int print_files(WIMStruct *w)
                                  NULL);
 }
 
-WIMStruct *new_wim_struct()
+static WIMStruct *new_wim_struct()
 {
        WIMStruct *w = CALLOC(1, sizeof(WIMStruct));
 #ifdef WITH_FUSE
@@ -149,7 +154,7 @@ static int append_metadata_resource_entry(struct lookup_table_entry *lte,
 }
 
 /* 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)
index 71a7a59..7f2ee17 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 /*
- * Copyright (C) 2010 Carl Thijssen
  * Copyright (C) 2012 Eric Biggers
  *
  * This file is part of wimlib, a library for working with WIM files.
@@ -30,7 +29,6 @@
 #include "config.h"
 #include "util.h"
 #include "list.h"
-
 #include "wimlib.h"
 
 #ifdef WITH_FUSE
@@ -45,7 +43,6 @@ struct inode;
 #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)
 
@@ -57,10 +54,6 @@ struct inode;
  * 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. */
@@ -98,7 +91,6 @@ struct resource_entry {
  * 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
@@ -123,7 +115,7 @@ struct wim_header {
        //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;
@@ -256,10 +248,6 @@ struct image_metadata {
        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 {
 
@@ -309,14 +297,11 @@ 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)
@@ -335,23 +320,13 @@ wim_const_security_data(const 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;
@@ -368,14 +343,19 @@ struct capture_config {
        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.
@@ -415,6 +395,11 @@ extern int write_header(const struct wim_header *hdr, FILE *out);
 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,
@@ -431,11 +416,6 @@ extern int new_joined_lookup_table(WIMStruct *w,
                                   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 {
@@ -466,6 +446,11 @@ extern int build_dentry_tree_ntfs(struct dentry **root_p,
                                  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);
 
@@ -499,44 +484,43 @@ extern int write_metadata_resource(WIMStruct *w);
 
 
 /* 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);
 
index 3afa498..292708c 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 /*
- * Copyright (C) 2010 Carl Thijssen
  * Copyright (C) 2012 Eric Biggers
  *
  * This file is part of wimlib, a library for working with WIM files.
@@ -35,7 +34,7 @@
 
 #include "list.h"
 #include "wimlib_internal.h"
-#include "io.h"
+#include "buffer_io.h"
 #include "dentry.h"
 #include "lookup_table.h"
 #include "xml.h"
index d438c81..c8bc57d 100644 (file)
 #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 */