+ struct CtdlCompressHeader zheader;
+ char *uncompressed_data;
+ char *compressed_data;
+ uLongf destLen, sourceLen;
+ size_t cplen;
+
+ memset(&zheader, 0, sizeof(struct CtdlCompressHeader));
+ cplen = sizeof(struct CtdlCompressHeader);
+ if (sizeof(struct CtdlCompressHeader) > cdb->len) {
+ cplen = cdb->len;
+ }
+ memcpy(&zheader, cdb->ptr, cplen);
+
+ compressed_data = cdb->ptr;
+ compressed_data += sizeof(struct CtdlCompressHeader);
+
+ sourceLen = (uLongf) zheader.compressed_len;
+ destLen = (uLongf) zheader.uncompressed_len;
+ uncompressed_data = malloc(zheader.uncompressed_len);
+
+ if (uncompress((Bytef *) uncompressed_data,
+ (uLongf *) & destLen, (const Bytef *) compressed_data, (uLong) sourceLen) != Z_OK) {
+ syslog(LOG_EMERG, "db: uncompress() error");
+ cdb_abort();
+ }
+
+ free(cdb->ptr);
+ cdb->len = (size_t) destLen;
+ cdb->ptr = uncompressed_data;
+}
+
+
+/*
+ * Store a piece of data. Returns 0 if the operation was successful. If a
+ * key already exists it should be overwritten.
+ */
+int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen)
+{
+
+ DBT dkey, ddata;
+ DB_TXN *tid;
+ int ret = 0;
+
+ struct CtdlCompressHeader zheader;
+ char *compressed_data = NULL;
+ int compressing = 0;
+ size_t buffer_len = 0;
+ uLongf destLen = 0;
+
+ memset(&dkey, 0, sizeof(DBT));
+ memset(&ddata, 0, sizeof(DBT));
+ dkey.size = ckeylen;
+ dkey.data = (void *) ckey;
+ ddata.size = cdatalen;
+ ddata.data = cdata;
+
+ /* Only compress Visit and UseTable records. Everything else is uncompressed. */
+ if ((cdb == CDB_VISIT) || (cdb == CDB_USETABLE)) {
+ compressing = 1;
+ zheader.magic = COMPRESS_MAGIC;
+ zheader.uncompressed_len = cdatalen;
+ buffer_len = ((cdatalen * 101) / 100) + 100 + sizeof(struct CtdlCompressHeader);
+ destLen = (uLongf) buffer_len;
+ compressed_data = malloc(buffer_len);
+ if (compress2((Bytef *) (compressed_data + sizeof(struct CtdlCompressHeader)),
+ &destLen, (Bytef *) cdata, (uLongf) cdatalen, 1) != Z_OK) {
+ syslog(LOG_EMERG, "db: compress2() error");
+ cdb_abort();
+ }
+ zheader.compressed_len = (size_t) destLen;
+ memcpy(compressed_data, &zheader, sizeof(struct CtdlCompressHeader));
+ ddata.size = (size_t) (sizeof(struct CtdlCompressHeader) + zheader.compressed_len);
+ ddata.data = compressed_data;