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 *AH)
 
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 _StartLOs (ArchiveHandle *AH, TocEntry *te)
 
static void _StartLO (ArchiveHandle *AH, TocEntry *te, Oid oid)
 
static void _EndLO (ArchiveHandle *AH, TocEntry *te, Oid oid)
 
static void _EndLOs (ArchiveHandle *AH, TocEntry *te)
 
static void _LoadLOs (ArchiveHandle *AH, TocEntry *te)
 
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 234 of file pg_backup_tar.c.

235 {
236  lclTocEntry *ctx;
237  char fn[K_STD_BUF_SIZE];
238 
240  if (te->dataDumper != NULL)
241  {
242  snprintf(fn, sizeof(fn), "%d.dat", te->dumpId);
243  ctx->filename = pg_strdup(fn);
244  }
245  else
246  {
247  ctx->filename = NULL;
248  ctx->TH = NULL;
249  }
250  te->formatData = (void *) ctx;
251 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define pg_malloc0_object(type)
Definition: fe_memutils.h:39
#define K_STD_BUF_SIZE
Definition: pg_backup_tar.c:63
#define snprintf
Definition: port.h:238
DataDumperPtr dataDumper
TAR_MEMBER * TH
Definition: pg_backup_tar.c:93
static void * fn(void *arg)
Definition: thread-alloc.c:119

References _tocEntry::dataDumper, _tocEntry::dumpId, lclTocEntry::filename, fn(), _tocEntry::formatData, K_STD_BUF_SIZE, pg_malloc0_object, pg_strdup(), snprintf, and lclTocEntry::TH.

Referenced by InitArchiveFmt_Tar().

◆ _CloseArchive()

static void _CloseArchive ( ArchiveHandle AH)
static

Definition at line 769 of file pg_backup_tar.c.

770 {
771  lclContext *ctx = (lclContext *) AH->formatData;
772  TAR_MEMBER *th;
773  RestoreOptions *ropt;
774  RestoreOptions *savRopt;
775  DumpOptions *savDopt;
776  int savVerbose,
777  i;
778 
779  if (AH->mode == archModeWrite)
780  {
781  /*
782  * Write the Header & TOC to the archive FIRST
783  */
784  th = tarOpen(AH, "toc.dat", 'w');
785  ctx->FH = th;
786  WriteHead(AH);
787  WriteToc(AH);
788  tarClose(AH, th); /* Not needed any more */
789 
790  /*
791  * Now send the data (tables & LOs)
792  */
793  WriteDataChunks(AH, NULL);
794 
795  /*
796  * Now this format wants to append a script which does a full restore
797  * if the files have been extracted.
798  */
799  th = tarOpen(AH, "restore.sql", 'w');
800 
801  tarPrintf(th, "--\n"
802  "-- NOTE:\n"
803  "--\n"
804  "-- File paths need to be edited. Search for $$PATH$$ and\n"
805  "-- replace it with the path to the directory containing\n"
806  "-- the extracted data files.\n"
807  "--\n");
808 
809  AH->CustomOutPtr = _scriptOut;
810 
811  ctx->isSpecialScript = 1;
812  ctx->scriptTH = th;
813 
814  ropt = NewRestoreOptions();
815  memcpy(ropt, AH->public.ropt, sizeof(RestoreOptions));
816  ropt->filename = NULL;
817  ropt->dropSchema = 1;
818  ropt->superuser = NULL;
819  ropt->suppressDumpWarnings = true;
820 
821  savDopt = AH->public.dopt;
822  savRopt = AH->public.ropt;
823 
824  SetArchiveOptions((Archive *) AH, NULL, ropt);
825 
826  savVerbose = AH->public.verbose;
827  AH->public.verbose = 0;
828 
829  RestoreArchive((Archive *) AH);
830 
831  SetArchiveOptions((Archive *) AH, savDopt, savRopt);
832 
833  AH->public.verbose = savVerbose;
834 
835  tarClose(AH, th);
836 
837  ctx->isSpecialScript = 0;
838 
839  /*
840  * EOF marker for tar files is two blocks of NULLs.
841  */
842  for (i = 0; i < TAR_BLOCK_SIZE * 2; i++)
843  {
844  if (fputc(0, ctx->tarFH) == EOF)
846  }
847 
848  /* Sync the output file if one is defined */
849  if (AH->dosync && AH->fSpec)
850  (void) fsync_fname(AH->fSpec, false);
851  }
852 
853  AH->FH = NULL;
854 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:756
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
RestoreOptions * NewRestoreOptions(void)
@ archModeWrite
Definition: pg_backup.h:51
void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
void RestoreArchive(Archive *AHX)
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:214
int verbose
Definition: pg_backup.h:217
RestoreOptions * ropt
Definition: pg_backup.h:215
CustomOutPtrType CustomOutPtr
FILE * tarFH
Definition: pg_backup_tar.c:83
TAR_MEMBER * FH
Definition: pg_backup_tar.c:86
TAR_MEMBER * scriptTH
Definition: pg_backup_tar.c:88
int isSpecialScript
Definition: pg_backup_tar.c:87

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().

◆ _EndData()

static void _EndData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 549 of file pg_backup_tar.c.

550 {
551  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
552 
553  /* Close the file */
554  tarClose(AH, tctx->TH);
555  tctx->TH = NULL;
556 }

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

Referenced by InitArchiveFmt_Tar().

◆ _EndLO()

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

Definition at line 922 of file pg_backup_tar.c.

923 {
924  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
925 
926  tarClose(AH, tctx->TH);
927 }

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

Referenced by InitArchiveFmt_Tar().

◆ _EndLOs()

static void _EndLOs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 936 of file pg_backup_tar.c.

937 {
938  lclContext *ctx = (lclContext *) AH->formatData;
939 
940  /* Write out a fake zero OID to mark end-of-LOs. */
941  /* WriteInt(AH, 0); */
942 
943  tarClose(AH, ctx->loToc);
944 }
TAR_MEMBER * loToc
Definition: pg_backup_tar.c:82

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

Referenced by InitArchiveFmt_Tar().

◆ _LoadLOs()

static void _LoadLOs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 643 of file pg_backup_tar.c.

644 {
645  Oid oid;
646  lclContext *ctx = (lclContext *) AH->formatData;
647  TAR_MEMBER *th;
648  size_t cnt;
649  bool foundLO = false;
650  char buf[4096];
651 
652  StartRestoreLOs(AH);
653 
654  /*
655  * The blobs_NNN.toc or blobs.toc file is fairly useless to us because it
656  * will appear only after the associated blob_NNN.dat files. For archive
657  * versions >= 16 we can look at the BLOBS entry's te->tag to discover the
658  * OID of the first blob we want to restore, and then search forward to
659  * find the appropriate blob_<oid>.dat file. For older versions we rely
660  * on the knowledge that there was only one BLOBS entry and just search
661  * for the first blob_<oid>.dat file. Once we find the first blob file to
662  * restore, restore all blobs until we reach the blobs[_NNN].toc file.
663  */
664  if (AH->version >= K_VERS_1_16)
665  {
666  /* We rely on atooid to not complain about nnnn..nnnn tags */
667  oid = atooid(te->tag);
668  snprintf(buf, sizeof(buf), "blob_%u.dat", oid);
669  th = tarOpen(AH, buf, 'r'); /* Advance to first desired file */
670  }
671  else
672  th = tarOpen(AH, NULL, 'r'); /* Open next file */
673 
674  while (th != NULL)
675  {
676  ctx->FH = th;
677 
678  if (strncmp(th->targetFile, "blob_", 5) == 0)
679  {
680  oid = atooid(&th->targetFile[5]);
681  if (oid != 0)
682  {
683  pg_log_info("restoring large object with OID %u", oid);
684 
685  StartRestoreLO(AH, oid, AH->public.ropt->dropSchema);
686 
687  while ((cnt = tarRead(buf, 4095, th)) > 0)
688  {
689  buf[cnt] = '\0';
690  ahwrite(buf, 1, cnt, AH);
691  }
692  EndRestoreLO(AH, oid);
693  foundLO = true;
694  }
695  tarClose(AH, th);
696  }
697  else
698  {
699  tarClose(AH, th);
700 
701  /*
702  * Once we have found the first LO, stop at the first non-LO entry
703  * (which will be 'blobs[_NNN].toc'). This coding would eat all
704  * the rest of the archive if there are no LOs ... but this
705  * function shouldn't be called at all in that case.
706  */
707  if (foundLO)
708  break;
709  }
710 
711  th = tarOpen(AH, NULL, 'r');
712  }
713  EndRestoreLOs(AH);
714 }
#define pg_log_info(...)
Definition: logging.h:124
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
void StartRestoreLOs(ArchiveHandle *AH)
void EndRestoreLO(ArchiveHandle *AH, Oid oid)
void EndRestoreLOs(ArchiveHandle *AH)
void StartRestoreLO(ArchiveHandle *AH, Oid oid, bool drop)
#define K_VERS_1_16
static size_t tarRead(void *buf, size_t len, TAR_MEMBER *th)
static char * buf
Definition: pg_test_fsync.c:73
unsigned int Oid
Definition: postgres_ext.h:31
#define atooid(x)
Definition: postgres_ext.h:42

References ahwrite(), atooid, buf, _restoreOptions::dropSchema, EndRestoreLO(), EndRestoreLOs(), lclContext::FH, _archiveHandle::formatData, K_VERS_1_16, pg_log_info, _archiveHandle::public, Archive::ropt, snprintf, StartRestoreLO(), StartRestoreLOs(), _tocEntry::tag, tarClose(), TAR_MEMBER::targetFile, tarOpen(), tarRead(), and _archiveHandle::version.

Referenced by _PrintTocData().

◆ _PrintExtraToc()

static void _PrintExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 285 of file pg_backup_tar.c.

286 {
287  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
288 
289  if (AH->public.verbose && ctx->filename != NULL)
290  ahprintf(AH, "-- File: %s\n", ctx->filename);
291 }
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 562 of file pg_backup_tar.c.

563 {
564  lclContext *ctx = (lclContext *) AH->formatData;
565  char buf[4096];
566  size_t cnt;
567  TAR_MEMBER *th;
568 
569  if (!filename)
570  return;
571 
572  th = tarOpen(AH, filename, 'r');
573  ctx->FH = th;
574 
575  while ((cnt = tarRead(buf, 4095, th)) > 0)
576  {
577  buf[cnt] = '\0';
578  ahwrite(buf, 1, cnt, AH);
579  }
580 
581  tarClose(AH, th);
582 }
static char * filename
Definition: pg_dumpall.c:119

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 589 of file pg_backup_tar.c.

590 {
591  lclContext *ctx = (lclContext *) AH->formatData;
592  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
593  int pos1;
594 
595  if (!tctx->filename)
596  return;
597 
598  /*
599  * If we're writing the special restore.sql script, emit a suitable
600  * command to include each table's data from the corresponding file.
601  *
602  * In the COPY case this is a bit klugy because the regular COPY command
603  * was already printed before we get control.
604  */
605  if (ctx->isSpecialScript)
606  {
607  if (te->copyStmt)
608  {
609  /* Abort the COPY FROM stdin */
610  ahprintf(AH, "\\.\n");
611 
612  /*
613  * The COPY statement should look like "COPY ... FROM stdin;\n",
614  * see dumpTableData().
615  */
616  pos1 = (int) strlen(te->copyStmt) - 13;
617  if (pos1 < 6 || strncmp(te->copyStmt, "COPY ", 5) != 0 ||
618  strcmp(te->copyStmt + pos1, " FROM stdin;\n") != 0)
619  pg_fatal("unexpected COPY statement syntax: \"%s\"",
620  te->copyStmt);
621 
622  /* Emit all but the FROM part ... */
623  ahwrite(te->copyStmt, 1, pos1, AH);
624  /* ... and insert modified FROM */
625  ahprintf(AH, " FROM '$$PATH$$/%s';\n\n", tctx->filename);
626  }
627  else
628  {
629  /* --inserts mode, no worries, just include the data file */
630  ahprintf(AH, "\\i $$PATH$$/%s\n\n", tctx->filename);
631  }
632 
633  return;
634  }
635 
636  if (strcmp(te->desc, "BLOBS") == 0)
637  _LoadLOs(AH, te);
638  else
639  _PrintFileData(AH, tctx->filename);
640 }
static void _PrintFileData(ArchiveHandle *AH, char *filename)
static void _LoadLOs(ArchiveHandle *AH, TocEntry *te)
#define pg_fatal(...)

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

Referenced by InitArchiveFmt_Tar().

◆ _ReadBuf()

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

Definition at line 757 of file pg_backup_tar.c.

758 {
759  lclContext *ctx = (lclContext *) AH->formatData;
760 
761  if (tarRead(buf, len, ctx->FH) != len)
762  /* We already would have exited for errors on reads, must be EOF */
763  pg_fatal("could not read from input file: end of file");
764 
765  ctx->filePos += len;
766 }
const void size_t len
pgoff_t filePos
Definition: pg_backup_tar.c:81

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

Referenced by InitArchiveFmt_Tar().

◆ _ReadByte()

static int _ReadByte ( ArchiveHandle AH)
static

Definition at line 731 of file pg_backup_tar.c.

732 {
733  lclContext *ctx = (lclContext *) AH->formatData;
734  size_t res;
735  unsigned char c;
736 
737  res = tarRead(&c, 1, ctx->FH);
738  if (res != 1)
739  /* We already would have exited for errors on reads, must be EOF */
740  pg_fatal("could not read from input file: end of file");
741  ctx->filePos += 1;
742  return c;
743 }
char * c

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

Referenced by InitArchiveFmt_Tar().

◆ _ReadExtraToc()

static void _ReadExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 265 of file pg_backup_tar.c.

266 {
267  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
268 
269  if (ctx == NULL)
270  {
272  te->formatData = (void *) ctx;
273  }
274 
275  ctx->filename = ReadStr(AH);
276  if (strlen(ctx->filename) == 0)
277  {
278  free(ctx->filename);
279  ctx->filename = NULL;
280  }
281  ctx->TH = NULL;
282 }
#define free(a)
Definition: header.h:65
char * ReadStr(ArchiveHandle *AH)

References lclTocEntry::filename, _tocEntry::formatData, free, if(), pg_malloc0_object, 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 857 of file pg_backup_tar.c.

858 {
859  lclContext *ctx = (lclContext *) AH->formatData;
860 
861  return tarWrite(buf, len, ctx->scriptTH);
862 }
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().

◆ _StartData()

static void _StartData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 294 of file pg_backup_tar.c.

295 {
296  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
297 
298  tctx->TH = tarOpen(AH, tctx->filename, 'w');
299 }

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

Referenced by InitArchiveFmt_Tar().

◆ _StartLO()

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

Definition at line 896 of file pg_backup_tar.c.

897 {
898  lclContext *ctx = (lclContext *) AH->formatData;
899  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
900  char fname[255];
901 
902  if (oid == 0)
903  pg_fatal("invalid OID for large object (%u)", oid);
904 
906  pg_fatal("compression is not supported by tar archive format");
907 
908  sprintf(fname, "blob_%u.dat", oid);
909 
910  tarPrintf(ctx->loToc, "%u %s\n", oid, fname);
911 
912  tctx->TH = tarOpen(AH, fname, 'w');
913 }
@ PG_COMPRESSION_NONE
Definition: compression.h:23
#define sprintf
Definition: port.h:240
pg_compress_specification compression_spec
pg_compress_algorithm algorithm
Definition: compression.h:34

References pg_compress_specification::algorithm, _archiveHandle::compression_spec, _archiveHandle::formatData, _tocEntry::formatData, lclContext::loToc, PG_COMPRESSION_NONE, pg_fatal, sprintf, tarOpen(), and tarPrintf().

Referenced by InitArchiveFmt_Tar().

◆ _StartLOs()

static void _StartLOs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 879 of file pg_backup_tar.c.

880 {
881  lclContext *ctx = (lclContext *) AH->formatData;
882  char fname[K_STD_BUF_SIZE];
883 
884  sprintf(fname, "blobs_%d.toc", te->dumpId);
885  ctx->loToc = tarOpen(AH, fname, 'w');
886 }

References _tocEntry::dumpId, _archiveHandle::formatData, K_STD_BUF_SIZE, lclContext::loToc, sprintf, and tarOpen().

Referenced by InitArchiveFmt_Tar().

◆ _tarAddFile()

static void _tarAddFile ( ArchiveHandle AH,
TAR_MEMBER th 
)
static

Definition at line 1014 of file pg_backup_tar.c.

1015 {
1016  lclContext *ctx = (lclContext *) AH->formatData;
1017  FILE *tmp = th->tmpFH; /* Grab it for convenience */
1018  char buf[32768];
1019  size_t cnt;
1020  pgoff_t len = 0;
1021  size_t res;
1022  size_t i,
1023  pad;
1024 
1025  /*
1026  * Find file len & go back to start.
1027  */
1028  if (fseeko(tmp, 0, SEEK_END) != 0)
1029  pg_fatal("error during file seek: %m");
1030  th->fileLen = ftello(tmp);
1031  if (th->fileLen < 0)
1032  pg_fatal("could not determine seek position in archive file: %m");
1033  if (fseeko(tmp, 0, SEEK_SET) != 0)
1034  pg_fatal("error during file seek: %m");
1035 
1036  _tarWriteHeader(th);
1037 
1038  while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0)
1039  {
1040  if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt)
1042  len += res;
1043  }
1044  if (!feof(tmp))
1045  READ_ERROR_EXIT(tmp);
1046 
1047  if (fclose(tmp) != 0) /* This *should* delete it... */
1048  pg_fatal("could not close temporary file: %m");
1049 
1050  if (len != th->fileLen)
1051  pg_fatal("actual file length (%lld) does not match expected (%lld)",
1052  (long long) len, (long long) th->fileLen);
1053 
1055  for (i = 0; i < pad; i++)
1056  {
1057  if (fputc('\0', th->tarFH) == EOF)
1059  }
1060 
1061  ctx->tarFHpos += len + pad;
1062 }
#define READ_ERROR_EXIT(fd)
static void _tarWriteHeader(TAR_MEMBER *th)
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:79
pgoff_t fileLen
Definition: pg_backup_tar.c:74
FILE * tarFH
Definition: pg_backup_tar.c:69
FILE * tmpFH
Definition: pg_backup_tar.c:70
pgoff_t tarFHpos
Definition: pg_backup_tar.c:84
#define ftello(stream)
Definition: win32_port.h:219
#define fseeko(stream, offset, origin)
Definition: win32_port.h:216
#define pgoff_t
Definition: win32_port.h:207

