PostgreSQL Source Code  git master
pg_backup_tar.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include "common/file_utils.h"
#include "fe_utils/string_utils.h"
#include "pg_backup_archiver.h"
#include "pg_backup_tar.h"
#include "pg_backup_utils.h"
#include "pgtar.h"
Include dependency graph for pg_backup_tar.c:

Go to the source code of this file.

Data Structures

struct  TAR_MEMBER
 
struct  lclContext
 
struct  lclTocEntry
 

Macros

#define K_STD_BUF_SIZE   1024
 

Functions

static void _ArchiveEntry (ArchiveHandle *AH, TocEntry *te)
 
static void _StartData (ArchiveHandle *AH, TocEntry *te)
 
static void _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 void _WriteBuf (ArchiveHandle *AH, const void *buf, size_t len)
 
static void _ReadBuf (ArchiveHandle *AH, void *buf, size_t len)
 
static void _CloseArchive (ArchiveHandle *AH)
 
static void _PrintTocData (ArchiveHandle *AH, TocEntry *te)
 
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)
 
static TAR_MEMBERtarOpen (ArchiveHandle *AH, const char *filename, char mode)
 
static void tarClose (ArchiveHandle *AH, TAR_MEMBER *TH)
 
static int tarPrintf (TAR_MEMBER *th, const char *fmt,...) pg_attribute_printf(2
 
static int static void _tarAddFile (ArchiveHandle *AH, TAR_MEMBER *th)
 
static TAR_MEMBER_tarPositionTo (ArchiveHandle *AH, const char *filename)
 
static size_t tarRead (void *buf, size_t len, TAR_MEMBER *th)
 
static size_t tarWrite (const void *buf, size_t len, TAR_MEMBER *th)
 
static void _tarWriteHeader (TAR_MEMBER *th)
 
static int _tarGetHeader (ArchiveHandle *AH, TAR_MEMBER *th)
 
static size_t _tarReadRaw (ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh)
 
static size_t _scriptOut (ArchiveHandle *AH, const void *buf, size_t len)
 
void InitArchiveFmt_Tar (ArchiveHandle *AH)
 
static void _PrintFileData (ArchiveHandle *AH, char *filename)
 
bool isValidTarHeader (char *header)
 

Macro Definition Documentation

◆ K_STD_BUF_SIZE

#define K_STD_BUF_SIZE   1024

Definition at line 63 of file pg_backup_tar.c.

Function Documentation

◆ _ArchiveEntry()

static void _ArchiveEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 243 of file pg_backup_tar.c.

244 {
245  lclTocEntry *ctx;
246  char fn[K_STD_BUF_SIZE];
247 
248  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
249  if (te->dataDumper != NULL)
250  {
251 #ifdef HAVE_LIBZ
252  if (AH->compression == 0)
253  sprintf(fn, "%d.dat", te->dumpId);
254  else
255  sprintf(fn, "%d.dat.gz", te->dumpId);
256 #else
257  sprintf(fn, "%d.dat", te->dumpId);
258 #endif
259  ctx->filename = pg_strdup(fn);
260  }
261  else
262  {
263  ctx->filename = NULL;
264  ctx->TH = NULL;
265  }
266  te->formatData = (void *) ctx;
267 }
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define K_STD_BUF_SIZE
Definition: pg_backup_tar.c:63
#define sprintf
Definition: port.h:224
DataDumperPtr dataDumper
TAR_MEMBER * TH
Definition: pg_backup_tar.c:98
static void * fn(void *arg)

References _archiveHandle::compression, _tocEntry::dataDumper, _tocEntry::dumpId, lclTocEntry::filename, fn(), _tocEntry::formatData, K_STD_BUF_SIZE, pg_malloc0(), pg_strdup(), sprintf, and lclTocEntry::TH.

Referenced by InitArchiveFmt_Tar().

◆ _CloseArchive()

static void _CloseArchive ( ArchiveHandle AH)
static

Definition at line 819 of file pg_backup_tar.c.

820 {
821  lclContext *ctx = (lclContext *) AH->formatData;
822  TAR_MEMBER *th;
823  RestoreOptions *ropt;
824  RestoreOptions *savRopt;
825  DumpOptions *savDopt;
826  int savVerbose,
827  i;
828 
829  if (AH->mode == archModeWrite)
830  {
831  /*
832  * Write the Header & TOC to the archive FIRST
833  */
834  th = tarOpen(AH, "toc.dat", 'w');
835  ctx->FH = th;
836  WriteHead(AH);
837  WriteToc(AH);
838  tarClose(AH, th); /* Not needed any more */
839 
840  /*
841  * Now send the data (tables & blobs)
842  */
843  WriteDataChunks(AH, NULL);
844 
845  /*
846  * Now this format wants to append a script which does a full restore
847  * if the files have been extracted.
848  */
849  th = tarOpen(AH, "restore.sql", 'w');
850 
851  tarPrintf(th, "--\n"
852  "-- NOTE:\n"
853  "--\n"
854  "-- File paths need to be edited. Search for $$PATH$$ and\n"
855  "-- replace it with the path to the directory containing\n"
856  "-- the extracted data files.\n"
857  "--\n");
858 
859  AH->CustomOutPtr = _scriptOut;
860 
861  ctx->isSpecialScript = 1;
862  ctx->scriptTH = th;
863 
864  ropt = NewRestoreOptions();
865  memcpy(ropt, AH->public.ropt, sizeof(RestoreOptions));
866  ropt->filename = NULL;
867  ropt->dropSchema = 1;
868  ropt->compression = 0;
869  ropt->superuser = NULL;
870  ropt->suppressDumpWarnings = true;
871 
872  savDopt = AH->public.dopt;
873  savRopt = AH->public.ropt;
874 
875  SetArchiveOptions((Archive *) AH, NULL, ropt);
876 
877  savVerbose = AH->public.verbose;
878  AH->public.verbose = 0;
879 
880  RestoreArchive((Archive *) AH);
881 
882  SetArchiveOptions((Archive *) AH, savDopt, savRopt);
883 
884  AH->public.verbose = savVerbose;
885 
886  tarClose(AH, th);
887 
888  ctx->isSpecialScript = 0;
889 
890  /*
891  * EOF marker for tar files is two blocks of NULLs.
892  */
893  for (i = 0; i < TAR_BLOCK_SIZE * 2; i++)
894  {
895  if (fputc(0, ctx->tarFH) == EOF)
897  }
898 
899  /* Sync the output file if one is defined */
900  if (AH->dosync && AH->fSpec)
901  (void) fsync_fname(AH->fSpec, false);
902  }
903 
904  AH->FH = NULL;
905 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:673
int i
Definition: isn.c:73
void RestoreArchive(Archive *AH)
RestoreOptions * NewRestoreOptions(void)
@ archModeWrite
Definition: pg_backup.h:49
void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
void WriteHead(ArchiveHandle *AH)
void WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
void WriteToc(ArchiveHandle *AH)
#define WRITE_ERROR_EXIT
static int tarPrintf(TAR_MEMBER *th, const char *fmt,...) pg_attribute_printf(2
static TAR_MEMBER * tarOpen(ArchiveHandle *AH, const char *filename, char mode)
static size_t _scriptOut(ArchiveHandle *AH, const void *buf, size_t len)
static void tarClose(ArchiveHandle *AH, TAR_MEMBER *TH)
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
DumpOptions * dopt
Definition: pg_backup.h:191
int verbose
Definition: pg_backup.h:194
RestoreOptions * ropt
Definition: pg_backup.h:192
CustomOutPtrType CustomOutPtr
FILE * tarFH
Definition: pg_backup_tar.c:88
TAR_MEMBER * FH
Definition: pg_backup_tar.c:91
TAR_MEMBER * scriptTH
Definition: pg_backup_tar.c:93
int isSpecialScript
Definition: pg_backup_tar.c:92

References _scriptOut(), archModeWrite, _archiveHandle::CustomOutPtr, Archive::dopt, _archiveHandle::FH, lclContext::FH, _archiveHandle::formatData, fsync_fname(), i, if(), lclContext::isSpecialScript, _archiveHandle::mode, NewRestoreOptions(), _archiveHandle::public, RestoreArchive(), Archive::ropt, lclContext::scriptTH, SetArchiveOptions(), TAR_BLOCK_SIZE, tarClose(), lclContext::tarFH, tarOpen(), tarPrintf(), Archive::verbose, WRITE_ERROR_EXIT, WriteDataChunks(), WriteHead(), and WriteToc().

Referenced by InitArchiveFmt_Tar().

◆ _EndBlob()

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

Definition at line 976 of file pg_backup_tar.c.

977 {
978  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
979 
980  tarClose(AH, tctx->TH);
981 }

References _tocEntry::formatData, tarClose(), and lclTocEntry::TH.

Referenced by InitArchiveFmt_Tar().

◆ _EndBlobs()

static void _EndBlobs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 990 of file pg_backup_tar.c.

991 {
992  lclContext *ctx = (lclContext *) AH->formatData;
993 
994  /* Write out a fake zero OID to mark end-of-blobs. */
995  /* WriteInt(AH, 0); */
996 
997  tarClose(AH, ctx->blobToc);
998 }
TAR_MEMBER * blobToc
Definition: pg_backup_tar.c:87

References lclContext::blobToc, _archiveHandle::formatData, and tarClose().

Referenced by InitArchiveFmt_Tar().

◆ _EndData()

static void _EndData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 618 of file pg_backup_tar.c.

619 {
620  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
621 
622  /* Close the file */
623  tarClose(AH, tctx->TH);
624  tctx->TH = NULL;
625 }

References _tocEntry::formatData, tarClose(), and lclTocEntry::TH.

Referenced by InitArchiveFmt_Tar().

◆ _LoadBlobs()

static void _LoadBlobs ( ArchiveHandle AH)
static

Definition at line 712 of file pg_backup_tar.c.

713 {
714  Oid oid;
715  lclContext *ctx = (lclContext *) AH->formatData;
716  TAR_MEMBER *th;
717  size_t cnt;
718  bool foundBlob = false;
719  char buf[4096];
720 
721  StartRestoreBlobs(AH);
722 
723  th = tarOpen(AH, NULL, 'r'); /* Open next file */
724  while (th != NULL)
725  {
726  ctx->FH = th;
727 
728  if (strncmp(th->targetFile, "blob_", 5) == 0)
729  {
730  oid = atooid(&th->targetFile[5]);
731  if (oid != 0)
732  {
733  pg_log_info("restoring large object with OID %u", oid);
734 
735  StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema);
736 
737  while ((cnt = tarRead(buf, 4095, th)) > 0)
738  {
739  buf[cnt] = '\0';
740  ahwrite(buf, 1, cnt, AH);
741  }
742  EndRestoreBlob(AH, oid);
743  foundBlob = true;
744  }
745  tarClose(AH, th);
746  }
747  else
748  {
749  tarClose(AH, th);
750 
751  /*
752  * Once we have found the first blob, stop at the first non-blob
753  * entry (which will be 'blobs.toc'). This coding would eat all
754  * the rest of the archive if there are no blobs ... but this
755  * function shouldn't be called at all in that case.
756  */
757  if (foundBlob)
758  break;
759  }
760 
761  th = tarOpen(AH, NULL, 'r');
762  }
763  EndRestoreBlobs(AH);
764 }
#define pg_log_info(...)
Definition: logging.h:88
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
void StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
void StartRestoreBlobs(ArchiveHandle *AH)
void EndRestoreBlob(ArchiveHandle *AH, Oid oid)
void EndRestoreBlobs(ArchiveHandle *AH)
static size_t tarRead(void *buf, size_t len, TAR_MEMBER *th)
static char * buf
Definition: pg_test_fsync.c:70
unsigned int Oid
Definition: postgres_ext.h:31
#define atooid(x)
Definition: postgres_ext.h:42

References ahwrite(), atooid, buf, _restoreOptions::dropSchema, EndRestoreBlob(), EndRestoreBlobs(), lclContext::FH, _archiveHandle::formatData, pg_log_info, _archiveHandle::public, Archive::ropt, StartRestoreBlob(), StartRestoreBlobs(), tarClose(), TAR_MEMBER::targetFile, tarOpen(), and tarRead().

Referenced by _PrintTocData().

◆ _PrintExtraToc()

static void _PrintExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 301 of file pg_backup_tar.c.

302 {
303  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
304 
305  if (AH->public.verbose && ctx->filename != NULL)
306  ahprintf(AH, "-- File: %s\n", ctx->filename);
307 }
int ahprintf(ArchiveHandle *AH, const char *fmt,...)

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

Referenced by InitArchiveFmt_Tar().

◆ _PrintFileData()

static void _PrintFileData ( ArchiveHandle AH,
char *  filename 
)
static

Definition at line 631 of file pg_backup_tar.c.

632 {
633  lclContext *ctx = (lclContext *) AH->formatData;
634  char buf[4096];
635  size_t cnt;
636  TAR_MEMBER *th;
637 
638  if (!filename)
639  return;
640 
641  th = tarOpen(AH, filename, 'r');
642  ctx->FH = th;
643 
644  while ((cnt = tarRead(buf, 4095, th)) > 0)
645  {
646  buf[cnt] = '\0';
647  ahwrite(buf, 1, cnt, AH);
648  }
649 
650  tarClose(AH, th);
651 }
static char * filename
Definition: pg_dumpall.c:92

References ahwrite(), buf, lclContext::FH, filename, _archiveHandle::formatData, if(), tarClose(), tarOpen(), and tarRead().

Referenced by _PrintTocData().

◆ _PrintTocData()

static void _PrintTocData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 658 of file pg_backup_tar.c.

659 {
660  lclContext *ctx = (lclContext *) AH->formatData;
661  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
662  int pos1;
663 
664  if (!tctx->filename)
665  return;
666 
667  /*
668  * If we're writing the special restore.sql script, emit a suitable
669  * command to include each table's data from the corresponding file.
670  *
671  * In the COPY case this is a bit klugy because the regular COPY command
672  * was already printed before we get control.
673  */
674  if (ctx->isSpecialScript)
675  {
676  if (te->copyStmt)
677  {
678  /* Abort the COPY FROM stdin */
679  ahprintf(AH, "\\.\n");
680 
681  /*
682  * The COPY statement should look like "COPY ... FROM stdin;\n",
683  * see dumpTableData().
684  */
685  pos1 = (int) strlen(te->copyStmt) - 13;
686  if (pos1 < 6 || strncmp(te->copyStmt, "COPY ", 5) != 0 ||
687  strcmp(te->copyStmt + pos1, " FROM stdin;\n") != 0)
688  fatal("unexpected COPY statement syntax: \"%s\"",
689  te->copyStmt);
690 
691  /* Emit all but the FROM part ... */
692  ahwrite(te->copyStmt, 1, pos1, AH);
693  /* ... and insert modified FROM */
694  ahprintf(AH, " FROM '$$PATH$$/%s';\n\n", tctx->filename);
695  }
696  else
697  {
698  /* --inserts mode, no worries, just include the data file */
699  ahprintf(AH, "\\i $$PATH$$/%s\n\n", tctx->filename);
700  }
701 
702  return;
703  }
704 
705  if (strcmp(te->desc, "BLOBS") == 0)
706  _LoadBlobs(AH);
707  else
708  _PrintFileData(AH, tctx->filename);
709 }
static void _LoadBlobs(ArchiveHandle *AH)
static void _PrintFileData(ArchiveHandle *AH, char *filename)
#define fatal(...)

References _LoadBlobs(), _PrintFileData(), ahprintf(), ahwrite(), _tocEntry::copyStmt, _tocEntry::desc, fatal, _archiveHandle::formatData, _tocEntry::formatData, and lclContext::isSpecialScript.

Referenced by InitArchiveFmt_Tar().

◆ _ReadBuf()

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

Definition at line 807 of file pg_backup_tar.c.

808 {
809  lclContext *ctx = (lclContext *) AH->formatData;
810 
811  if (tarRead(buf, len, ctx->FH) != len)
812  /* We already would have exited for errors on reads, must be EOF */
813  fatal("could not read from input file: end of file");
814 
815  ctx->filePos += len;
816 }
const void size_t len
pgoff_t filePos
Definition: pg_backup_tar.c:86

References buf, fatal, lclContext::FH, lclContext::filePos, _archiveHandle::formatData, if(), len, and tarRead().

Referenced by InitArchiveFmt_Tar().

◆ _ReadByte()

static int _ReadByte ( ArchiveHandle AH)
static

Definition at line 781 of file pg_backup_tar.c.

782 {
783  lclContext *ctx = (lclContext *) AH->formatData;
784  size_t res;
785  unsigned char c;
786 
787  res = tarRead(&c, 1, ctx->FH);
788  if (res != 1)
789  /* We already would have exited for errors on reads, must be EOF */
790  fatal("could not read from input file: end of file");
791  ctx->filePos += 1;
792  return c;
793 }
char * c

References fatal, lclContext::FH, lclContext::filePos, _archiveHandle::formatData, res, and tarRead().

Referenced by InitArchiveFmt_Tar().

◆ _ReadExtraToc()

static void _ReadExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 281 of file pg_backup_tar.c.

282 {
283  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
284 
285  if (ctx == NULL)
286  {
287  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
288  te->formatData = (void *) ctx;
289  }
290 
291  ctx->filename = ReadStr(AH);
292  if (strlen(ctx->filename) == 0)
293  {
294  free(ctx->filename);
295  ctx->filename = NULL;
296  }
297  ctx->TH = NULL;
298 }
#define free(a)
Definition: header.h:65
char * ReadStr(ArchiveHandle *AH)

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

Referenced by InitArchiveFmt_Tar().

◆ _scriptOut()

static size_t _scriptOut ( ArchiveHandle AH,
const void *  buf,
size_t  len 
)
static

Definition at line 908 of file pg_backup_tar.c.

909 {
910  lclContext *ctx = (lclContext *) AH->formatData;
911 
912  return tarWrite(buf, len, ctx->scriptTH);
913 }
static size_t tarWrite(const void *buf, size_t len, TAR_MEMBER *th)

References buf, _archiveHandle::formatData, len, lclContext::scriptTH, and tarWrite().

Referenced by _CloseArchive().

◆ _StartBlob()

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

Definition at line 947 of file pg_backup_tar.c.

948 {
949  lclContext *ctx = (lclContext *) AH->formatData;
950  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
951  char fname[255];
952  char *sfx;
953 
954  if (oid == 0)
955  fatal("invalid OID for large object (%u)", oid);
956 
957  if (AH->compression != 0)
958  sfx = ".gz";
959  else
960  sfx = "";
961 
962  sprintf(fname, "blob_%u.dat%s", oid, sfx);
963 
964  tarPrintf(ctx->blobToc, "%u %s\n", oid, fname);
965 
966  tctx->TH = tarOpen(AH, fname, 'w');
967 }

References lclContext::blobToc, _archiveHandle::compression, fatal, _archiveHandle::formatData, _tocEntry::formatData, sprintf, tarOpen(), and tarPrintf().

Referenced by InitArchiveFmt_Tar().

◆ _StartBlobs()

static void _StartBlobs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 930 of file pg_backup_tar.c.

931 {
932  lclContext *ctx = (lclContext *) AH->formatData;
933  char fname[K_STD_BUF_SIZE];
934 
935  sprintf(fname, "blobs.toc");
936  ctx->blobToc = tarOpen(AH, fname, 'w');
937 }

References lclContext::blobToc, _archiveHandle::formatData, K_STD_BUF_SIZE, sprintf, and tarOpen().

Referenced by InitArchiveFmt_Tar().

◆ _StartData()

static void _StartData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 310 of file pg_backup_tar.c.

311 {
312  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
313 
314  tctx->TH = tarOpen(AH, tctx->filename, 'w');
315 }

References lclTocEntry::filename, _tocEntry::formatData, tarOpen(), and lclTocEntry::TH.

Referenced by InitArchiveFmt_Tar().

◆ _tarAddFile()

static void _tarAddFile ( ArchiveHandle AH,
TAR_MEMBER th 
)
static

Definition at line 1068 of file pg_backup_tar.c.

1069 {
1070  lclContext *ctx = (lclContext *) AH->formatData;
1071  FILE *tmp = th->tmpFH; /* Grab it for convenience */
1072  char buf[32768];
1073  size_t cnt;
1074  pgoff_t len = 0;
1075  size_t res;
1076  size_t i,
1077  pad;
1078 
1079  /*
1080  * Find file len & go back to start.
1081  */
1082  if (fseeko(tmp, 0, SEEK_END) != 0)
1083  fatal("error during file seek: %m");
1084  th->fileLen = ftello(tmp);
1085  if (th->fileLen < 0)
1086  fatal("could not determine seek position in archive file: %m");
1087  if (fseeko(tmp, 0, SEEK_SET) != 0)
1088  fatal("error during file seek: %m");
1089 
1090  _tarWriteHeader(th);
1091 
1092  while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0)
1093  {
1094  if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt)
1096  len += res;
1097  }
1098  if (!feof(tmp))
1099  READ_ERROR_EXIT(tmp);
1100 
1101  if (fclose(tmp) != 0) /* This *should* delete it... */
1102  fatal("could not close temporary file: %m");
1103 
1104  if (len != th->fileLen)
1105  {
1106  char buf1[32],
1107  buf2[32];
1108 
1109  snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);
1110  snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen);
1111  fatal("actual file length (%s) does not match expected (%s)",
1112  buf1, buf2);
1113  }
1114 
1116  for (i = 0; i < pad; i++)
1117  {
1118  if (fputc('\0', th->tarFH) == EOF)
1120  }
1121 
1122  ctx->tarFHpos += len + pad;
1123 }
#define INT64_FORMAT
Definition: c.h:483
#define READ_ERROR_EXIT(fd)
static void _tarWriteHeader(TAR_MEMBER *th)
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
#define snprintf
Definition: port.h:222
pgoff_t fileLen
Definition: pg_backup_tar.c:79
FILE * tarFH
Definition: pg_backup_tar.c:74
FILE * tmpFH
Definition: pg_backup_tar.c:75
pgoff_t tarFHpos
Definition: pg_backup_tar.c:89
#define ftello(stream)
Definition: win32_port.h:218
#define fseeko(stream, offset, origin)
Definition: win32_port.h:215
#define pgoff_t
Definition: win32_port.h:208

