summaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_backup_custom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/pg_backup_custom.c')
-rw-r--r--src/bin/pg_dump/pg_backup_custom.c1034
1 files changed, 0 insertions, 1034 deletions
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
deleted file mode 100644
index 69ab37534da..00000000000
--- a/src/bin/pg_dump/pg_backup_custom.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pg_backup_custom.c
- *
- * Implements the custom output format.
- *
- * The comments with the routined in this code are a good place to
- * understand how to write a new format.
- *
- * See the headers to pg_restore for more details.
- *
- * Copyright (c) 2000, Philip Warner
- * Rights are granted to use this software in any way so long
- * as this notice is not removed.
- *
- * The author is not responsible for loss or damages that may
- * and any liability will be limited to the time taken to fix any
- * related bug.
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.19 2002/05/29 01:38:56 tgl Exp $
- *
- * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
- *
- * Initial version.
- *
- * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
- *
- * - Check results of IO routines more carefully.
- *
- *-------------------------------------------------------------------------
- */
-
-#include "pg_backup.h"
-#include "pg_backup_archiver.h"
-
-#include <errno.h>
-
-/*--------
- * Routines in the format interface
- *--------
- */
-
-static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
-static void _StartData(ArchiveHandle *AH, TocEntry *te);
-static int _WriteData(ArchiveHandle *AH, const void *data, int dLen);
-static void _EndData(ArchiveHandle *AH, TocEntry *te);
-static int _WriteByte(ArchiveHandle *AH, const int i);
-static int _ReadByte(ArchiveHandle *);
-static int _WriteBuf(ArchiveHandle *AH, const void *buf, int len);
-static int _ReadBuf(ArchiveHandle *AH, void *buf, int len);
-static void _CloseArchive(ArchiveHandle *AH);
-static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
-static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
-static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
-static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
-
-static void _PrintData(ArchiveHandle *AH);
-static void _skipData(ArchiveHandle *AH);
-static void _skipBlobs(ArchiveHandle *AH);
-
-static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
-static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
-static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
-static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
-static void _LoadBlobs(ArchiveHandle *AH);
-
-/*------------
- * Buffers used in zlib compression and extra data stored in archive and
- * in TOC entries.
- *------------
- */
-#define zlibOutSize 4096
-#define zlibInSize 4096
-
-typedef struct
-{
- z_streamp zp;
- char *zlibOut;
- char *zlibIn;
- int inSize;
- int hasSeek;
- int filePos;
- int dataStart;
-} lclContext;
-
-typedef struct
-{
- int dataPos;
- int dataLen;
-} lclTocEntry;
-
-
-/*------
- * Static declarations
- *------
- */
-static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id);
-static void _StartDataCompressor(ArchiveHandle *AH, TocEntry *te);
-static void _EndDataCompressor(ArchiveHandle *AH, TocEntry *te);
-static int _getFilePos(ArchiveHandle *AH, lclContext *ctx);
-static int _DoDeflate(ArchiveHandle *AH, lclContext *ctx, int flush);
-
-static char *modulename = gettext_noop("custom archiver");
-
-
-
-/*
- * Init routine required by ALL formats. This is a global routine
- * and should be declared in pg_backup_archiver.h
- *
- * It's task is to create any extra archive context (using AH->formatData),
- * and to initialize the supported function pointers.
- *
- * It should also prepare whatever it's input source is for reading/writing,
- * and in the case of a read mode connection, it should load the Header & TOC.
- */
-void
-InitArchiveFmt_Custom(ArchiveHandle *AH)
-{
- lclContext *ctx;
-
- /* Assuming static functions, this can be copied for each format. */
- AH->ArchiveEntryPtr = _ArchiveEntry;
- AH->StartDataPtr = _StartData;
- AH->WriteDataPtr = _WriteData;
- AH->EndDataPtr = _EndData;
- AH->WriteBytePtr = _WriteByte;
- AH->ReadBytePtr = _ReadByte;
- AH->WriteBufPtr = _WriteBuf;
- AH->ReadBufPtr = _ReadBuf;
- AH->ClosePtr = _CloseArchive;
- AH->PrintTocDataPtr = _PrintTocData;
- AH->ReadExtraTocPtr = _ReadExtraToc;
- AH->WriteExtraTocPtr = _WriteExtraToc;
- AH->PrintExtraTocPtr = _PrintExtraToc;
-
- AH->StartBlobsPtr = _StartBlobs;
- AH->StartBlobPtr = _StartBlob;
- AH->EndBlobPtr = _EndBlob;
- AH->EndBlobsPtr = _EndBlobs;
-
- /*
- * Set up some special context used in compressing data.
- */
- ctx = (lclContext *) malloc(sizeof(lclContext));
- if (ctx == NULL)
- die_horribly(AH, modulename, "out of memory\n");
- AH->formatData = (void *) ctx;
-
- ctx->zp = (z_streamp) malloc(sizeof(z_stream));
- if (ctx->zp == NULL)
- die_horribly(AH, modulename, "out of memory\n");
-
- /* Initialize LO buffering */
- AH->lo_buf_size = LOBBUFSIZE;
- AH->lo_buf = (void *)malloc(LOBBUFSIZE);
- if(AH->lo_buf == NULL)
- die_horribly(AH, modulename, "out of memory\n");
-
- /*
- * zlibOutSize is the buffer size we tell zlib it can output to. We
- * actually allocate one extra byte because some routines want to
- * append a trailing zero byte to the zlib output. The input buffer
- * is expansible and is always of size ctx->inSize; zlibInSize is just
- * the initial default size for it.
- */
- ctx->zlibOut = (char *) malloc(zlibOutSize + 1);
- ctx->zlibIn = (char *) malloc(zlibInSize);
- ctx->inSize = zlibInSize;
- ctx->filePos = 0;
-
- if (ctx->zlibOut == NULL || ctx->zlibIn == NULL)
- die_horribly(AH, modulename, "out of memory\n");
-
- /*
- * Now open the file
- */
- if (AH->mode == archModeWrite)
- {
-
- if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
- AH->FH = fopen(AH->fSpec, PG_BINARY_W);
- else
- AH->FH = stdout;
-
- if (!AH->FH)
- die_horribly(AH, modulename, "could not open archive file %s: %s\n", AH->fSpec, strerror(errno));
-
- ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
-
- }
- else
- {
-
- if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
- AH->FH = fopen(AH->fSpec, PG_BINARY_R);
- else
- AH->FH = stdin;
- if (!AH->FH)
- die_horribly(AH, modulename, "could not open archive file %s: %s\n", AH->fSpec, strerror(errno));
-
- ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
-
- ReadHead(AH);
- ReadToc(AH);
- ctx->dataStart = _getFilePos(AH, ctx);
- }
-
-}
-
-/*
- * Called by the Archiver when the dumper creates a new TOC entry.
- *
- * Optional.
- *
- * Set up extrac format-related TOC data.
-*/
-static void
-_ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
-{
- lclTocEntry *ctx;
-
- ctx = (lclTocEntry *) calloc(1, sizeof(lclTocEntry));
- if (te->dataDumper)
- ctx->dataPos = -1;
- else
- ctx->dataPos = 0;
- ctx->dataLen = 0;
- te->formatData = (void *) ctx;
-
-}
-
-/*
- * Called by the Archiver to save any extra format-related TOC entry
- * data.
- *
- * Optional.
- *
- * Use the Archiver routines to write data - they are non-endian, and
- * maintain other important file information.
- */
-static void
-_WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
-{
- lclTocEntry *ctx = (lclTocEntry *) te->formatData;
-
- WriteInt(AH, ctx->dataPos);
- WriteInt(AH, ctx->dataLen);
-}
-
-/*
- * Called by the Archiver to read any extra format-related TOC data.
- *
- * Optional.
- *
- * Needs to match the order defined in _WriteExtraToc, and sould also
- * use the Archiver input routines.
- */
-static void
-_ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
-{
- lclTocEntry *ctx = (lclTocEntry *) te->formatData;
-
- if (ctx == NULL)
- {
- ctx = (lclTocEntry *) malloc(sizeof(lclTocEntry));
- te->formatData = (void *) ctx;
- }
-
- ctx->dataPos = ReadInt(AH);
- ctx->dataLen = ReadInt(AH);
-}
-
-/*
- * Called by the Archiver when restoring an archive to output a comment
- * that includes useful information about the TOC entry.
- *
- * Optional.
- *
- */
-static void
-_PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
-{
- lclTocEntry *ctx = (lclTocEntry *) te->formatData;
-
- ahprintf(AH, "-- Data Pos: %d (Length %d)\n", ctx->dataPos, ctx->dataLen);
-}
-
-/*
- * Called by the archiver when saving TABLE DATA (not schema). This routine
- * should save whatever format-specific information is needed to read
- * the archive back.
- *
- * It is called just prior to the dumper's 'DataDumper' routine being called.
- *
- * Optional, but strongly recommended.
- *
- */
-static void
-_StartData(ArchiveHandle *AH, TocEntry *te)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
-
- tctx->dataPos = _getFilePos(AH, ctx);
-
- _WriteByte(AH, BLK_DATA); /* Block type */
- WriteInt(AH, te->id); /* For sanity check */
-
- _StartDataCompressor(AH, te);
-
-}
-
-/*
- * Called by archiver when dumper calls WriteData. This routine is
- * called for both BLOB and TABLE data; it is the responsibility of
- * the format to manage each kind of data using StartBlob/StartData.
- *
- * It should only be called from withing a DataDumper routine.
- *
- * Mandatory.
- *
- */
-static int
-_WriteData(ArchiveHandle *AH, const void *data, int dLen)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- z_streamp zp = ctx->zp;
-
- zp->next_in = (void *) data;
- zp->avail_in = dLen;
-
- while (zp->avail_in != 0)
- {
- /* printf("Deflating %d bytes\n", dLen); */
- _DoDeflate(AH, ctx, 0);
- }
- return dLen;
-}
-
-/*
- * Called by the archiver when a dumper's 'DataDumper' routine has
- * finished.
- *
- * Optional.
- *
- */
-static void
-_EndData(ArchiveHandle *AH, TocEntry *te)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
-
- _EndDataCompressor(AH, te);
-
- tctx->dataLen = _getFilePos(AH, ctx) - tctx->dataPos;
-}
-
-/*
- * Called by the archiver when starting to save all BLOB DATA (not schema).
- * This routine should save whatever format-specific information is needed
- * to read the BLOBs back into memory.
- *
- * It is called just prior to the dumper's DataDumper routine.
- *
- * Optional, but strongly recommended.
- *
- */
-static void
-_StartBlobs(ArchiveHandle *AH, TocEntry *te)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
-
- tctx->dataPos = _getFilePos(AH, ctx);
-
- _WriteByte(AH, BLK_BLOBS); /* Block type */
- WriteInt(AH, te->id); /* For sanity check */
-
-}
-
-/*
- * Called by the archiver when the dumper calls StartBlob.
- *
- * Mandatory.
- *
- * Must save the passed OID for retrieval at restore-time.
- */
-static void
-_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
-{
- if (oid == 0)
- die_horribly(AH, modulename, "invalid OID for large object\n");
-
- WriteInt(AH, oid);
- _StartDataCompressor(AH, te);
-}
-
-/*
- * Called by the archiver when the dumper calls EndBlob.
- *
- * Optional.
- *
- */
-static void
-_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
-{
- _EndDataCompressor(AH, te);
-}
-
-/*
- * Called by the archiver when finishing saving all BLOB DATA.
- *
- * Optional.
- *
- */
-static void
-_EndBlobs(ArchiveHandle *AH, TocEntry *te)
-{
- /* Write out a fake zero OID to mark end-of-blobs. */
- WriteInt(AH, 0);
-}
-
-/*
- * Print data for a gievn TOC entry
-*/
-static void
-_PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int id;
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
- int blkType;
- int found = 0;
-
- if (tctx->dataPos == 0)
- return;
-
- if (!ctx->hasSeek || tctx->dataPos < 0)
- {
-
- /* Skip over unnecessary blocks until we get the one we want. */
-
- found = 0;
-
- _readBlockHeader(AH, &blkType, &id);
-
- while (id != te->id)
- {
-
- if ((TocIDRequired(AH, id, ropt) & 2) != 0)
- die_horribly(AH, modulename,
- "Dumping a specific TOC data block out of order is not supported"
- " without id on this input stream (fseek required)\n");
-
- switch (blkType)
- {
-
- case BLK_DATA:
-
- _skipData(AH);
- break;
-
- case BLK_BLOBS:
-
- _skipBlobs(AH);
- break;
-
- default: /* Always have a default */
-
- die_horribly(AH, modulename,
- "unrecognized data block type (%d) while searching archive\n",
- blkType);
- break;
- }
-
- _readBlockHeader(AH, &blkType, &id);
-
- }
-
- }
- else
- {
-
- /* Grab it */
-
- if (fseek(AH->FH, tctx->dataPos, SEEK_SET) != 0)
- die_horribly(AH, modulename, "error during file seek: %s\n", strerror(errno));
-
- _readBlockHeader(AH, &blkType, &id);
-
- }
-
- /* Are we sane? */
- if (id != te->id)
- die_horribly(AH, modulename, "found unexpected block ID (%d) when reading data - expected %d\n",
- id, te->id);
-
- switch (blkType)
- {
-
- case BLK_DATA:
-
- _PrintData(AH);
- break;
-
- case BLK_BLOBS:
-
- if (!AH->connection)
- die_horribly(AH, modulename, "large objects cannot be loaded without a database connection\n");
-
- _LoadBlobs(AH);
- break;
-
- default: /* Always have a default */
-
- die_horribly(AH, modulename, "unrecognized data block type %d while restoring archive\n",
- blkType);
- break;
- }
-
- ahprintf(AH, "\n\n");
-}
-
-/*
- * Print data from current file position.
-*/
-static void
-_PrintData(ArchiveHandle *AH)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- z_streamp zp = ctx->zp;
- int blkLen;
- char *in = ctx->zlibIn;
- int cnt;
-
-#ifdef HAVE_LIBZ
- int res;
- char *out = ctx->zlibOut;
-#endif
-
-#ifdef HAVE_LIBZ
-
- res = Z_OK;
-
- if (AH->compression != 0)
- {
- zp->zalloc = Z_NULL;
- zp->zfree = Z_NULL;
- zp->opaque = Z_NULL;
-
- if (inflateInit(zp) != Z_OK)
- die_horribly(AH, modulename, "could not initialize compression library: %s\n", zp->msg);
- }
-#endif
-
- blkLen = ReadInt(AH);
- while (blkLen != 0)
- {
- if (blkLen + 1 > ctx->inSize)
- {
- free(ctx->zlibIn);
- ctx->zlibIn = NULL;
- ctx->zlibIn = (char *) malloc(blkLen + 1);
- if (!ctx->zlibIn)
- die_horribly(AH, modulename, "out of memory\n");
-
- ctx->inSize = blkLen + 1;
- in = ctx->zlibIn;
- }
-
- cnt = fread(in, 1, blkLen, AH->FH);
- if (cnt != blkLen)
- die_horribly(AH, modulename, "could not read data block - expected %d, got %d\n", blkLen, cnt);
-
- ctx->filePos += blkLen;
-
- zp->next_in = in;
- zp->avail_in = blkLen;
-
-#ifdef HAVE_LIBZ
-
- if (AH->compression != 0)
- {
-
- while (zp->avail_in != 0)
- {
- zp->next_out = out;
- zp->avail_out = zlibOutSize;
- res = inflate(zp, 0);
- if (res != Z_OK && res != Z_STREAM_END)
- die_horribly(AH, modulename, "unable to uncompress data: %s\n", zp->msg);
-
- out[zlibOutSize - zp->avail_out] = '\0';
- ahwrite(out, 1, zlibOutSize - zp->avail_out, AH);
- }
- }
- else
- {
-#endif
- in[zp->avail_in] = '\0';
- ahwrite(in, 1, zp->avail_in, AH);
- zp->avail_in = 0;
-
-#ifdef HAVE_LIBZ
- }
-#endif
-
- blkLen = ReadInt(AH);
-
- }
-
-#ifdef HAVE_LIBZ
- if (AH->compression != 0)
- {
- zp->next_in = NULL;
- zp->avail_in = 0;
- while (res != Z_STREAM_END)
- {
- zp->next_out = out;
- zp->avail_out = zlibOutSize;
- res = inflate(zp, 0);
- if (res != Z_OK && res != Z_STREAM_END)
- die_horribly(AH, modulename, "unable to uncompress data: %s\n", zp->msg);
-
- out[zlibOutSize - zp->avail_out] = '\0';
- ahwrite(out, 1, zlibOutSize - zp->avail_out, AH);
- }
- if (inflateEnd(zp) != Z_OK)
- die_horribly(AH, modulename, "could not close compression library: %s\n", zp->msg);
- }
-#endif
-
-}
-
-static void
-_LoadBlobs(ArchiveHandle *AH)
-{
- Oid oid;
-
- StartRestoreBlobs(AH);
-
- oid = ReadInt(AH);
- while (oid != 0)
- {
- StartRestoreBlob(AH, oid);
- _PrintData(AH);
- EndRestoreBlob(AH, oid);
- oid = ReadInt(AH);
- }
-
- EndRestoreBlobs(AH);
-
-}
-
-/*
- * Skip the BLOBs from the current file position.
- * BLOBS are written sequentially as data blocks (see below).
- * Each BLOB is preceded by it's original OID.
- * A zero OID indicated the end of the BLOBS
- */
-static void
-_skipBlobs(ArchiveHandle *AH)
-{
- Oid oid;
-
- oid = ReadInt(AH);
- while (oid != 0)
- {
- _skipData(AH);
- oid = ReadInt(AH);
- }
-}
-
-/*
- * Skip data from current file position.
- * Data blocks are formatted as an integer length, followed by data.
- * A zero length denoted the end of the block.
-*/
-static void
-_skipData(ArchiveHandle *AH)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int blkLen;
- char *in = ctx->zlibIn;
- int cnt;
-
- blkLen = ReadInt(AH);
- while (blkLen != 0)
- {
- if (blkLen > ctx->inSize)
- {
- free(ctx->zlibIn);
- ctx->zlibIn = (char *) malloc(blkLen);
- ctx->inSize = blkLen;
- in = ctx->zlibIn;
- }
- cnt = fread(in, 1, blkLen, AH->FH);
- if (cnt != blkLen)
- die_horribly(AH, modulename, "could not read data block - expected %d, got %d\n", blkLen, cnt);
-
- ctx->filePos += blkLen;
-
- blkLen = ReadInt(AH);
- }
-
-}
-
-/*
- * Write a byte of data to the archive.
- *
- * Mandatory.
- *
- * Called by the archiver to do integer & byte output to the archive.
- * These routines are only used to read & write headers & TOC.
- *
- */
-static int
-_WriteByte(ArchiveHandle *AH, const int i)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int res;
-
- res = fputc(i, AH->FH);
- if (res != EOF)
- ctx->filePos += 1;
- else
- die_horribly(AH, modulename, "could not write byte: %s\n", strerror(errno));
- return res;
-}
-
-/*
- * Read a byte of data from the archive.
- *
- * Mandatory
- *
- * Called by the archiver to read bytes & integers from the archive.
- * These routines are only used to read & write headers & TOC.
- *
- */
-static int
-_ReadByte(ArchiveHandle *AH)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int res;
-
- res = fgetc(AH->FH);
- if (res != EOF)
- ctx->filePos += 1;
- return res;
-}
-
-/*
- * Write a buffer of data to the archive.
- *
- * Mandatory.
- *
- * Called by the archiver to write a block of bytes to the archive.
- * These routines are only used to read & write headers & TOC.
- *
- */
-static int
-_WriteBuf(ArchiveHandle *AH, const void *buf, int len)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int res;
-
- res = fwrite(buf, 1, len, AH->FH);
-
- if (res != len)
- die_horribly(AH, modulename, "write error in _WriteBuf (%d != %d)\n", res, len);
-
- ctx->filePos += res;
- return res;
-}
-
-/*
- * Read a block of bytes from the archive.
- *
- * Mandatory.
- *
- * Called by the archiver to read a block of bytes from the archive
- * These routines are only used to read & write headers & TOC.
- *
- */
-static int
-_ReadBuf(ArchiveHandle *AH, void *buf, int len)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int res;
-
- res = fread(buf, 1, len, AH->FH);
- ctx->filePos += res;
-
- return res;
-}
-
-/*
- * Close the archive.
- *
- * Mandatory.
- *
- * When writing the archive, this is the routine that actually starts
- * the process of saving it to files. No data should be written prior
- * to this point, since the user could sort the TOC after creating it.
- *
- * If an archive is to be written, this toutine must call:
- * WriteHead to save the archive header
- * WriteToc to save the TOC entries
- * WriteDataChunks to save all DATA & BLOBs.
- *
- */
-static void
-_CloseArchive(ArchiveHandle *AH)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int tpos;
-
- if (AH->mode == archModeWrite)
- {
- WriteHead(AH);
- tpos = ftell(AH->FH);
- WriteToc(AH);
- ctx->dataStart = _getFilePos(AH, ctx);
- WriteDataChunks(AH);
-
- /*
- * This is not an essential operation - it is really only needed
- * if we expect to be doing seeks to read the data back - it may
- * be ok to just use the existing self-consistent block
- * formatting.
- */
- if (ctx->hasSeek)
- {
- fseek(AH->FH, tpos, SEEK_SET);
- WriteToc(AH);
- }
- }
-
- if (fclose(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close archive file: %s\n", strerror(errno));
-
- AH->FH = NULL;
-}
-
-/*--------------------------------------------------
- * END OF FORMAT CALLBACKS
- *--------------------------------------------------
- */
-
-/*
- * Get the current position in the archive file.
- */
-static int
-_getFilePos(ArchiveHandle *AH, lclContext *ctx)
-{
- int pos;
-
- if (ctx->hasSeek)
- {
- pos = ftell(AH->FH);
- if (pos != ctx->filePos)
- {
- write_msg(modulename, "WARNING: ftell mismatch with expected position -- ftell ignored\n");
- pos = ctx->filePos;
- }
- }
- else
- pos = ctx->filePos;
- return pos;
-}
-
-/*
- * Read a data block header. The format changed in V1.3, so we
- * put the code here for simplicity.
- */
-static void
-_readBlockHeader(ArchiveHandle *AH, int *type, int *id)
-{
- if (AH->version < K_VERS_1_3)
- *type = BLK_DATA;
- else
- *type = _ReadByte(AH);;
-
- *id = ReadInt(AH);
-}
-
-/*
- * If zlib is available, then startit up. This is called from
- * StartData & StartBlob. The buffers are setup in the Init routine.
- *
- */
-static void
-_StartDataCompressor(ArchiveHandle *AH, TocEntry *te)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- z_streamp zp = ctx->zp;
-
-#ifdef HAVE_LIBZ
-
- if (AH->compression < 0 || AH->compression > 9)
- AH->compression = Z_DEFAULT_COMPRESSION;
-
- if (AH->compression != 0)
- {
- zp->zalloc = Z_NULL;
- zp->zfree = Z_NULL;
- zp->opaque = Z_NULL;
-
- if (deflateInit(zp, AH->compression) != Z_OK)
- die_horribly(AH, modulename, "could not initialize compression library: %s\n", zp->msg);
- }
-
-#else
-
- AH->compression = 0;
-#endif
-
- /* Just be paranoid - maybe End is called after Start, with no Write */
- zp->next_out = ctx->zlibOut;
- zp->avail_out = zlibOutSize;
-}
-
-/*
- * Send compressed data to the output stream (via ahwrite).
- * Each data chunk is preceded by it's length.
- * In the case of Z0, or no zlib, just write the raw data.
- *
- */
-static int
-_DoDeflate(ArchiveHandle *AH, lclContext *ctx, int flush)
-{
- z_streamp zp = ctx->zp;
-
-#ifdef HAVE_LIBZ
- char *out = ctx->zlibOut;
- int res = Z_OK;
-
- if (AH->compression != 0)
- {
- res = deflate(zp, flush);
- if (res == Z_STREAM_ERROR)
- die_horribly(AH, modulename, "could not compress data: %s\n", zp->msg);
-
- if (((flush == Z_FINISH) && (zp->avail_out < zlibOutSize))
- || (zp->avail_out == 0)
- || (zp->avail_in != 0)
- )
- {
- /*
- * Extra paranoia: avoid zero-length chunks since a zero
- * length chunk is the EOF marker. This should never happen
- * but...
- */
- if (zp->avail_out < zlibOutSize)
- {
- /*
- * printf("Wrote %d byte deflated chunk\n", zlibOutSize -
- * zp->avail_out);
- */
- WriteInt(AH, zlibOutSize - zp->avail_out);
- if (fwrite(out, 1, zlibOutSize - zp->avail_out, AH->FH) != (zlibOutSize - zp->avail_out))
- die_horribly(AH, modulename, "could not write compressed chunk\n");
- ctx->filePos += zlibOutSize - zp->avail_out;
- }
- zp->next_out = out;
- zp->avail_out = zlibOutSize;
- }
- }
- else
-#endif
- {
- if (zp->avail_in > 0)
- {
- WriteInt(AH, zp->avail_in);
- if (fwrite(zp->next_in, 1, zp->avail_in, AH->FH) != zp->avail_in)
- die_horribly(AH, modulename, "could not write uncompressed chunk\n");
- ctx->filePos += zp->avail_in;
- zp->avail_in = 0;
- }
- else
- {
-#ifdef HAVE_LIBZ
- if (flush == Z_FINISH)
- res = Z_STREAM_END;
-#endif
- }
-
-
- }
-
-#ifdef HAVE_LIBZ
- return res;
-#else
- return 1;
-#endif
-
-}
-
-/*
- * Terminate zlib context and flush it's buffers. If no zlib
- * then just return.
- *
- */
-static void
-_EndDataCompressor(ArchiveHandle *AH, TocEntry *te)
-{
-
-#ifdef HAVE_LIBZ
- lclContext *ctx = (lclContext *) AH->formatData;
- z_streamp zp = ctx->zp;
- int res;
-
- if (AH->compression != 0)
- {
- zp->next_in = NULL;
- zp->avail_in = 0;
-
- do
- {
- /* printf("Ending data output\n"); */
- res = _DoDeflate(AH, ctx, Z_FINISH);
- } while (res != Z_STREAM_END);
-
- if (deflateEnd(zp) != Z_OK)
- die_horribly(AH, modulename, "could not close compression stream: %s\n", zp->msg);
- }
-#endif
-
- /* Send the end marker */
- WriteInt(AH, 0);
-}