References _tarWriteHeader(), buf, TAR_MEMBER::fileLen, _archiveHandle::formatData, fseeko, ftello, i, if(), len, pg_fatal, pgoff_t, READ_ERROR_EXIT, res, 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 1140 of file pg_backup_tar.c.

1141 {
1142  lclContext *ctx = (lclContext *) AH->formatData;
1143  char h[TAR_BLOCK_SIZE];
1144  char tag[100 + 1];
1145  int sum,
1146  chk;
1147  pgoff_t len;
1148  pgoff_t hPos;
1149  bool gotBlock = false;
1150 
1151  while (!gotBlock)
1152  {
1153  /* Save the pos for reporting purposes */
1154  hPos = ctx->tarFHpos;
1155 
1156  /* Read the next tar block, return EOF, exit if short */
1157  len = _tarReadRaw(AH, h, TAR_BLOCK_SIZE, NULL, ctx->tarFH);
1158  if (len == 0) /* EOF */
1159  return 0;
1160 
1161  if (len != TAR_BLOCK_SIZE)
1162  pg_fatal(ngettext("incomplete tar header found (%lu byte)",
1163  "incomplete tar header found (%lu bytes)",
1164  len),
1165  (unsigned long) len);
1166 
1167  /* Calc checksum */
1168  chk = tarChecksum(h);
1169  sum = read_tar_number(&h[TAR_OFFSET_CHECKSUM], 8);
1170 
1171  /*
1172  * If the checksum failed, see if it is a null block. If so, silently
1173  * continue to the next block.
1174  */
1175  if (chk == sum)
1176  gotBlock = true;
1177  else
1178  {
1179  int i;
1180 
1181  for (i = 0; i < TAR_BLOCK_SIZE; i++)
1182  {
1183  if (h[i] != 0)
1184  {
1185  gotBlock = true;
1186  break;
1187  }
1188  }
1189  }
1190  }
1191 
1192  /* Name field is 100 bytes, might not be null-terminated */
1193  strlcpy(tag, &h[TAR_OFFSET_NAME], 100 + 1);
1194 
1195  len = read_tar_number(&h[TAR_OFFSET_SIZE], 12);
1196 
1197  pg_log_debug("TOC Entry %s at %llu (length %llu, checksum %d)",
1198  tag, (unsigned long long) hPos, (unsigned long long) len, sum);
1199 
1200  if (chk != sum)
1201  pg_fatal("corrupt tar header found in %s (expected %d, computed %d) file position %llu",
1202  tag, sum, chk, (unsigned long long) ftello(ctx->tarFH));
1203 
1204  th->targetFile = pg_strdup(tag);
1205  th->fileLen = len;
1206 
1207  return 1;
1208 }
#define ngettext(s, p, n)
Definition: c.h:1181
#define pg_log_debug(...)
Definition: logging.h:133
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
@ TAR_OFFSET_NAME
Definition: pgtar.h:39
@ TAR_OFFSET_SIZE
Definition: pgtar.h:43
@ TAR_OFFSET_CHECKSUM
Definition: pgtar.h:45
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * targetFile
Definition: pg_backup_tar.c:71

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