References _tarWriteHeader(), buf, fatal, TAR_MEMBER::fileLen, _archiveHandle::formatData, fseeko, ftello, i, if(), INT64_FORMAT, len, pgoff_t, READ_ERROR_EXIT, res, snprintf, TAR_MEMBER::tarFH, lclContext::tarFHpos, tarPaddingBytesRequired(), TAR_MEMBER::tmpFH, and WRITE_ERROR_EXIT.

Referenced by tarClose().

◆ _tarGetHeader()

static int _tarGetHeader ( ArchiveHandle AH,
TAR_MEMBER th 
)
static

Definition at line 1211 of file pg_backup_tar.c.

1212 {
1213  lclContext *ctx = (lclContext *) AH->formatData;
1214  char h[TAR_BLOCK_SIZE];
1215  char tag[100 + 1];
1216  int sum,
1217  chk;
1218  pgoff_t len;
1219  pgoff_t hPos;
1220  bool gotBlock = false;
1221 
1222  while (!gotBlock)
1223  {
1224  /* Save the pos for reporting purposes */
1225  hPos = ctx->tarFHpos;
1226 
1227  /* Read the next tar block, return EOF, exit if short */
1228  len = _tarReadRaw(AH, h, TAR_BLOCK_SIZE, NULL, ctx->tarFH);
1229  if (len == 0) /* EOF */
1230  return 0;
1231 
1232  if (len != TAR_BLOCK_SIZE)
1233  fatal(ngettext("incomplete tar header found (%lu byte)",
1234  "incomplete tar header found (%lu bytes)",
1235  len),
1236  (unsigned long) len);
1237 
1238  /* Calc checksum */
1239  chk = tarChecksum(h);
1240  sum = read_tar_number(&h[148], 8);
1241 
1242  /*
1243  * If the checksum failed, see if it is a null block. If so, silently
1244  * continue to the next block.
1245  */
1246  if (chk == sum)
1247  gotBlock = true;
1248  else
1249  {
1250  int i;
1251 
1252  for (i = 0; i < TAR_BLOCK_SIZE; i++)
1253  {
1254  if (h[i] != 0)
1255  {
1256  gotBlock = true;
1257  break;
1258  }
1259  }
1260  }
1261  }
1262 
1263  /* Name field is 100 bytes, might not be null-terminated */
1264  strlcpy(tag, &h[0], 100 + 1);
1265 
1266  len = read_tar_number(&h[124], 12);
1267 
1268  {
1269  char posbuf[32];
1270  char lenbuf[32];
1271 
1272  snprintf(posbuf, sizeof(posbuf), UINT64_FORMAT, (uint64) hPos);
1273  snprintf(lenbuf, sizeof(lenbuf), UINT64_FORMAT, (uint64) len);
1274  pg_log_debug("TOC Entry %s at %s (length %s, checksum %d)",
1275  tag, posbuf, lenbuf, sum);
1276  }
1277 
1278  if (chk != sum)
1279  {
1280  char posbuf[32];
1281 
1282  snprintf(posbuf, sizeof(posbuf), UINT64_FORMAT,
1283  (uint64) ftello(ctx->tarFH));
1284  fatal("corrupt tar header found in %s (expected %d, computed %d) file position %s",
1285  tag, sum, chk, posbuf);
1286  }
1287 
1288  th->targetFile = pg_strdup(tag);
1289  th->fileLen = len;
1290 
1291  return 1;
1292 }
#define ngettext(s, p, n)
Definition: c.h:1179
#define UINT64_FORMAT
Definition: c.h:484
#define pg_log_debug(...)
Definition: logging.h:92
static size_t _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh)
while(p+4<=pend)
uint64 read_tar_number(const char *s, int len)
Definition: tar.c:58
int tarChecksum(char *header)
Definition: tar.c:90
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * targetFile
Definition: pg_backup_tar.c:76

