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 #ifndef lint
00034 static char copyright[] =
00035 "@(#) Copyright (c) 2002-2004\n\
00036 Netherlands Forensic Institute. All rights reserved.\n";
00037 #endif
00038
00039
00040 #ifdef HAVE_CONFIG_H
00041 #include <config.h>
00042 #endif
00043
00044 #ifdef HAVE_LIBZ
00045 #include <zlib.h>
00046 #else
00047 #error: libz not present
00048 #endif
00049
00050 #include <assert.h>
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <string.h>
00054 #include <unistd.h>
00055
00056 #include "rdd.h"
00057 #include "writer.h"
00058
00059 #define ZBUF_SIZE 32768
00060
00061 #define z_inbuf_empty(z) ((z)->avail_in <= 0)
00062 #define z_outbuf_full(z) ((z)->avail_out <= 0)
00063
00064
00065
00066 static int zlib_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte);
00067 static int zlib_close(RDD_WRITER *w);
00068 static int zlib_compare_address(RDD_WRITER *w, struct addrinfo *address, int *result);
00069
00070 static RDD_WRITE_OPS zlib_write_ops = {
00071 zlib_write,
00072 zlib_close,
00073 zlib_compare_address
00074 };
00075
00076 typedef struct _RDD_ZLIB_WRITER {
00077 RDD_WRITER *parent;
00078 z_stream zstate;
00079 unsigned char *zbuf;
00080 } RDD_ZLIB_WRITER;
00081
00082 int
00083 rdd_open_zlib_writer(RDD_WRITER **self, RDD_WRITER *parent)
00084 {
00085 RDD_WRITER *w = 0;
00086 RDD_ZLIB_WRITER *state = 0;
00087 unsigned char *zbuf = 0;
00088 int rc = RDD_OK;
00089
00090 if (self == 0) {
00091 return RDD_BADARG;
00092 }
00093 if (parent == 0) {
00094 return RDD_BADARG;
00095 }
00096
00097 rc = rdd_new_writer(&w, &zlib_write_ops, sizeof(RDD_ZLIB_WRITER));
00098 if (rc != RDD_OK) {
00099 goto error;
00100 }
00101 state = (RDD_ZLIB_WRITER *) w->state;
00102
00103 if ((zbuf = malloc(ZBUF_SIZE)) == 0) {
00104 rc = RDD_NOMEM;
00105 goto error;
00106 }
00107 state->zbuf = zbuf;
00108 state->parent = parent;
00109
00110 memset(&state->zstate, 0, sizeof(z_stream));
00111 state->zstate.zalloc = Z_NULL;
00112 state->zstate.zfree = Z_NULL;
00113 state->zstate.opaque = 0;
00114 state->zstate.next_out = zbuf;
00115 state->zstate.avail_out = ZBUF_SIZE;
00116
00117 rc = deflateInit(&state->zstate, Z_DEFAULT_COMPRESSION);
00118 switch (rc) {
00119 case Z_OK:
00120 break;
00121 case Z_MEM_ERROR:
00122 rc = RDD_NOMEM;
00123 goto error;
00124 default:
00125 rc = RDD_ECOMPRESS;
00126 goto error;
00127 }
00128
00129 *self = w;
00130 return RDD_OK;
00131
00132 error:
00133 *self = 0;
00134 if (zbuf != 0) free(zbuf);
00135 if (state != 0) free(state);
00136 if (w != 0) free(w);
00137 return rc;
00138 }
00139
00140
00141
00142
00143 static int
00144 flush(RDD_ZLIB_WRITER *state)
00145 {
00146 z_stream *z = &state->zstate;
00147
00148 unsigned filled;
00149 int rc;
00150
00151 filled = ZBUF_SIZE - z->avail_out;
00152
00153 if ((rc = rdd_writer_write(state->parent, state->zbuf, filled)) != 0) {
00154 return rc;
00155 }
00156 z->next_out = state->zbuf;
00157 z->avail_out = ZBUF_SIZE;
00158
00159 return RDD_OK;
00160 }
00161
00162
00163
00164 static int
00165 zlib_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte)
00166 {
00167 RDD_ZLIB_WRITER *state = w->state;
00168 z_stream *z = &state->zstate;
00169 int rc;
00170
00171 z->next_in = (unsigned char *) buf;
00172 z->avail_in = nbyte;
00173
00174 while (z->avail_in > 0) {
00175 if (z_outbuf_full(z)) {
00176 if ((rc = flush(state)) != RDD_OK) {
00177 return rc;
00178 }
00179 }
00180 assert(! z_outbuf_full(z));
00181 rc = deflate(z, Z_NO_FLUSH);
00182 if (rc != Z_OK && rc != Z_STREAM_END) {
00183 return RDD_ECOMPRESS;
00184 }
00185 }
00186
00187 return RDD_OK;
00188 }
00189
00190 static int
00191 zlib_cleanup(RDD_WRITER *self)
00192 {
00193 int rc;
00194 if (self == 0) {
00195 return RDD_BADARG;
00196 }
00197
00198 RDD_ZLIB_WRITER *state = self->state;
00199
00200
00201
00202 if ((rc = rdd_writer_close(state->parent)) != RDD_OK) {
00203 return rc;
00204 }
00205
00206
00207 free(state->zbuf);
00208 state->zbuf = 0;
00209
00210 return RDD_OK;
00211 }
00212 static int
00213 zlib_close(RDD_WRITER *self)
00214 {
00215 RDD_ZLIB_WRITER *state = self->state;
00216 z_stream *z = &state->zstate;
00217 int rc = RDD_OK;
00218
00219 assert(z_inbuf_empty(z));
00220
00221
00222
00223
00224 while (1) {
00225 if (z_outbuf_full(z)) {
00226 if ((rc = flush(state)) != RDD_OK) {
00227 return rc;
00228 }
00229 }
00230 assert(! z_outbuf_full(z));
00231 rc = deflate(z, Z_FINISH);
00232 if (rc == Z_STREAM_END) {
00233 break;
00234 } else if (rc != Z_OK) {
00235 return RDD_ECOMPRESS;
00236 }
00237 }
00238
00239 if ((rc = flush(state)) != RDD_OK) {
00240 return rc;
00241 }
00242
00243 if ((rc = zlib_cleanup(self)) != RDD_OK) {
00244 return rc;
00245 }
00246
00247 return RDD_OK;
00248 }
00249
00250 static int
00251 zlib_compare_address(RDD_WRITER *self, struct addrinfo *address, int *result)
00252 {
00253 RDD_ZLIB_WRITER *state = self->state;
00254 return rdd_compare_address(state->parent, address, result);
00255 }