Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Functions | Variables

pg_backup_directory.c File Reference

#include "compress_io.h"
#include "pg_backup_utils.h"
#include "parallel.h"
#include <dirent.h>
#include <sys/stat.h>
Include dependency graph for pg_backup_directory.c:

Go to the source code of this file.

Data Structures

struct  lclContext
struct  lclTocEntry

Functions

static void _ArchiveEntry (ArchiveHandle *AH, TocEntry *te)
static void _StartData (ArchiveHandle *AH, TocEntry *te)
static void _EndData (ArchiveHandle *AH, TocEntry *te)
static size_t _WriteData (ArchiveHandle *AH, const void *data, size_t dLen)
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 _ReopenArchive (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)
static void _LoadBlobs (ArchiveHandle *AH, RestoreOptions *ropt)
static void _Clone (ArchiveHandle *AH)
static void _DeClone (ArchiveHandle *AH)
static char * _MasterStartParallelItem (ArchiveHandle *AH, TocEntry *te, T_Action act)
static int _MasterEndParallelItem (ArchiveHandle *AH, TocEntry *te, const char *str, T_Action act)
static char * _WorkerJobRestoreDirectory (ArchiveHandle *AH, TocEntry *te)
static char * _WorkerJobDumpDirectory (ArchiveHandle *AH, TocEntry *te)
static void setFilePath (ArchiveHandle *AH, char *buf, const char *relativeFilename)
void InitArchiveFmt_Directory (ArchiveHandle *AH)
static void _PrintFileData (ArchiveHandle *AH, char *filename, RestoreOptions *ropt)

Variables

static const char * modulename = gettext_noop("directory archiver")

Function Documentation

static void _ArchiveEntry ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 234 of file pg_backup_directory.c.

References _tocEntry::dataDumper, _tocEntry::desc, _tocEntry::dumpId, lclTocEntry::filename, fn(), _tocEntry::formatData, MAXPGPATH, pg_malloc0(), pg_strdup(), and snprintf().

{
    lclTocEntry *tctx;
    char        fn[MAXPGPATH];

    tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
    if (te->dataDumper)
    {
        snprintf(fn, MAXPGPATH, "%d.dat", te->dumpId);
        tctx->filename = pg_strdup(fn);
    }
    else if (strcmp(te->desc, "BLOBS") == 0)
        tctx->filename = pg_strdup("blobs.toc");
    else
        tctx->filename = NULL;

    te->formatData = (void *) tctx;
}

static void _Clone ( ArchiveHandle AH  )  [static]

Definition at line 725 of file pg_backup_directory.c.

References _archiveHandle::formatData, and pg_malloc().

{
    lclContext *ctx = (lclContext *) AH->formatData;

    AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
    memcpy(AH->formatData, ctx, sizeof(lclContext));
    ctx = (lclContext *) AH->formatData;

    /*
     * Note: we do not make a local lo_buf because we expect at most one BLOBS
     * entry per archive, so no parallelism is possible.  Likewise,
     * TOC-entry-local state isn't an issue because any one TOC entry is
     * touched by just one worker child.
     */

    /*
     * We also don't copy the ParallelState pointer (pstate), only the master
     * process ever writes to it.
     */
}

static void _CloseArchive ( ArchiveHandle AH  )  [static]

Definition at line 564 of file pg_backup_directory.c.

References archModeWrite, cfclose(), cfopen_write(), lclContext::dataFH, exit_horribly(), _archiveHandle::FH, _archiveHandle::format, _archiveHandle::formatData, _archiveHandle::mode, modulename, NULL, ParallelBackupEnd(), ParallelBackupStart(), PG_BINARY_W, lclContext::pstate, setFilePath(), strerror(), WriteDataChunks(), WriteHead(), and WriteToc().

