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 #include <assert.h>
00045 #include <stdlib.h>
00046 #include <sys/types.h>
00047 #include <errno.h>
00048 #include <string.h>
00049 #include <unistd.h>
00050 #include <zlib.h>
00051
00052 #include "rdd.h"
00053 #include "reader.h"
00054
00055 #define ZBUF_SIZE 32768
00056
00057 #define z_inbuf_empty(z) ((z)->avail_in <= 0)
00058 #define z_outbuf_full(z) ((z)->avail_out <= 0)
00059
00060 typedef struct _RDD_ZLIB_READER {
00061 RDD_READER *parent;
00062 unsigned char *zbuf;
00063 z_stream zstate;
00064 rdd_count_t pos;
00065 } RDD_ZLIB_READER;
00066
00067
00068
00069
00070 static int rdd_zlib_read(RDD_READER *r, unsigned char *buf, unsigned nbyte,
00071 unsigned *nread);
00072 static int rdd_zlib_tell(RDD_READER *r, rdd_count_t *pos);
00073 static int rdd_zlib_seek(RDD_READER *r, rdd_count_t pos);
00074 static int rdd_zlib_close(RDD_READER *r, int recurse);
00075
00076 static RDD_READ_OPS zlib_read_ops = {
00077 rdd_zlib_read,
00078 rdd_zlib_tell,
00079 rdd_zlib_seek,
00080 rdd_zlib_close
00081 };
00082
00083 int
00084 rdd_open_zlib_reader(RDD_READER **self, RDD_READER *parent)
00085 {
00086 RDD_READER *r = 0;
00087 RDD_ZLIB_READER *state = 0;
00088 unsigned char *zbuf = 0;
00089 int rc = RDD_OK;
00090
00091 rc = rdd_new_reader(&r, &zlib_read_ops, sizeof(RDD_ZLIB_READER));
00092 if (rc != RDD_OK) {
00093 goto error;
00094 }
00095 state = (RDD_ZLIB_READER *) r->state;
00096
00097 if ((zbuf = malloc(ZBUF_SIZE)) == 0) {
00098 rc = RDD_NOMEM;
00099 goto error;
00100 }
00101
00102 state->parent = parent;
00103 state->zbuf = zbuf;
00104 state->pos = 0;
00105
00106 memset(&state->zstate, 0, sizeof(z_stream));
00107 state->zstate.zalloc = Z_NULL;
00108 state->zstate.zfree = Z_NULL;
00109 state->zstate.opaque = 0;
00110 state->zstate.next_in = Z_NULL;
00111 state->zstate.avail_in = 0;
00112 state->zstate.next_out = Z_NULL;
00113 state->zstate.avail_out = 0;
00114
00115 rc = inflateInit(&state->zstate);
00116 if (rc == Z_MEM_ERROR) {
00117 rc = RDD_NOMEM;
00118 goto error;
00119 } else if (rc != Z_OK) {
00120 rc = RDD_ECOMPRESS;
00121 goto error;
00122 }
00123
00124 *self = r;
00125 return RDD_OK;
00126
00127 error:
00128 *self = 0;
00129 if (zbuf != 0) free(zbuf);
00130 if (state != 0) free(state);
00131 if (r != 0) free(r);
00132 return rc;
00133 }
00134
00135 static int
00136 rdd_zlib_read(RDD_READER *self, unsigned char *buf, unsigned nbyte,
00137 unsigned *nread)
00138 {
00139 RDD_ZLIB_READER *state = self->state;
00140 z_stream *z = &state->zstate;
00141 int rc;
00142
00143 *nread = 0;
00144
00145 z->next_out = buf;
00146 z->avail_out = nbyte;
00147
00148 while (z->avail_out > 0) {
00149 if (z->avail_in == 0) {
00150
00151
00152
00153
00154 z->next_in = state->zbuf;
00155 rc = rdd_reader_read(state->parent,
00156 state->zbuf, ZBUF_SIZE, &z->avail_in);
00157 if (rc != RDD_OK) {
00158 return rc;
00159 }
00160 }
00161
00162 rc = inflate(z, Z_NO_FLUSH);
00163 if (rc == Z_STREAM_END) {
00164 break;
00165 } else if (rc != Z_OK) {
00166 return RDD_ECOMPRESS;
00167 }
00168 }
00169
00170 *nread = z->next_out - buf;
00171 state->pos += *nread;
00172 return RDD_OK;
00173 }
00174
00175 static int
00176 rdd_zlib_tell(RDD_READER *self, rdd_count_t *pos)
00177 {
00178 RDD_ZLIB_READER *state = self->state;
00179
00180 *pos = state->pos;
00181 return RDD_OK;
00182 }
00183
00184 static int
00185 rdd_zlib_seek(RDD_READER *self, rdd_count_t pos)
00186 {
00187 return RDD_ESEEK;
00188 }
00189
00190 static int
00191 rdd_zlib_close(RDD_READER *self, int recurse)
00192 {
00193 RDD_ZLIB_READER *state = self->state;
00194 int rc;
00195
00196 if ((rc = inflateEnd(&state->zstate)) != Z_OK) {
00197 return RDD_ECOMPRESS;
00198 }
00199
00200 if (recurse) {
00201 if ((rc = rdd_reader_close(state->parent, 1)) != RDD_OK) {
00202 return rc;
00203 }
00204 }
00205
00206 free(state->zbuf);
00207 state->zbuf = 0;
00208
00209 return RDD_OK;
00210 }