References _tarReadRaw(), fatal, TAR_MEMBER::fileLen, _archiveHandle::formatData, ftello, i, len, ngettext, pg_log_debug, pg_strdup(), pgoff_t, read_tar_number(), snprintf, strlcpy(), TAR_BLOCK_SIZE, tarChecksum(), lclContext::tarFH, lclContext::tarFHpos, TAR_MEMBER::targetFile, UINT64_FORMAT, and while().

Referenced by _tarPositionTo().

◆ _tarPositionTo()

static TAR_MEMBER * _tarPositionTo ( ArchiveHandle AH,
const char *  filename 
)
static

Definition at line 1127 of file pg_backup_tar.c.

1128 {
1129  lclContext *ctx = (lclContext *) AH->formatData;
1130  TAR_MEMBER *th = pg_malloc0(sizeof(TAR_MEMBER));
1131  char c;
1132  char header[TAR_BLOCK_SIZE];
1133  size_t i,
1134  len,
1135  blks;
1136  int id;
1137 
1138  th->AH = AH;
1139 
1140  /* Go to end of current file, if any */
1141  if (ctx->tarFHpos != 0)
1142  {
1143  char buf1[100],
1144  buf2[100];
1145 
1146  snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ctx->tarFHpos);
1147  snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ctx->tarNextMember);
1148  pg_log_debug("moving from position %s to next member at file position %s",
1149  buf1, buf2);
1150 
1151  while (ctx->tarFHpos < ctx->tarNextMember)
1152  _tarReadRaw(AH, &c, 1, NULL, ctx->tarFH);
1153  }
1154 
1155  {
1156  char buf[100];
1157 
1158  snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ctx->tarFHpos);
1159  pg_log_debug("now at file position %s", buf);
1160  }
1161 
1162  /* We are at the start of the file, or at the next member */
1163 
1164  /* Get the header */
1165  if (!_tarGetHeader(AH, th))
1166  {
1167  if (filename)
1168  fatal("could not find header for file \"%s\" in tar archive", filename);
1169  else
1170  {
1171  /*
1172  * We're just scanning the archive for the next file, so return
1173  * null
1174  */
1175  free(th);
1176  return NULL;
1177  }
1178  }
1179 
1180  while (filename != NULL && strcmp(th->targetFile, filename) != 0)
1181  {
1182  pg_log_debug("skipping tar member %s", th->targetFile);
1183 
1184  id = atoi(th->targetFile);
1185  if ((TocIDRequired(AH, id) & REQ_DATA) != 0)
1186  fatal("restoring data out of order is not supported in this archive format: "
1187  "\"%s\" is required, but comes before \"%s\" in the archive file.",
1188  th->targetFile, filename);
1189 
1190  /* Header doesn't match, so read to next header */
1191  len = th->fileLen;
1192  len += tarPaddingBytesRequired(th->fileLen);
1193  blks = len / TAR_BLOCK_SIZE; /* # of tar blocks */
1194 
1195  for (i = 0; i < blks; i++)
1196  _tarReadRaw(AH, &header[0], TAR_BLOCK_SIZE, NULL, ctx->tarFH);
1197 
1198  if (!_tarGetHeader(AH, th))
1199  fatal("could not find header for file \"%s\" in tar archive", filename);
1200  }
1201 
1202  ctx->tarNextMember = ctx->tarFHpos + th->fileLen
1203  + tarPaddingBytesRequired(th->fileLen);
1204  th->pos = 0;
1205 
1206  return th;
1207 }
int TocIDRequired(ArchiveHandle *AH, DumpId id)
#define REQ_DATA
static int _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:212
pgoff_t tarNextMember
Definition: pg_backup_tar.c:90