{
    lclContext *ctx = (lclContext *) AH->formatData;

    if (AH->mode == archModeWrite)
    {
        cfp        *tocFH;
        char        fname[MAXPGPATH];

        setFilePath(AH, fname, "toc.dat");

        /* this will actually fork the processes for a parallel backup */
        ctx->pstate = ParallelBackupStart(AH, NULL);

        /* The TOC is always created uncompressed */
        tocFH = cfopen_write(fname, PG_BINARY_W, 0);
        if (tocFH == NULL)
            exit_horribly(modulename, "could not open output file \"%s\": %s\n",
                          fname, strerror(errno));
        ctx->dataFH = tocFH;

        /*
         * Write 'tar' in the format field of the toc.dat file. The directory
         * is compatible with 'tar', so there's no point having a different
         * format code for it.
         */
        AH->format = archTar;
        WriteHead(AH);
        AH->format = archDirectory;
        WriteToc(AH);
        if (cfclose(tocFH) != 0)
            exit_horribly(modulename, "could not close TOC file: %s\n",
                          strerror(errno));
        WriteDataChunks(AH, ctx->pstate);

        ParallelBackupEnd(AH, ctx->pstate);
    }
    AH->FH = NULL;
}

static void _DeClone ( ArchiveHandle AH  )  [static]

Definition at line 747 of file pg_backup_directory.c.

References _archiveHandle::formatData, and free.

{
    lclContext *ctx = (lclContext *) AH->formatData;

    free(ctx);
}

static void _EndBlob ( ArchiveHandle AH,
TocEntry te,
Oid  oid 
) [static]

Definition at line 669 of file pg_backup_directory.c.

References lclContext::blobsTocFH, buf, cfclose(), cfwrite(), lclContext::dataFH, exit_horribly(), _archiveHandle::formatData, modulename, and snprintf().

{
    lclContext *ctx = (lclContext *) AH->formatData;
    char        buf[50];
    int         len;

    /* Close the BLOB data file itself */
    cfclose(ctx->dataFH);
    ctx->dataFH = NULL;

    /* register the blob in blobs.toc */
    len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid);
    if (cfwrite(buf, len, ctx->blobsTocFH) != len)
        exit_horribly(modulename, "could not write to blobs TOC file\n");
}

static void _EndBlobs ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 691 of file pg_backup_directory.c.

References lclContext::blobsTocFH, cfclose(), and _archiveHandle::formatData.

{
    lclContext *ctx = (lclContext *) AH->formatData;

    cfclose(ctx->blobsTocFH);
    ctx->blobsTocFH = NULL;
}

static void _EndData ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 367 of file pg_backup_directory.c.

References cfclose(), lclContext::dataFH, and _archiveHandle::formatData.

{
    lclContext *ctx = (lclContext *) AH->formatData;

    /* Close the file */
    cfclose(ctx->dataFH);

    ctx->dataFH = NULL;
}

static void _LoadBlobs ( ArchiveHandle AH,
RestoreOptions ropt 
) [static]

Definition at line 432 of file pg_backup_directory.c.

References _PrintFileData(), lclContext::blobsTocFH, cfclose(), cfeof(), cfgets(), cfopen_read(), lclContext::directory, _restoreOptions::dropSchema, EndRestoreBlob(), EndRestoreBlobs(), exit_horribly(), _archiveHandle::formatData, MAXPGPATH, modulename, NULL, PG_BINARY_R, setFilePath(), snprintf(), StartRestoreBlob(), StartRestoreBlobs(), and strerror().

Referenced by _PrintTocData().

{
    Oid         oid;
    lclContext *ctx = (lclContext *) AH->formatData;
    char        fname[MAXPGPATH];
    char        line[MAXPGPATH];

    StartRestoreBlobs(AH);

    setFilePath(AH, fname, "blobs.toc");

    ctx->blobsTocFH = cfopen_read(fname, PG_BINARY_R);

    if (ctx->blobsTocFH == NULL)
        exit_horribly(modulename, "could not open large object TOC file \"%s\" for input: %s\n",
                      fname, strerror(errno));

    /* Read the blobs TOC file line-by-line, and process each blob */
    while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL)
    {
        char        fname[MAXPGPATH];
        char        path[MAXPGPATH];

        if (sscanf(line, "%u %s\n", &oid, fname) != 2)
            exit_horribly(modulename, "invalid line in large object TOC file \"%s\": \"%s\"\n",
                          fname, line);

        StartRestoreBlob(AH, oid, ropt->dropSchema);
        snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
        _PrintFileData(AH, path, ropt);
        EndRestoreBlob(AH, oid);
    }
    if (!cfeof(ctx->blobsTocFH))
        exit_horribly(modulename, "error reading large object TOC file \"%s\"\n",
                      fname);

    if (cfclose(ctx->blobsTocFH) != 0)
        exit_horribly(modulename, "could not close large object TOC file \"%s\": %s\n",
                      fname, strerror(errno));

    ctx->blobsTocFH = NULL;

    EndRestoreBlobs(AH);
}

