2000-07-21 13:40:08 +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
|
2001-03-22 05:01:46 +01:00
|
|
|
* Rights are granted to use this software in any way so long
|
|
|
|
* as this notice is not removed.
|
2000-07-21 13:40:08 +02:00
|
|
|
*
|
|
|
|
* The author is not responsible for loss or damages that may
|
|
|
|
* result from it's use.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2001-09-21 23:58:30 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_files.c,v 1.13 2001/09/21 21:58:30 petere Exp $
|
2000-07-21 13:40:08 +02:00
|
|
|
*
|
|
|
|
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
|
|
|
|
*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Initial version.
|
2000-07-21 13:40:08 +02:00
|
|
|
*
|
2001-01-12 05:32:07 +01:00
|
|
|
* Modifications - 04-Jan-2001 - pjw@rhyme.com.au
|
|
|
|
*
|
2001-03-22 05:01:46 +01:00
|
|
|
* - Check results of IO routines more carefully.
|
2001-01-12 05:32:07 +01:00
|
|
|
*
|
2000-07-21 13:40:08 +02:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "pg_backup.h"
|
|
|
|
#include "pg_backup_archiver.h"
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
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);
|
2001-04-01 07:42:51 +02:00
|
|
|
static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
|
|
|
|
static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
|
2001-03-22 05:01:46 +01:00
|
|
|
static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
#define K_STD_BUF_SIZE 1024
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int hasSeek;
|
|
|
|
int filePos;
|
|
|
|
FILE *blobToc;
|
2000-07-21 13:40:08 +02:00
|
|
|
} lclContext;
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2001-03-22 05:01:46 +01:00
|
|
|
gzFile *FH;
|
2000-07-21 13:40:08 +02:00
|
|
|
#else
|
2001-03-22 05:01:46 +01:00
|
|
|
FILE *FH;
|
2000-07-21 13:40:08 +02:00
|
|
|
#endif
|
2001-03-22 05:01:46 +01:00
|
|
|
char *filename;
|
2000-07-21 13:40:08 +02:00
|
|
|
} lclTocEntry;
|
|
|
|
|
2001-07-03 22:21:50 +02:00
|
|
|
static char *modulename = gettext_noop("file archiver");
|
2001-03-22 05:01:46 +01:00
|
|
|
static void _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt);
|
|
|
|
static void _getBlobTocEntry(ArchiveHandle *AH, int *oid, char *fname);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Initializer
|
2000-07-21 13:40:08 +02:00
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
void
|
|
|
|
InitArchiveFmt_Files(ArchiveHandle *AH)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
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)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-06-27 23:21:37 +02:00
|
|
|
write_msg(modulename, "WARNING:\n"
|
2001-07-03 22:21:50 +02:00
|
|
|
" This format is for demonstration purposes; it is not intended for\n"
|
2001-06-27 23:21:37 +02:00
|
|
|
" normal use. Files will be written in the current working directory.\n");
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
|
2000-07-21 13:40:08 +02:00
|
|
|
AH->FH = fopen(AH->fSpec, PG_BINARY_W);
|
2001-03-22 05:01:46 +01:00
|
|
|
else
|
2000-07-21 13:40:08 +02:00
|
|
|
AH->FH = stdout;
|
2001-01-12 05:32:07 +01:00
|
|
|
|
|
|
|
if (AH->FH == NULL)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(NULL, modulename, "could not open output file: %s\n", strerror(errno));
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (AH->compression < 0 || AH->compression > 9)
|
2000-07-21 13:40:08 +02:00
|
|
|
AH->compression = Z_DEFAULT_COMPRESSION;
|
|
|
|
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* Read Mode */
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
|
2000-07-21 13:40:08 +02:00
|
|
|
AH->FH = fopen(AH->fSpec, PG_BINARY_R);
|
2001-03-22 05:01:46 +01:00
|
|
|
else
|
2000-07-21 13:40:08 +02:00
|
|
|
AH->FH = stdin;
|
2001-01-12 05:32:07 +01:00
|
|
|
|
|
|
|
if (AH->FH == NULL)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(NULL, modulename, "could not open input file: %s\n", strerror(errno));
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
|
|
|
|
|
|
|
|
ReadHead(AH);
|
|
|
|
ReadToc(AH);
|
2001-03-23 02:27:12 +01:00
|
|
|
/* Nothing else in the file... */
|
|
|
|
if (fclose(AH->FH) != 0)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* - Start a new TOC entry
|
2001-03-22 05:01:46 +01:00
|
|
|
* Setup the output file name.
|
2000-07-21 13:40:08 +02:00
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *ctx;
|
|
|
|
char fn[K_STD_BUF_SIZE];
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
ctx = (lclTocEntry *) malloc(sizeof(lclTocEntry));
|
|
|
|
if (te->dataDumper)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
#ifdef HAVE_LIBZ
|
2001-03-22 05:01:46 +01:00
|
|
|
if (AH->compression == 0)
|
2000-07-21 13:40:08 +02:00
|
|
|
sprintf(fn, "%d.dat", te->id);
|
2001-03-22 05:01:46 +01:00
|
|
|
else
|
2000-07-21 13:40:08 +02:00
|
|
|
sprintf(fn, "%d.dat.gz", te->id);
|
|
|
|
#else
|
|
|
|
sprintf(fn, "%d.dat", te->id);
|
|
|
|
#endif
|
|
|
|
ctx->filename = strdup(fn);
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
ctx->filename = NULL;
|
|
|
|
ctx->FH = NULL;
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
|
|
|
te->formatData = (void *) ctx;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *ctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (ctx->filename)
|
2000-07-21 13:40:08 +02:00
|
|
|
WriteStr(AH, ctx->filename);
|
2001-03-22 05:01:46 +01:00
|
|
|
else
|
2000-07-21 13:40:08 +02:00
|
|
|
WriteStr(AH, "");
|
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *ctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (ctx == NULL)
|
|
|
|
{
|
|
|
|
ctx = (lclTocEntry *) malloc(sizeof(lclTocEntry));
|
|
|
|
te->formatData = (void *) ctx;
|
|
|
|
}
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
ctx->filename = ReadStr(AH);
|
|
|
|
if (strlen(ctx->filename) == 0)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
free(ctx->filename);
|
|
|
|
ctx->filename = NULL;
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
|
|
|
ctx->FH = NULL;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *ctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
ahprintf(AH, "-- File: %s\n", ctx->filename);
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_StartData(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
|
|
|
char fmode[10];
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
sprintf(fmode, "wb%d", AH->compression);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBZ
|
2001-03-22 05:01:46 +01:00
|
|
|
tctx->FH = gzopen(tctx->filename, fmode);
|
2000-07-21 13:40:08 +02:00
|
|
|
#else
|
2001-03-22 05:01:46 +01:00
|
|
|
tctx->FH = fopen(tctx->filename, PG_BINARY_W);
|
2000-07-21 13:40:08 +02:00
|
|
|
#endif
|
2001-01-12 05:32:07 +01:00
|
|
|
|
|
|
|
if (tctx->FH == NULL)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not open data file for output\n");
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int
|
|
|
|
_WriteData(ArchiveHandle *AH, const void *data, int dLen)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
GZWRITE((void *) data, 1, dLen, tctx->FH);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
return dLen;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_EndData(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
/* Close the file */
|
2001-03-23 02:27:12 +01:00
|
|
|
if (GZCLOSE(tctx->FH) != 0)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not close data file\n");
|
2001-03-23 02:27:12 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
tctx->FH = NULL;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
/*
|
|
|
|
* Print data for a given file
|
2000-07-21 13:40:08 +02:00
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
char buf[4096];
|
|
|
|
int cnt;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (!filename)
|
2000-07-21 13:40:08 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBZ
|
2001-03-22 05:01:46 +01:00
|
|
|
AH->FH = gzopen(filename, "rb");
|
2000-07-21 13:40:08 +02:00
|
|
|
#else
|
2001-03-22 05:01:46 +01:00
|
|
|
AH->FH = fopen(filename, PG_BINARY_R);
|
2000-07-21 13:40:08 +02:00
|
|
|
#endif
|
|
|
|
|
2001-01-12 05:32:07 +01:00
|
|
|
if (AH->FH == NULL)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not open data file for input\n");
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
while ((cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
buf[cnt] = '\0';
|
|
|
|
ahwrite(buf, 1, cnt, AH);
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-23 02:27:12 +01:00
|
|
|
if (GZCLOSE(AH->FH) != 0)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not close data file after reading\n");
|
2001-03-23 02:27:12 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print data for a given TOC entry
|
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (!tctx->filename)
|
2000-07-21 13:40:08 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (strcmp(te->desc, "BLOBS") == 0)
|
|
|
|
_LoadBlobs(AH, ropt);
|
|
|
|
else
|
|
|
|
_PrintFileData(AH, tctx->filename, ropt);
|
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_getBlobTocEntry(ArchiveHandle *AH, int *oid, char fname[K_STD_BUF_SIZE])
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
char blobTe[K_STD_BUF_SIZE];
|
|
|
|
int fpos;
|
|
|
|
int eos;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
if (fgets(&blobTe[0], K_STD_BUF_SIZE - 1, ctx->blobToc) != NULL)
|
|
|
|
{
|
|
|
|
*oid = atoi(blobTe);
|
|
|
|
|
|
|
|
fpos = strcspn(blobTe, " ");
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
strncpy(fname, &blobTe[fpos + 1], K_STD_BUF_SIZE - 1);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
eos = strlen(fname) - 1;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
if (fname[eos] == '\n')
|
|
|
|
fname[eos] = '\0';
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
*oid = 0;
|
|
|
|
fname[0] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
int oid;
|
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
char fname[K_STD_BUF_SIZE];
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2000-10-31 15:20:30 +01:00
|
|
|
StartRestoreBlobs(AH);
|
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
ctx->blobToc = fopen("blobs.toc", PG_BINARY_R);
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (ctx->blobToc == NULL)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "could not open large object TOC for input: %s\n", strerror(errno));
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
_getBlobTocEntry(AH, &oid, fname);
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
while (oid != 0)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
StartRestoreBlob(AH, oid);
|
|
|
|
_PrintFileData(AH, fname, ropt);
|
|
|
|
EndRestoreBlob(AH, oid);
|
|
|
|
_getBlobTocEntry(AH, &oid, fname);
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-23 02:27:12 +01:00
|
|
|
if (fclose(ctx->blobToc) != 0)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
|
2000-10-31 15:20:30 +01:00
|
|
|
|
|
|
|
EndRestoreBlobs(AH);
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int
|
|
|
|
_WriteByte(ArchiveHandle *AH, const int i)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (fputc(i, AH->FH) == EOF)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not write byte\n");
|
2001-01-12 05:32:07 +01:00
|
|
|
|
|
|
|
ctx->filePos += 1;
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
return 1;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int
|
|
|
|
_ReadByte(ArchiveHandle *AH)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
int res;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
res = fgetc(AH->FH);
|
|
|
|
if (res != EOF)
|
2000-07-21 13:40:08 +02:00
|
|
|
ctx->filePos += 1;
|
2001-03-22 05:01:46 +01:00
|
|
|
return res;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int
|
|
|
|
_WriteBuf(ArchiveHandle *AH, const void *buf, int len)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = fwrite(buf, 1, len, AH->FH);
|
2001-01-12 05:32:07 +01:00
|
|
|
if (res != len)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "write error in _WriteBuf (%d != %d)\n", res, len);
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
ctx->filePos += res;
|
|
|
|
return res;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int
|
|
|
|
_ReadBuf(ArchiveHandle *AH, void *buf, int len)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
int res;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
res = fread(buf, 1, len, AH->FH);
|
|
|
|
ctx->filePos += res;
|
|
|
|
return res;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_CloseArchive(ArchiveHandle *AH)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
if (AH->mode == archModeWrite)
|
|
|
|
{
|
2000-07-21 13:40:08 +02:00
|
|
|
WriteHead(AH);
|
|
|
|
WriteToc(AH);
|
2001-03-23 02:27:12 +01:00
|
|
|
if (fclose(AH->FH) != 0)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
|
2000-07-21 13:40:08 +02:00
|
|
|
WriteDataChunks(AH);
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
AH->FH = NULL;
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* BLOB support
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Called by the archiver when starting to save all BLOB DATA (not schema).
|
2000-07-21 13:40:08 +02:00
|
|
|
* This routine should save whatever format-specific information is needed
|
2001-03-22 05:01:46 +01:00
|
|
|
* to read the BLOBs back into memory.
|
2000-07-21 13:40:08 +02:00
|
|
|
*
|
|
|
|
* It is called just prior to the dumper's DataDumper routine.
|
|
|
|
*
|
|
|
|
* Optional, but strongly recommended.
|
|
|
|
*
|
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_StartBlobs(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
char fname[K_STD_BUF_SIZE];
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
sprintf(fname, "blobs.toc");
|
|
|
|
ctx->blobToc = fopen(fname, PG_BINARY_W);
|
2001-01-12 05:32:07 +01:00
|
|
|
|
|
|
|
if (ctx->blobToc == NULL)
|
2001-06-27 23:21:37 +02:00
|
|
|
die_horribly(AH, modulename,
|
2001-09-21 23:58:30 +02:00
|
|
|
"could not open large object TOC for output: %s\n", strerror(errno));
|
2001-01-12 05:32:07 +01:00
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called by the archiver when the dumper calls StartBlob.
|
|
|
|
*
|
|
|
|
* Mandatory.
|
|
|
|
*
|
|
|
|
* Must save the passed OID for retrieval at restore-time.
|
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
2001-04-01 07:42:51 +02:00
|
|
|
_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
|
|
|
char fmode[10];
|
|
|
|
char fname[255];
|
|
|
|
char *sfx;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (oid == 0)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
if (AH->compression != 0)
|
|
|
|
sfx = ".gz";
|
|
|
|
else
|
|
|
|
sfx = "";
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
sprintf(fmode, "wb%d", AH->compression);
|
2000-07-21 13:40:08 +02:00
|
|
|
sprintf(fname, "blob_%d.dat%s", oid, sfx);
|
|
|
|
|
|
|
|
fprintf(ctx->blobToc, "%d %s\n", oid, fname);
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBZ
|
2001-03-22 05:01:46 +01:00
|
|
|
tctx->FH = gzopen(fname, fmode);
|
2000-07-21 13:40:08 +02:00
|
|
|
#else
|
2001-03-22 05:01:46 +01:00
|
|
|
tctx->FH = fopen(fname, PG_BINARY_W);
|
2000-07-21 13:40:08 +02:00
|
|
|
#endif
|
|
|
|
|
2001-01-12 05:32:07 +01:00
|
|
|
if (tctx->FH == NULL)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "could not open large object file\n");
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called by the archiver when the dumper calls EndBlob.
|
|
|
|
*
|
|
|
|
* Optional.
|
|
|
|
*
|
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
2001-04-01 07:42:51 +02:00
|
|
|
_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-23 02:27:12 +01:00
|
|
|
if (GZCLOSE(tctx->FH) != 0)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "could not close large object file\n");
|
2000-07-21 13:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Called by the archiver when finishing saving all BLOB DATA.
|
2000-07-21 13:40:08 +02:00
|
|
|
*
|
|
|
|
* Optional.
|
|
|
|
*
|
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
static void
|
|
|
|
_EndBlobs(ArchiveHandle *AH, TocEntry *te)
|
2000-07-21 13:40:08 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
lclContext *ctx = (lclContext *) AH->formatData;
|
|
|
|
|
2000-07-21 13:40:08 +02:00
|
|
|
/* Write out a fake zero OID to mark end-of-blobs. */
|
2001-03-22 05:01:46 +01:00
|
|
|
/* WriteInt(AH, 0); */
|
2000-07-21 13:40:08 +02:00
|
|
|
|
2001-03-23 02:27:12 +01:00
|
|
|
if (fclose(ctx->blobToc) != 0)
|
2001-09-21 23:58:30 +02:00
|
|
|
die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
|
2000-07-21 13:40:08 +02:00
|
|
|
|
|
|
|
}
|
2001-03-23 02:27:12 +01:00
|
|
|
|