Referenced by _tarPositionTo().

◆ _tarPositionTo()

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

Definition at line 1066 of file pg_backup_tar.c.

1067 {
1068  lclContext *ctx = (lclContext *) AH->formatData;
1070  char c;
1071  char header[TAR_BLOCK_SIZE];
1072  size_t i,
1073  len,
1074  blks;
1075  int id;
1076 
1077  th->AH = AH;
1078 
1079  /* Go to end of current file, if any */
1080  if (ctx->tarFHpos != 0)
1081  {
1082  pg_log_debug("moving from position %lld to next member at file position %lld",
1083  (long long) ctx->tarFHpos, (long long) ctx->tarNextMember);
1084 
1085  while (ctx->tarFHpos < ctx->tarNextMember)
1086  _tarReadRaw(AH, &c, 1, NULL, ctx->tarFH);
1087  }
1088 
1089  pg_log_debug("now at file position %lld", (long long) ctx->tarFHpos);
1090 
1091  /* We are at the start of the file, or at the next member */
1092 
1093  /* Get the header */
1094  if (!_tarGetHeader(AH, th))
1095  {
1096  if (filename)
1097  pg_fatal("could not find header for file \"%s\" in tar archive", filename);
1098  else
1099  {
1100  /*
1101  * We're just scanning the archive for the next file, so return
1102  * null
1103  */
1104  free(th);
1105  return NULL;
1106  }
1107  }
1108 
1109  while (filename != NULL && strcmp(th->targetFile, filename) != 0)
1110  {
1111  pg_log_debug("skipping tar member %s", th->targetFile);
1112 
1113  id = atoi(th->targetFile);
1114  if ((TocIDRequired(AH, id) & REQ_DATA) != 0)
1115  pg_fatal("restoring data out of order is not supported in this archive format: "
1116  "\"%s\" is required, but comes before \"%s\" in the archive file.",
1117  th->targetFile, filename);
1118 
1119  /* Header doesn't match, so read to next header */
1120  len = th->fileLen;
1121  len += tarPaddingBytesRequired(th->fileLen);
1122  blks = len / TAR_BLOCK_SIZE; /* # of tar blocks */
1123 
1124  for (i = 0; i < blks; i++)
1125  _tarReadRaw(AH, &header[0], TAR_BLOCK_SIZE, NULL, ctx->tarFH);
1126 
1127  if (!_tarGetHeader(AH, th))
1128  pg_fatal("could not find header for file \"%s\" in tar archive", filename);
1129  }
1130 
1131  ctx->tarNextMember = ctx->tarFHpos + th->fileLen
1132  + tarPaddingBytesRequired(th->fileLen);
1133  th->pos = 0;
1134 
1135  return th;
1136 }
int TocIDRequired(ArchiveHandle *AH, DumpId id)
#define REQ_DATA
static int _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
pgoff_t tarNextMember
Definition: pg_backup_tar.c:85