static int _MasterEndParallelItem ( ArchiveHandle AH,
TocEntry te,
const char *  str,
T_Action  act 
) [static]

Definition at line 847 of file pg_backup_directory.c.

References ACT_DUMP, ACT_RESTORE, Assert, _tocEntry::dumpId, Archive::n_errors, _archiveHandle::public, and status().

{
    DumpId      dumpId;
    int         nBytes,
                n_errors;
    int         status = 0;

    if (act == ACT_DUMP)
    {
        sscanf(str, "%u%n", &dumpId, &nBytes);

        Assert(dumpId == te->dumpId);
        Assert(nBytes == strlen(str));
    }
    else if (act == ACT_RESTORE)
    {
        sscanf(str, "%u %u %u%n", &dumpId, &status, &n_errors, &nBytes);

        Assert(dumpId == te->dumpId);
        Assert(nBytes == strlen(str));

        AH->public.n_errors += n_errors;
    }

    return status;
}

static char * _MasterStartParallelItem ( ArchiveHandle AH,
TocEntry te,
T_Action  act 
) [static]

Definition at line 760 of file pg_backup_directory.c.

References ACT_DUMP, ACT_RESTORE, buf, _tocEntry::dumpId, and snprintf().

{
    /*
     * A static char is okay here, even on Windows because we call this
     * function only from one process (the master).
     */
    static char buf[64];

    if (act == ACT_DUMP)
        snprintf(buf, sizeof(buf), "DUMP %d", te->dumpId);
    else if (act == ACT_RESTORE)
        snprintf(buf, sizeof(buf), "RESTORE %d", te->dumpId);

    return buf;
}

static void _PrintExtraToc ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 305 of file pg_backup_directory.c.

References ahprintf(), lclTocEntry::filename, _tocEntry::formatData, _archiveHandle::public, and Archive::verbose.

{
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;

    if (AH->public.verbose && tctx->filename)
        ahprintf(AH, "-- File: %s\n", tctx->filename);
}

static void _PrintFileData ( ArchiveHandle AH,
char *  filename,
RestoreOptions ropt 
) [static]

Definition at line 381 of file pg_backup_directory.c.

References ahwrite(), buf, cfclose(), cfopen_read(), cfread(), exit_horribly(), free, modulename, PG_BINARY_R, pg_malloc(), strerror(), and ZLIB_OUT_SIZE.

Referenced by _LoadBlobs(), and _PrintTocData().

{
    size_t      cnt;
    char       *buf;
    size_t      buflen;
    cfp        *cfp;

    if (!filename)
        return;

    cfp = cfopen_read(filename, PG_BINARY_R);

    if (!cfp)
        exit_horribly(modulename, "could not open input file \"%s\": %s\n",
                      filename, strerror(errno));

    buf = pg_malloc(ZLIB_OUT_SIZE);
    buflen = ZLIB_OUT_SIZE;

    while ((cnt = cfread(buf, buflen, cfp)))
        ahwrite(buf, 1, cnt, AH);

    free(buf);
    if (cfclose(cfp) !=0)
        exit_horribly(modulename, "could not close data file: %s\n",
                      strerror(errno));
}

static void _PrintTocData ( ArchiveHandle AH,
TocEntry te,
RestoreOptions ropt 
) [static]

Definition at line 413 of file pg_backup_directory.c.

References _LoadBlobs(), _PrintFileData(), _tocEntry::desc, lclTocEntry::filename, _tocEntry::formatData, and setFilePath().

{
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;

    if (!tctx->filename)
        return;

    if (strcmp(te->desc, "BLOBS") == 0)
        _LoadBlobs(AH, ropt);
    else
    {
        char        fname[MAXPGPATH];

        setFilePath(AH, fname, tctx->filename);
        _PrintFileData(AH, fname, ropt);
    }
}

static size_t _ReadBuf ( ArchiveHandle AH,
void *  buf,
size_t  len 
) [static]