References _tarGetHeader(), _tarReadRaw(), TAR_MEMBER::AH, buf, fatal, TAR_MEMBER::fileLen, filename, _archiveHandle::formatData, free, header(), i, INT64_FORMAT, len, pg_log_debug, pg_malloc0(), TAR_MEMBER::pos, REQ_DATA, snprintf, TAR_BLOCK_SIZE, lclContext::tarFH, lclContext::tarFHpos, TAR_MEMBER::targetFile, lclContext::tarNextMember, tarPaddingBytesRequired(), and TocIDRequired().

Referenced by tarOpen().

◆ _tarReadRaw()

static size_t _tarReadRaw ( ArchiveHandle AH,
void *  buf,
size_t  len,
TAR_MEMBER th,
FILE *  fh 
)
static

Definition at line 508 of file pg_backup_tar.c.

509 {
510  lclContext *ctx = (lclContext *) AH->formatData;
511  size_t avail;
512  size_t used = 0;
513  size_t res = 0;
514 
515  Assert(th || fh);
516 
517  avail = AH->lookaheadLen - AH->lookaheadPos;
518  if (avail > 0)
519  {
520  /* We have some lookahead bytes to use */
521  if (avail >= len) /* Just use the lookahead buffer */
522  used = len;
523  else
524  used = avail;
525 
526  /* Copy, and adjust buffer pos */
527  memcpy(buf, AH->lookahead + AH->lookaheadPos, used);
528  AH->lookaheadPos += used;
529 
530  /* Adjust required length */
531  len -= used;
532  }
533 
534  /* Read the file if len > 0 */
535  if (len > 0)
536  {
537  if (fh)
538  {
539  res = fread(&((char *) buf)[used], 1, len, fh);
540  if (res != len && !feof(fh))
541  READ_ERROR_EXIT(fh);
542  }
543  else if (th)
544  {
545  if (th->zFH)
546  {
547  res = GZREAD(&((char *) buf)[used], 1, len, th->zFH);
548  if (res != len && !GZEOF(th->zFH))
549  {
550 #ifdef HAVE_LIBZ
551  int errnum;
552  const char *errmsg = gzerror(th->zFH, &errnum);
553 
554  fatal("could not read from input file: %s",
555  errnum == Z_ERRNO ? strerror(errno) : errmsg);
556 #else
557  fatal("could not read from input file: %s",
558  strerror(errno));
559 #endif
560  }
561  }
562  else
563  {
564  res = fread(&((char *) buf)[used], 1, len, th->nFH);
565  if (res != len && !feof(th->nFH))
566  READ_ERROR_EXIT(th->nFH);
567  }
568  }
569  }
570 
571  ctx->tarFHpos += res + used;
572 
573  return (res + used);
574 }
int errmsg(const char *fmt,...)
Definition: elog.c:909
Assert(fmt[strlen(fmt) - 1] !='\n')
#define GZEOF(fh)
#define GZREAD(p, s, n, fh)
#define strerror
Definition: port.h:235
FILE * zFH
Definition: pg_backup_tar.c:71
FILE * nFH
Definition: pg_backup_tar.c:73

