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 #include "outfile.h"
00066
00067
00068
00069
00070 typedef struct _RDD_CHECKSUM_BLOCKFILTER {
00071 char *path;
00072 FILE *fp;
00073 rdd_checksum_t checksum;
00074 rdd_checksum_algorithm_t algorithm;
00075 } RDD_CHECKSUM_BLOCKFILTER;
00076
00077
00078
00079 static int checksum_input(RDD_FILTER *f,
00080 const unsigned char *buf, unsigned nbyte);
00081 static int checksum_block(RDD_FILTER *f, unsigned nbyte);
00082 static int checksum_close(RDD_FILTER *f);
00083 static int checksum_free(RDD_FILTER *f);
00084
00085 static RDD_FILTER_OPS checksum_ops = {
00086 checksum_input,
00087 checksum_block,
00088 checksum_close,
00089 0,
00090 checksum_free
00091 };
00092
00093 static void
00094 reset_checksum(RDD_CHECKSUM_BLOCKFILTER *state)
00095 {
00096 switch (state->algorithm) {
00097 case RDD_ADLER32:
00098 state->checksum = adler32(0, NULL, 0);
00099 break;
00100 case RDD_CRC32:
00101 state->checksum = crc32(0, NULL, 0);
00102 break;
00103 }
00104 }
00105
00106 static void
00107 init_header(RDD_CHECKSUM_FILE_HEADER* rec,
00108 int type, size_t blocksize,
00109 off_t offset, off_t imgsize)
00110 {
00111 memset(rec, '\000', sizeof(RDD_CHECKSUM_FILE_HEADER));
00112 rec->magic = RDD_CHECKSUM_MAGIC;
00113 rec->version = RDD_CHECKSUM_VERSION;
00114 rec->flags |= type;
00115 rec->blocksize = blocksize;
00116 rec->offset = offset;
00117 rec->reserved = 0x0000;
00118 rec->imagesize = imgsize;
00119 }
00120
00121 static int
00122 checksum_input(RDD_FILTER *f, const unsigned char *buf, unsigned nbyte)
00123 {
00124 RDD_CHECKSUM_BLOCKFILTER *state = (RDD_CHECKSUM_BLOCKFILTER *) f->state;
00125
00126 switch (state->algorithm) {
00127 case RDD_ADLER32:
00128 state->checksum = adler32(state->checksum, buf, nbyte);
00129 break;
00130 case RDD_CRC32:
00131 state->checksum = crc32(state->checksum, buf, nbyte);
00132 break;
00133 }
00134
00135 return RDD_OK;
00136 }
00137
00138 static int
00139 checksum_block(RDD_FILTER *f, unsigned pos)
00140 {
00141 RDD_CHECKSUM_BLOCKFILTER *state = (RDD_CHECKSUM_BLOCKFILTER *) f->state;
00142 rdd_checksum_t checksum = state->checksum;
00143
00144 if (fwrite(&checksum, sizeof checksum, 1, state->fp) < 1) {
00145 return RDD_EWRITE;
00146 }
00147 reset_checksum(state);
00148
00149 return RDD_OK;
00150 }
00151
00152 static int
00153 checksum_close(RDD_FILTER *f)
00154 {
00155 RDD_CHECKSUM_BLOCKFILTER *state = (RDD_CHECKSUM_BLOCKFILTER *) f->state;
00156
00157 outfile_fclose(state->fp, state->path);
00158 state->fp = NULL;
00159
00160 return RDD_OK;
00161 }
00162
00163 static int
00164 checksum_free(RDD_FILTER *f)
00165 {
00166 RDD_CHECKSUM_BLOCKFILTER *state = (RDD_CHECKSUM_BLOCKFILTER *) f->state;
00167
00168 free(state->path);
00169 state->path = 0;
00170
00171 return RDD_OK;
00172 }
00173
00174 static int
00175 new_checksum_blockfilter(RDD_FILTER **self, rdd_checksum_algorithm_t alg,
00176 unsigned blocksize, const char *outpath, int overwrite)
00177 {
00178 RDD_FILTER *f = 0;
00179 RDD_CHECKSUM_BLOCKFILTER *state = 0;
00180 RDD_CHECKSUM_FILE_HEADER header;
00181 char *path = 0;
00182 FILE *fp = NULL;
00183 int rc = RDD_OK;
00184
00185 if(self == 0 || outpath == 0){
00186 return RDD_BADARG;
00187 }
00188
00189 if (blocksize == 0){
00190 return RDD_BADARG;
00191 }
00192
00193 if (alg != RDD_ADLER32 && alg != RDD_CRC32){
00194 return RDD_BADARG;
00195 }
00196
00197 rc = rdd_new_filter(&f, &checksum_ops, sizeof(RDD_CHECKSUM_BLOCKFILTER),
00198 blocksize);
00199 if (rc != RDD_OK) {
00200 goto error;
00201 }
00202 state = (RDD_CHECKSUM_BLOCKFILTER *)f->state;
00203
00204 if ((path = malloc(strlen(outpath) + 1)) == 0) {
00205 rc = RDD_NOMEM;
00206 goto error;
00207 }
00208 strcpy(path, outpath);
00209
00210 if ((rc = outfile_fopen(&fp, outpath, overwrite)) != RDD_OK) {
00211 goto error;
00212 }
00213
00214 state->path = path;
00215 state->fp = fp;
00216 state->algorithm = alg;
00217 reset_checksum(state);
00218
00219 init_header(&header, alg, blocksize, 0, 0);
00220 if (fwrite((const void *) &header, sizeof(header), 1, state->fp) < 1) {
00221 rc = RDD_EWRITE;
00222 goto error;
00223 }
00224
00225 *self = f;
00226 return RDD_OK;
00227
00228 error:
00229 *self = 0;
00230 if (fp != NULL) fclose(fp);
00231 if (path != 0) free(path);
00232 if (state != 0) free(state);
00233 if (f != 0) free(f);
00234 return rc;
00235 }
00236
00237 int
00238 rdd_new_adler32_blockfilter(RDD_FILTER **f,
00239 unsigned blocksize, const char *outpath, int overwrite)
00240 {
00241 return new_checksum_blockfilter(f, RDD_ADLER32,
00242 blocksize, outpath, overwrite);
00243 }
00244
00245 int
00246 rdd_new_crc32_blockfilter(RDD_FILTER **f,
00247 unsigned blocksize, const char *outpath, int overwrite)
00248 {
00249 return new_checksum_blockfilter(f, RDD_CRC32,
00250 blocksize, outpath, overwrite);
00251 }