00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef lint
00039 static char copyright[] =
00040 "@(#) Copyright (c) 2002\n\
00041 Netherlands Forensic Institute. All rights reserved.\n";
00042 #endif
00043
00044 #ifdef HAVE_CONFIG_H
00045 #include <config.h>
00046 #endif
00047 #include <assert.h>
00048 #include <ctype.h>
00049 #include <errno.h>
00050 #include <limits.h>
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <string.h>
00054 #include <sys/types.h>
00055 #include <sys/stat.h>
00056 #include <unistd.h>
00057 #include <zlib.h>
00058
00059 #include "rdd.h"
00060 #include "rdd_internals.h"
00061 #include "error.h"
00062 #include "writer.h"
00063 #include "filter.h"
00064 #include "filterset.h"
00065
00066
00067
00068
00069 typedef struct _RDD_VERIFY_BLOCKFILTER {
00070 FILE *fp;
00071 rdd_checksum_t checksum;
00072 rdd_checksum_algorithm_t algorithm;
00073 int swap;
00074 rdd_count_t blocknum;
00075 unsigned blocksize;
00076 rdd_count_t num_error;
00077 rdd_fltr_error_fun error_fun;
00078 void *error_env;
00079 } RDD_VERIFY_BLOCKFILTER;
00080
00081
00082
00083 static int verify_input(RDD_FILTER *f,
00084 const unsigned char *buf, unsigned nbyte);
00085 static int verify_block(RDD_FILTER *f, unsigned nbyte);
00086 static int verify_get_result(RDD_FILTER *f, unsigned char *buf, unsigned nbyte);
00087
00088 static RDD_FILTER_OPS verify_ops = {
00089 verify_input,
00090 verify_block,
00091 0,
00092 verify_get_result,
00093 0
00094 };
00095
00096 static void
00097 reset_checksum(RDD_VERIFY_BLOCKFILTER *state)
00098 {
00099 switch (state->algorithm) {
00100 case RDD_ADLER32:
00101 state->checksum = adler32(0, NULL, 0);
00102 break;
00103 case RDD_CRC32:
00104 state->checksum = crc32(0, NULL, 0);
00105 break;
00106 }
00107 }
00108
00109 static int
00110 verify_input(RDD_FILTER *f, const unsigned char *buf, unsigned nbyte)
00111 {
00112 RDD_VERIFY_BLOCKFILTER *state = (RDD_VERIFY_BLOCKFILTER *) f->state;
00113
00114 switch (state->algorithm) {
00115 case RDD_ADLER32:
00116 state->checksum = adler32(state->checksum, buf, nbyte);
00117 break;
00118 case RDD_CRC32:
00119 state->checksum = crc32(state->checksum, buf, nbyte);
00120 break;
00121 }
00122
00123 return RDD_OK;
00124 }
00125
00126 static u_int32_t
00127 swap32(u_int32_t n)
00128 {
00129 return
00130 ((n << 24) & 0xff000000)
00131 | ((n << 8) & 0x00ff0000)
00132 | ((n >> 8) & 0x0000ff00)
00133 | ((n >> 24) & 0x000000ff)
00134 ;
00135 }
00136
00137 static int
00138 read_chksum(RDD_VERIFY_BLOCKFILTER *state, rdd_checksum_t *result)
00139 {
00140 rdd_checksum_t chksum;
00141
00142 if (fread(&chksum, sizeof chksum, 1, state->fp) != 1) {
00143 return RDD_EREAD;
00144 }
00145 if (state->swap) {
00146 chksum = swap32(chksum);
00147 }
00148 *result = chksum;
00149 return RDD_OK;
00150 }
00151
00152 static void
00153 verify_checksum(RDD_VERIFY_BLOCKFILTER *state, u_int32_t stored_checksum)
00154 {
00155 rdd_count_t offset;
00156
00157 if (state->checksum == stored_checksum) {
00158 return;
00159 }
00160
00161 state->num_error++;
00162
00163 if (state->error_fun != 0) {
00164 offset = state->blocknum * state->blocksize;
00165 (*state->error_fun)(offset,
00166 stored_checksum, state->checksum,
00167 state->error_env);
00168 }
00169 }
00170
00171 static int
00172 verify_block(RDD_FILTER *f, unsigned pos)
00173 {
00174 RDD_VERIFY_BLOCKFILTER *state = (RDD_VERIFY_BLOCKFILTER *) f->state;
00175 rdd_checksum_t stored_checksum;
00176 int rc;
00177
00178 if ((rc = read_chksum(state, &stored_checksum)) != RDD_OK) {
00179 return rc;
00180 }
00181
00182 verify_checksum(state, stored_checksum);
00183
00184 reset_checksum(state);
00185
00186 state->blocknum++;
00187
00188 return RDD_OK;
00189 }
00190
00191 static int
00192 verify_get_result(RDD_FILTER *f, unsigned char *buf, unsigned nbyte)
00193 {
00194 RDD_VERIFY_BLOCKFILTER *state = (RDD_VERIFY_BLOCKFILTER *) f->state;
00195
00196 if (nbyte < sizeof(unsigned)) {
00197 return RDD_NOMEM;
00198 }
00199
00200 memcpy(buf, &state->num_error, sizeof(state->num_error));
00201
00202 return RDD_OK;
00203 }
00204
00205 static int
00206 new_verify_checksum_blockfilter(RDD_FILTER **self,
00207 rdd_checksum_algorithm_t alg, FILE *fp, unsigned blocksize, int swap,
00208 rdd_fltr_error_fun error_fun, void *error_env)
00209 {
00210 RDD_FILTER *f = 0;
00211 RDD_VERIFY_BLOCKFILTER *state = 0;
00212 int rc = RDD_OK;
00213
00214 if (blocksize <= 0) return RDD_BADARG;
00215 if (alg != RDD_ADLER32 && alg != RDD_CRC32) return RDD_BADARG;
00216
00217 rc = rdd_new_filter(&f, &verify_ops,
00218 sizeof(RDD_VERIFY_BLOCKFILTER), blocksize);
00219 if (rc != RDD_OK) {
00220 goto error;
00221 }
00222 state = (RDD_VERIFY_BLOCKFILTER *)f->state;
00223
00224 state->fp = fp;
00225 state->algorithm = alg;
00226 state->swap = swap;
00227 state->blocknum = 0;
00228 state->blocksize = blocksize;
00229 state->num_error = 0;
00230 state->error_fun = error_fun;
00231 state->error_env = error_env;
00232 reset_checksum(state);
00233
00234 *self = f;
00235 return RDD_OK;
00236
00237 error:
00238 *self = 0;
00239 if (fp != NULL) fclose(fp);
00240 if (state != 0) free(state);
00241 if (f != 0) free(f);
00242 return rc;
00243 }
00244
00245 int
00246 rdd_new_verify_adler32_blockfilter(RDD_FILTER **f, FILE *fp,
00247 unsigned blocksize, int swap, rdd_fltr_error_fun err, void *env)
00248 {
00249 return new_verify_checksum_blockfilter(f, RDD_ADLER32,
00250 fp, blocksize, swap,
00251 err, env);
00252 }
00253
00254 int
00255 rdd_new_verify_crc32_blockfilter(RDD_FILTER **f, FILE *fp,
00256 unsigned blocksize, int swap, rdd_fltr_error_fun err, void *env)
00257 {
00258 return new_verify_checksum_blockfilter(f, RDD_CRC32,
00259 fp, blocksize, swap,
00260 err, env);
00261 }