]> wimlib.net Git - wimlib/blobdiff - src/verify.c
Add wimlib_verify_wim()
[wimlib] / src / verify.c
index 2c0105bb97b248fd4a24a3dd5f946fa2dea17573..a83b1d3b0bcbaf03c414c729d9a0462389c951b2 100644 (file)
@@ -1,11 +1,11 @@
 /*
  * verify.c
  *
- * Verify stream reference counts.
+ * Verify WIM files.
  */
 
 /*
- * Copyright (C) 2012, 2013 Eric Biggers
+ * Copyright (C) 2012, 2013, 2014 Eric Biggers
  *
  * This file is part of wimlib, a library for working with WIM files.
  *
@@ -31,6 +31,7 @@
 #include "wimlib/error.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
+#include "wimlib/progress.h"
 #include "wimlib/security.h"
 
 static int
@@ -97,3 +98,131 @@ wim_recalculate_refcnts(WIMStruct *wim)
        wim->refcnts_ok = 1;
        return 0;
 }
+
+static int
+append_lte_to_list(struct wim_lookup_table_entry *lte, void *_list)
+{
+       list_add(&lte->extraction_list, (struct list_head *)_list);
+       return 0;
+}
+
+struct verify_stream_list_ctx {
+       wimlib_progress_func_t progfunc;
+       void *progctx;
+       union wimlib_progress_info *progress;
+};
+
+static int
+end_verify_stream(struct wim_lookup_table_entry *lte, int status, void *_ctx)
+{
+       struct verify_stream_list_ctx *ctx = _ctx;
+
+       if (status)
+               return status;
+
+       ctx->progress->verify_streams.completed_streams++;
+       ctx->progress->verify_streams.completed_bytes += lte->size;
+
+       return call_progress(ctx->progfunc, WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
+                            ctx->progress, ctx->progctx);
+}
+
+static int
+verify_image_streams_present(struct wim_image_metadata *imd,
+                            struct wim_lookup_table *lookup_table)
+{
+       struct wim_inode *inode;
+       int ret;
+
+       image_for_each_inode(inode, imd) {
+               ret = inode_resolve_streams(inode, lookup_table, false);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/* API function documented in wimlib.h  */
+WIMLIBAPI int
+wimlib_verify_wim(WIMStruct *wim, int verify_flags)
+{
+       int ret;
+       LIST_HEAD(stream_list);
+       union wimlib_progress_info progress;
+       struct verify_stream_list_ctx ctx;
+       struct wim_lookup_table_entry *lte;
+       struct read_stream_list_callbacks cbs = {
+               .end_stream = end_verify_stream,
+               .end_stream_ctx = &ctx,
+       };
+
+       /* Check parameters  */
+
+       if (!wim)
+               return WIMLIB_ERR_INVALID_PARAM;
+
+       if (verify_flags)
+               return WIMLIB_ERR_INVALID_PARAM;
+
+       /* Verify the images  */
+
+       if (wim_has_metadata(wim)) {
+
+               memset(&progress, 0, sizeof(progress));
+               progress.verify_image.wimfile = wim->filename;
+               progress.verify_image.total_images = wim->hdr.image_count;
+
+               for (int i = 1; i <= wim->hdr.image_count; i++) {
+
+                       progress.verify_image.current_image = i;
+
+                       ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_BEGIN_VERIFY_IMAGE,
+                                           &progress, wim->progctx);
+                       if (ret)
+                               return ret;
+
+                       ret = select_wim_image(wim, i);
+                       if (ret)
+                               return ret;
+
+                       ret = verify_image_streams_present(wim_get_current_image_metadata(wim),
+                                                          wim->lookup_table);
+                       if (ret)
+                               return ret;
+
+                       ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_END_VERIFY_IMAGE,
+                                           &progress, wim->progctx);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               WARNING("\"%"TS"\" does not contain image metadata.  Skipping image verification.",
+                       wim->filename);
+       }
+
+       /* Verify the streams  */
+
+       for_lookup_table_entry(wim->lookup_table, append_lte_to_list, &stream_list);
+
+       memset(&progress, 0, sizeof(progress));
+
+       progress.verify_streams.wimfile = wim->filename;
+       list_for_each_entry(lte, &stream_list, extraction_list) {
+               progress.verify_streams.total_streams++;
+               progress.verify_streams.total_bytes += lte->size;
+       }
+
+       ctx.progfunc = wim->progfunc;
+       ctx.progctx = wim->progctx;
+       ctx.progress = &progress;
+
+       ret = call_progress(ctx.progfunc, WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
+                           ctx.progress, ctx.progctx);
+       if (ret)
+               return ret;
+
+       return read_stream_list(&stream_list,
+                               offsetof(struct wim_lookup_table_entry,
+                                        extraction_list),
+                               &cbs, VERIFY_STREAM_HASHES);
+}