Definition at line 541 of file pg_backup_directory.c.

References cfread(), lclContext::dataFH, and _archiveHandle::formatData.

{
    lclContext *ctx = (lclContext *) AH->formatData;
    size_t      res;

    res = cfread(buf, len, ctx->dataFH);

    return res;
}

static int _ReadByte ( ArchiveHandle AH  )  [static]

Definition at line 502 of file pg_backup_directory.c.

References cfgetc(), lclContext::dataFH, exit_horribly(), _archiveHandle::formatData, and modulename.

{
    lclContext *ctx = (lclContext *) AH->formatData;
    int         res;

    res = cfgetc(ctx->dataFH);
    if (res == EOF)
        exit_horribly(modulename, "unexpected end of file\n");

    return res;
}

static void _ReadExtraToc ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 282 of file pg_backup_directory.c.

References lclTocEntry::filename, _tocEntry::formatData, free, NULL, pg_malloc0(), and ReadStr().

{
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;

    if (tctx == NULL)
    {
        tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
        te->formatData = (void *) tctx;
    }

    tctx->filename = ReadStr(AH);
    if (strlen(tctx->filename) == 0)
    {
        free(tctx->filename);
        tctx->filename = NULL;
    }
}

static void _ReopenArchive ( ArchiveHandle AH  )  [static]

Definition at line 608 of file pg_backup_directory.c.

{
    /*
     * Our TOC is in memory, our data files are opened by each child anyway as
     * they are separate. We support reopening the archive by just doing
     * nothing.
     */
}

static void _StartBlob ( ArchiveHandle AH,
TocEntry te,
Oid  oid 
) [static]

Definition at line 649 of file pg_backup_directory.c.

References cfopen_write(), _archiveHandle::compression, lclContext::dataFH, lclContext::directory, exit_horribly(), _archiveHandle::formatData, MAXPGPATH, modulename, NULL, PG_BINARY_W, snprintf(), and strerror().

{
    lclContext *ctx = (lclContext *) AH->formatData;
    char        fname[MAXPGPATH];

    snprintf(fname, MAXPGPATH, "%s/blob_%u.dat", ctx->directory, oid);

    ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);

    if (ctx->dataFH == NULL)
        exit_horribly(modulename, "could not open output file \"%s\": %s\n",
                      fname, strerror(errno));
}

static void _StartBlobs ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 629 of file pg_backup_directory.c.

References lclContext::blobsTocFH, cfopen_write(), exit_horribly(), _archiveHandle::formatData, MAXPGPATH, modulename, NULL, setFilePath(), and strerror().

{
    lclContext *ctx = (lclContext *) AH->formatData;
    char        fname[MAXPGPATH];

    setFilePath(AH, fname, "blobs.toc");

    /* The blob TOC file is never compressed */
    ctx->blobsTocFH = cfopen_write(fname, "ab", 0);
    if (ctx->blobsTocFH == NULL)
        exit_horribly(modulename, "could not open output file \"%s\": %s\n",
                      fname, strerror(errno));
}

static void _StartData ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 323 of file pg_backup_directory.c.

References cfopen_write(), _archiveHandle::compression, exit_horribly(), lclTocEntry::filename, _archiveHandle::formatData, _tocEntry::formatData, modulename, NULL, PG_BINARY_W, setFilePath(), and strerror().

{
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;
    lclContext *ctx = (lclContext *) AH->formatData;
    char        fname[MAXPGPATH];

    setFilePath(AH, fname, tctx->filename);

    ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
    if (ctx->dataFH == NULL)
        exit_horribly(modulename, "could not open output file \"%s\": %s\n",
                      fname, strerror(errno));
}

static char * _WorkerJobDumpDirectory ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 788 of file pg_backup_directory.c.

References buf, _tocEntry::dumpId, exit_horribly(), _tocEntry::formatData, modulename, pg_malloc(), snprintf(), and WriteDataChunksForTocEntry().