References _tarGetHeader(), _tarReadRaw(), TAR_MEMBER::AH, TAR_MEMBER::fileLen, filename, _archiveHandle::formatData, free, i, len, pg_fatal, pg_log_debug, pg_malloc0_object, TAR_MEMBER::pos, REQ_DATA, 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 462 of file pg_backup_tar.c.

463 {
464  lclContext *ctx = (lclContext *) AH->formatData;
465  size_t avail;
466  size_t used = 0;
467  size_t res = 0;
468 
469  Assert(th || fh);
470 
471  avail = AH->lookaheadLen - AH->lookaheadPos;
472  if (avail > 0)
473  {
474  /* We have some lookahead bytes to use */
475  if (avail >= len) /* Just use the lookahead buffer */
476  used = len;
477  else
478  used = avail;
479 
480  /* Copy, and adjust buffer pos */
481  memcpy(buf, AH->lookahead + AH->lookaheadPos, used);
482  AH->lookaheadPos += used;
483 
484  /* Adjust required length */
485  len -= used;
486  }
487 
488  /* Read the file if len > 0 */
489  if (len > 0)
490  {
491  if (fh)
492  {
493  res = fread(&((char *) buf)[used], 1, len, fh);
494  if (res != len && !feof(fh))
495  READ_ERROR_EXIT(fh);
496  }
497  else if (th)
498  {
499  res = fread(&((char *) buf)[used], 1, len, th->nFH);
500  if (res != len && !feof(th->nFH))
501  READ_ERROR_EXIT(th->nFH);
502  }
503  }
504 
505  ctx->tarFHpos += res + used;
506 
507  return (res + used);
508 }
#define Assert(condition)
Definition: c.h:858
FILE * nFH
Definition: pg_backup_tar.c:68