References Assert(), buf, errmsg(), fatal, _archiveHandle::formatData, GZEOF, GZREAD, len, _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, TAR_MEMBER::nFH, READ_ERROR_EXIT, res, strerror, lclContext::tarFHpos, and TAR_MEMBER::zFH.

Referenced by _tarGetHeader(), _tarPositionTo(), and tarRead().

◆ _tarWriteHeader()

static void _tarWriteHeader ( TAR_MEMBER th)
static

Definition at line 1296 of file pg_backup_tar.c.

1297 {
1298  char h[TAR_BLOCK_SIZE];
1299 
1300  tarCreateHeader(h, th->targetFile, NULL, th->fileLen,
1301  0600, 04000, 02000, time(NULL));
1302 
1303  /* Now write the completed header. */
1304  if (fwrite(h, 1, TAR_BLOCK_SIZE, th->tarFH) != TAR_BLOCK_SIZE)
1306 }
enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
Definition: tar.c:114

References TAR_MEMBER::fileLen, TAR_BLOCK_SIZE, tarCreateHeader(), TAR_MEMBER::tarFH, TAR_MEMBER::targetFile, and WRITE_ERROR_EXIT.

Referenced by _tarAddFile().

◆ _WriteBuf()

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

Definition at line 796 of file pg_backup_tar.c.