{
    /*
     * short fixed-size string + some ID so far, this needs to be malloc'ed
     * instead of static because we work with threads on windows
     */
    const int   buflen = 64;
    char       *buf = (char *) pg_malloc(buflen);
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;

    /* This should never happen */
    if (!tctx)
        exit_horribly(modulename, "Error during backup\n");

    /*
     * This function returns void. We either fail and die horribly or
     * succeed... A failure will be detected by the parent when the child dies
     * unexpectedly.
     */
    WriteDataChunksForTocEntry(AH, te);

    snprintf(buf, buflen, "OK DUMP %d", te->dumpId);

    return buf;
}

static char * _WorkerJobRestoreDirectory ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 819 of file pg_backup_directory.c.

References ParallelArgs::AH, buf, _tocEntry::dumpId, Archive::n_errors, parallel_restore(), pg_malloc(), _archiveHandle::public, snprintf(), ParallelArgs::te, and WORKER_IGNORED_ERRORS.

{
    /*
     * short fixed-size string + some ID so far, this needs to be malloc'ed
     * instead of static because we work with threads on windows
     */
    const int   buflen = 64;
    char       *buf = (char *) pg_malloc(buflen);
    ParallelArgs pargs;
    int         status;

    pargs.AH = AH;
    pargs.te = te;

    status = parallel_restore(&pargs);

    snprintf(buf, buflen, "OK RESTORE %d %d %d", te->dumpId, status,
             status == WORKER_IGNORED_ERRORS ? AH->public.n_errors : 0);

    return buf;
}

static size_t _WriteBuf ( ArchiveHandle AH,
const void *  buf,
size_t  len 
) [static]

Definition at line 519 of file pg_backup_directory.c.

References cfwrite(), checkAborting(), lclContext::dataFH, exit_horribly(), _archiveHandle::formatData, modulename, and strerror().

{
    lclContext *ctx = (lclContext *) AH->formatData;
    size_t      res;

    /* Are we aborting? */
    checkAborting(AH);

    res = cfwrite(buf, len, ctx->dataFH);
    if (res != len)
        exit_horribly(modulename, "could not write to output file: %s\n",
                      strerror(errno));

    return res;
}

static int _WriteByte ( ArchiveHandle AH,
const int  i 
) [static]

Definition at line 484 of file pg_backup_directory.c.

References cfwrite(), lclContext::dataFH, exit_horribly(), _archiveHandle::formatData, and modulename.

{
    unsigned char c = (unsigned char) i;
    lclContext *ctx = (lclContext *) AH->formatData;

    if (cfwrite(&c, 1, ctx->dataFH) != 1)
        exit_horribly(modulename, "could not write byte\n");

    return 1;
}

static size_t _WriteData ( ArchiveHandle AH,
const void *  data,
size_t  dLen 
) [static]

Definition at line 347 of file pg_backup_directory.c.

References cfwrite(), checkAborting(), lclContext::dataFH, and _archiveHandle::formatData.

{
    lclContext *ctx = (lclContext *) AH->formatData;

    if (dLen == 0)
        return 0;

    /* Are we aborting? */
    checkAborting(AH);

    return cfwrite(data, dLen, ctx->dataFH);
}

static void _WriteExtraToc ( ArchiveHandle AH,
TocEntry te 
) [static]

Definition at line 261 of file pg_backup_directory.c.

References lclTocEntry::filename, _tocEntry::formatData, and WriteStr().

{
    lclTocEntry *tctx = (lclTocEntry *) te->formatData;

    /*
     * A dumpable object has set tctx->filename, any other object has not.
     * (see _ArchiveEntry).
     */
    if (tctx->filename)
        WriteStr(AH, tctx->filename);
    else
        WriteStr(AH, "");
}

void InitArchiveFmt_Directory ( ArchiveHandle AH  ) 

Definition at line 111 of file pg_backup_directory.c.

