]> wimlib.net Git - wimlib/blob - src/verify.c
configure.ac: generate version number from git commit and tags
[wimlib] / src / verify.c
1 /*
2  * verify.c
3  *
4  * Verify WIM files.
5  */
6
7 /*
8  * Copyright (C) 2012, 2013, 2014 Eric Biggers
9  *
10  * This file is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU Lesser General Public License as published by the Free
12  * Software Foundation; either version 3 of the License, or (at your option) any
13  * later version.
14  *
15  * This file is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this file; if not, see http://www.gnu.org/licenses/.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "wimlib/blob_table.h"
29 #include "wimlib/dentry.h"
30 #include "wimlib/error.h"
31 #include "wimlib/metadata.h"
32 #include "wimlib/progress.h"
33 #include "wimlib/security.h"
34
35 static int
36 append_blob_to_list(struct blob_descriptor *blob, void *_list)
37 {
38         list_add(&blob->extraction_list, (struct list_head *)_list);
39         return 0;
40 }
41
42 struct verify_blob_list_ctx {
43         wimlib_progress_func_t progfunc;
44         void *progctx;
45         union wimlib_progress_info *progress;
46         u64 next_progress;
47 };
48
49 static int
50 verify_continue_blob(const struct blob_descriptor *blob, u64 offset,
51                      const void *chunk, size_t size, void *_ctx)
52 {
53         struct verify_blob_list_ctx *ctx = _ctx;
54         union wimlib_progress_info *progress = ctx->progress;
55
56         if (offset + size == blob->size)
57                 progress->verify_streams.completed_streams++;
58
59         progress->verify_streams.completed_bytes += size;
60
61         if (progress->verify_streams.completed_bytes >= ctx->next_progress) {
62
63                 int ret = call_progress(ctx->progfunc,
64                                         WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
65                                         progress, ctx->progctx);
66                 if (ret)
67                         return ret;
68
69                 set_next_progress(progress->verify_streams.completed_bytes,
70                                   progress->verify_streams.total_bytes,
71                                   &ctx->next_progress);
72         }
73         return 0;
74 }
75
76 static int
77 verify_file_data_present(struct wim_image_metadata *imd,
78                          struct blob_table *blob_table)
79 {
80         struct wim_inode *inode;
81         int ret;
82
83         image_for_each_inode(inode, imd) {
84                 ret = inode_resolve_streams(inode, blob_table, false);
85                 if (ret)
86                         return ret;
87         }
88         return 0;
89 }
90
91 /* API function documented in wimlib.h  */
92 WIMLIBAPI int
93 wimlib_verify_wim(WIMStruct *wim, int verify_flags)
94 {
95         int ret;
96         LIST_HEAD(blob_list);
97         union wimlib_progress_info progress;
98         struct verify_blob_list_ctx ctx;
99         struct blob_descriptor *blob;
100         struct read_blob_callbacks cbs = {
101                 .continue_blob  = verify_continue_blob,
102                 .ctx            = &ctx,
103         };
104
105         /* Check parameters  */
106
107         if (!wim)
108                 return WIMLIB_ERR_INVALID_PARAM;
109
110         if (verify_flags)
111                 return WIMLIB_ERR_INVALID_PARAM;
112
113         /* Verify the images  */
114
115         if (wim_has_metadata(wim)) {
116
117                 memset(&progress, 0, sizeof(progress));
118                 progress.verify_image.wimfile = wim->filename;
119                 progress.verify_image.total_images = wim->hdr.image_count;
120
121                 for (int i = 1; i <= wim->hdr.image_count; i++) {
122
123                         progress.verify_image.current_image = i;
124
125                         ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_BEGIN_VERIFY_IMAGE,
126                                             &progress, wim->progctx);
127                         if (ret)
128                                 return ret;
129
130                         ret = select_wim_image(wim, i);
131                         if (ret)
132                                 return ret;
133
134                         ret = verify_file_data_present(wim_get_current_image_metadata(wim),
135                                                        wim->blob_table);
136                         if (ret)
137                                 return ret;
138
139                         ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_END_VERIFY_IMAGE,
140                                             &progress, wim->progctx);
141                         if (ret)
142                                 return ret;
143                 }
144         } else {
145                 WARNING("\"%"TS"\" does not contain image metadata.  Skipping image verification.",
146                         wim->filename);
147         }
148
149         /* Verify the blobs: SHA-1 message digests must match  */
150
151         for_blob_in_table(wim->blob_table, append_blob_to_list, &blob_list);
152
153         memset(&progress, 0, sizeof(progress));
154
155         progress.verify_streams.wimfile = wim->filename;
156         list_for_each_entry(blob, &blob_list, extraction_list) {
157                 progress.verify_streams.total_streams++;
158                 progress.verify_streams.total_bytes += blob->size;
159         }
160
161         ctx.progfunc = wim->progfunc;
162         ctx.progctx = wim->progctx;
163         ctx.progress = &progress;
164         ctx.next_progress = 0;
165
166         ret = call_progress(ctx.progfunc, WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
167                             ctx.progress, ctx.progctx);
168         if (ret)
169                 return ret;
170
171         return read_blob_list(&blob_list,
172                               offsetof(struct blob_descriptor, extraction_list),
173                               &cbs, VERIFY_BLOB_HASHES);
174 }