References Assert, buf, _archiveHandle::formatData, len, _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, TAR_MEMBER::nFH, READ_ERROR_EXIT, res, and lclContext::tarFHpos.

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

◆ _tarWriteHeader()

static void _tarWriteHeader ( TAR_MEMBER th)
static

Definition at line 1212 of file pg_backup_tar.c.

1213 {
1214  char h[TAR_BLOCK_SIZE];
1215 
1216  tarCreateHeader(h, th->targetFile, NULL, th->fileLen,
1217  0600, 04000, 02000, time(NULL));
1218 
1219  /* Now write the completed header. */
1220  if (fwrite(h, 1, TAR_BLOCK_SIZE, th->tarFH) != TAR_BLOCK_SIZE)
1222 }
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 746 of file pg_backup_tar.c.

747 {
748  lclContext *ctx = (lclContext *) AH->formatData;
749 
750  if (tarWrite(buf, len, ctx->FH) != len)
752 
753  ctx->filePos += len;
754 }

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 718 of file pg_backup_tar.c.

719 {
720  lclContext *ctx = (lclContext *) AH->formatData;
721  char b = i; /* Avoid endian problems */
722 
723  if (tarWrite(&b, 1, ctx->FH) != 1)
725 
726  ctx->filePos += 1;
727  return 1;
728 }
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 540 of file pg_backup_tar.c.