References _archiveHandle::ArchiveEntryPtr, archModeWrite, lclContext::blobsTocFH, cfclose(), cfopen_read(), _archiveHandle::ClonePtr, closedir(), _archiveHandle::ClosePtr, dirent::d_name, lclContext::dataFH, _archiveHandle::DeClonePtr, lclContext::directory, _archiveHandle::EndBlobPtr, _archiveHandle::EndBlobsPtr, _archiveHandle::EndDataPtr, exit_horribly(), _archiveHandle::format, _archiveHandle::formatData, _archiveHandle::fSpec, _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, LOBBUFSIZE, _archiveHandle::MasterEndParallelItemPtr, _archiveHandle::MasterStartParallelItemPtr, mkdir, _archiveHandle::mode, modulename, NULL, opendir(), PG_BINARY_R, pg_malloc(), pg_malloc0(), _archiveHandle::PrintExtraTocPtr, _archiveHandle::PrintTocDataPtr, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, readdir(), _archiveHandle::ReadExtraTocPtr, ReadHead(), ReadToc(), _archiveHandle::ReopenPtr, setFilePath(), _archiveHandle::StartBlobPtr, _archiveHandle::StartBlobsPtr, _archiveHandle::StartDataPtr, strerror(), _archiveHandle::WorkerJobDumpPtr, _archiveHandle::WorkerJobRestorePtr, _archiveHandle::WriteBufPtr, _archiveHandle::WriteBytePtr, _archiveHandle::WriteDataPtr, and _archiveHandle::WriteExtraTocPtr.

Referenced by _allocAH().

{
    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 = _ReopenArchive;
    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 = _Clone;
    AH->DeClonePtr = _DeClone;

    AH->WorkerJobRestorePtr = _WorkerJobRestoreDirectory;
    AH->WorkerJobDumpPtr = _WorkerJobDumpDirectory;

    AH->MasterStartParallelItemPtr = _MasterStartParallelItem;
    AH->MasterEndParallelItemPtr = _MasterEndParallelItem;

    /* Set up our private context */
    ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
    AH->formatData = (void *) ctx;

    ctx->dataFH = NULL;
    ctx->blobsTocFH = NULL;

    /* Initialize LO buffering */
    AH->lo_buf_size = LOBBUFSIZE;
    AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);

    /*
     * Now open the TOC file
     */

    if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
        exit_horribly(modulename, "no output directory specified\n");

    ctx->directory = AH->fSpec;

    if (AH->mode == archModeWrite)
    {
        struct stat st;
        bool        is_empty = false;

        /* we accept an empty existing directory */
        if (stat(ctx->directory, &st) == 0 && S_ISDIR(st.st_mode))
        {
            DIR        *dir = opendir(ctx->directory);

            if (dir)
            {
                struct dirent *d;

                is_empty = true;
                while ((d = readdir(dir)))
                {
                    if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0)
                    {
                        is_empty = false;
                        break;
                    }
                }
                closedir(dir);
            }
        }

        if (!is_empty && mkdir(ctx->directory, 0700) < 0)
            exit_horribly(modulename, "could not create directory \"%s\": %s\n",
                          ctx->directory, strerror(errno));
    }
    else
    {                           /* Read Mode */
        char        fname[MAXPGPATH];
        cfp        *tocFH;

        setFilePath(AH, fname, "toc.dat");

        tocFH = cfopen_read(fname, PG_BINARY_R);
        if (tocFH == NULL)
            exit_horribly(modulename,
                          "could not open input file \"%s\": %s\n",
                          fname, strerror(errno));

        ctx->dataFH = tocFH;

        /*
         * The TOC of a directory format dump shares the format code of the
         * tar format.
         */
        AH->format = archTar;
        ReadHead(AH);
        AH->format = archDirectory;
        ReadToc(AH);

        /* Nothing else in the file, so close it again... */
        if (cfclose(tocFH) != 0)
            exit_horribly(modulename, "could not close TOC file: %s\n",
                          strerror(errno));
        ctx->dataFH = NULL;
    }
}

static void setFilePath ( ArchiveHandle AH,
char *  buf,
const char *  relativeFilename 
) [static]

Definition at line 706 of file pg_backup_directory.c.

References lclContext::directory, exit_horribly(), _archiveHandle::formatData, and modulename.

Referenced by _CloseArchive(), _LoadBlobs(), _PrintTocData(), _StartBlobs(), _StartData(), and InitArchiveFmt_Directory().

{
    lclContext *ctx = (lclContext *) AH->formatData;
    char       *dname;

    dname = ctx->directory;

    if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
        exit_horribly(modulename, "file name too long: \"%s\"\n", dname);

    strcpy(buf, dname);
    strcat(buf, "/");
    strcat(buf, relativeFilename);
}


Variable Documentation

const char* modulename = gettext_noop("directory archiver") [static]