797 {
798  lclContext *ctx = (lclContext *) AH->formatData;
799 
800  if (tarWrite(buf, len, ctx->FH) != len)
802 
803  ctx->filePos += len;
804 }

References buf, lclContext::FH, lclContext::filePos, _archiveHandle::formatData, if(), len, tarWrite(), and WRITE_ERROR_EXIT.

Referenced by InitArchiveFmt_Tar().

◆ _WriteByte()

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

Definition at line 768 of file pg_backup_tar.c.

769 {
770  lclContext *ctx = (lclContext *) AH->formatData;
771  char b = i; /* Avoid endian problems */
772 
773  if (tarWrite(&b, 1, ctx->FH) != 1)
775 
776  ctx->filePos += 1;
777  return 1;
778 }
int b
Definition: isn.c:70

References b, lclContext::FH, lclContext::filePos, _archiveHandle::formatData, i, if(), tarWrite(), and WRITE_ERROR_EXIT.

Referenced by InitArchiveFmt_Tar().

◆ _WriteData()

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

Definition at line 609 of file pg_backup_tar.c.

610 {
611  lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData;
612 
613  if (tarWrite(data, dLen, tctx->TH) != dLen)
615 }
const void * data
struct _tocEntry * currToc

References _archiveHandle::currToc, data, _tocEntry::formatData, if(), tarWrite(), lclTocEntry::TH, and WRITE_ERROR_EXIT.

Referenced by InitArchiveFmt_Tar().

◆ _WriteExtraToc()

static void _WriteExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 270 of file pg_backup_tar.c.

271 {
272  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
273 
274  if (ctx->filename)
275  WriteStr(AH, ctx->filename);
276  else
277  WriteStr(AH, "");
278 }
size_t WriteStr(ArchiveHandle *AH, const char *c)

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

Referenced by InitArchiveFmt_Tar().

◆ InitArchiveFmt_Tar()

void InitArchiveFmt_Tar ( ArchiveHandle AH)

Definition at line 126 of file pg_backup_tar.c.