541 {
542  lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData;
543 
544  if (tarWrite(data, dLen, tctx->TH) != dLen)
546 }
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 254 of file pg_backup_tar.c.

255 {
256  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
257 
258  if (ctx->filename)
259  WriteStr(AH, ctx->filename);
260  else
261  WriteStr(AH, "");
262 }
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 121 of file pg_backup_tar.c.

122 {
123  lclContext *ctx;
124 
125  /* Assuming static functions, this can be copied for each format. */
127  AH->StartDataPtr = _StartData;
128  AH->WriteDataPtr = _WriteData;
129  AH->EndDataPtr = _EndData;
130  AH->WriteBytePtr = _WriteByte;
131  AH->ReadBytePtr = _ReadByte;
132  AH->WriteBufPtr = _WriteBuf;
133  AH->ReadBufPtr = _ReadBuf;
134  AH->ClosePtr = _CloseArchive;
135  AH->ReopenPtr = NULL;
140 
141  AH->StartLOsPtr = _StartLOs;
142  AH->StartLOPtr = _StartLO;
143  AH->EndLOPtr = _EndLO;
144  AH->EndLOsPtr = _EndLOs;
145  AH->ClonePtr = NULL;
146  AH->DeClonePtr = NULL;
147 
148  AH->WorkerJobDumpPtr = NULL;
149  AH->WorkerJobRestorePtr = NULL;
150 
151  /*
152  * Set up some special context used in compressing data.
153  */
155  AH->formatData = (void *) ctx;
156  ctx->filePos = 0;
157  ctx->isSpecialScript = 0;
158 
159  /*
160  * Now open the tar file, and load the TOC if we're in read mode.
161  */
162  if (AH->mode == archModeWrite)
163  {
164  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
165  {
166  ctx->tarFH = fopen(AH->fSpec, PG_BINARY_W);
167  if (ctx->tarFH == NULL)
168  pg_fatal("could not open TOC file \"%s\" for output: %m",
169  AH->fSpec);
170  }
171  else
172  {
173  ctx->tarFH = stdout;
174  if (ctx->tarFH == NULL)
175  pg_fatal("could not open TOC file for output: %m");
176  }
177 
178  ctx->tarFHpos = 0;
179 
180  /*
181  * Make unbuffered since we will dup() it, and the buffers screw each
182  * other
183  */
184  /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
185 
186  ctx->hasSeek = checkSeek(ctx->tarFH);
187 
188  /*
189  * We don't support compression because reading the files back is not
190  * possible since gzdopen uses buffered IO which totally screws file
191  * positioning.
192  */
194  pg_fatal("compression is not supported by tar archive format");
195  }
196  else
197  { /* Read Mode */
198  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
199  {
200  ctx->tarFH = fopen(AH->fSpec, PG_BINARY_R);
201  if (ctx->tarFH == NULL)
202  pg_fatal("could not open TOC file \"%s\" for input: %m",
203  AH->fSpec);
204  }
205  else
206  {
207  ctx->tarFH = stdin;
208  if (ctx->tarFH == NULL)
209  pg_fatal("could not open TOC file for input: %m");
210  }
211 
212  /*
213  * Make unbuffered since we will dup() it, and the buffers screw each
214  * other
215  */
216  /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
217 
218  ctx->tarFHpos = 0;
219 
220  ctx->hasSeek = checkSeek(ctx->tarFH);
221 
222  ctx->FH = (void *) tarOpen(AH, "toc.dat", 'r');
223  ReadHead(AH);
224  ReadToc(AH);
225  tarClose(AH, ctx->FH); /* Nothing else in the file... */
226  }
227 }
#define PG_BINARY_R
Definition: c.h:1275
#define PG_BINARY_W
Definition: c.h:1276
bool checkSeek(FILE *fp)
void ReadHead(ArchiveHandle *AH)
void ReadToc(ArchiveHandle *AH)
static void _PrintTocData(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 _StartLOs(ArchiveHandle *AH, TocEntry *te)
static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _EndLO(ArchiveHandle *AH, TocEntry *te, Oid oid)
static void _EndLOs(ArchiveHandle *AH, TocEntry *te)
static int _WriteByte(ArchiveHandle *AH, const int i)
static void _StartLO(ArchiveHandle *AH, TocEntry *te, Oid oid)
static int _ReadByte(ArchiveHandle *AH)
static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
static void _EndData(ArchiveHandle *AH, TocEntry *te)
static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
DeClonePtrType DeClonePtr
EndLOsPtrType EndLOsPtr
ReadExtraTocPtrType ReadExtraTocPtr
WorkerJobDumpPtrType WorkerJobDumpPtr
StartLOsPtrType StartLOsPtr
ArchiveEntryPtrType ArchiveEntryPtr
WriteDataPtrType WriteDataPtr
StartLOPtrType StartLOPtr
ClonePtrType ClonePtr
WriteBufPtrType WriteBufPtr
EndLOPtrType EndLOPtr
WriteExtraTocPtrType WriteExtraTocPtr
ReadBytePtrType ReadBytePtr
WorkerJobRestorePtrType WorkerJobRestorePtr
PrintTocDataPtrType PrintTocDataPtr
WriteBytePtrType WriteBytePtr
ReadBufPtrType ReadBufPtr
PrintExtraTocPtrType PrintExtraTocPtr
StartDataPtrType StartDataPtr
ReopenPtrType ReopenPtr
EndDataPtrType EndDataPtr
ClosePtrType ClosePtr

References _ArchiveEntry(), _CloseArchive(), _EndData(), _EndLO(), _EndLOs(), _PrintExtraToc(), _PrintTocData(), _ReadBuf(), _ReadByte(), _ReadExtraToc(), _StartData(), _StartLO(), _StartLOs(), _WriteBuf(), _WriteByte(), _WriteData(), _WriteExtraToc(), archModeWrite, checkSeek(), lclContext::FH, lclContext::filePos, lclContext::hasSeek, lclContext::isSpecialScript, PG_BINARY_R, PG_BINARY_W, PG_COMPRESSION_NONE, pg_fatal, pg_malloc0_object, ReadHead(), ReadToc(), generate_unaccent_rules::stdout, tarClose(), lclContext::tarFH, lclContext::tarFHpos, and tarOpen().

Referenced by _allocAH().

◆ isValidTarHeader()

bool isValidTarHeader ( char *  header)

Definition at line 988 of file pg_backup_tar.c.

989 {
990  int sum;
991  int chk = tarChecksum(header);
992 
993  sum = read_tar_number(&header[TAR_OFFSET_CHECKSUM], 8);
994 
995  if (sum != chk)
996  return false;
997 
998  /* POSIX tar format */
999  if (memcmp(&header[TAR_OFFSET_MAGIC], "ustar\0", 6) == 0 &&
1000  memcmp(&header[TAR_OFFSET_VERSION], "00", 2) == 0)
1001  return true;
1002  /* GNU tar format */
1003  if (memcmp(&header[TAR_OFFSET_MAGIC], "ustar \0", 8) == 0)
1004  return true;
1005  /* not-quite-POSIX format written by pre-9.3 pg_dump */
1006  if (memcmp(&header[TAR_OFFSET_MAGIC], "ustar00\0", 8) == 0)
1007  return true;
1008 
1009  return false;
1010 }
@ TAR_OFFSET_VERSION
Definition: pgtar.h:49
@ TAR_OFFSET_MAGIC
Definition: pgtar.h:48

References read_tar_number(), TAR_OFFSET_CHECKSUM, TAR_OFFSET_MAGIC, TAR_OFFSET_VERSION, and tarChecksum().

Referenced by _discoverArchiveFormat().

◆ tarClose()

static void tarClose ( ArchiveHandle AH,
TAR_MEMBER th 
)
static

Definition at line 398 of file pg_backup_tar.c.

399 {
401  pg_fatal("compression is not supported by tar archive format");
402 
403  if (th->mode == 'w')
404  _tarAddFile(AH, th); /* This will close the temp file */
405 
406  /*
407  * else Nothing to do for normal read since we don't dup() normal file
408  * handle, and we don't use temp files.
409  */
410 
411  free(th->targetFile);
412 
413  th->nFH = NULL;
414 }
static int static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)

