diff options
Diffstat (limited to 'src/bin/pg_dump/pg_backup_files.c')
-rw-r--r-- | src/bin/pg_dump/pg_backup_files.c | 786 |
1 files changed, 483 insertions, 303 deletions
diff --git a/src/bin/pg_dump/pg_backup_files.c b/src/bin/pg_dump/pg_backup_files.c index ef2ea57f2ce..1583a497b9c 100644 --- a/src/bin/pg_dump/pg_backup_files.c +++ b/src/bin/pg_dump/pg_backup_files.c @@ -1,303 +1,483 @@ -/*-------------------------------------------------------------------------
- *
- * 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 {
-#ifdef HAVE_LIBZ
- 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) {
-#ifdef HAVE_LIBZ
- 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);
-
-#ifdef HAVE_LIBZ
- 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;
-
-#ifdef HAVE_LIBZ
- 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;
-}
-
+/*------------------------------------------------------------------------- + * + * 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); + +static void _StartBlobs(ArchiveHandle* AH, TocEntry* te); +static void _StartBlob(ArchiveHandle* AH, TocEntry* te, int oid); +static void _EndBlob(ArchiveHandle* AH, TocEntry* te, int oid); +static void _EndBlobs(ArchiveHandle* AH, TocEntry* te); + +#define K_STD_BUF_SIZE 1024 + +typedef struct { + int hasSeek; + int filePos; + FILE *blobToc; +} lclContext; + +typedef struct { +#ifdef HAVE_LIBZ + gzFile *FH; +#else + FILE *FH; +#endif + char *filename; +} lclTocEntry; + +static char* progname = "Archiver(files)"; +static void _LoadBlobs(ArchiveHandle* AH, RestoreOptions *ropt); +static void _getBlobTocEntry(ArchiveHandle* AH, int *oid, char *fname); + +/* + * 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; + + 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)); + AH->formatData = (void*)ctx; + ctx->filePos = 0; + + /* + * Now open the TOC file + */ + if (AH->mode == archModeWrite) { + + fprintf(stderr, "\n*************************************************************\n" + "* WARNING: This format is for demonstration purposes. It is *\n" + "* not intended for general use. Files will be dumped *\n" + "* into the current working directory. *\n" + "***************************************************************\n\n"); + + 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 { /* Read Mode */ + + 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[K_STD_BUF_SIZE]; + + ctx = (lclTocEntry*)malloc(sizeof(lclTocEntry)); + if (te->dataDumper) { +#ifdef HAVE_LIBZ + 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); + +#ifdef HAVE_LIBZ + 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 file + */ +static void _PrintFileData(ArchiveHandle* AH, char *filename, RestoreOptions *ropt) +{ + char buf[4096]; + int cnt; + + if (!filename) + return; + +#ifdef HAVE_LIBZ + AH->FH = gzopen(filename,"rb"); +#else + AH->FH = fopen(filename,PG_BINARY_R); +#endif + + while ( (cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0) { + buf[cnt] = '\0'; + ahwrite(buf, 1, cnt, AH); + } + + GZCLOSE(AH->FH); +} + + +/* + * Print data for a given TOC entry +*/ +static void _PrintTocData(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt) +{ + lclTocEntry* tctx = (lclTocEntry*) te->formatData; + + if (!tctx->filename) + return; + + if (strcmp(te->desc, "BLOBS") == 0) + _LoadBlobs(AH, ropt); + else + { + _PrintFileData(AH, tctx->filename, ropt); + } +} + +static void _getBlobTocEntry(ArchiveHandle* AH, int *oid, char fname[K_STD_BUF_SIZE]) +{ + lclContext* ctx = (lclContext*)AH->formatData; + char blobTe[K_STD_BUF_SIZE]; + int fpos; + int eos; + + if (fgets(&blobTe[0], K_STD_BUF_SIZE - 1, ctx->blobToc) != NULL) + { + *oid = atoi(blobTe); + + fpos = strcspn(blobTe, " "); + + strncpy(fname, &blobTe[fpos+1], K_STD_BUF_SIZE - 1); + + eos = strlen(fname)-1; + + if (fname[eos] == '\n') + fname[eos] = '\0'; + + } else { + + *oid = 0; + fname[0] = '\0'; + } +} + +static void _LoadBlobs(ArchiveHandle* AH, RestoreOptions *ropt) +{ + int oid; + lclContext* ctx = (lclContext*)AH->formatData; + char fname[K_STD_BUF_SIZE]; + + ctx->blobToc = fopen("blobs.toc", PG_BINARY_R); + + _getBlobTocEntry(AH, &oid, fname); + + while(oid != 0) + { + StartRestoreBlob(AH, oid); + _PrintFileData(AH, fname, ropt); + EndRestoreBlob(AH, oid); + _getBlobTocEntry(AH, &oid, fname); + } + + fclose(ctx->blobToc); +} + + +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; +} + + + +/* + * BLOB support + */ + +/* + * 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; + char fname[K_STD_BUF_SIZE]; + + sprintf(fname, "blobs.toc"); + ctx->blobToc = fopen(fname, PG_BINARY_W); + +} + +/* + * 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, int oid) +{ + lclContext* ctx = (lclContext*)AH->formatData; + lclTocEntry* tctx = (lclTocEntry*)te->formatData; + char fmode[10]; + char fname[255]; + char *sfx; + + if (oid == 0) + die_horribly(AH, "%s: illegal OID for BLOB (%d)\n", progname, oid); + + if (AH->compression != 0) + sfx = ".gz"; + else + sfx = ""; + + sprintf(fmode, "wb%d", AH->compression); + sprintf(fname, "blob_%d.dat%s", oid, sfx); + + fprintf(ctx->blobToc, "%d %s\n", oid, fname); + +#ifdef HAVE_LIBZ + tctx->FH = gzopen(fname, fmode); +#else + tctx->FH = fopen(fname, PG_BINARY_W); +#endif + +} + +/* + * Called by the archiver when the dumper calls EndBlob. + * + * Optional. + * + */ +static void _EndBlob(ArchiveHandle* AH, TocEntry* te, int oid) +{ + lclTocEntry* tctx = (lclTocEntry*)te->formatData; + + GZCLOSE(tctx->FH); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * Optional. + * + */ +static void _EndBlobs(ArchiveHandle* AH, TocEntry* te) +{ + lclContext* ctx = (lclContext*)AH->formatData; + /* Write out a fake zero OID to mark end-of-blobs. */ + /* WriteInt(AH, 0); */ + + fclose(ctx->blobToc); + +} + + |