127 {
128  lclContext *ctx;
129 
130  /* Assuming static functions, this can be copied for each format. */
132  AH->StartDataPtr = _StartData;
133  AH->WriteDataPtr = _WriteData;
134  AH->EndDataPtr = _EndData;
135  AH->WriteBytePtr = _WriteByte;
136  AH->ReadBytePtr = _ReadByte;
137  AH->WriteBufPtr = _WriteBuf;
138  AH->ReadBufPtr = _ReadBuf;
139  AH->ClosePtr = _CloseArchive;
140  AH->ReopenPtr = NULL;
145 
147  AH->StartBlobPtr = _StartBlob;
148  AH->EndBlobPtr = _EndBlob;
149  AH->EndBlobsPtr = _EndBlobs;
150  AH->ClonePtr = NULL;
151  AH->DeClonePtr = NULL;
152 
153  AH->WorkerJobDumpPtr = NULL;
154  AH->WorkerJobRestorePtr = NULL;
155 
156  /*
157  * Set up some special context used in compressing data.
158  */
159  ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
160  AH->formatData = (void *) ctx;
161  ctx->filePos = 0;
162  ctx->isSpecialScript = 0;
163 
164  /* Initialize LO buffering */
165  AH->lo_buf_size = LOBBUFSIZE;
166  AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
167 
168  /*
169  * Now open the tar file, and load the TOC if we're in read mode.
170  */
171  if (AH->mode == archModeWrite)
172  {
173  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
174  {
175  ctx->tarFH = fopen(AH->fSpec, PG_BINARY_W);
176  if (ctx->tarFH == NULL)
177  fatal("could not open TOC file \"%s\" for output: %m",
178  AH->fSpec);
179  }
180  else
181  {
182  ctx->tarFH = stdout;
183  if (ctx->tarFH == NULL)
184  fatal("could not open TOC file for output: %m");
185  }
186 
187  ctx->tarFHpos = 0;
188 
189  /*
190  * Make unbuffered since we will dup() it, and the buffers screw each
191  * other
192  */
193  /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
194 
195  ctx->hasSeek = checkSeek(ctx->tarFH);
196 
197  /*
198  * We don't support compression because reading the files back is not
199  * possible since gzdopen uses buffered IO which totally screws file
200  * positioning.
201  */
202  if (AH->compression != 0)
203  fatal("compression is not supported by tar archive format");
204  }
205  else
206  { /* Read Mode */
207  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
208  {
209  ctx->tarFH = fopen(AH->fSpec, PG_BINARY_R);
210  if (ctx->tarFH == NULL)
211  fatal("could not open TOC file \"%s\" for input: %m",
212  AH->fSpec);
213  }
214  else
215  {
216  ctx->tarFH = stdin;
217  if (ctx->tarFH == NULL)
218  fatal("could not open TOC file for input: %m");
219  }
220 
221  /*
222  * Make unbuffered since we will dup() it, and the buffers screw each
223  * other
224  */
225  /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
226 
227  ctx->tarFHpos = 0;
228 
229  ctx->hasSeek = checkSeek(ctx->tarFH);
230 
231  ctx->FH = (void *) tarOpen(AH, "toc.dat", 'r');
232  ReadHead(AH);
233  ReadToc(AH);
234  tarClose(AH, ctx->FH); /* Nothing else in the file... */
235  }
236 }
#define PG_BINARY_R
Definition: c.h:1270
#define PG_BINARY_W
Definition: c.h:1271
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
bool checkSeek(FILE *fp)
void ReadHead(ArchiveHandle *AH)
void ReadToc(ArchiveHandle *AH)
#define LOBBUFSIZE
static void _PrintTocData(ArchiveHandle *AH, TocEntry *te)
static void _StartBlobs(ArchiveHandle *AH, TocEntry *te)
static void _StartData(ArchiveHandle *AH, TocEntry *te)
static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
static void _CloseArchive(ArchiveHandle *AH)
static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
static int _WriteByte(ArchiveHandle *AH, const int i)
static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
static void _EndData(ArchiveHandle *AH, TocEntry *te)
static void _EndBlobs(ArchiveHandle *AH, TocEntry *te)
static int _ReadByte(ArchiveHandle *)
static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
DeClonePtrType DeClonePtr
ReadExtraTocPtrType ReadExtraTocPtr
WorkerJobDumpPtrType WorkerJobDumpPtr
EndBlobPtrType EndBlobPtr
ArchiveEntryPtrType ArchiveEntryPtr
WriteDataPtrType WriteDataPtr
ClonePtrType ClonePtr
StartBlobsPtrType StartBlobsPtr
WriteBufPtrType WriteBufPtr
StartBlobPtrType StartBlobPtr
WriteExtraTocPtrType WriteExtraTocPtr
ReadBytePtrType ReadBytePtr
WorkerJobRestorePtrType WorkerJobRestorePtr
PrintTocDataPtrType PrintTocDataPtr
WriteBytePtrType WriteBytePtr
ReadBufPtrType ReadBufPtr
PrintExtraTocPtrType PrintExtraTocPtr
EndBlobsPtrType EndBlobsPtr
StartDataPtrType StartDataPtr
ReopenPtrType ReopenPtr
EndDataPtrType EndDataPtr
ClosePtrType ClosePtr

References _ArchiveEntry(), _CloseArchive(), _EndBlob(), _EndBlobs(), _EndData(), _PrintExtraToc(), _PrintTocData(), _ReadBuf(), _ReadByte(), _ReadExtraToc(), _StartBlob(), _StartBlobs(), _StartData(), _WriteBuf(), _WriteByte(), _WriteData(), _WriteExtraToc(), archModeWrite, checkSeek(), fatal, lclContext::FH, lclContext::filePos, lclContext::hasSeek, lclContext::isSpecialScript, LOBBUFSIZE, PG_BINARY_R, PG_BINARY_W, pg_malloc(), pg_malloc0(), ReadHead(), ReadToc(), generate_unaccent_rules::stdout, tarClose(), lclContext::tarFH, lclContext::tarFHpos, and tarOpen().

Referenced by _allocAH().

◆ isValidTarHeader()

bool isValidTarHeader ( char *  header)

Definition at line 1042 of file pg_backup_tar.c.

1043 {
1044  int sum;
1045  int chk = tarChecksum(header);
1046 
1047  sum = read_tar_number(&header[148], 8);
1048 
1049  if (sum != chk)
1050  return false;
1051 
1052  /* POSIX tar format */
1053  if (memcmp(&header[257], "ustar\0", 6) == 0 &&
1054  memcmp(&header[263], "00", 2) == 0)
1055  return true;
1056  /* GNU tar format */
1057  if (memcmp(&header[257], "ustar \0", 8) == 0)
1058  return true;
1059  /* not-quite-POSIX format written by pre-9.3 pg_dump */
1060  if (memcmp(&header[257], "ustar00\0", 8) == 0)
1061  return true;
1062 
1063  return false;
1064 }

References header(), read_tar_number(), and tarChecksum().

Referenced by _discoverArchiveFormat().

◆ tarClose()

static void tarClose ( ArchiveHandle AH,
TAR_MEMBER TH 
)
static

Definition at line 435 of file pg_backup_tar.c.

436 {
437  /*
438  * Close the GZ file since we dup'd. This will flush the buffers.
439  */
440  if (AH->compression != 0)
441  {
442  errno = 0; /* in case gzclose() doesn't set it */
443  if (GZCLOSE(th->zFH) != 0)
444  fatal("could not close tar member: %m");
445  }
446 
447  if (th->mode == 'w')
448  _tarAddFile(AH, th); /* This will close the temp file */
449 
450  /*
451  * else Nothing to do for normal read since we don't dup() normal file
452  * handle, and we don't use temp files.
453  */
454 
455  if (th->targetFile)
456  free(th->targetFile);
457 
458  th->nFH = NULL;
459  th->zFH = NULL;
460 }
#define GZCLOSE(fh)
static int static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)

References _tarAddFile(), _archiveHandle::compression, fatal, free, GZCLOSE, TAR_MEMBER::mode, TAR_MEMBER::nFH, TAR_MEMBER::targetFile, and TAR_MEMBER::zFH.

Referenced by _CloseArchive(), _EndBlob(), _EndBlobs(), _EndData(), _LoadBlobs(), _PrintFileData(), and InitArchiveFmt_Tar().

◆ tarOpen()

static TAR_MEMBER * tarOpen ( ArchiveHandle AH,
const char *  filename,
char  mode 
)
static

Definition at line 318 of file pg_backup_tar.c.