References _tarAddFile(), pg_compress_specification::algorithm, _archiveHandle::compression_spec, free, TAR_MEMBER::mode, TAR_MEMBER::nFH, PG_COMPRESSION_NONE, pg_fatal, and TAR_MEMBER::targetFile.

Referenced by _CloseArchive(), _EndData(), _EndLO(), _EndLOs(), _LoadLOs(), _PrintFileData(), and InitArchiveFmt_Tar().

◆ tarOpen()

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

Definition at line 302 of file pg_backup_tar.c.

303 {
304  lclContext *ctx = (lclContext *) AH->formatData;
305  TAR_MEMBER *tm;
306 
307  if (mode == 'r')
308  {
309  tm = _tarPositionTo(AH, filename);
310  if (!tm) /* Not found */
311  {
312  if (filename)
313  {
314  /*
315  * Couldn't find the requested file. Future: do SEEK(0) and
316  * retry.
317  */
318  pg_fatal("could not find file \"%s\" in archive", filename);
319  }
320  else
321  {
322  /* Any file OK, none left, so return NULL */
323  return NULL;
324  }
325  }
326 
328  tm->nFH = ctx->tarFH;
329  else
330  pg_fatal("compression is not supported by tar archive format");
331  }
332  else
333  {
334  int old_umask;
335 
337 
338  /*
339  * POSIX does not require, but permits, tmpfile() to restrict file
340  * permissions. Given an OS crash after we write data, the filesystem
341  * might retain the data but forget tmpfile()'s unlink(). If so, the
342  * file mode protects confidentiality of the data written.
343  */
344  old_umask = umask(S_IRWXG | S_IRWXO);
345 
346 #ifndef WIN32
347  tm->tmpFH = tmpfile();
348 #else
349 
350  /*
351  * On WIN32, tmpfile() generates a filename in the root directory,
352  * which requires administrative permissions on certain systems. Loop
353  * until we find a unique file name we can create.
354  */
355  while (1)
356  {
357  char *name;
358  int fd;
359 
360  name = _tempnam(NULL, "pg_temp_");
361  if (name == NULL)
362  break;
363  fd = open(name, O_RDWR | O_CREAT | O_EXCL | O_BINARY |
364  O_TEMPORARY, S_IRUSR | S_IWUSR);
365  free(name);
366 
367  if (fd != -1) /* created a file */
368  {
369  tm->tmpFH = fdopen(fd, "w+b");
370  break;
371  }
372  else if (errno != EEXIST) /* failure other than file exists */
373  break;
374  }
375 #endif
376 
377  if (tm->tmpFH == NULL)
378  pg_fatal("could not generate temporary file name: %m");
379 
380  umask(old_umask);
381 
383  tm->nFH = tm->tmpFH;
384  else
385  pg_fatal("compression is not supported by tar archive format");
386 
387  tm->AH = AH;
388  tm->targetFile = pg_strdup(filename);
389  }
390 
391  tm->mode = mode;
392  tm->tarFH = ctx->tarFH;
393 
394  return tm;
395 }
static struct pg_tm tm
Definition: localtime.c:104
static TAR_MEMBER * _tarPositionTo(ArchiveHandle *AH, const char *filename)
static PgChecksumMode mode
Definition: pg_checksums.c:56
static int fd(const char *x, int i)
Definition: preproc-init.c:105
const char * name
#define S_IRWXG
Definition: win32_port.h:310
#define S_IRWXO
Definition: win32_port.h:322
#define S_IRUSR
Definition: win32_port.h:289
#define S_IWUSR
Definition: win32_port.h:292

