2000-07-04 16:25:28 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* pg_backup_files.c
|
|
|
|
*
|
|
|
|
* This file is copied from the 'custom' format file, but dumps data into
|
|
|
|
* separate files, and the TOC into the 'main' file.
|
|
|
|
*
|
|
|
|
* IT IS FOR DEMONSTRATION PURPOSES ONLY.
|
|
|
|
*
|
|
|
|
* (and could probably be used as a basis for writing a tar file)
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* result from it's use.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
*
|
|
|
|
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
|
|
|
|
*
|
|
|
|
* Initial version.
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "pg_backup.h"
|
|
|
|
#include "pg_backup_archiver.h"
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int hasSeek;
|
|
|
|
int filePos;
|
|
|
|
} lclContext;
|
|
|
|
|
|
|
|
typedef struct {
|
2000-07-06 20:39:39 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2000-07-04 16:25:28 +02:00
|
|
|
gzFile *FH;
|
|
|
|
#else
|
|
|
|
FILE *FH;
|
|
|
|
#endif
|
|
|
|
char *filename;
|
|
|
|
} lclTocEntry;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initializer
|
|
|
|
*/
|
|
|
|
void InitArchiveFmt_Files(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;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up some special context used in compressing data.
|
|
|
|
*/
|
|
|
|
ctx = (lclContext*)malloc(sizeof(lclContext));
|
|
|
|
AH->formatData = (void*)ctx;
|
|
|
|
ctx->filePos = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now open the TOC file
|
|
|
|
*/
|
|
|
|
if (AH->mode == archModeWrite) {
|
|
|
|
if (AH->fSpec && strcmp(AH->fSpec,"") != 0) {
|
|
|
|
AH->FH = fopen(AH->fSpec, PG_BINARY_W);
|
|
|
|
} else {
|
|
|
|
AH->FH = stdout;
|
|
|
|
}
|
|
|
|
ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
|
|
|
|
|
|
|
|
if (AH->compression < 0 || AH->compression > 9) {
|
|
|
|
AH->compression = Z_DEFAULT_COMPRESSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (AH->fSpec && strcmp(AH->fSpec,"") != 0) {
|
|
|
|
AH->FH = fopen(AH->fSpec, PG_BINARY_R);
|
|
|
|
} else {
|
|
|
|
AH->FH = stdin;
|
|
|
|
}
|
|
|
|
ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
|
|
|
|
|
|
|
|
ReadHead(AH);
|
|
|
|
ReadToc(AH);
|
|
|
|
fclose(AH->FH); /* Nothing else in the file... */
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* - Start a new TOC entry
|
|
|
|
* Setup the output file name.
|
|
|
|
*/
|
|
|
|
static void _ArchiveEntry(ArchiveHandle* AH, TocEntry* te)
|
|
|
|
{
|
|
|
|
lclTocEntry* ctx;
|
|
|
|
char fn[1024];
|
|
|
|
|
|
|
|
ctx = (lclTocEntry*)malloc(sizeof(lclTocEntry));
|
|
|
|
if (te->dataDumper) {
|
2000-07-06 20:39:39 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2000-07-04 16:25:28 +02:00
|
|
|
if (AH->compression == 0) {
|
|
|
|
sprintf(fn, "%d.dat", te->id);
|
|
|
|
} else {
|
|
|
|
sprintf(fn, "%d.dat.gz", te->id);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
sprintf(fn, "%d.dat", te->id);
|
|
|
|
#endif
|
|
|
|
ctx->filename = strdup(fn);
|
|
|
|
} else {
|
|
|
|
ctx->filename = NULL;
|
|
|
|
ctx->FH = NULL;
|
|
|
|
}
|
|
|
|
te->formatData = (void*)ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _WriteExtraToc(ArchiveHandle* AH, TocEntry* te)
|
|
|
|
{
|
|
|
|
lclTocEntry* ctx = (lclTocEntry*)te->formatData;
|
|
|
|
|
|
|
|
if (ctx->filename) {
|
|
|
|
WriteStr(AH, ctx->filename);
|
|
|
|
} else {
|
|
|
|
WriteStr(AH, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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->filename = ReadStr(AH);
|
|
|
|
if (strlen(ctx->filename) == 0) {
|
|
|
|
free(ctx->filename);
|
|
|
|
ctx->filename = NULL;
|
|
|
|
}
|
|
|
|
ctx->FH = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _PrintExtraToc(ArchiveHandle* AH, TocEntry* te)
|
|
|
|
{
|
|
|
|
lclTocEntry* ctx = (lclTocEntry*)te->formatData;
|
|
|
|
|
|
|
|
ahprintf(AH, "-- File: %s\n", ctx->filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _StartData(ArchiveHandle* AH, TocEntry* te)
|
|
|
|
{
|
|
|
|
lclTocEntry* tctx = (lclTocEntry*)te->formatData;
|
|
|
|
char fmode[10];
|
|
|
|
|
|
|
|
sprintf(fmode, "wb%d", AH->compression);
|
|
|
|
|
2000-07-06 20:39:39 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2000-07-04 16:25:28 +02:00
|
|
|
tctx->FH = gzopen(tctx->filename, fmode);
|
|
|
|
#else
|
|
|
|
tctx->FH = fopen(tctx->filename, PG_BINARY_W);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _WriteData(ArchiveHandle* AH, const void* data, int dLen)
|
|
|
|
{
|
|
|
|
lclTocEntry* tctx = (lclTocEntry*)AH->currToc->formatData;
|
|
|
|
|
|
|
|
GZWRITE((void*)data, 1, dLen, tctx->FH);
|
|
|
|
|
|
|
|
return dLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _EndData(ArchiveHandle* AH, TocEntry* te)
|
|
|
|
{
|
|
|
|
lclTocEntry* tctx = (lclTocEntry*) te->formatData;
|
|
|
|
|
|
|
|
/* Close the file */
|
|
|
|
GZCLOSE(tctx->FH);
|
|
|
|
tctx->FH = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print data for a given TOC entry
|
|
|
|
*/
|
|
|
|
static void _PrintTocData(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt)
|
|
|
|
{
|
|
|
|
lclTocEntry* tctx = (lclTocEntry*) te->formatData;
|
|
|
|
char buf[4096];
|
|
|
|
int cnt;
|
|
|
|
|
|
|
|
if (!tctx->filename)
|
|
|
|
return;
|
|
|
|
|
2000-07-06 20:39:39 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2000-07-04 16:25:28 +02:00
|
|
|
AH->FH = gzopen(tctx->filename,"rb");
|
|
|
|
#else
|
|
|
|
AH->FH = fopen(tctx->filename,PG_BINARY_R);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ahprintf(AH, "--\n-- Data for TOC Entry ID %d (OID %s) %s %s\n--\n\n",
|
|
|
|
te->id, te->oid, te->desc, te->name);
|
|
|
|
|
|
|
|
while ( (cnt = GZREAD(buf, 1, 4096, AH->FH)) > 0) {
|
|
|
|
ahwrite(buf, 1, cnt, AH);
|
|
|
|
}
|
|
|
|
|
|
|
|
GZCLOSE(AH->FH);
|
|
|
|
|
|
|
|
ahprintf(AH, "\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _ReadByte(ArchiveHandle* AH)
|
|
|
|
{
|
|
|
|
lclContext* ctx = (lclContext*)AH->formatData;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = fgetc(AH->FH);
|
|
|
|
if (res != EOF) {
|
|
|
|
ctx->filePos += 1;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _WriteBuf(ArchiveHandle* AH, const void* buf, int len)
|
|
|
|
{
|
|
|
|
lclContext* ctx = (lclContext*)AH->formatData;
|
|
|
|
int res;
|
|
|
|
res = fwrite(buf, 1, len, AH->FH);
|
|
|
|
ctx->filePos += res;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _CloseArchive(ArchiveHandle* AH)
|
|
|
|
{
|
|
|
|
if (AH->mode == archModeWrite) {
|
|
|
|
WriteHead(AH);
|
|
|
|
WriteToc(AH);
|
|
|
|
fclose(AH->FH);
|
|
|
|
WriteDataChunks(AH);
|
|
|
|
}
|
|
|
|
|
|
|
|
AH->FH = NULL;
|
|
|
|
}
|
|
|
|
|