319 {
320  lclContext *ctx = (lclContext *) AH->formatData;
321  TAR_MEMBER *tm;
322 
323 #ifdef HAVE_LIBZ
324  char fmode[14];
325 #endif
326 
327  if (mode == 'r')
328  {
329  tm = _tarPositionTo(AH, filename);
330  if (!tm) /* Not found */
331  {
332  if (filename)
333  {
334  /*
335  * Couldn't find the requested file. Future: do SEEK(0) and
336  * retry.
337  */
338  fatal("could not find file \"%s\" in archive", filename);
339  }
340  else
341  {
342  /* Any file OK, none left, so return NULL */
343  return NULL;
344  }
345  }
346 
347 #ifdef HAVE_LIBZ
348 
349  if (AH->compression == 0)
350  tm->nFH = ctx->tarFH;
351  else
352  fatal("compression is not supported by tar archive format");
353  /* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */
354 #else
355  tm->nFH = ctx->tarFH;
356 #endif
357  }
358  else
359  {
360  int old_umask;
361 
362  tm = pg_malloc0(sizeof(TAR_MEMBER));
363 
364  /*
365  * POSIX does not require, but permits, tmpfile() to restrict file
366  * permissions. Given an OS crash after we write data, the filesystem
367  * might retain the data but forget tmpfile()'s unlink(). If so, the
368  * file mode protects confidentiality of the data written.
369  */
370  old_umask = umask(S_IRWXG | S_IRWXO);
371 
372 #ifndef WIN32
373  tm->tmpFH = tmpfile();
374 #else
375 
376  /*
377  * On WIN32, tmpfile() generates a filename in the root directory,
378  * which requires administrative permissions on certain systems. Loop
379  * until we find a unique file name we can create.
380  */
381  while (1)
382  {
383  char *name;
384  int fd;
385 
386  name = _tempnam(NULL, "pg_temp_");
387  if (name == NULL)
388  break;
389  fd = open(name, O_RDWR | O_CREAT | O_EXCL | O_BINARY |
390  O_TEMPORARY, S_IRUSR | S_IWUSR);
391  free(name);
392 
393  if (fd != -1) /* created a file */
394  {
395  tm->tmpFH = fdopen(fd, "w+b");
396  break;
397  }
398  else if (errno != EEXIST) /* failure other than file exists */
399  break;
400  }
401 #endif
402 
403  if (tm->tmpFH == NULL)
404  fatal("could not generate temporary file name: %m");
405 
406  umask(old_umask);
407 
408 #ifdef HAVE_LIBZ
409 
410  if (AH->compression != 0)
411  {
412  sprintf(fmode, "wb%d", AH->compression);
413  tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
414  if (tm->zFH == NULL)
415  fatal("could not open temporary file");
416  }
417  else
418  tm->nFH = tm->tmpFH;
419 #else
420 
421  tm->nFH = tm->tmpFH;
422 #endif
423 
424  tm->AH = AH;
425  tm->targetFile = pg_strdup(filename);
426  }
427 
428  tm->mode = mode;
429  tm->tarFH = ctx->tarFH;
430 
431  return tm;
432 }
const char * name
Definition: encode.c:561
static struct pg_tm tm
Definition: localtime.c:102
static TAR_MEMBER * _tarPositionTo(ArchiveHandle *AH, const char *filename)
static PgChecksumMode mode
Definition: pg_checksums.c:65
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define S_IRWXG
Definition: win32_port.h:309
#define S_IRWXO
Definition: win32_port.h:321
#define S_IRUSR
Definition: win32_port.h:288
#define S_IWUSR
Definition: win32_port.h:291

References _tarPositionTo(), _archiveHandle::compression, fatal, fd(), filename, _archiveHandle::formatData, free, if(), mode, name, pg_malloc0(), pg_strdup(), S_IRUSR, S_IRWXG, S_IRWXO, S_IWUSR, sprintf, lclContext::tarFH, and tm.

Referenced by _CloseArchive(), _LoadBlobs(), _PrintFileData(), _StartBlob(), _StartBlobs(), _StartData(), and InitArchiveFmt_Tar().

◆ tarPrintf()

static int tarPrintf ( TAR_MEMBER th,
const char *  fmt,
  ... 
)
static

Definition at line 1008 of file pg_backup_tar.c.

1009 {
1010  int save_errno = errno;
1011  char *p;
1012  size_t len = 128; /* initial assumption about buffer size */
1013  size_t cnt;
1014 
1015  for (;;)
1016  {
1017  va_list args;
1018 
1019  /* Allocate work buffer. */
1020  p = (char *) pg_malloc(len);
1021 
1022  /* Try to format the data. */
1023  errno = save_errno;
1024  va_start(args, fmt);
1025  cnt = pvsnprintf(p, len, fmt, args);
1026  va_end(args);
1027 
1028  if (cnt < len)
1029  break; /* success */
1030 
1031  /* Release buffer and loop around to try again with larger len. */
1032  free(p);
1033  len = cnt;
1034  }
1035 
1036  cnt = tarWrite(p, cnt, th);
1037  free(p);
1038  return (int) cnt;
1039 }
va_end(args)
static void const char * fmt
va_start(args, fmt)
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition: psprintf.c:106

References generate_unaccent_rules::args, fmt, free, len, pg_malloc(), pvsnprintf(), tarWrite(), va_end(), and va_start().

Referenced by _CloseArchive(), and _StartBlob().

◆ tarRead()

static size_t tarRead ( void *  buf,
size_t  len,
TAR_MEMBER th 
)
static

Definition at line 577 of file pg_backup_tar.c.

578 {
579  size_t res;
580 
581  if (th->pos + len > th->fileLen)
582  len = th->fileLen - th->pos;
583 
584  if (len <= 0)
585  return 0;
586 
587  res = _tarReadRaw(th->AH, buf, len, th, NULL);
588 
589  th->pos += res;
590 
591  return res;
592 }
pgoff_t pos
Definition: pg_backup_tar.c:78
ArchiveHandle * AH
Definition: pg_backup_tar.c:80

References _tarReadRaw(), TAR_MEMBER::AH, buf, TAR_MEMBER::fileLen, len, TAR_MEMBER::pos, and res.

Referenced by _LoadBlobs(), _PrintFileData(), _ReadBuf(), and _ReadByte().

◆ tarWrite()

static size_t tarWrite ( const void *  buf,
size_t  len,
TAR_MEMBER th 
)
static

Definition at line 595 of file pg_backup_tar.c.

596 {
597  size_t res;
598 
599  if (th->zFH != NULL)
600  res = GZWRITE(buf, 1, len, th->zFH);
601  else
602  res = fwrite(buf, 1, len, th->nFH);
603 
604  th->pos += res;
605  return res;
606 }
#define GZWRITE(p, s, n, fh)

References buf, GZWRITE, len, TAR_MEMBER::nFH, TAR_MEMBER::pos, res, and TAR_MEMBER::zFH.

Referenced by _scriptOut(), _WriteBuf(), _WriteByte(), _WriteData(), and tarPrintf().