References _tarPositionTo(), pg_compress_specification::algorithm, _archiveHandle::compression_spec, fd(), filename, _archiveHandle::formatData, free, if(), mode, name, PG_COMPRESSION_NONE, pg_fatal, pg_malloc0_object, pg_strdup(), S_IRUSR, S_IRWXG, S_IRWXO, S_IWUSR, lclContext::tarFH, and tm.

Referenced by _CloseArchive(), _LoadLOs(), _PrintFileData(), _StartData(), _StartLO(), _StartLOs(), and InitArchiveFmt_Tar().

◆ tarPrintf()

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

Definition at line 954 of file pg_backup_tar.c.

955 {
956  int save_errno = errno;
957  char *p;
958  size_t len = 128; /* initial assumption about buffer size */
959  size_t cnt;
960 
961  for (;;)
962  {
963  va_list args;
964 
965  /* Allocate work buffer. */
966  p = (char *) pg_malloc(len);
967 
968  /* Try to format the data. */
969  errno = save_errno;
970  va_start(args, fmt);
971  cnt = pvsnprintf(p, len, fmt, args);
972  va_end(args);
973 
974  if (cnt < len)
975  break; /* success */
976 
977  /* Release buffer and loop around to try again with larger len. */
978  free(p);
979  len = cnt;
980  }
981 
982  cnt = tarWrite(p, cnt, th);
983  free(p);
984  return (int) cnt;
985 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static void const char * fmt
va_end(args)
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 _StartLO().

◆ tarRead()

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

Definition at line 511 of file pg_backup_tar.c.

512 {
513  size_t res;
514 
515  if (th->pos + len > th->fileLen)
516  len = th->fileLen - th->pos;
517 
518  if (len <= 0)
519  return 0;
520 
521  res = _tarReadRaw(th->AH, buf, len, th, NULL);
522 
523  th->pos += res;
524 
525  return res;
526 }
pgoff_t pos
Definition: pg_backup_tar.c:73
ArchiveHandle * AH
Definition: pg_backup_tar.c:75

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

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

◆ tarWrite()

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

Definition at line 529 of file pg_backup_tar.c.

530 {
531  size_t res;
532 
533  res = fwrite(buf, 1, len, th->nFH);
534 
535  th->pos += res;
536  return res;
537 }

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

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