+++ /dev/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
- * src/bin/pg_dump/pg_backup_files.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "pg_backup_archiver.h"
-#include "dumputils.h"
-#include "dumpmem.h"
-
-static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
-static void _StartData(ArchiveHandle *AH, TocEntry *te);
-static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
-static void _EndData(ArchiveHandle *AH, TocEntry *te);
-static int _WriteByte(ArchiveHandle *AH, const int i);
-static int _ReadByte(ArchiveHandle *);
-static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
-static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t 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, Oid oid);
-static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
-static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
-
-#define K_STD_BUF_SIZE 1024
-
-typedef struct
-{
- int hasSeek;
- pgoff_t filePos;
- FILE *blobToc;
-} lclContext;
-
-typedef struct
-{
-#ifdef HAVE_LIBZ
- gzFile FH;
-#else
- FILE *FH;
-#endif
- char *filename;
-} lclTocEntry;
-
-static const char *modulename = gettext_noop("file archiver");
-static void _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt);
-static void _getBlobTocEntry(ArchiveHandle *AH, Oid *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->ReopenPtr = NULL;
- AH->PrintTocDataPtr = _PrintTocData;
- AH->ReadExtraTocPtr = _ReadExtraToc;
- AH->WriteExtraTocPtr = _WriteExtraToc;
- AH->PrintExtraTocPtr = _PrintExtraToc;
-
- AH->StartBlobsPtr = _StartBlobs;
- AH->StartBlobPtr = _StartBlob;
- AH->EndBlobPtr = _EndBlob;
- AH->EndBlobsPtr = _EndBlobs;
- AH->ClonePtr = NULL;
- AH->DeClonePtr = NULL;
-
- /*
- * Set up some special context used in compressing data.
- */
- ctx = (lclContext *) pg_calloc(1, sizeof(lclContext));
- AH->formatData = (void *) ctx;
- ctx->filePos = 0;
-
- /* Initialize LO buffering */
- AH->lo_buf_size = LOBBUFSIZE;
- AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
-
- /*
- * Now open the TOC file
- */
- if (AH->mode == archModeWrite)
- {
-
- write_msg(modulename, "WARNING:\n"
- " This format is for demonstration purposes; it is not intended for\n"
- " normal use. Files will be written in the current working directory.\n");
-
- if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
- {
- AH->FH = fopen(AH->fSpec, PG_BINARY_W);
- if (AH->FH == NULL)
- exit_horribly(modulename, "could not open output file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
- }
- else
- {
- AH->FH = stdout;
- if (AH->FH == NULL)
- exit_horribly(modulename, "could not open output file: %s\n",
- strerror(errno));
- }
-
- ctx->hasSeek = checkSeek(AH->FH);
-
- 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);
- if (AH->FH == NULL)
- exit_horribly(modulename, "could not open input file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
- }
- else
- {
- AH->FH = stdin;
- if (AH->FH == NULL)
- exit_horribly(modulename, "could not open input file: %s\n",
- strerror(errno));
- }
-
- ctx->hasSeek = checkSeek(AH->FH);
-
- ReadHead(AH);
- ReadToc(AH);
- /* Nothing else in the file... */
- if (fclose(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
- }
-}
-
-/*
- * - 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 *) pg_calloc(1, sizeof(lclTocEntry));
- if (te->dataDumper)
- {
-#ifdef HAVE_LIBZ
- if (AH->compression == 0)
- sprintf(fn, "%d.dat", te->dumpId);
- else
- sprintf(fn, "%d.dat.gz", te->dumpId);
-#else
- sprintf(fn, "%d.dat", te->dumpId);
-#endif
- ctx->filename = pg_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 *) pg_calloc(1, 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;
-
- if (AH->public.verbose)
- 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
-
- if (tctx->FH == NULL)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- tctx->filename, strerror(errno));
-}
-
-static size_t
-_WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
-{
- lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData;
-
- GZWRITE(data, 1, dLen, tctx->FH);
-
- return dLen;
-}
-
-static void
-_EndData(ArchiveHandle *AH, TocEntry *te)
-{
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
-
- /* Close the file */
- if (GZCLOSE(tctx->FH) != 0)
- die_horribly(AH, modulename, "could not close data file\n");
-
- tctx->FH = NULL;
-}
-
-/*
- * Print data for a given file
- */
-static void
-_PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
-{
- char buf[4096];
- size_t cnt;
-
- if (!filename)
- return;
-
-#ifdef HAVE_LIBZ
- AH->FH = gzopen(filename, "rb");
-#else
- AH->FH = fopen(filename, PG_BINARY_R);
-#endif
-
- if (AH->FH == NULL)
- die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
- filename, strerror(errno));
-
- while ((cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0)
- {
- buf[cnt] = '\0';
- ahwrite(buf, 1, cnt, AH);
- }
-
- if (GZCLOSE(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close data file after reading\n");
-}
-
-
-/*
- * 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, Oid *oid, char fname[K_STD_BUF_SIZE])
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- char blobTe[K_STD_BUF_SIZE];
-
- if (fgets(blobTe, sizeof(blobTe), ctx->blobToc) != NULL)
- {
- size_t fpos;
- size_t eos;
-
- *oid = atooid(blobTe);
-
- fpos = strcspn(blobTe, " ");
-
- strlcpy(fname, &blobTe[fpos + 1], K_STD_BUF_SIZE);
-
- eos = strlen(fname) - 1;
-
- if (fname[eos] == '\n')
- fname[eos] = '\0';
- }
- else
- {
- *oid = 0;
- fname[0] = '\0';
- }
-}
-
-static void
-_LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
-{
- Oid oid;
- lclContext *ctx = (lclContext *) AH->formatData;
- char fname[K_STD_BUF_SIZE];
-
- StartRestoreBlobs(AH);
-
- ctx->blobToc = fopen("blobs.toc", PG_BINARY_R);
-
- if (ctx->blobToc == NULL)
- die_horribly(AH, modulename, "could not open large object TOC for input: %s\n", strerror(errno));
-
- _getBlobTocEntry(AH, &oid, fname);
-
- while (oid != 0)
- {
- StartRestoreBlob(AH, oid, ropt->dropSchema);
- _PrintFileData(AH, fname, ropt);
- EndRestoreBlob(AH, oid);
- _getBlobTocEntry(AH, &oid, fname);
- }
-
- if (fclose(ctx->blobToc) != 0)
- die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
-
- EndRestoreBlobs(AH);
-}
-
-
-static int
-_WriteByte(ArchiveHandle *AH, const int i)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
-
- if (fputc(i, AH->FH) == EOF)
- die_horribly(AH, modulename, "could not write byte\n");
-
- ctx->filePos += 1;
-
- return 1;
-}
-
-static int
-_ReadByte(ArchiveHandle *AH)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- int res;
-
- res = getc(AH->FH);
- if (res == EOF)
- die_horribly(AH, modulename, "unexpected end of file\n");
- ctx->filePos += 1;
- return res;
-}
-
-static size_t
-_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- size_t res;
-
- res = fwrite(buf, 1, len, AH->FH);
- if (res != len)
- die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
-
- ctx->filePos += res;
- return res;
-}
-
-static size_t
-_ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- size_t 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);
- if (fclose(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
- 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);
-
- if (ctx->blobToc == NULL)
- die_horribly(AH, modulename,
- "could not open large object TOC for output: %s\n", strerror(errno));
-}
-
-/*
- * 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)
-{
- lclContext *ctx = (lclContext *) AH->formatData;
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
- char fmode[10];
- char fname[255];
- char *sfx;
-
- if (oid == 0)
- die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
-
- if (AH->compression != 0)
- sfx = ".gz";
- else
- sfx = "";
-
- sprintf(fmode, "wb%d", AH->compression);
- sprintf(fname, "blob_%u.dat%s", oid, sfx);
-
- fprintf(ctx->blobToc, "%u %s\n", oid, fname);
-
-#ifdef HAVE_LIBZ
- tctx->FH = gzopen(fname, fmode);
-#else
- tctx->FH = fopen(fname, PG_BINARY_W);
-#endif
-
- if (tctx->FH == NULL)
- die_horribly(AH, modulename, "could not open large object file \"%s\" for input: %s\n",
- fname, strerror(errno));
-}
-
-/*
- * Called by the archiver when the dumper calls EndBlob.
- *
- * Optional.
- */
-static void
-_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
-{
- lclTocEntry *tctx = (lclTocEntry *) te->formatData;
-
- if (GZCLOSE(tctx->FH) != 0)
- die_horribly(AH, modulename, "could not close large object file\n");
-}
-
-/*
- * 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); */
-
- if (fclose(ctx->blobToc) != 0)
- die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
-}