PostgreSQL Source Code  git master
pg_backup_archiver.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "parallel.h"
#include "pg_backup_archiver.h"
#include "pg_backup_db.h"
#include "pg_backup_utils.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "libpq/libpq-fs.h"
Include dependency graph for pg_backup_archiver.c:

Go to the source code of this file.

Data Structures

struct  _outputContext
 

Macros

#define TEXT_DUMP_HEADER   "--\n-- PostgreSQL database dump\n--\n\n"
 
#define TEXT_DUMPALL_HEADER   "--\n-- PostgreSQL database cluster dump\n--\n\n"
 

Typedefs

typedef struct _outputContext OutputContext
 

Functions

static ArchiveHandle_allocAH (const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
 
static void _getObjectDescription (PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
 
static void _printTocEntry (ArchiveHandle *AH, TocEntry *te, bool isData)
 
static char * replace_line_endings (const char *str)
 
static void _doSetFixedOutputState (ArchiveHandle *AH)
 
static void _doSetSessionAuth (ArchiveHandle *AH, const char *user)
 
static void _doSetWithOids (ArchiveHandle *AH, const bool withOids)
 
static void _reconnectToDB (ArchiveHandle *AH, const char *dbname)
 
static void _becomeUser (ArchiveHandle *AH, const char *user)
 
static void _becomeOwner (ArchiveHandle *AH, TocEntry *te)
 
static void _selectOutputSchema (ArchiveHandle *AH, const char *schemaName)
 
static void _selectTablespace (ArchiveHandle *AH, const char *tablespace)
 
static void processEncodingEntry (ArchiveHandle *AH, TocEntry *te)
 
static void processStdStringsEntry (ArchiveHandle *AH, TocEntry *te)
 
static void processSearchPathEntry (ArchiveHandle *AH, TocEntry *te)
 
static teReqs _tocEntryRequired (TocEntry *te, teSection curSection, ArchiveHandle *AH)
 
static RestorePass _tocEntryRestorePass (TocEntry *te)
 
static bool _tocEntryIsACL (TocEntry *te)
 
static void _disableTriggersIfNecessary (ArchiveHandle *AH, TocEntry *te)
 
static void _enableTriggersIfNecessary (ArchiveHandle *AH, TocEntry *te)
 
static void buildTocEntryArrays (ArchiveHandle *AH)
 
static void _moveBefore (ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
 
static int _discoverArchiveFormat (ArchiveHandle *AH)
 
static int RestoringToDB (ArchiveHandle *AH)
 
static void dump_lo_buf (ArchiveHandle *AH)
 
static void dumpTimestamp (ArchiveHandle *AH, const char *msg, time_t tim)
 
static void SetOutput (ArchiveHandle *AH, const char *filename, int compression)
 
static OutputContext SaveOutput (ArchiveHandle *AH)
 
static void RestoreOutput (ArchiveHandle *AH, OutputContext savedContext)
 
static int restore_toc_entry (ArchiveHandle *AH, TocEntry *te, bool is_parallel)
 
static void restore_toc_entries_prefork (ArchiveHandle *AH, TocEntry *pending_list)
 
static void restore_toc_entries_parallel (ArchiveHandle *AH, ParallelState *pstate, TocEntry *pending_list)
 
static void restore_toc_entries_postfork (ArchiveHandle *AH, TocEntry *pending_list)
 
static void par_list_header_init (TocEntry *l)
 
static void par_list_append (TocEntry *l, TocEntry *te)
 
static void par_list_remove (TocEntry *te)
 
static void move_to_ready_list (TocEntry *pending_list, TocEntry *ready_list, RestorePass pass)
 
static TocEntryget_next_work_item (ArchiveHandle *AH, TocEntry *ready_list, ParallelState *pstate)
 
static void mark_dump_job_done (ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
 
static void mark_restore_job_done (ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
 
static void fix_dependencies (ArchiveHandle *AH)
 
static bool has_lock_conflicts (TocEntry *te1, TocEntry *te2)
 
static void repoint_table_dependencies (ArchiveHandle *AH)
 
static void identify_locking_dependencies (ArchiveHandle *AH, TocEntry *te)
 
static void reduce_dependencies (ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
 
static void mark_create_done (ArchiveHandle *AH, TocEntry *te)
 
static void inhibit_data_for_failed_table (ArchiveHandle *AH, TocEntry *te)
 
static void StrictNamesCheck (RestoreOptions *ropt)
 
DumpOptionsNewDumpOptions (void)
 
void InitDumpOptions (DumpOptions *opts)
 
DumpOptionsdumpOptionsFromRestoreOptions (RestoreOptions *ropt)
 
static void setupRestoreWorker (Archive *AHX)
 
ArchiveCreateArchive (const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupDumpWorker)
 
ArchiveOpenArchive (const char *FileSpec, const ArchiveFormat fmt)
 
void CloseArchive (Archive *AHX)
 
void SetArchiveOptions (Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
 
void ProcessArchiveRestoreOptions (Archive *AHX)
 
void RestoreArchive (Archive *AHX)
 
RestoreOptionsNewRestoreOptions (void)
 
void WriteData (Archive *AHX, const void *data, size_t dLen)
 
void ArchiveEntry (Archive *AHX, CatalogId catalogId, DumpId dumpId, const char *tag, const char *namespace, const char *tablespace, const char *owner, bool withOids, const char *desc, teSection section, const char *defn, const char *dropStmt, const char *copyStmt, const DumpId *deps, int nDeps, DataDumperPtr dumpFn, void *dumpArg)
 
void PrintTOCSummary (Archive *AHX)
 
int StartBlob (Archive *AHX, Oid oid)
 
int EndBlob (Archive *AHX, Oid oid)
 
void StartRestoreBlobs (ArchiveHandle *AH)
 
void EndRestoreBlobs (ArchiveHandle *AH)
 
void StartRestoreBlob (ArchiveHandle *AH, Oid oid, bool drop)
 
void EndRestoreBlob (ArchiveHandle *AH, Oid oid)
 
void SortTocFromFile (Archive *AHX)
 
void archputs (const char *s, Archive *AH)
 
int archprintf (Archive *AH, const char *fmt,...)
 
int ahprintf (ArchiveHandle *AH, const char *fmt,...)
 
void ahlog (ArchiveHandle *AH, int level, const char *fmt,...)
 
void ahwrite (const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 
void warn_or_exit_horribly (ArchiveHandle *AH, const char *modulename, const char *fmt,...)
 
TocEntrygetTocEntryByDumpId (ArchiveHandle *AH, DumpId id)
 
teReqs TocIDRequired (ArchiveHandle *AH, DumpId id)
 
size_t WriteOffset (ArchiveHandle *AH, pgoff_t o, int wasSet)
 
int ReadOffset (ArchiveHandle *AH, pgoff_t *o)
 
size_t WriteInt (ArchiveHandle *AH, int i)
 
int ReadInt (ArchiveHandle *AH)
 
size_t WriteStr (ArchiveHandle *AH, const char *c)
 
char * ReadStr (ArchiveHandle *AH)
 
void WriteDataChunks (ArchiveHandle *AH, ParallelState *pstate)
 
void WriteDataChunksForTocEntry (ArchiveHandle *AH, TocEntry *te)
 
void WriteToc (ArchiveHandle *AH)
 
void ReadToc (ArchiveHandle *AH)
 
static void _setWithOids (ArchiveHandle *AH, TocEntry *te)
 
void WriteHead (ArchiveHandle *AH)
 
void ReadHead (ArchiveHandle *AH)
 
bool checkSeek (FILE *fp)
 
int parallel_restore (ArchiveHandle *AH, TocEntry *te)
 
ArchiveHandleCloneArchive (ArchiveHandle *AH)
 
void DeCloneArchive (ArchiveHandle *AH)
 

Variables

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

Macro Definition Documentation

◆ TEXT_DUMP_HEADER

#define TEXT_DUMP_HEADER   "--\n-- PostgreSQL database dump\n--\n\n"

Definition at line 42 of file pg_backup_archiver.c.

Referenced by _discoverArchiveFormat().

◆ TEXT_DUMPALL_HEADER

#define TEXT_DUMPALL_HEADER   "--\n-- PostgreSQL database cluster dump\n--\n\n"

Definition at line 43 of file pg_backup_archiver.c.

Referenced by _discoverArchiveFormat().

Typedef Documentation

◆ OutputContext

Function Documentation

◆ _allocAH()

static ArchiveHandle * _allocAH ( const char *  FileSpec,
const ArchiveFormat  fmt,
const int  compression,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupWorkerPtr 
)
static

Definition at line 2300 of file pg_backup_archiver.c.

References _discoverArchiveFormat(), archCustom, archDirectory, _archiveHandle::archiveDumpVersion, archModeWrite, archNull, archTar, archUnknown, _archiveHandle::compression, _archiveHandle::createDate, _archiveHandle::currSchema, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::currWithOids, dosync, _archiveHandle::dosync, Archive::encoding, exit_horribly(), Archive::exit_on_error, _archiveHandle::format, _archiveHandle::fSpec, _archiveHandle::gzOut, InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), InitArchiveFmt_Null(), InitArchiveFmt_Tar(), _archiveHandle::intSize, K_VERS_SELF, _archiveHandle::mode, modulename, Archive::n_errors, _tocEntry::next, _archiveHandle::OF, _archiveHandle::offSize, pg_malloc0(), pg_strdup(), pgoff_t, _tocEntry::prev, _archiveHandle::promptPassword, _archiveHandle::public, _archiveHandle::SetupWorkerPtr, _archiveHandle::sqlparse, Archive::std_strings, _archiveHandle::toc, TRI_DEFAULT, _archiveHandle::version, and write_msg().

Referenced by CreateArchive(), and OpenArchive().

2303 {
2304  ArchiveHandle *AH;
2305 
2306 #if 0
2307  write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);
2308 #endif
2309 
2310  AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2311 
2312  /* AH->debugLevel = 100; */
2313 
2314  AH->version = K_VERS_SELF;
2315 
2316  /* initialize for backwards compatible string processing */
2317  AH->public.encoding = 0; /* PG_SQL_ASCII */
2318  AH->public.std_strings = false;
2319 
2320  /* sql error handling */
2321  AH->public.exit_on_error = true;
2322  AH->public.n_errors = 0;
2323 
2324  AH->archiveDumpVersion = PG_VERSION;
2325 
2326  AH->createDate = time(NULL);
2327 
2328  AH->intSize = sizeof(int);
2329  AH->offSize = sizeof(pgoff_t);
2330  if (FileSpec)
2331  {
2332  AH->fSpec = pg_strdup(FileSpec);
2333 
2334  /*
2335  * Not used; maybe later....
2336  *
2337  * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2338  * i--) if (AH->workDir[i-1] == '/')
2339  */
2340  }
2341  else
2342  AH->fSpec = NULL;
2343 
2344  AH->currUser = NULL; /* unknown */
2345  AH->currSchema = NULL; /* ditto */
2346  AH->currTablespace = NULL; /* ditto */
2347  AH->currWithOids = -1; /* force SET */
2348 
2349  AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2350 
2351  AH->toc->next = AH->toc;
2352  AH->toc->prev = AH->toc;
2353 
2354  AH->mode = mode;
2355  AH->compression = compression;
2356  AH->dosync = dosync;
2357 
2358  memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2359 
2360  /* Open stdout with no compression for AH output handle */
2361  AH->gzOut = 0;
2362  AH->OF = stdout;
2363 
2364  /*
2365  * On Windows, we need to use binary mode to read/write non-text files,
2366  * which include all archive formats as well as compressed plain text.
2367  * Force stdin/stdout into binary mode if that is what we are using.
2368  */
2369 #ifdef WIN32
2370  if ((fmt != archNull || compression != 0) &&
2371  (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2372  {
2373  if (mode == archModeWrite)
2374  _setmode(fileno(stdout), O_BINARY);
2375  else
2376  _setmode(fileno(stdin), O_BINARY);
2377  }
2378 #endif
2379 
2380  AH->SetupWorkerPtr = setupWorkerPtr;
2381 
2382  if (fmt == archUnknown)
2383  AH->format = _discoverArchiveFormat(AH);
2384  else
2385  AH->format = fmt;
2386 
2388 
2389  switch (AH->format)
2390  {
2391  case archCustom:
2393  break;
2394 
2395  case archNull:
2396  InitArchiveFmt_Null(AH);
2397  break;
2398 
2399  case archDirectory:
2401  break;
2402 
2403  case archTar:
2404  InitArchiveFmt_Tar(AH);
2405  break;
2406 
2407  default:
2408  exit_horribly(modulename, "unrecognized file format \"%d\"\n", fmt);
2409  }
2410 
2411  return AH;
2412 }
struct _tocEntry * next
#define K_VERS_SELF
static bool dosync
Definition: pg_dump.c:95
void InitArchiveFmt_Tar(ArchiveHandle *AH)
int n_errors
Definition: pg_backup.h:207
int encoding
Definition: pg_backup.h:198
SetupWorkerPtrType SetupWorkerPtr
#define pgoff_t
Definition: win32_port.h:206
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
struct _tocEntry * toc
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
sqlparseInfo sqlparse
struct _tocEntry * prev
ArchiveFormat format
static int _discoverArchiveFormat(ArchiveHandle *AH)
void InitArchiveFmt_Directory(ArchiveHandle *AH)
void InitArchiveFmt_Null(ArchiveHandle *AH)
void InitArchiveFmt_Custom(ArchiveHandle *AH)
void write_msg(const char *modulename, const char *fmt,...)
void exit_horribly(const char *modulename, const char *fmt,...)
bool exit_on_error
Definition: pg_backup.h:206
static const char * modulename
bool std_strings
Definition: pg_backup.h:199

◆ _becomeOwner()

static void _becomeOwner ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3310 of file pg_backup_archiver.c.

References _becomeUser(), _restoreOptions::noOwner, _tocEntry::owner, _archiveHandle::public, Archive::ropt, and _restoreOptions::use_setsessauth.

Referenced by _printTocEntry(), restore_toc_entry(), and RestoreArchive().

3311 {
3312  RestoreOptions *ropt = AH->public.ropt;
3313 
3314  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3315  return;
3316 
3317  _becomeUser(AH, te->owner);
3318 }
RestoreOptions * ropt
Definition: pg_backup.h:184
static void _becomeUser(ArchiveHandle *AH, const char *user)
int use_setsessauth
Definition: pg_backup.h:68

◆ _becomeUser()

static void _becomeUser ( ArchiveHandle AH,
const char *  user 
)
static

Definition at line 3286 of file pg_backup_archiver.c.

References _doSetSessionAuth(), _archiveHandle::currUser, free, and pg_strdup().

Referenced by _becomeOwner(), _disableTriggersIfNecessary(), and _enableTriggersIfNecessary().

3287 {
3288  if (!user)
3289  user = ""; /* avoid null pointers */
3290 
3291  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3292  return; /* no need to do anything */
3293 
3294  _doSetSessionAuth(AH, user);
3295 
3296  /*
3297  * NOTE: currUser keeps track of what the imaginary session user in our
3298  * script is
3299  */
3300  if (AH->currUser)
3301  free(AH->currUser);
3302  AH->currUser = pg_strdup(user);
3303 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
#define free(a)
Definition: header.h:65
static char * user
Definition: pg_regress.c:93

◆ _disableTriggersIfNecessary()

static void _disableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 972 of file pg_backup_archiver.c.

References _becomeUser(), ahlog(), ahprintf(), _archiveHandle::connection, _restoreOptions::dataOnly, _restoreOptions::disable_triggers, fmtQualifiedId(), PQserverVersion(), _archiveHandle::public, Archive::ropt, _restoreOptions::superuser, and _tocEntry::tag.

Referenced by restore_toc_entry().

973 {
974  RestoreOptions *ropt = AH->public.ropt;
975 
976  /* This hack is only needed in a data-only restore */
977  if (!ropt->dataOnly || !ropt->disable_triggers)
978  return;
979 
980  ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
981 
982  /*
983  * Become superuser if possible, since they are the only ones who can
984  * disable constraint triggers. If -S was not given, assume the initial
985  * user identity is a superuser. (XXX would it be better to become the
986  * table owner?)
987  */
988  _becomeUser(AH, ropt->superuser);
989 
990  /*
991  * Disable them.
992  */
993  ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
995  te->namespace,
996  te->tag));
997 }
RestoreOptions * ropt
Definition: pg_backup.h:184
static void _becomeUser(ArchiveHandle *AH, const char *user)
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6106
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
char * superuser
Definition: pg_backup.h:70
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
const char * fmtQualifiedId(int remoteVersion, const char *schema, const char *id)
Definition: string_utils.c:150
int disable_triggers
Definition: pg_backup.h:66

◆ _discoverArchiveFormat()

static int _discoverArchiveFormat ( ArchiveHandle AH)
static

Definition at line 2095 of file pg_backup_archiver.c.

References archDirectory, archTar, buf, exit_horribly(), _archiveHandle::format, free, fseeko, _archiveHandle::fSpec, _archiveHandle::intSize, isValidTarHeader(), K_VERS_1_7, _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, _archiveHandle::lookaheadSize, MAKE_ARCHIVE_VERSION, MAXPGPATH, modulename, _archiveHandle::offSize, PG_BINARY_R, pg_malloc0(), READ_ERROR_EXIT, _archiveHandle::readHeader, S_ISDIR, S_ISREG, sig, snprintf(), stat, strerror(), TEXT_DUMP_HEADER, TEXT_DUMPALL_HEADER, _archiveHandle::version, and write_msg().

Referenced by _allocAH().

2096 {
2097  FILE *fh;
2098  char sig[6]; /* More than enough */
2099  size_t cnt;
2100  int wantClose = 0;
2101 
2102 #if 0
2103  write_msg(modulename, "attempting to ascertain archive format\n");
2104 #endif
2105 
2106  if (AH->lookahead)
2107  free(AH->lookahead);
2108 
2109  AH->lookaheadSize = 512;
2110  AH->lookahead = pg_malloc0(512);
2111  AH->lookaheadLen = 0;
2112  AH->lookaheadPos = 0;
2113 
2114  if (AH->fSpec)
2115  {
2116  struct stat st;
2117 
2118  wantClose = 1;
2119 
2120  /*
2121  * Check if the specified archive is a directory. If so, check if
2122  * there's a "toc.dat" (or "toc.dat.gz") file in it.
2123  */
2124  if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2125  {
2126  char buf[MAXPGPATH];
2127 
2128  if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
2129  exit_horribly(modulename, "directory name too long: \"%s\"\n",
2130  AH->fSpec);
2131  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2132  {
2133  AH->format = archDirectory;
2134  return AH->format;
2135  }
2136 
2137 #ifdef HAVE_LIBZ
2138  if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
2139  exit_horribly(modulename, "directory name too long: \"%s\"\n",
2140  AH->fSpec);
2141  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2142  {
2143  AH->format = archDirectory;
2144  return AH->format;
2145  }
2146 #endif
2147  exit_horribly(modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
2148  AH->fSpec);
2149  fh = NULL; /* keep compiler quiet */
2150  }
2151  else
2152  {
2153  fh = fopen(AH->fSpec, PG_BINARY_R);
2154  if (!fh)
2155  exit_horribly(modulename, "could not open input file \"%s\": %s\n",
2156  AH->fSpec, strerror(errno));
2157  }
2158  }
2159  else
2160  {
2161  fh = stdin;
2162  if (!fh)
2163  exit_horribly(modulename, "could not open input file: %s\n",
2164  strerror(errno));
2165  }
2166 
2167  if ((cnt = fread(sig, 1, 5, fh)) != 5)
2168  {
2169  if (ferror(fh))
2170  exit_horribly(modulename, "could not read input file: %s\n", strerror(errno));
2171  else
2172  exit_horribly(modulename, "input file is too short (read %lu, expected 5)\n",
2173  (unsigned long) cnt);
2174  }
2175 
2176  /* Save it, just in case we need it later */
2177  memcpy(&AH->lookahead[0], sig, 5);
2178  AH->lookaheadLen = 5;
2179 
2180  if (strncmp(sig, "PGDMP", 5) == 0)
2181  {
2182  int byteread;
2183  char vmaj,
2184  vmin,
2185  vrev;
2186 
2187  /*
2188  * Finish reading (most of) a custom-format header.
2189  *
2190  * NB: this code must agree with ReadHead().
2191  */
2192  if ((byteread = fgetc(fh)) == EOF)
2193  READ_ERROR_EXIT(fh);
2194 
2195  vmaj = byteread;
2196 
2197  if ((byteread = fgetc(fh)) == EOF)
2198  READ_ERROR_EXIT(fh);
2199 
2200  vmin = byteread;
2201 
2202  /* Save these too... */
2203  AH->lookahead[AH->lookaheadLen++] = vmaj;
2204  AH->lookahead[AH->lookaheadLen++] = vmin;
2205 
2206  /* Check header version; varies from V1.0 */
2207  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
2208  {
2209  if ((byteread = fgetc(fh)) == EOF)
2210  READ_ERROR_EXIT(fh);
2211 
2212  vrev = byteread;
2213  AH->lookahead[AH->lookaheadLen++] = vrev;
2214  }
2215  else
2216  vrev = 0;
2217 
2218  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
2219 
2220  if ((AH->intSize = fgetc(fh)) == EOF)
2221  READ_ERROR_EXIT(fh);
2222  AH->lookahead[AH->lookaheadLen++] = AH->intSize;
2223 
2224  if (AH->version >= K_VERS_1_7)
2225  {
2226  if ((AH->offSize = fgetc(fh)) == EOF)
2227  READ_ERROR_EXIT(fh);
2228  AH->lookahead[AH->lookaheadLen++] = AH->offSize;
2229  }
2230  else
2231  AH->offSize = AH->intSize;
2232 
2233  if ((byteread = fgetc(fh)) == EOF)
2234  READ_ERROR_EXIT(fh);
2235 
2236  AH->format = byteread;
2237  AH->lookahead[AH->lookaheadLen++] = AH->format;
2238  }
2239  else
2240  {
2241  /*
2242  * *Maybe* we have a tar archive format file or a text dump ... So,
2243  * read first 512 byte header...
2244  */
2245  cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2246  /* read failure is checked below */
2247  AH->lookaheadLen += cnt;
2248 
2249  if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) &&
2250  (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 ||
2251  strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
2252  {
2253  /*
2254  * looks like it's probably a text format dump. so suggest they
2255  * try psql
2256  */
2257  exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n");
2258  }
2259 
2260  if (AH->lookaheadLen != 512)
2261  {
2262  if (feof(fh))
2263  exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n");
2264  else
2265  READ_ERROR_EXIT(fh);
2266  }
2267 
2268  if (!isValidTarHeader(AH->lookahead))
2269  exit_horribly(modulename, "input file does not appear to be a valid archive\n");
2270 
2271  AH->format = archTar;
2272  }
2273 
2274  /* If we can't seek, then mark the header as read */
2275  if (fseeko(fh, 0, SEEK_SET) != 0)
2276  {
2277  /*
2278  * NOTE: Formats that use the lookahead buffer can unset this in their
2279  * Init routine.
2280  */
2281  AH->readHeader = 1;
2282  }
2283  else
2284  AH->lookaheadLen = 0; /* Don't bother since we've reset the file */
2285 
2286  /* Close the file */
2287  if (wantClose)
2288  if (fclose(fh) != 0)
2289  exit_horribly(modulename, "could not close input file: %s\n",
2290  strerror(errno));
2291 
2292  return AH->format;
2293 }
#define TEXT_DUMP_HEADER
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
bool isValidTarHeader(char *header)
#define PG_BINARY_R
Definition: c.h:1082
#define K_VERS_1_7
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
#define MAKE_ARCHIVE_VERSION(major, minor, rev)
static char * buf
Definition: pg_test_fsync.c:67
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
ArchiveFormat format
#define TEXT_DUMPALL_HEADER
static int sig
Definition: pg_ctl.c:81
#define fseeko(stream, offset, origin)
Definition: win32_port.h:212
#define free(a)
Definition: header.h:65
void write_msg(const char *modulename, const char *fmt,...)
#define S_ISDIR(m)
Definition: win32_port.h:307
void exit_horribly(const char *modulename, const char *fmt,...)
const char * strerror(int errnum)
Definition: strerror.c:19
#define READ_ERROR_EXIT(fd)
static const char * modulename

◆ _doSetFixedOutputState()

static void _doSetFixedOutputState ( ArchiveHandle AH)
static

Definition at line 3113 of file pg_backup_archiver.c.

References ahprintf(), _restoreOptions::enable_row_security, Archive::encoding, fmtId(), pg_encoding_to_char(), _archiveHandle::public, Archive::ropt, Archive::searchpath, Archive::std_strings, and _restoreOptions::use_role.

Referenced by _reconnectToDB(), CloneArchive(), restore_toc_entries_postfork(), and RestoreArchive().

3114 {
3115  RestoreOptions *ropt = AH->public.ropt;
3116 
3117  /*
3118  * Disable timeouts to allow for slow commands, idle parallel workers, etc
3119  */
3120  ahprintf(AH, "SET statement_timeout = 0;\n");
3121  ahprintf(AH, "SET lock_timeout = 0;\n");
3122  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3123 
3124  /* Select the correct character set encoding */
3125  ahprintf(AH, "SET client_encoding = '%s';\n",
3127 
3128  /* Select the correct string literal syntax */
3129  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3130  AH->public.std_strings ? "on" : "off");
3131 
3132  /* Select the role to be used during restore */
3133  if (ropt && ropt->use_role)
3134  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3135 
3136  /* Select the dump-time search_path */
3137  if (AH->public.searchpath)
3138  ahprintf(AH, "%s", AH->public.searchpath);
3139 
3140  /* Make sure function checking is disabled */
3141  ahprintf(AH, "SET check_function_bodies = false;\n");
3142 
3143  /* Avoid annoying notices etc */
3144  ahprintf(AH, "SET client_min_messages = warning;\n");
3145  if (!AH->public.std_strings)
3146  ahprintf(AH, "SET escape_string_warning = off;\n");
3147 
3148  /* Adjust row-security state */
3149  if (ropt && ropt->enable_row_security)
3150  ahprintf(AH, "SET row_security = on;\n");
3151  else
3152  ahprintf(AH, "SET row_security = off;\n");
3153 
3154  ahprintf(AH, "\n");
3155 }
RestoreOptions * ropt
Definition: pg_backup.h:184
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
char * use_role
Definition: pg_backup.h:71
int encoding
Definition: pg_backup.h:198
int enable_row_security
Definition: pg_backup.h:123
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
char * searchpath
Definition: pg_backup.h:202
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:607
bool std_strings
Definition: pg_backup.h:199

◆ _doSetSessionAuth()

static void _doSetSessionAuth ( ArchiveHandle AH,
const char *  user 
)
static

Definition at line 3163 of file pg_backup_archiver.c.

References ahprintf(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendStringLiteralAHX, _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), exit_horribly(), modulename, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), and RestoringToDB().

Referenced by _becomeUser().

3164 {
3166 
3167  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3168 
3169  /*
3170  * SQL requires a string literal here. Might as well be correct.
3171  */
3172  if (user && *user)
3173  appendStringLiteralAHX(cmd, user, AH);
3174  else
3175  appendPQExpBufferStr(cmd, "DEFAULT");
3176  appendPQExpBufferChar(cmd, ';');
3177 
3178  if (RestoringToDB(AH))
3179  {
3180  PGresult *res;
3181 
3182  res = PQexec(AH->connection, cmd->data);
3183 
3184  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3185  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3186  exit_horribly(modulename, "could not set session user to \"%s\": %s",
3188 
3189  PQclear(res);
3190  }
3191  else
3192  ahprintf(AH, "%s\n\n", cmd->data);
3193 
3194  destroyPQExpBuffer(cmd);
3195 }
static int RestoringToDB(ArchiveHandle *AH)
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define appendStringLiteralAHX(buf, str, AH)
void exit_horribly(const char *modulename, const char *fmt,...)
static char * user
Definition: pg_regress.c:93
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897
static const char * modulename

◆ _doSetWithOids()

static void _doSetWithOids ( ArchiveHandle AH,
const bool  withOids 
)
static

Definition at line 3203 of file pg_backup_archiver.c.

References ahprintf(), appendPQExpBuffer(), _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), modulename, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), RestoringToDB(), and warn_or_exit_horribly().

Referenced by _setWithOids().

3204 {
3206 
3207  appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?
3208  "true" : "false");
3209 
3210  if (RestoringToDB(AH))
3211  {
3212  PGresult *res;
3213 
3214  res = PQexec(AH->connection, cmd->data);
3215 
3216  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3218  "could not set default_with_oids: %s",
3219  PQerrorMessage(AH->connection));
3220 
3221  PQclear(res);
3222  }
3223  else
3224  ahprintf(AH, "%s\n\n", cmd->data);
3225 
3226  destroyPQExpBuffer(cmd);
3227 }
static int RestoringToDB(ArchiveHandle *AH)
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void PQclear(PGresult *res)
Definition: fe-exec.c:671
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897
static const char * modulename

◆ _enableTriggersIfNecessary()

static void _enableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 1000 of file pg_backup_archiver.c.

References _becomeUser(), ahlog(), ahprintf(), _archiveHandle::connection, _restoreOptions::dataOnly, _restoreOptions::disable_triggers, fmtQualifiedId(), PQserverVersion(), _archiveHandle::public, Archive::ropt, _restoreOptions::superuser, and _tocEntry::tag.

Referenced by restore_toc_entry().

1001 {
1002  RestoreOptions *ropt = AH->public.ropt;
1003 
1004  /* This hack is only needed in a data-only restore */
1005  if (!ropt->dataOnly || !ropt->disable_triggers)
1006  return;
1007 
1008  ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
1009 
1010  /*
1011  * Become superuser if possible, since they are the only ones who can
1012  * disable constraint triggers. If -S was not given, assume the initial
1013  * user identity is a superuser. (XXX would it be better to become the
1014  * table owner?)
1015  */
1016  _becomeUser(AH, ropt->superuser);
1017 
1018  /*
1019  * Enable them.
1020  */
1021  ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1023  te->namespace,
1024  te->tag));
1025 }
RestoreOptions * ropt
Definition: pg_backup.h:184
static void _becomeUser(ArchiveHandle *AH, const char *user)
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6106
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
char * superuser
Definition: pg_backup.h:70
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
const char * fmtQualifiedId(int remoteVersion, const char *schema, const char *id)
Definition: string_utils.c:150
int disable_triggers
Definition: pg_backup.h:66

◆ _getObjectDescription()

static void _getObjectDescription ( PQExpBuffer  buf,
TocEntry te,
ArchiveHandle AH 
)
static

Definition at line 3455 of file pg_backup_archiver.c.

References appendPQExpBuffer(), appendPQExpBufferStr(), _tocEntry::desc, _tocEntry::dropStmt, fmtId(), free, modulename, pg_strdup(), _tocEntry::tag, generate_unaccent_rules::type, and write_msg().

Referenced by _printTocEntry().

3456 {
3457  const char *type = te->desc;
3458 
3459  /* Use ALTER TABLE for views and sequences */
3460  if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0 ||
3461  strcmp(type, "MATERIALIZED VIEW") == 0)
3462  type = "TABLE";
3463 
3464  /* objects that don't require special decoration */
3465  if (strcmp(type, "COLLATION") == 0 ||
3466  strcmp(type, "CONVERSION") == 0 ||
3467  strcmp(type, "DOMAIN") == 0 ||
3468  strcmp(type, "TABLE") == 0 ||
3469  strcmp(type, "TYPE") == 0 ||
3470  strcmp(type, "FOREIGN TABLE") == 0 ||
3471  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3472  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3473  strcmp(type, "STATISTICS") == 0 ||
3474  /* non-schema-specified objects */
3475  strcmp(type, "DATABASE") == 0 ||
3476  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3477  strcmp(type, "SCHEMA") == 0 ||
3478  strcmp(type, "EVENT TRIGGER") == 0 ||
3479  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3480  strcmp(type, "SERVER") == 0 ||
3481  strcmp(type, "PUBLICATION") == 0 ||
3482  strcmp(type, "SUBSCRIPTION") == 0 ||
3483  strcmp(type, "USER MAPPING") == 0)
3484  {
3485  appendPQExpBuffer(buf, "%s ", type);
3486  if (te->namespace && *te->namespace)
3487  appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3488  appendPQExpBufferStr(buf, fmtId(te->tag));
3489  return;
3490  }
3491 
3492  /* BLOBs just have a name, but it's numeric so must not use fmtId */
3493  if (strcmp(type, "BLOB") == 0)
3494  {
3495  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3496  return;
3497  }
3498 
3499  /*
3500  * These object types require additional decoration. Fortunately, the
3501  * information needed is exactly what's in the DROP command.
3502  */
3503  if (strcmp(type, "AGGREGATE") == 0 ||
3504  strcmp(type, "FUNCTION") == 0 ||
3505  strcmp(type, "OPERATOR") == 0 ||
3506  strcmp(type, "OPERATOR CLASS") == 0 ||
3507  strcmp(type, "OPERATOR FAMILY") == 0 ||
3508  strcmp(type, "PROCEDURE") == 0)
3509  {
3510  /* Chop "DROP " off the front and make a modifiable copy */
3511  char *first = pg_strdup(te->dropStmt + 5);
3512  char *last;
3513 
3514  /* point to last character in string */
3515  last = first + strlen(first) - 1;
3516 
3517  /* Strip off any ';' or '\n' at the end */
3518  while (last >= first && (*last == '\n' || *last == ';'))
3519  last--;
3520  *(last + 1) = '\0';
3521 
3522  appendPQExpBufferStr(buf, first);
3523 
3524  free(first);
3525  return;
3526  }
3527 
3528  write_msg(modulename, "WARNING: don't know how to set owner for object type \"%s\"\n",
3529  type);
3530 }
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define free(a)
Definition: header.h:65
void write_msg(const char *modulename, const char *fmt,...)
static const char * modulename

◆ _moveBefore()

static void _moveBefore ( ArchiveHandle AH,
TocEntry pos,
TocEntry te 
)
static

Definition at line 1827 of file pg_backup_archiver.c.

References _tocEntry::next, and _tocEntry::prev.

Referenced by SortTocFromFile().

1828 {
1829  /* Unlink te from list */
1830  te->prev->next = te->next;
1831  te->next->prev = te->prev;
1832 
1833  /* and insert it before "pos" */
1834  te->prev = pos->prev;
1835  te->next = pos;
1836  pos->prev->next = te;
1837  pos->prev = te;
1838 }
struct _tocEntry * next
struct _tocEntry * prev

◆ _printTocEntry()

static void _printTocEntry ( ArchiveHandle AH,
TocEntry te,
bool  isData 
)
static

Definition at line 3540 of file pg_backup_archiver.c.

References _becomeOwner(), _getObjectDescription(), _selectOutputSchema(), _selectTablespace(), _setWithOids(), _tocEntryIsACL(), ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _tocEntry::catalogId, createPQExpBuffer(), _archiveHandle::currUser, PQExpBufferData::data, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, destroyPQExpBuffer(), _tocEntry::dropStmt, _tocEntry::dumpId, fmtId(), free, i, modulename, _tocEntry::nDeps, _restoreOptions::noOwner, _restoreOptions::noTablespace, _archiveHandle::noTocComments, CatalogId::oid, _tocEntry::owner, pg_strdup(), _archiveHandle::PrintExtraTocPtr, _archiveHandle::public, replace_line_endings(), Archive::ropt, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _restoreOptions::use_setsessauth, Archive::verbose, and write_msg().

Referenced by restore_toc_entry().

3541 {
3542  RestoreOptions *ropt = AH->public.ropt;
3543 
3544  /* Select owner, schema, and tablespace as necessary */
3545  _becomeOwner(AH, te);
3546  _selectOutputSchema(AH, te->namespace);
3547  _selectTablespace(AH, te->tablespace);
3548 
3549  /* Set up OID mode too */
3550  if (strcmp(te->desc, "TABLE") == 0)
3551  _setWithOids(AH, te);
3552 
3553  /* Emit header comment for item */
3554  if (!AH->noTocComments)
3555  {
3556  const char *pfx;
3557  char *sanitized_name;
3558  char *sanitized_schema;
3559  char *sanitized_owner;
3560 
3561  if (isData)
3562  pfx = "Data for ";
3563  else
3564  pfx = "";
3565 
3566  ahprintf(AH, "--\n");
3567  if (AH->public.verbose)
3568  {
3569  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3570  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3571  if (te->nDeps > 0)
3572  {
3573  int i;
3574 
3575  ahprintf(AH, "-- Dependencies:");
3576  for (i = 0; i < te->nDeps; i++)
3577  ahprintf(AH, " %d", te->dependencies[i]);
3578  ahprintf(AH, "\n");
3579  }
3580  }
3581 
3582  /*
3583  * Zap any line endings embedded in user-supplied fields, to prevent
3584  * corruption of the dump (which could, in the worst case, present an
3585  * SQL injection vulnerability if someone were to incautiously load a
3586  * dump containing objects with maliciously crafted names).
3587  */
3588  sanitized_name = replace_line_endings(te->tag);
3589  if (te->namespace)
3590  sanitized_schema = replace_line_endings(te->namespace);
3591  else
3592  sanitized_schema = pg_strdup("-");
3593  if (!ropt->noOwner)
3594  sanitized_owner = replace_line_endings(te->owner);
3595  else
3596  sanitized_owner = pg_strdup("-");
3597 
3598  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3599  pfx, sanitized_name, te->desc, sanitized_schema,
3600  sanitized_owner);
3601 
3602  free(sanitized_name);
3603  free(sanitized_schema);
3604  free(sanitized_owner);
3605 
3606  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3607  {
3608  char *sanitized_tablespace;
3609 
3610  sanitized_tablespace = replace_line_endings(te->tablespace);
3611  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3612  free(sanitized_tablespace);
3613  }
3614  ahprintf(AH, "\n");
3615 
3616  if (AH->PrintExtraTocPtr != NULL)
3617  AH->PrintExtraTocPtr(AH, te);
3618  ahprintf(AH, "--\n\n");
3619  }
3620 
3621  /*
3622  * Actually print the definition.
3623  *
3624  * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
3625  * versions put into CREATE SCHEMA. We have to do this when --no-owner
3626  * mode is selected. This is ugly, but I see no other good way ...
3627  */
3628  if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
3629  {
3630  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3631  }
3632  else
3633  {
3634  if (strlen(te->defn) > 0)
3635  ahprintf(AH, "%s\n\n", te->defn);
3636  }
3637 
3638  /*
3639  * If we aren't using SET SESSION AUTH to determine ownership, we must
3640  * instead issue an ALTER OWNER command. We assume that anything without
3641  * a DROP command is not a separately ownable object. All the categories
3642  * with DROP commands must appear in one list or the other.
3643  */
3644  if (!ropt->noOwner && !ropt->use_setsessauth &&
3645  strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
3646  {
3647  if (strcmp(te->desc, "AGGREGATE") == 0 ||
3648  strcmp(te->desc, "BLOB") == 0 ||
3649  strcmp(te->desc, "COLLATION") == 0 ||
3650  strcmp(te->desc, "CONVERSION") == 0 ||
3651  strcmp(te->desc, "DATABASE") == 0 ||
3652  strcmp(te->desc, "DOMAIN") == 0 ||
3653  strcmp(te->desc, "FUNCTION") == 0 ||
3654  strcmp(te->desc, "OPERATOR") == 0 ||
3655  strcmp(te->desc, "OPERATOR CLASS") == 0 ||
3656  strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
3657  strcmp(te->desc, "PROCEDURE") == 0 ||
3658  strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
3659  strcmp(te->desc, "SCHEMA") == 0 ||
3660  strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3661  strcmp(te->desc, "TABLE") == 0 ||
3662  strcmp(te->desc, "TYPE") == 0 ||
3663  strcmp(te->desc, "VIEW") == 0 ||
3664  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3665  strcmp(te->desc, "SEQUENCE") == 0 ||
3666  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3667  strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
3668  strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 ||
3669  strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 ||
3670  strcmp(te->desc, "SERVER") == 0 ||
3671  strcmp(te->desc, "STATISTICS") == 0 ||
3672  strcmp(te->desc, "PUBLICATION") == 0 ||
3673  strcmp(te->desc, "SUBSCRIPTION") == 0)
3674  {
3675  PQExpBuffer temp = createPQExpBuffer();
3676 
3677  appendPQExpBufferStr(temp, "ALTER ");
3678  _getObjectDescription(temp, te, AH);
3679  appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
3680  ahprintf(AH, "%s\n\n", temp->data);
3681  destroyPQExpBuffer(temp);
3682  }
3683  else if (strcmp(te->desc, "CAST") == 0 ||
3684  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
3685  strcmp(te->desc, "CONSTRAINT") == 0 ||
3686  strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
3687  strcmp(te->desc, "DEFAULT") == 0 ||
3688  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
3689  strcmp(te->desc, "INDEX") == 0 ||
3690  strcmp(te->desc, "RULE") == 0 ||
3691  strcmp(te->desc, "TRIGGER") == 0 ||
3692  strcmp(te->desc, "ROW SECURITY") == 0 ||
3693  strcmp(te->desc, "POLICY") == 0 ||
3694  strcmp(te->desc, "USER MAPPING") == 0)
3695  {
3696  /* these object types don't have separate owners */
3697  }
3698  else
3699  {
3700  write_msg(modulename, "WARNING: don't know how to set owner for object type \"%s\"\n",
3701  te->desc);
3702  }
3703  }
3704 
3705  /*
3706  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3707  * commands, so we can no longer assume we know the current auth setting.
3708  */
3709  if (_tocEntryIsACL(te))
3710  {
3711  if (AH->currUser)
3712  free(AH->currUser);
3713  AH->currUser = NULL;
3714  }
3715 }
Oid tableoid
Definition: pg_backup.h:231
RestoreOptions * ropt
Definition: pg_backup.h:184
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
CatalogId catalogId
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
static bool _tocEntryIsACL(TocEntry *te)
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * replace_line_endings(const char *str)
DumpId * dependencies
static void _setWithOids(ArchiveHandle *AH, TocEntry *te)
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te)
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
int use_setsessauth
Definition: pg_backup.h:68
int verbose
Definition: pg_backup.h:186
#define free(a)
Definition: header.h:65
void write_msg(const char *modulename, const char *fmt,...)
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
int i
PrintExtraTocPtrType PrintExtraTocPtr
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
static const char * modulename
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)

◆ _reconnectToDB()

static void _reconnectToDB ( ArchiveHandle AH,
const char *  dbname 
)
static

Definition at line 3240 of file pg_backup_archiver.c.

References _doSetFixedOutputState(), ahprintf(), appendPsqlMetaConnect(), _archiveHandle::currSchema, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::currWithOids, PQExpBufferData::data, free, initPQExpBuffer(), ReconnectToServer(), RestoringToDB(), and termPQExpBuffer().

Referenced by restore_toc_entry().

3241 {
3242  if (RestoringToDB(AH))
3243  ReconnectToServer(AH, dbname, NULL);
3244  else
3245  {
3246  if (dbname)
3247  {
3248  PQExpBufferData connectbuf;
3249 
3250  initPQExpBuffer(&connectbuf);
3251  appendPsqlMetaConnect(&connectbuf, dbname);
3252  ahprintf(AH, "%s\n", connectbuf.data);
3253  termPQExpBuffer(&connectbuf);
3254  }
3255  else
3256  ahprintf(AH, "%s\n", "\\connect -\n");
3257  }
3258 
3259  /*
3260  * NOTE: currUser keeps track of what the imaginary session user in our
3261  * script is. It's now effectively reset to the original userID.
3262  */
3263  if (AH->currUser)
3264  free(AH->currUser);
3265  AH->currUser = NULL;
3266 
3267  /* don't assume we still know the output schema, tablespace, etc either */
3268  if (AH->currSchema)
3269  free(AH->currSchema);
3270  AH->currSchema = NULL;
3271  if (AH->currTablespace)
3272  free(AH->currTablespace);
3273  AH->currTablespace = NULL;
3274  AH->currWithOids = -1;
3275 
3276  /* re-establish fixed state */
3278 }
static int RestoringToDB(ArchiveHandle *AH)
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser)
Definition: pg_backup_db.c:83
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:596
static void _doSetFixedOutputState(ArchiveHandle *AH)
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
#define free(a)
Definition: header.h:65
char * dbname
Definition: streamutil.c:51
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ _selectOutputSchema()

static void _selectOutputSchema ( ArchiveHandle AH,
const char *  schemaName 
)
static

Definition at line 3340 of file pg_backup_archiver.c.

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currSchema, PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), free, modulename, pg_strdup(), PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), _archiveHandle::public, RestoringToDB(), Archive::searchpath, and warn_or_exit_horribly().

Referenced by _printTocEntry(), restore_toc_entry(), and RestoreArchive().

3341 {
3342  PQExpBuffer qry;
3343 
3344  /*
3345  * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3346  * that search_path rather than switching to entry-specific paths.
3347  * Otherwise, it's an old archive that will not restore correctly unless
3348  * we set the search_path as it's expecting.
3349  */
3350  if (AH->public.searchpath)
3351  return;
3352 
3353  if (!schemaName || *schemaName == '\0' ||
3354  (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3355  return; /* no need to do anything */
3356 
3357  qry = createPQExpBuffer();
3358 
3359  appendPQExpBuffer(qry, "SET search_path = %s",
3360  fmtId(schemaName));
3361  if (strcmp(schemaName, "pg_catalog") != 0)
3362  appendPQExpBufferStr(qry, ", pg_catalog");
3363 
3364  if (RestoringToDB(AH))
3365  {
3366  PGresult *res;
3367 
3368  res = PQexec(AH->connection, qry->data);
3369 
3370  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3372  "could not set search_path to \"%s\": %s",
3373  schemaName, PQerrorMessage(AH->connection));
3374 
3375  PQclear(res);
3376  }
3377  else
3378  ahprintf(AH, "%s;\n\n", qry->data);
3379 
3380  if (AH->currSchema)
3381  free(AH->currSchema);
3382  AH->currSchema = pg_strdup(schemaName);
3383 
3384  destroyPQExpBuffer(qry);
3385 }
static int RestoringToDB(ArchiveHandle *AH)
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
char * searchpath
Definition: pg_backup.h:202
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define free(a)
Definition: header.h:65
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897
static const char * modulename

◆ _selectTablespace()

static void _selectTablespace ( ArchiveHandle AH,
const char *  tablespace 
)
static

Definition at line 3392 of file pg_backup_archiver.c.

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currTablespace, PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), free, modulename, _restoreOptions::noTablespace, pg_strdup(), PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), _archiveHandle::public, RestoringToDB(), Archive::ropt, tablespace, and warn_or_exit_horribly().

Referenced by _printTocEntry().

3393 {
3394  RestoreOptions *ropt = AH->public.ropt;
3395  PQExpBuffer qry;
3396  const char *want,
3397  *have;
3398 
3399  /* do nothing in --no-tablespaces mode */
3400  if (ropt->noTablespace)
3401  return;
3402 
3403  have = AH->currTablespace;
3404  want = tablespace;
3405 
3406  /* no need to do anything for non-tablespace object */
3407  if (!want)
3408  return;
3409 
3410  if (have && strcmp(want, have) == 0)
3411  return; /* no need to do anything */
3412 
3413  qry = createPQExpBuffer();
3414 
3415  if (strcmp(want, "") == 0)
3416  {
3417  /* We want the tablespace to be the database's default */
3418  appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3419  }
3420  else
3421  {
3422  /* We want an explicit tablespace */
3423  appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3424  }
3425 
3426  if (RestoringToDB(AH))
3427  {
3428  PGresult *res;
3429 
3430  res = PQexec(AH->connection, qry->data);
3431 
3432  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3434  "could not set default_tablespace to %s: %s",
3435  fmtId(want), PQerrorMessage(AH->connection));
3436 
3437  PQclear(res);
3438  }
3439  else
3440  ahprintf(AH, "%s;\n\n", qry->data);
3441 
3442  if (AH->currTablespace)
3443  free(AH->currTablespace);
3444  AH->currTablespace = pg_strdup(want);
3445 
3446  destroyPQExpBuffer(qry);
3447 }
static int RestoringToDB(ArchiveHandle *AH)
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
RestoreOptions * ropt
Definition: pg_backup.h:184
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * tablespace
Definition: pgbench.c:156
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define free(a)
Definition: header.h:65
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897
static const char * modulename

◆ _setWithOids()

static void _setWithOids ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3325 of file pg_backup_archiver.c.

References _doSetWithOids(), _archiveHandle::currWithOids, and _tocEntry::withOids.

Referenced by _printTocEntry().

3326 {
3327  if (AH->currWithOids != te->withOids)
3328  {
3329  _doSetWithOids(AH, te->withOids);
3330  AH->currWithOids = te->withOids;
3331  }
3332 }
static void _doSetWithOids(ArchiveHandle *AH, const bool withOids)

◆ _tocEntryIsACL()

static bool _tocEntryIsACL ( TocEntry te)
static

Definition at line 3098 of file pg_backup_archiver.c.

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

3099 {
3100  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3101  if (strcmp(te->desc, "ACL") == 0 ||
3102  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3103  strcmp(te->desc, "DEFAULT ACL") == 0)
3104  return true;
3105  return false;
3106 }

◆ _tocEntryRequired()

static teReqs _tocEntryRequired ( TocEntry te,
teSection  curSection,
ArchiveHandle AH 
)
static

Definition at line 2827 of file pg_backup_archiver.c.

References _tocEntryIsACL(), _restoreOptions::aclsSkip, _restoreOptions::binary_upgrade, _restoreOptions::createDB, _restoreOptions::dataOnly, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, DUMP_DATA, DUMP_POST_DATA, DUMP_PRE_DATA, _tocEntry::dumpId, _restoreOptions::dumpSections, _restoreOptions::functionNames, _tocEntry::hadDumper, SimpleStringList::head, _restoreOptions::idWanted, _restoreOptions::indexNames, _tocEntry::nDeps, _restoreOptions::no_comments, _restoreOptions::no_publications, _restoreOptions::no_security_labels, _restoreOptions::no_subscriptions, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_SPECIAL, Archive::ropt, _restoreOptions::schemaExcludeNames, _restoreOptions::schemaNames, _restoreOptions::schemaOnly, SECTION_DATA, SECTION_POST_DATA, SECTION_PRE_DATA, _restoreOptions::selFunction, _restoreOptions::selIndex, _restoreOptions::selTable, _restoreOptions::selTrigger, _restoreOptions::selTypes, _restoreOptions::sequence_data, simple_string_list_member(), _restoreOptions::tableNames, _tocEntry::tag, TocIDRequired(), and _restoreOptions::triggerNames.

Referenced by PrintTOCSummary(), and ProcessArchiveRestoreOptions().

2828 {
2829  teReqs res = REQ_SCHEMA | REQ_DATA;
2830  RestoreOptions *ropt = AH->public.ropt;
2831 
2832  /* These items are treated specially */
2833  if (strcmp(te->desc, "ENCODING") == 0 ||
2834  strcmp(te->desc, "STDSTRINGS") == 0 ||
2835  strcmp(te->desc, "SEARCHPATH") == 0)
2836  return REQ_SPECIAL;
2837 
2838  /*
2839  * DATABASE and DATABASE PROPERTIES also have a special rule: they are
2840  * restored in createDB mode, and not restored otherwise, independently of
2841  * all else.
2842  */
2843  if (strcmp(te->desc, "DATABASE") == 0 ||
2844  strcmp(te->desc, "DATABASE PROPERTIES") == 0)
2845  {
2846  if (ropt->createDB)
2847  return REQ_SCHEMA;
2848  else
2849  return 0;
2850  }
2851 
2852  /*
2853  * Process exclusions that affect certain classes of TOC entries.
2854  */
2855 
2856  /* If it's an ACL, maybe ignore it */
2857  if (ropt->aclsSkip && _tocEntryIsACL(te))
2858  return 0;
2859 
2860  /* If it's a comment, maybe ignore it */
2861  if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
2862  return 0;
2863 
2864  /* If it's a publication, maybe ignore it */
2865  if (ropt->no_publications && strcmp(te->desc, "PUBLICATION") == 0)
2866  return 0;
2867 
2868  /* If it's a security label, maybe ignore it */
2869  if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
2870  return 0;
2871 
2872  /* If it's a subscription, maybe ignore it */
2873  if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
2874  return 0;
2875 
2876  /* Ignore it if section is not to be dumped/restored */
2877  switch (curSection)
2878  {
2879  case SECTION_PRE_DATA:
2880  if (!(ropt->dumpSections & DUMP_PRE_DATA))
2881  return 0;
2882  break;
2883  case SECTION_DATA:
2884  if (!(ropt->dumpSections & DUMP_DATA))
2885  return 0;
2886  break;
2887  case SECTION_POST_DATA:
2888  if (!(ropt->dumpSections & DUMP_POST_DATA))
2889  return 0;
2890  break;
2891  default:
2892  /* shouldn't get here, really, but ignore it */
2893  return 0;
2894  }
2895 
2896  /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
2897  if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2898  return 0;
2899 
2900  /*
2901  * Check options for selective dump/restore.
2902  */
2903  if (strcmp(te->desc, "ACL") == 0 ||
2904  strcmp(te->desc, "COMMENT") == 0 ||
2905  strcmp(te->desc, "SECURITY LABEL") == 0)
2906  {
2907  /* Database properties react to createDB, not selectivity options. */
2908  if (strncmp(te->tag, "DATABASE ", 9) == 0)
2909  {
2910  if (!ropt->createDB)
2911  return 0;
2912  }
2913  else if (ropt->schemaNames.head != NULL ||
2914  ropt->schemaExcludeNames.head != NULL ||
2915  ropt->selTypes)
2916  {
2917  /*
2918  * In a selective dump/restore, we want to restore these dependent
2919  * TOC entry types only if their parent object is being restored.
2920  * Without selectivity options, we let through everything in the
2921  * archive. Note there may be such entries with no parent, eg
2922  * non-default ACLs for built-in objects.
2923  *
2924  * This code depends on the parent having been marked already,
2925  * which should be the case; if it isn't, perhaps due to
2926  * SortTocFromFile rearrangement, skipping the dependent entry
2927  * seems prudent anyway.
2928  *
2929  * Ideally we'd handle, eg, table CHECK constraints this way too.
2930  * But it's hard to tell which of their dependencies is the one to
2931  * consult.
2932  */
2933  if (te->nDeps != 1 ||
2934  TocIDRequired(AH, te->dependencies[0]) == 0)
2935  return 0;
2936  }
2937  }
2938  else
2939  {
2940  /* Apply selective-restore rules for standalone TOC entries. */
2941  if (ropt->schemaNames.head != NULL)
2942  {
2943  /* If no namespace is specified, it means all. */
2944  if (!te->namespace)
2945  return 0;
2946  if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
2947  return 0;
2948  }
2949 
2950  if (ropt->schemaExcludeNames.head != NULL &&
2951  te->namespace &&
2952  simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
2953  return 0;
2954 
2955  if (ropt->selTypes)
2956  {
2957  if (strcmp(te->desc, "TABLE") == 0 ||
2958  strcmp(te->desc, "TABLE DATA") == 0 ||
2959  strcmp(te->desc, "VIEW") == 0 ||
2960  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
2961  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
2962  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
2963  strcmp(te->desc, "SEQUENCE") == 0 ||
2964  strcmp(te->desc, "SEQUENCE SET") == 0)
2965  {
2966  if (!ropt->selTable)
2967  return 0;
2968  if (ropt->tableNames.head != NULL &&
2970  return 0;
2971  }
2972  else if (strcmp(te->desc, "INDEX") == 0)
2973  {
2974  if (!ropt->selIndex)
2975  return 0;
2976  if (ropt->indexNames.head != NULL &&
2978  return 0;
2979  }
2980  else if (strcmp(te->desc, "FUNCTION") == 0 ||
2981  strcmp(te->desc, "AGGREGATE") == 0 ||
2982  strcmp(te->desc, "PROCEDURE") == 0)
2983  {
2984  if (!ropt->selFunction)
2985  return 0;
2986  if (ropt->functionNames.head != NULL &&
2988  return 0;
2989  }
2990  else if (strcmp(te->desc, "TRIGGER") == 0)
2991  {
2992  if (!ropt->selTrigger)
2993  return 0;
2994  if (ropt->triggerNames.head != NULL &&
2996  return 0;
2997  }
2998  else
2999  return 0;
3000  }
3001  }
3002 
3003  /*
3004  * Determine whether the TOC entry contains schema and/or data components,
3005  * and mask off inapplicable REQ bits. If it had a dataDumper, assume
3006  * it's both schema and data. Otherwise it's probably schema-only, but
3007  * there are exceptions.
3008  */
3009  if (!te->hadDumper)
3010  {
3011  /*
3012  * Special Case: If 'SEQUENCE SET' or anything to do with BLOBs, then
3013  * it is considered a data entry. We don't need to check for the
3014  * BLOBS entry or old-style BLOB COMMENTS, because they will have
3015  * hadDumper = true ... but we do need to check new-style BLOB ACLs,
3016  * comments, etc.
3017  */
3018  if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
3019  strcmp(te->desc, "BLOB") == 0 ||
3020  (strcmp(te->desc, "ACL") == 0 &&
3021  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3022  (strcmp(te->desc, "COMMENT") == 0 &&
3023  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3024  (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3025  strncmp(te->tag, "LARGE OBJECT ", 13) == 0))
3026  res = res & REQ_DATA;
3027  else
3028  res = res & ~REQ_DATA;
3029  }
3030 
3031  /* If there's no definition command, there's no schema component */
3032  if (!te->defn || !te->defn[0])
3033  res = res & ~REQ_SCHEMA;
3034 
3035  /*
3036  * Special case: <Init> type with <Max OID> tag; this is obsolete and we
3037  * always ignore it.
3038  */
3039  if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
3040  return 0;
3041 
3042  /* Mask it if we only want schema */
3043  if (ropt->schemaOnly)
3044  {
3045  /*
3046  * The sequence_data option overrides schemaOnly for SEQUENCE SET.
3047  *
3048  * In binary-upgrade mode, even with schemaOnly set, we do not mask
3049  * out large objects. (Only large object definitions, comments and
3050  * other metadata should be generated in binary-upgrade mode, not the
3051  * actual data, but that need not concern us here.)
3052  */
3053  if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
3054  !(ropt->binary_upgrade &&
3055  (strcmp(te->desc, "BLOB") == 0 ||
3056  (strcmp(te->desc, "ACL") == 0 &&
3057  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3058  (strcmp(te->desc, "COMMENT") == 0 &&
3059  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3060  (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3061  strncmp(te->tag, "LARGE OBJECT ", 13) == 0))))
3062  res = res & REQ_SCHEMA;
3063  }
3064 
3065  /* Mask it if we only want data */
3066  if (ropt->dataOnly)
3067  res = res & REQ_DATA;
3068 
3069  return res;
3070 }
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition: simple_list.c:87
SimpleStringList triggerNames
Definition: pg_backup.h:106
RestoreOptions * ropt
Definition: pg_backup.h:184
SimpleStringList schemaNames
Definition: pg_backup.h:104
static bool _tocEntryIsACL(TocEntry *te)
bool * idWanted
Definition: pg_backup.h:122
SimpleStringList tableNames
Definition: pg_backup.h:107
DumpId * dependencies
SimpleStringList functionNames
Definition: pg_backup.h:103
int no_security_labels
Definition: pg_backup.h:79
int no_subscriptions
Definition: pg_backup.h:80
teReqs TocIDRequired(ArchiveHandle *AH, DumpId id)
SimpleStringListCell * head
Definition: simple_list.h:42
SimpleStringList indexNames
Definition: pg_backup.h:102
int no_publications
Definition: pg_backup.h:78
SimpleStringList schemaExcludeNames
Definition: pg_backup.h:105

◆ _tocEntryRestorePass()

static RestorePass _tocEntryRestorePass ( TocEntry te)
static

Definition at line 3078 of file pg_backup_archiver.c.

References _tocEntry::desc, RESTORE_PASS_ACL, and RESTORE_PASS_MAIN.

Referenced by move_to_ready_list(), reduce_dependencies(), restore_toc_entries_prefork(), and RestoreArchive().

3079 {
3080  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3081  if (strcmp(te->desc, "ACL") == 0 ||
3082  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3083  strcmp(te->desc, "DEFAULT ACL") == 0)
3084  return RESTORE_PASS_ACL;
3085  if (strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3086  return RESTORE_PASS_REFRESH;
3087  return RESTORE_PASS_MAIN;
3088 }

◆ ahlog()

void ahlog ( ArchiveHandle AH,
int  level,
const char *  fmt,
  ... 
)

◆ ahprintf()

int ahprintf ( ArchiveHandle AH,
const char *  fmt,
  ... 
)

Definition at line 1611 of file pg_backup_archiver.c.

References ahwrite(), generate_unaccent_rules::args, free, pg_malloc(), and pvsnprintf().

Referenced by _disableTriggersIfNecessary(), _doSetFixedOutputState(), _doSetSessionAuth(), _doSetWithOids(), _enableTriggersIfNecessary(), _EndBlob(), _EndBlobs(), _EndData(), _PrintExtraToc(), _PrintTocData(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), _selectTablespace(), _StartBlob(), _StartBlobs(), _WriteBlobData(), DropBlobIfExists(), dump_lo_buf(), dumpTimestamp(), EndRestoreBlob(), EndRestoreBlobs(), PrintTOCSummary(), restore_toc_entry(), RestoreArchive(), StartRestoreBlob(), and StartRestoreBlobs().

1612 {
1613  char *p;
1614  size_t len = 128; /* initial assumption about buffer size */
1615  size_t cnt;
1616 
1617  for (;;)
1618  {
1619  va_list args;
1620 
1621  /* Allocate work buffer. */
1622  p = (char *) pg_malloc(len);
1623 
1624  /* Try to format the data. */
1625  va_start(args, fmt);
1626  cnt = pvsnprintf(p, len, fmt, args);
1627  va_end(args);
1628 
1629  if (cnt < len)
1630  break; /* success */
1631 
1632  /* Release buffer and loop around to try again with larger len. */
1633  free(p);
1634  len = cnt;
1635  }
1636 
1637  ahwrite(p, 1, cnt, AH);
1638  free(p);
1639  return (int) cnt;
1640 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition: psprintf.c:104
#define free(a)
Definition: header.h:65
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)

◆ ahwrite()

void ahwrite ( const void *  ptr,
size_t  size,
size_t  nmemb,
ArchiveHandle AH 
)

Definition at line 1713 of file pg_backup_archiver.c.

References _archiveHandle::CustomOutPtr, dump_lo_buf(), ExecuteSqlCommandBuf(), _archiveHandle::gzOut, GZWRITE, _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, _archiveHandle::lo_buf_used, _archiveHandle::OF, _archiveHandle::public, remaining, RestoringToDB(), WRITE_ERROR_EXIT, and _archiveHandle::writingBlob.

Referenced by _LoadBlobs(), _PrintFileData(), _PrintTocData(), _WriteData(), ahprintf(), EndCompressor(), and ReadDataFromArchiveNone().

1714 {
1715  int bytes_written = 0;
1716 
1717  if (AH->writingBlob)
1718  {
1719  size_t remaining = size * nmemb;
1720 
1721  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1722  {
1723  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1724 
1725  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1726  ptr = (const void *) ((const char *) ptr + avail);
1727  remaining -= avail;
1728  AH->lo_buf_used += avail;
1729  dump_lo_buf(AH);
1730  }
1731 
1732  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1733  AH->lo_buf_used += remaining;
1734 
1735  bytes_written = size * nmemb;
1736  }
1737  else if (AH->gzOut)
1738  bytes_written = GZWRITE(ptr, size, nmemb, AH->OF);
1739  else if (AH->CustomOutPtr)
1740  bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1741 
1742  else
1743  {
1744  /*
1745  * If we're doing a restore, and it's direct to DB, and we're
1746  * connected then send it to the DB.
1747  */
1748  if (RestoringToDB(AH))
1749  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1750  else
1751  bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size;
1752  }
1753 
1754  if (bytes_written != size * nmemb)
1756 
1757  return;
1758 }
int remaining
Definition: informix.c:692
static int RestoringToDB(ArchiveHandle *AH)
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
Definition: pg_backup_db.c:561
static void dump_lo_buf(ArchiveHandle *AH)
#define GZWRITE(p, s, n, fh)
CustomOutPtrType CustomOutPtr
#define WRITE_ERROR_EXIT

◆ ArchiveEntry()

void ArchiveEntry ( Archive AHX,
CatalogId  catalogId,
DumpId  dumpId,
const char *  tag,
const char *  namespace,
const char *  tablespace,
const char *  owner,
bool  withOids,
const char *  desc,
teSection  section,
const char *  defn,
const char *  dropStmt,
const char *  copyStmt,
const DumpId deps,
int  nDeps,
DataDumperPtr  dumpFn,
void *  dumpArg 
)

Definition at line 1052 of file pg_backup_archiver.c.

References _archiveHandle::ArchiveEntryPtr, _tocEntry::catalogId, _tocEntry::dataDumper, _tocEntry::dataDumperArg, _tocEntry::dependencies, _tocEntry::dumpId, _tocEntry::formatData, _tocEntry::hadDumper, _archiveHandle::maxDumpId, _tocEntry::nDeps, _tocEntry::next, pg_malloc(), pg_malloc0(), pg_strdup(), _tocEntry::prev, _tocEntry::section, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocCount, and true.

Referenced by dumpAccessMethod(), dumpACL(), dumpAgg(), dumpAttrDef(), dumpBaseType(), dumpBlob(), dumpCast(), dumpCollation(), dumpComment(), dumpCompositeType(), dumpCompositeTypeColComments(), dumpConstraint(), dumpConversion(), dumpDatabase(), dumpDefaultACL(), dumpDomain(), dumpDumpableObject(), dumpEncoding(), dumpEnumType(), dumpEventTrigger(), dumpExtension(), dumpForeignDataWrapper(), dumpForeignServer(), dumpFunc(), dumpIndex(), dumpIndexAttach(), dumpNamespace(), dumpOpclass(), dumpOpfamily(), dumpOpr(), dumpPolicy(), dumpProcLang(), dumpPublication(), dumpPublicationTable(), dumpRangeType(), dumpRule(), dumpSearchPath(), dumpSecLabel(), dumpSequence(), dumpSequenceData(), dumpShellType(), dumpStatisticsExt(), dumpStdStrings(), dumpSubscription(), dumpTableComment(), dumpTableData(), dumpTableSchema(), dumpTableSecLabel(), dumpTransform(), dumpTrigger(), dumpTSConfig(), dumpTSDictionary(), dumpTSParser(), dumpTSTemplate(), dumpUndefinedType(), dumpUserMappings(), and refreshMatViewData().

1063 {
1064  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1065  TocEntry *newToc;
1066 
1067  newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1068 
1069  AH->tocCount++;
1070  if (dumpId > AH->maxDumpId)
1071  AH->maxDumpId = dumpId;
1072 
1073  newToc->prev = AH->toc->prev;
1074  newToc->next = AH->toc;
1075  AH->toc->prev->next = newToc;
1076  AH->toc->prev = newToc;
1077 
1078  newToc->catalogId = catalogId;
1079  newToc->dumpId = dumpId;
1080  newToc->section = section;
1081 
1082  newToc->tag = pg_strdup(tag);
1083  newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
1084  newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
1085  newToc->owner = pg_strdup(owner);
1086  newToc->withOids = withOids;
1087  newToc->desc = pg_strdup(desc);
1088  newToc->defn = pg_strdup(defn);
1089  newToc->dropStmt = pg_strdup(dropStmt);
1090  newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
1091 
1092  if (nDeps > 0)
1093  {
1094  newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
1095  memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
1096  newToc->nDeps = nDeps;
1097  }
1098  else
1099  {
1100  newToc->dependencies = NULL;
1101  newToc->nDeps = 0;
1102  }
1103 
1104  newToc->dataDumper = dumpFn;
1105  newToc->dataDumperArg = dumpArg;
1106  newToc->hadDumper = dumpFn ? true : false;
1107 
1108  newToc->formatData = NULL;
1109 
1110  if (AH->ArchiveEntryPtr != NULL)
1111  AH->ArchiveEntryPtr(AH, newToc);
1112 }
struct _tocEntry * next
int DumpId
Definition: pg_backup.h:235
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
CatalogId catalogId
void * dataDumperArg
DataDumperPtr dataDumper
teSection section
#define true
Definition: c.h:279
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
struct _tocEntry * toc
DumpId * dependencies
char * tablespace
Definition: pgbench.c:156
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
struct _tocEntry * prev
ArchiveEntryPtrType ArchiveEntryPtr

◆ archprintf()

int archprintf ( Archive AH,
const char *  fmt,
  ... 
)

Definition at line 1478 of file pg_backup_archiver.c.

References generate_unaccent_rules::args, free, pg_malloc(), pvsnprintf(), and WriteData().

1479 {
1480  char *p;
1481  size_t len = 128; /* initial assumption about buffer size */
1482  size_t cnt;
1483 
1484  for (;;)
1485  {
1486  va_list args;
1487 
1488  /* Allocate work buffer. */
1489  p = (char *) pg_malloc(len);
1490 
1491  /* Try to format the data. */
1492  va_start(args, fmt);
1493  cnt = pvsnprintf(p, len, fmt, args);
1494  va_end(args);
1495 
1496  if (cnt < len)
1497  break; /* success */
1498 
1499  /* Release buffer and loop around to try again with larger len. */
1500  free(p);
1501  len = cnt;
1502  }
1503 
1504  WriteData(AH, p, cnt);
1505  free(p);
1506  return (int) cnt;
1507 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition: psprintf.c:104
void WriteData(Archive *AHX, const void *data, size_t dLen)
#define free(a)
Definition: header.h:65

◆ archputs()

void archputs ( const char *  s,
Archive AH 
)

Definition at line 1470 of file pg_backup_archiver.c.

References WriteData().

Referenced by dumpTableData_insert().

1471 {
1472  WriteData(AH, s, strlen(s));
1473  return;
1474 }
void WriteData(Archive *AHX, const void *data, size_t dLen)

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1852 of file pg_backup_archiver.c.

References _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, exit_horribly(), _archiveHandle::maxDumpId, modulename, _tocEntry::nDeps, _tocEntry::next, pg_malloc0(), _archiveHandle::tableDataId, _archiveHandle::toc, and _archiveHandle::tocsByDumpId.

Referenced by getTocEntryByDumpId(), and RestoreArchive().

1853 {
1854  DumpId maxDumpId = AH->maxDumpId;
1855  TocEntry *te;
1856 
1857  AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
1858  AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1859 
1860  for (te = AH->toc->next; te != AH->toc; te = te->next)
1861  {
1862  /* this check is purely paranoia, maxDumpId should be correct */
1863  if (te->dumpId <= 0 || te->dumpId > maxDumpId)
1864  exit_horribly(modulename, "bad dumpId\n");
1865 
1866  /* tocsByDumpId indexes all TOCs by their dump ID */
1867  AH->tocsByDumpId[te->dumpId] = te;
1868 
1869  /*
1870  * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1871  * TOC entry that has a DATA item. We compute this by reversing the
1872  * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1873  * just one dependency and it is the TABLE item.
1874  */
1875  if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
1876  {
1877  DumpId tableId = te->dependencies[0];
1878 
1879  /*
1880  * The TABLE item might not have been in the archive, if this was
1881  * a data-only dump; but its dump ID should be less than its data
1882  * item's dump ID, so there should be a place for it in the array.
1883  */
1884  if (tableId <= 0 || tableId > maxDumpId)
1885  exit_horribly(modulename, "bad table dumpId for TABLE DATA item\n");
1886 
1887  AH->tableDataId[tableId] = te->dumpId;
1888  }
1889  }
1890 }
struct _tocEntry * next
int DumpId
Definition: pg_backup.h:235
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
struct _tocEntry * toc
DumpId * dependencies
struct _tocEntry ** tocsByDumpId
void exit_horribly(const char *modulename, const char *fmt,...)
static const char * modulename

◆ checkSeek()

bool checkSeek ( FILE *  fp)

Definition at line 3872 of file pg_backup_archiver.c.

References fseeko, ftello, and pgoff_t.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

3873 {
3874  pgoff_t tpos;
3875 
3876  /*
3877  * If pgoff_t is wider than long, we must have "real" fseeko and not an
3878  * emulation using fseek. Otherwise report no seek capability.
3879  */
3880 #ifndef HAVE_FSEEKO
3881  if (sizeof(pgoff_t) > sizeof(long))
3882  return false;
3883 #endif
3884 
3885  /* Check that ftello works on this file */
3886  tpos = ftello(fp);
3887  if (tpos < 0)
3888  return false;
3889 
3890  /*
3891  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
3892  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
3893  * successful no-op even on files that are otherwise unseekable.
3894  */
3895  if (fseeko(fp, tpos, SEEK_SET) != 0)
3896  return false;
3897 
3898  return true;
3899 }
#define pgoff_t
Definition: win32_port.h:206
#define ftello(stream)
Definition: win32_port.h:215
#define fseeko(stream, offset, origin)
Definition: win32_port.h:212

◆ CloneArchive()

ArchiveHandle* CloneArchive ( ArchiveHandle AH)

Definition at line 4722 of file pg_backup_archiver.c.

References _doSetFixedOutputState(), appendConnStrVal(), appendPQExpBuffer(), archModeRead, Assert, _archiveHandle::ClonePtr, _archiveHandle::connCancel, ConnectDatabase(), _archiveHandle::connection, connstr, _archiveHandle::currSchema, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::currWithOids, PQExpBufferData::data, _restoreOptions::dbname, initPQExpBuffer(), _archiveHandle::mode, Archive::n_errors, pg_malloc(), pg_strdup(), _restoreOptions::pghost, pghost, _restoreOptions::pgport, pgport, PQdb(), PQhost(), PQport(), PQuser(), _restoreOptions::promptPassword, _archiveHandle::public, Archive::ropt, _archiveHandle::savedPassword, _archiveHandle::sqlparse, termPQExpBuffer(), TRI_NO, _restoreOptions::username, and username.

Referenced by RunWorker().

4723 {
4724  ArchiveHandle *clone;
4725 
4726  /* Make a "flat" copy */
4727  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4728  memcpy(clone, AH, sizeof(ArchiveHandle));
4729 
4730  /* Handle format-independent fields */
4731  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4732 
4733  /* The clone will have its own connection, so disregard connection state */
4734  clone->connection = NULL;
4735  clone->connCancel = NULL;
4736  clone->currUser = NULL;
4737  clone->currSchema = NULL;
4738  clone->currTablespace = NULL;
4739  clone->currWithOids = -1;
4740 
4741  /* savedPassword must be local in case we change it while connecting */
4742  if (clone->savedPassword)
4743  clone->savedPassword = pg_strdup(clone->savedPassword);
4744 
4745  /* clone has its own error count, too */
4746  clone->public.n_errors = 0;
4747 
4748  /*
4749  * Connect our new clone object to the database: In parallel restore the
4750  * parent is already disconnected, because we can connect the worker
4751  * processes independently to the database (no snapshot sync required). In
4752  * parallel backup we clone the parent's existing connection.
4753  */
4754  if (AH->mode == archModeRead)
4755  {
4756  RestoreOptions *ropt = AH->public.ropt;
4757 
4758  Assert(AH->connection == NULL);
4759 
4760  /* this also sets clone->connection */
4761  ConnectDatabase((Archive *) clone, ropt->dbname,
4762  ropt->pghost, ropt->pgport, ropt->username,
4763  ropt->promptPassword);
4764 
4765  /* re-establish fixed state */
4766  _doSetFixedOutputState(clone);
4767  }
4768  else
4769  {
4771  char *pghost;
4772  char *pgport;
4773  char *username;
4774 
4775  Assert(AH->connection != NULL);
4776 
4777  /*
4778  * Even though we are technically accessing the parent's database
4779  * object here, these functions are fine to be called like that
4780  * because all just return a pointer and do not actually send/receive
4781  * any data to/from the database.
4782  */
4783  initPQExpBuffer(&connstr);
4784  appendPQExpBuffer(&connstr, "dbname=");
4785  appendConnStrVal(&connstr, PQdb(AH->connection));
4786  pghost = PQhost(AH->connection);
4787  pgport = PQport(AH->connection);
4788  username = PQuser(AH->connection);
4789 
4790  /* this also sets clone->connection */
4791  ConnectDatabase((Archive *) clone, connstr.data,
4792  pghost, pgport, username, TRI_NO);
4793 
4794  termPQExpBuffer(&connstr);
4795  /* setupDumpWorker will fix up connection state */
4796  }
4797 
4798  /* Let the format-specific code have a chance too */
4799  clone->ClonePtr(clone);
4800 
4801  Assert(clone->connection != NULL);
4802  return clone;
4803 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
RestoreOptions * ropt
Definition: pg_backup.h:184
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
char * username
Definition: pg_backup.h:113
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:551
char * PQport(const PGconn *conn)
Definition: fe-connect.c:6035
int n_errors
Definition: pg_backup.h:207
PGcancel *volatile connCancel
char * PQuser(const PGconn *conn)
Definition: fe-connect.c:5991
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void _doSetFixedOutputState(ArchiveHandle *AH)
sqlparseInfo sqlparse
char * pghost
Definition: pgbench.c:193
static char * username
Definition: initdb.c:132
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:6016
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:5983
#define Assert(condition)
Definition: c.h:699
ClonePtrType ClonePtr
char * pgport
Definition: pgbench.c:194
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
void ConnectDatabase(Archive *AH, const char *dbname, const char *pghost, const char *pgport, const char *username, trivalue prompt_password)
Definition: pg_backup_db.c:240
static char * connstr
Definition: pg_dumpall.c:59
trivalue promptPassword
Definition: pg_backup.h:115

◆ CloseArchive()

void CloseArchive ( Archive AHX)

Definition at line 236 of file pg_backup_archiver.c.

References _archiveHandle::ClosePtr, exit_horribly(), GZCLOSE, _archiveHandle::gzOut, modulename, _archiveHandle::OF, and strerror().

Referenced by main().

237 {
238  int res = 0;
239  ArchiveHandle *AH = (ArchiveHandle *) AHX;
240 
241  AH->ClosePtr(AH);
242 
243  /* Close the output */
244  if (AH->gzOut)
245  res = GZCLOSE(AH->OF);
246  else if (AH->OF != stdout)
247  res = fclose(AH->OF);
248 
249  if (res != 0)
250  exit_horribly(modulename, "could not close output file: %s\n",
251  strerror(errno));
252 }
#define GZCLOSE(fh)
void exit_horribly(const char *modulename, const char *fmt,...)
const char * strerror(int errnum)
Definition: strerror.c:19
ClosePtrType ClosePtr
static const char * modulename

◆ CreateArchive()

Archive* CreateArchive ( const char *  FileSpec,
const ArchiveFormat  fmt,
const int  compression,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupDumpWorker 
)

Definition at line 213 of file pg_backup_archiver.c.

References _allocAH().

Referenced by main().

217 {
218  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, dosync,
219  mode, setupDumpWorker);
220 
221  return (Archive *) AH;
222 }
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
static bool dosync
Definition: pg_dump.c:95
static void setupDumpWorker(Archive *AHX)
Definition: pg_dump.c:1180

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 4811 of file pg_backup_archiver.c.

References Assert, _archiveHandle::connection, sqlparseInfo::curCmd, _archiveHandle::currSchema, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::DeClonePtr, destroyPQExpBuffer(), free, _archiveHandle::savedPassword, and _archiveHandle::sqlparse.

Referenced by RunWorker().

4812 {
4813  /* Should not have an open database connection */
4814  Assert(AH->connection == NULL);
4815 
4816  /* Clear format-specific state */
4817  AH->DeClonePtr(AH);
4818 
4819  /* Clear state allocated by CloneArchive */
4820  if (AH->sqlparse.curCmd)
4822 
4823  /* Clear any connection-local state */
4824  if (AH->currUser)
4825  free(AH->currUser);
4826  if (AH->currSchema)
4827  free(AH->currSchema);
4828  if (AH->currTablespace)
4829  free(AH->currTablespace);
4830  if (AH->savedPassword)
4831  free(AH->savedPassword);
4832 
4833  free(AH);
4834 }
PQExpBuffer curCmd
DeClonePtrType DeClonePtr
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
sqlparseInfo sqlparse
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:699

◆ dump_lo_buf()

static void dump_lo_buf ( ArchiveHandle AH)
static

Definition at line 1670 of file pg_backup_archiver.c.

References ahlog(), ahprintf(), appendByteaLiteralAHX, buf, _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), exit_horribly(), _archiveHandle::lo_buf, _archiveHandle::lo_buf_used, lo_write(), _archiveHandle::loFd, modulename, ngettext, and _archiveHandle::writingBlob.

Referenced by ahwrite(), and EndRestoreBlob().

1671 {
1672  if (AH->connection)
1673  {
1674  size_t res;
1675 
1676  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1677  ahlog(AH, 5, ngettext("wrote %lu byte of large object data (result = %lu)\n",
1678  "wrote %lu bytes of large object data (result = %lu)\n",
1679  AH->lo_buf_used),
1680  (unsigned long) AH->lo_buf_used, (unsigned long) res);
1681  if (res != AH->lo_buf_used)
1683  "could not write to large object (result: %lu, expected: %lu)\n",
1684  (unsigned long) res, (unsigned long) AH->lo_buf_used);
1685  }
1686  else
1687  {
1689 
1691  (const unsigned char *) AH->lo_buf,
1692  AH->lo_buf_used,
1693  AH);
1694 
1695  /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1696  AH->writingBlob = 0;
1697  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1698  AH->writingBlob = 1;
1699 
1700  destroyPQExpBuffer(buf);
1701  }
1702  AH->lo_buf_used = 0;
1703 }
#define appendByteaLiteralAHX(buf, str, len, AH)
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
static char * buf
Definition: pg_test_fsync.c:67
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:170
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
#define ngettext(s, p, n)
Definition: c.h:1022
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void exit_horribly(const char *modulename, const char *fmt,...)
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
static const char * modulename

◆ dumpOptionsFromRestoreOptions()

DumpOptions* dumpOptionsFromRestoreOptions ( RestoreOptions ropt)

Definition at line 155 of file pg_backup_archiver.c.

References _restoreOptions::aclsSkip, _dumpOptions::aclsSkip, _restoreOptions::column_inserts, _dumpOptions::column_inserts, _restoreOptions::createDB, _restoreOptions::dataOnly, _dumpOptions::dataOnly, _restoreOptions::disable_dollar_quoting, _dumpOptions::disable_dollar_quoting, _restoreOptions::disable_triggers, _dumpOptions::disable_triggers, _restoreOptions::dropSchema, _restoreOptions::dump_inserts, _dumpOptions::dump_inserts, _restoreOptions::dumpSections, _dumpOptions::dumpSections, _restoreOptions::enable_row_security, _dumpOptions::enable_row_security, _restoreOptions::if_exists, _dumpOptions::if_exists, _restoreOptions::include_everything, _dumpOptions::include_everything, _restoreOptions::lockWaitTimeout, _dumpOptions::lockWaitTimeout, NewDumpOptions(), _restoreOptions::no_comments, _dumpOptions::no_comments, _restoreOptions::no_publications, _dumpOptions::no_publications, _restoreOptions::no_security_labels, _dumpOptions::no_security_labels, _restoreOptions::no_subscriptions, _dumpOptions::no_subscriptions, _restoreOptions::noOwner, _restoreOptions::noTablespace, _dumpOptions::outputClean, _dumpOptions::outputCreateDB, _dumpOptions::outputNoOwner, _dumpOptions::outputNoTablespaces, _dumpOptions::outputSuperuser, _restoreOptions::schemaOnly, _dumpOptions::schemaOnly, _restoreOptions::sequence_data, _dumpOptions::sequence_data, _restoreOptions::superuser, _restoreOptions::use_setsessauth, and _dumpOptions::use_setsessauth.

Referenced by SetArchiveOptions().

156 {
157  DumpOptions *dopt = NewDumpOptions();
158 
159  /* this is the inverse of what's at the end of pg_dump.c's main() */
160  dopt->outputClean = ropt->dropSchema;
161  dopt->dataOnly = ropt->dataOnly;
162  dopt->schemaOnly = ropt->schemaOnly;
163  dopt->if_exists = ropt->if_exists;
164  dopt->column_inserts = ropt->column_inserts;
165  dopt->dumpSections = ropt->dumpSections;
166  dopt->aclsSkip = ropt->aclsSkip;
167  dopt->outputSuperuser = ropt->superuser;
168  dopt->outputCreateDB = ropt->createDB;
169  dopt->outputNoOwner = ropt->noOwner;
170  dopt->outputNoTablespaces = ropt->noTablespace;
171  dopt->disable_triggers = ropt->disable_triggers;
172  dopt->use_setsessauth = ropt->use_setsessauth;
174  dopt->dump_inserts = ropt->dump_inserts;
175  dopt->no_comments = ropt->no_comments;
176  dopt->no_publications = ropt->no_publications;
178  dopt->no_subscriptions = ropt->no_subscriptions;
179  dopt->lockWaitTimeout = ropt->lockWaitTimeout;
182  dopt->sequence_data = ropt->sequence_data;
183 
184  return dopt;
185 }
int column_inserts
Definition: pg_backup.h:148
int disable_triggers
Definition: pg_backup.h:158
int disable_dollar_quoting
Definition: pg_backup.h:73
bool schemaOnly
Definition: pg_backup.h:139
int no_subscriptions
Definition: pg_backup.h:153
int no_publications
Definition: pg_backup.h:152
DumpOptions * NewDumpOptions(void)
int sequence_data
Definition: pg_backup.h:174
const char * lockWaitTimeout
Definition: pg_backup.h:89
int use_setsessauth
Definition: pg_backup.h:160
int disable_dollar_quoting
Definition: pg_backup.h:146
int column_inserts
Definition: pg_backup.h:75
const char * lockWaitTimeout
Definition: pg_backup.h:143
bool dataOnly
Definition: pg_backup.h:140
bool include_everything
Definition: pg_backup.h:165
char * outputSuperuser
Definition: pg_backup.h:172
int include_everything
Definition: pg_backup.h:90
int no_security_labels
Definition: pg_backup.h:79
int dumpSections
Definition: pg_backup.h:141
int enable_row_security
Definition: pg_backup.h:123
int dump_inserts
Definition: pg_backup.h:147
int outputNoOwner
Definition: pg_backup.h:171
int no_security_labels
Definition: pg_backup.h:151
int no_subscriptions
Definition: pg_backup.h:80
char * superuser
Definition: pg_backup.h:70
bool aclsSkip
Definition: pg_backup.h:142
int use_setsessauth
Definition: pg_backup.h:68
int enable_row_security
Definition: pg_backup.h:161
int outputCreateDB
Definition: pg_backup.h:168
int outputClean
Definition: pg_backup.h:167
int no_comments
Definition: pg_backup.h:150
int outputNoTablespaces
Definition: pg_backup.h:159
int no_publications
Definition: pg_backup.h:78
int disable_triggers
Definition: pg_backup.h:66

◆ dumpTimestamp()

static void dumpTimestamp ( ArchiveHandle AH,
const char *  msg,
time_t  tim 
)
static

Definition at line 3906 of file pg_backup_archiver.c.

References ahprintf(), buf, and PGDUMP_STRFTIME_FMT.

Referenced by RestoreArchive().

3907 {
3908  char buf[64];
3909 
3910  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
3911  ahprintf(AH, "-- %s %s\n\n", msg, buf);
3912 }
static char * buf
Definition: pg_test_fsync.c:67
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33

◆ EndBlob()

int EndBlob ( Archive AHX,
Oid  oid 
)

Definition at line 1245 of file pg_backup_archiver.c.

References _archiveHandle::currToc, and _archiveHandle::EndBlobPtr.

Referenced by dumpBlobs().

1246 {
1247  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1248 
1249  if (AH->EndBlobPtr)
1250  AH->EndBlobPtr(AH, AH->currToc, oid);
1251 
1252  return 1;
1253 }
struct _tocEntry * currToc
EndBlobPtrType EndBlobPtr

◆ EndRestoreBlob()

void EndRestoreBlob ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1349 of file pg_backup_archiver.c.

References ahprintf(), _archiveHandle::connection, dump_lo_buf(), _archiveHandle::lo_buf_used, lo_close(), _archiveHandle::loFd, and _archiveHandle::writingBlob.

Referenced by _LoadBlobs().

1350 {
1351  if (AH->lo_buf_used > 0)
1352  {
1353  /* Write remaining bytes from the LO buffer */
1354  dump_lo_buf(AH);
1355  }
1356 
1357  AH->writingBlob = 0;
1358 
1359  if (AH->connection)
1360  {
1361  lo_close(AH->connection, AH->loFd);
1362  AH->loFd = -1;
1363  }
1364  else
1365  {
1366  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1367  }
1368 }
int lo_close(PGconn *conn, int fd)
Definition: fe-lobj.c:99
static void dump_lo_buf(ArchiveHandle *AH)
int ahprintf(ArchiveHandle *AH, const char *fmt,...)

◆ EndRestoreBlobs()

void EndRestoreBlobs ( ArchiveHandle AH)

Definition at line 1282 of file pg_backup_archiver.c.

References ahlog(), ahprintf(), _archiveHandle::blobCount, CommitTransaction(), _archiveHandle::connection, ngettext, _archiveHandle::public, Archive::ropt, and _restoreOptions::single_txn.

Referenced by _LoadBlobs().

1283 {
1284  RestoreOptions *ropt = AH->public.ropt;
1285 
1286  if (!ropt->single_txn)
1287  {
1288  if (AH->connection)
1289  CommitTransaction(&AH->public);
1290  else
1291  ahprintf(AH, "COMMIT;\n\n");
1292  }
1293 
1294  ahlog(AH, 1, ngettext("restored %d large object\n",
1295  "restored %d large objects\n",
1296  AH->blobCount),
1297  AH->blobCount);
1298 }
RestoreOptions * ropt
Definition: pg_backup.h:184
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
#define ngettext(s, p, n)
Definition: c.h:1022
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
static void CommitTransaction(void)
Definition: xact.c:1933

◆ fix_dependencies()

static void fix_dependencies ( ArchiveHandle AH)
static

Definition at line 4438 of file pg_backup_archiver.c.

References _tocEntry::depCount, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, i, identify_locking_dependencies(), K_VERS_1_11, _tocEntry::lockDeps, _tocEntry::nDeps, _tocEntry::next, _tocEntry::nLockDeps, _tocEntry::nRevDeps, _tocEntry::par_next, _tocEntry::par_prev, pg_malloc(), repoint_table_dependencies(), _tocEntry::revDeps, _archiveHandle::toc, _archiveHandle::tocsByDumpId, and _archiveHandle::version.

Referenced by IndexSetParentIndex(), and restore_toc_entries_prefork().

4439 {
4440  TocEntry *te;
4441  int i;
4442 
4443  /*
4444  * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4445  * items are marked as not being in any parallel-processing list.
4446  */
4447  for (te = AH->toc->next; te != AH->toc; te = te->next)
4448  {
4449  te->depCount = te->nDeps;
4450  te->revDeps = NULL;
4451  te->nRevDeps = 0;
4452  te->par_prev = NULL;
4453  te->par_next = NULL;
4454  }
4455 
4456  /*
4457  * POST_DATA items that are shown as depending on a table need to be
4458  * re-pointed to depend on that table's data, instead. This ensures they
4459  * won't get scheduled until the data has been loaded.
4460  */
4462 
4463  /*
4464  * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4465  * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4466  * one BLOB COMMENTS in such files.)
4467  */
4468  if (AH->version < K_VERS_1_11)
4469  {
4470  for (te = AH->toc->next; te != AH->toc; te = te->next)
4471  {
4472  if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4473  {
4474  TocEntry *te2;
4475 
4476  for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4477  {
4478  if (strcmp(te2->desc, "BLOBS") == 0)
4479  {
4480  te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4481  te->dependencies[0] = te2->dumpId;
4482  te->nDeps++;
4483  te->depCount++;
4484  break;
4485  }
4486  }
4487  break;
4488  }
4489  }
4490  }
4491 
4492  /*
4493  * At this point we start to build the revDeps reverse-dependency arrays,
4494  * so all changes of dependencies must be complete.
4495  */
4496 
4497  /*
4498  * Count the incoming dependencies for each item. Also, it is possible
4499  * that the dependencies list items that are not in the archive at all
4500  * (that should not happen in 9.2 and later, but is highly likely in older
4501  * archives). Subtract such items from the depCounts.
4502  */
4503  for (te = AH->toc->next; te != AH->toc; te = te->next)
4504  {
4505  for (i = 0; i < te->nDeps; i++)
4506  {
4507  DumpId depid = te->dependencies[i];
4508 
4509  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4510  AH->tocsByDumpId[depid]->nRevDeps++;
4511  else
4512  te->depCount--;
4513  }
4514  }
4515 
4516  /*
4517  * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4518  * it as a counter below.
4519  */
4520  for (te = AH->toc->next; te != AH->toc; te = te->next)
4521  {
4522  if (te->nRevDeps > 0)
4523  te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4524  te->nRevDeps = 0;
4525  }
4526 
4527  /*
4528  * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4529  * better agree with the loops above.
4530  */
4531  for (te = AH->toc->next; te != AH->toc; te = te->next)
4532  {
4533  for (i = 0; i < te->nDeps; i++)
4534  {
4535  DumpId depid = te->dependencies[i];
4536 
4537  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4538  {
4539  TocEntry *otherte = AH->tocsByDumpId[depid];
4540 
4541  otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4542  }
4543  }
4544  }
4545 
4546  /*
4547  * Lastly, work out the locking dependencies.
4548  */
4549  for (te = AH->toc->next; te != AH->toc; te = te->next)
4550  {
4551  te->lockDeps = NULL;
4552  te->nLockDeps = 0;
4554  }
4555 }
struct _tocEntry * next
int DumpId
Definition: pg_backup.h:235
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
DumpId * lockDeps
struct _tocEntry * toc
DumpId * dependencies
struct _tocEntry * par_prev
struct _tocEntry * par_next
DumpId * revDeps
struct _tocEntry ** tocsByDumpId
static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
int i
#define K_VERS_1_11
static void repoint_table_dependencies(ArchiveHandle *AH)

◆ get_next_work_item()

static TocEntry * get_next_work_item ( ArchiveHandle AH,
TocEntry ready_list,
ParallelState pstate 
)
static

Definition at line 4289 of file pg_backup_archiver.c.

References ahlog(), has_lock_conflicts(), i, ParallelState::numWorkers, _tocEntry::par_next, _tocEntry::section, SECTION_DATA, and ParallelState::te.

Referenced by restore_toc_entries_parallel().

4291 {
4292  bool pref_non_data = false; /* or get from AH->ropt */
4293  TocEntry *data_te = NULL;
4294  TocEntry *te;
4295  int i,
4296  k;
4297 
4298  /*
4299  * Bogus heuristics for pref_non_data
4300  */
4301  if (pref_non_data)
4302  {
4303  int count = 0;
4304 
4305  for (k = 0; k < pstate->numWorkers; k++)
4306  {
4307  TocEntry *running_te = pstate->te[k];
4308 
4309  if (running_te != NULL &&
4310  running_te->section == SECTION_DATA)
4311  count++;
4312  }
4313  if (pstate->numWorkers == 0 || count * 4 < pstate->numWorkers)
4314  pref_non_data = false;
4315  }
4316 
4317  /*
4318  * Search the ready_list until we find a suitable item.
4319  */
4320  for (te = ready_list->par_next; te != ready_list; te = te->par_next)
4321  {
4322  bool conflicts = false;
4323 
4324  /*
4325  * Check to see if the item would need exclusive lock on something
4326  * that a currently running item also needs lock on, or vice versa. If
4327  * so, we don't want to schedule them together.
4328  */
4329  for (i = 0; i < pstate->numWorkers; i++)
4330  {
4331  TocEntry *running_te = pstate->te[i];
4332 
4333  if (running_te == NULL)
4334  continue;
4335  if (has_lock_conflicts(te, running_te) ||
4336  has_lock_conflicts(running_te, te))
4337  {
4338  conflicts = true;
4339  break;
4340  }
4341  }
4342 
4343  if (conflicts)
4344  continue;
4345 
4346  if (pref_non_data && te->section == SECTION_DATA)
4347  {
4348  if (data_te == NULL)
4349  data_te = te;
4350  continue;
4351  }
4352 
4353  /* passed all tests, so this item can run */
4354  return te;
4355  }
4356 
4357  if (data_te != NULL)
4358  return data_te;
4359 
4360  ahlog(AH, 2, "no item ready\n");
4361  return NULL;
4362 }
teSection section
struct _tocEntry * par_next
TocEntry ** te
Definition: parallel.h:44
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
int i
static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2)
int numWorkers
Definition: parallel.h:42

◆ getTocEntryByDumpId()

TocEntry* getTocEntryByDumpId ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 1893 of file pg_backup_archiver.c.

References buildTocEntryArrays(), and _archiveHandle::tocsByDumpId.

Referenced by parseWorkerCommand(), SortTocFromFile(), and TocIDRequired().

1894 {
1895  /* build index arrays if we didn't already */
1896  if (AH->tocsByDumpId == NULL)
1897  buildTocEntryArrays(AH);
1898 
1899  if (id > 0 && id <= AH->maxDumpId)
1900  return AH->tocsByDumpId[id];
1901 
1902  return NULL;
1903 }
static void buildTocEntryArrays(ArchiveHandle *AH)
struct _tocEntry ** tocsByDumpId

◆ has_lock_conflicts()

static bool has_lock_conflicts ( TocEntry te1,
TocEntry te2 
)
static

Definition at line 4192 of file pg_backup_archiver.c.

References _tocEntry::dependencies, _tocEntry::lockDeps, _tocEntry::nDeps, and _tocEntry::nLockDeps.

Referenced by get_next_work_item().

4193 {
4194  int j,
4195  k;
4196 
4197  for (j = 0; j < te1->nLockDeps; j++)
4198  {
4199  for (k = 0; k < te2->nDeps; k++)
4200  {
4201  if (te1->lockDeps[j] == te2->dependencies[k])
4202  return true;
4203  }
4204  }
4205  return false;
4206 }
DumpId * lockDeps
DumpId * dependencies

◆ identify_locking_dependencies()

static void identify_locking_dependencies ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4592 of file pg_backup_archiver.c.

References _tocEntry::dependencies, _tocEntry::desc, free, i, _tocEntry::lockDeps, _tocEntry::nDeps, _tocEntry::nLockDeps, pg_malloc(), pg_realloc(), and _archiveHandle::tocsByDumpId.

Referenced by fix_dependencies().

4593 {
4594  DumpId *lockids;
4595  int nlockids;
4596  int i;
4597 
4598  /* Quick exit if no dependencies at all */
4599  if (te->nDeps == 0)
4600  return;
4601 
4602  /* Exit if this entry doesn't need exclusive lock on other objects */
4603  if (!(strcmp(te->desc, "CONSTRAINT") == 0 ||
4604  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
4605  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
4606  strcmp(te->desc, "RULE") == 0 ||
4607  strcmp(te->desc, "TRIGGER") == 0))
4608  return;
4609 
4610  /*
4611  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4612  * item listed among its dependencies. Originally all of these would have
4613  * been TABLE items, but repoint_table_dependencies would have repointed
4614  * them to the TABLE DATA items if those are present (which they might not
4615  * be, eg in a schema-only dump). Note that all of the entries we are
4616  * processing here are POST_DATA; otherwise there might be a significant
4617  * difference between a dependency on a table and a dependency on its
4618  * data, so that closer analysis would be needed here.
4619  */
4620  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4621  nlockids = 0;
4622  for (i = 0; i < te->nDeps; i++)
4623  {
4624  DumpId depid = te->dependencies[i];
4625 
4626  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4627  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4628  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4629  lockids[nlockids++] = depid;
4630  }
4631 
4632  if (nlockids == 0)
4633  {
4634  free(lockids);
4635  return;
4636  }
4637 
4638  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4639  te->nLockDeps = nlockids;
4640 }
int DumpId
Definition: pg_backup.h:235
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
DumpId * lockDeps
DumpId * dependencies
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define free(a)
Definition: header.h:65
struct _tocEntry ** tocsByDumpId
int i

◆ inhibit_data_for_failed_table()

static void inhibit_data_for_failed_table ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4702 of file pg_backup_archiver.c.

References ahlog(), _tocEntry::dumpId, _tocEntry::reqs, _archiveHandle::tableDataId, _tocEntry::tag, and _archiveHandle::tocsByDumpId.

Referenced by mark_restore_job_done(), and restore_toc_entry().

4703 {
4704  ahlog(AH, 1, "table \"%s\" could not be created, will not restore its data\n",
4705  te->tag);
4706 
4707  if (AH->tableDataId[te->dumpId] != 0)
4708  {
4709  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4710 
4711  ted->reqs = 0;
4712  }
4713 }
struct _tocEntry ** tocsByDumpId
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)

◆ InitDumpOptions()

void InitDumpOptions ( DumpOptions opts)

Definition at line 142 of file pg_backup_archiver.c.

References DUMP_UNSECTIONED, _dumpOptions::dumpSections, and _dumpOptions::include_everything.

Referenced by main(), and NewDumpOptions().

143 {
144  memset(opts, 0, sizeof(DumpOptions));
145  /* set any fields that shouldn't default to zeroes */
146  opts->include_everything = true;
148 }
bool include_everything
Definition: pg_backup.h:165
int dumpSections
Definition: pg_backup.h:141

◆ mark_create_done()

static void mark_create_done ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4687 of file pg_backup_archiver.c.

References _tocEntry::created, _tocEntry::dumpId, _archiveHandle::tableDataId, and _archiveHandle::tocsByDumpId.

Referenced by mark_restore_job_done(), and restore_toc_entry().

4688 {
4689  if (AH->tableDataId[te->dumpId] != 0)
4690  {
4691  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4692 
4693  ted->created = true;
4694  }
4695 }
struct _tocEntry ** tocsByDumpId

◆ mark_dump_job_done()

static void mark_dump_job_done ( ArchiveHandle AH,
TocEntry te,
int  status,
void *  callback_data 
)
static

Definition at line 2458 of file pg_backup_archiver.c.

References ahlog(), _tocEntry::desc, _tocEntry::dumpId, exit_horribly(), modulename, and _tocEntry::tag.

Referenced by WriteDataChunks().

2462 {
2463  ahlog(AH, 1, "finished item %d %s %s\n",
2464  te->dumpId, te->desc, te->tag);
2465 
2466  if (status != 0)
2467  exit_horribly(modulename, "worker process failed: exit code %d\n",
2468  status);
2469 }
void exit_horribly(const char *modulename, const char *fmt,...)
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static const char * modulename

◆ mark_restore_job_done()

static void mark_restore_job_done ( ArchiveHandle AH,
TocEntry te,
int  status,
void *  callback_data 
)
static

Definition at line 4397 of file pg_backup_archiver.c.

References ahlog(), _tocEntry::desc, _tocEntry::dumpId, exit_horribly(), inhibit_data_for_failed_table(), mark_create_done(), modulename, Archive::n_errors, _archiveHandle::public, reduce_dependencies(), _tocEntry::tag, WORKER_CREATE_DONE, WORKER_IGNORED_ERRORS, and WORKER_INHIBIT_DATA.

Referenced by restore_toc_entries_parallel().

4401 {
4402  TocEntry *ready_list = (TocEntry *) callback_data;
4403 
4404  ahlog(AH, 1, "finished item %d %s %s\n",
4405  te->dumpId, te->desc, te->tag);
4406 
4407  if (status == WORKER_CREATE_DONE)
4408  mark_create_done(AH, te);
4409  else if (status == WORKER_INHIBIT_DATA)
4410  {
4412  AH->public.n_errors++;
4413  }
4414  else if (status == WORKER_IGNORED_ERRORS)
4415  AH->public.n_errors++;
4416  else if (status != 0)
4417  exit_horribly(modulename, "worker process failed: exit code %d\n",
4418  status);
4419 
4420  reduce_dependencies(AH, te, ready_list);
4421 }
#define WORKER_CREATE_DONE
int n_errors
Definition: pg_backup.h:207
#define WORKER_IGNORED_ERRORS
static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
#define WORKER_INHIBIT_DATA
static void mark_create_done(ArchiveHandle *AH, TocEntry *te)
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
void exit_horribly(const char *modulename, const char *fmt,...)
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static const char * modulename

◆ move_to_ready_list()

static void move_to_ready_list ( TocEntry pending_list,
TocEntry ready_list,
RestorePass  pass 
)
static

Definition at line 4251 of file pg_backup_archiver.c.

References _tocEntryRestorePass(), _tocEntry::depCount, par_list_append(), par_list_remove(), and _tocEntry::par_next.

Referenced by restore_toc_entries_parallel().

4253 {
4254  TocEntry *te;
4255  TocEntry *next_te;
4256 
4257  for (te = pending_list->par_next; te != pending_list; te = next_te)
4258  {
4259  /* must save list link before possibly moving te to other list */
4260  next_te = te->par_next;
4261 
4262  if (te->depCount == 0 &&
4263  _tocEntryRestorePass(te) == pass)
4264  {
4265  /* Remove it from pending_list ... */
4266  par_list_remove(te);
4267  /* ... and add to ready_list */
4268  par_list_append(ready_list, te);
4269  }
4270  }
4271 }
static RestorePass _tocEntryRestorePass(TocEntry *te)
struct _tocEntry * par_next
static void par_list_append(TocEntry *l, TocEntry *te)
static void par_list_remove(TocEntry *te)

◆ NewDumpOptions()

DumpOptions* NewDumpOptions ( void  )

Definition at line 130 of file pg_backup_archiver.c.

References InitDumpOptions(), and pg_malloc().

Referenced by dumpOptionsFromRestoreOptions().

131 {
132  DumpOptions *opts = (DumpOptions *) pg_malloc(sizeof(DumpOptions));
133 
134  InitDumpOptions(opts);
135  return opts;
136 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void InitDumpOptions(DumpOptions *opts)

◆ NewRestoreOptions()

RestoreOptions* NewRestoreOptions ( void  )

Definition at line 957 of file pg_backup_archiver.c.

References archUnknown, DUMP_UNSECTIONED, _restoreOptions::dumpSections, _restoreOptions::format, pg_malloc0(), _restoreOptions::promptPassword, and TRI_DEFAULT.

Referenced by _CloseArchive(), and main().

958 {
959  RestoreOptions *opts;
960 
961  opts = (RestoreOptions *) pg_malloc0(sizeof(RestoreOptions));
962 
963  /* set any fields that shouldn't default to zeroes */
964  opts->format = archUnknown;
965  opts->promptPassword = TRI_DEFAULT;
967 
968  return opts;
969 }
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
trivalue promptPassword
Definition: pg_backup.h:115

◆ OpenArchive()

Archive* OpenArchive ( const char *  FileSpec,
const ArchiveFormat  fmt 
)

Definition at line 227 of file pg_backup_archiver.c.

References _allocAH(), archModeRead, and setupRestoreWorker().

Referenced by main().

228 {
229  ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, true, archModeRead, setupRestoreWorker);
230 
231  return (Archive *) AH;
232 }
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
static void setupRestoreWorker(Archive *AHX)

◆ par_list_append()

static void par_list_append ( TocEntry l,
TocEntry te 
)
static

Definition at line 4224 of file pg_backup_archiver.c.

References _tocEntry::par_next, and _tocEntry::par_prev.

Referenced by move_to_ready_list(), reduce_dependencies(), and restore_toc_entries_prefork().

4225 {
4226  te->par_prev = l->par_prev;
4227  l->par_prev->par_next = te;
4228  l->par_prev = te;
4229  te->par_next = l;
4230 }
struct _tocEntry * par_prev
struct _tocEntry * par_next

◆ par_list_header_init()

static void par_list_header_init ( TocEntry l)
static

Definition at line 4217 of file pg_backup_archiver.c.

References _tocEntry::par_next, and _tocEntry::par_prev.

Referenced by restore_toc_entries_parallel(), and RestoreArchive().

4218 {
4219  l->par_prev = l->par_next = l;
4220 }
struct _tocEntry * par_prev
struct _tocEntry * par_next

◆ par_list_remove()

static void par_list_remove ( TocEntry te)
static

Definition at line 4234 of file pg_backup_archiver.c.

References _tocEntry::par_next, and _tocEntry::par_prev.

Referenced by move_to_ready_list(), reduce_dependencies(), and restore_toc_entries_parallel().

4235 {
4236  te->par_prev->par_next = te->par_next;
4237  te->par_next->par_prev = te->par_prev;
4238  te->par_prev = NULL;
4239  te->par_next = NULL;
4240 }
struct _tocEntry * par_prev
struct _tocEntry * par_next

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4374 of file pg_backup_archiver.c.

References Assert, _archiveHandle::connection, Archive::n_errors, _archiveHandle::public, restore_toc_entry(), and status().

Referenced by _WorkerJobRestoreCustom(), and _WorkerJobRestoreDirectory().

4375 {
4376  int status;
4377 
4378  Assert(AH->connection != NULL);
4379 
4380  /* Count only errors associated with this TOC entry */
4381  AH->public.n_errors = 0;
4382 
4383  /* Restore the TOC item */
4384  status = restore_toc_entry(AH, te, true);
4385 
4386  return status;
4387 }
int n_errors
Definition: pg_backup.h:207
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
#define Assert(condition)
Definition: c.h:699
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ PrintTOCSummary()

void PrintTOCSummary ( Archive AHX)

Definition at line 1116 of file pg_backup_archiver.c.

References _tocEntryRequired(), ahprintf(), archCustom, _archiveHandle::archdbname, archDirectory, ARCHIVE_MAJOR, ARCHIVE_MINOR, ARCHIVE_REV, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, archTar, _tocEntry::catalogId, _archiveHandle::compression, _archiveHandle::createDate, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, _restoreOptions::filename, _archiveHandle::format, free, i, _archiveHandle::intSize, _tocEntry::nDeps, _tocEntry::next, _archiveHandle::offSize, CatalogId::oid, _tocEntry::owner, pg_strdup(), PGDUMP_STRFTIME_FMT, _archiveHandle::public, replace_line_endings(), REQ_DATA, REQ_SCHEMA, RestoreOutput(), Archive::ropt, SaveOutput(), _tocEntry::section, SECTION_NONE, SECTION_PRE_DATA, SetOutput(), _restoreOptions::strict_names, StrictNamesCheck(), CatalogId::tableoid, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocCount, _restoreOptions::verbose, and _archiveHandle::version.

Referenced by main().

1117 {
1118  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1119  RestoreOptions *ropt = AH->public.ropt;
1120  TocEntry *te;
1121  teSection curSection;
1122  OutputContext sav;
1123  const char *fmtName;
1124  char stamp_str[64];
1125 
1126  sav = SaveOutput(AH);
1127  if (ropt->filename)
1128  SetOutput(AH, ropt->filename, 0 /* no compression */ );
1129 
1130  if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT,
1131  localtime(&AH->createDate)) == 0)
1132  strcpy(stamp_str, "[unknown]");
1133 
1134  ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1135  ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
1137  AH->tocCount, AH->compression);
1138 
1139  switch (AH->format)
1140  {
1141  case archCustom:
1142  fmtName = "CUSTOM";
1143  break;
1144  case archDirectory:
1145  fmtName = "DIRECTORY";
1146  break;
1147  case archTar:
1148  fmtName = "TAR";
1149  break;
1150  default:
1151  fmtName = "UNKNOWN";
1152  }
1153 
1154  ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1156  ahprintf(AH, "; Format: %s\n", fmtName);
1157  ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
1158  ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
1159  if (AH->archiveRemoteVersion)
1160  ahprintf(AH, "; Dumped from database version: %s\n",
1161  AH->archiveRemoteVersion);
1162  if (AH->archiveDumpVersion)
1163  ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1164  AH->archiveDumpVersion);
1165 
1166  ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1167 
1168  curSection = SECTION_PRE_DATA;
1169  for (te = AH->toc->next; te != AH->toc; te = te->next)
1170  {
1171  if (te->section != SECTION_NONE)
1172  curSection = te->section;
1173  if (ropt->verbose ||
1174  (_tocEntryRequired(te, curSection, AH) & (REQ_SCHEMA | REQ_DATA)) != 0)
1175  {
1176  char *sanitized_name;
1177  char *sanitized_schema;
1178  char *sanitized_owner;
1179 
1180  /*
1181  * As in _printTocEntry(), sanitize strings that might contain
1182  * newlines, to ensure that each logical output line is in fact
1183  * one physical output line. This prevents confusion when the
1184  * file is read by "pg_restore -L". Note that we currently don't
1185  * bother to quote names, meaning that the name fields aren't
1186  * automatically parseable. "pg_restore -L" doesn't care because
1187  * it only examines the dumpId field, but someday we might want to
1188  * try harder.
1189  */
1190  sanitized_name = replace_line_endings(te->tag);
1191  if (te->namespace)
1192  sanitized_schema = replace_line_endings(te->namespace);
1193  else
1194  sanitized_schema = pg_strdup("-");
1195  sanitized_owner = replace_line_endings(te->owner);
1196 
1197  ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1198  te->catalogId.tableoid, te->catalogId.oid,
1199  te->desc, sanitized_schema, sanitized_name,
1200  sanitized_owner);
1201 
1202  free(sanitized_name);
1203  free(sanitized_schema);
1204  free(sanitized_owner);
1205  }
1206  if (ropt->verbose && te->nDeps > 0)
1207  {
1208  int i;
1209 
1210  ahprintf(AH, ";\tdepends on:");
1211  for (i = 0; i < te->nDeps; i++)
1212  ahprintf(AH, " %d", te->dependencies[i]);
1213  ahprintf(AH, "\n");
1214  }
1215  }
1216 
1217  /* Enforce strict names checking */
1218  if (ropt->strict_names)
1219  StrictNamesCheck(ropt);
1220 
1221  if (ropt->filename)
1222  RestoreOutput(AH, sav);
1223 }
struct _tocEntry * next
Oid tableoid
Definition: pg_backup.h:231
RestoreOptions * ropt
Definition: pg_backup.h:184
CatalogId catalogId
static void SetOutput(ArchiveHandle *AH, const char *filename, int compression)
teSection section
const char * filename
Definition: pg_backup.h:83
static char * replace_line_endings(const char *str)
struct _tocEntry * toc
DumpId * dependencies
#define ARCHIVE_REV(version)
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
#define ARCHIVE_MINOR(version)
ArchiveFormat format
static void StrictNamesCheck(RestoreOptions *ropt)
#define ARCHIVE_MAJOR(version)
static OutputContext SaveOutput(ArchiveHandle *AH)
#define free(a)
Definition: header.h:65
enum _teSection teSection
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33
static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
int i
static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)

◆ ProcessArchiveRestoreOptions()

void ProcessArchiveRestoreOptions ( Archive AHX)

Definition at line 269 of file pg_backup_archiver.c.

References _tocEntryRequired(), archModeRead, exit_horribly(), _archiveHandle::mode, modulename, _tocEntry::next, _archiveHandle::public, _tocEntry::reqs, Archive::ropt, _tocEntry::section, SECTION_DATA, SECTION_NONE, SECTION_POST_DATA, SECTION_PRE_DATA, _restoreOptions::strict_names, StrictNamesCheck(), _archiveHandle::toc, and write_msg().

Referenced by main().

270 {
271  ArchiveHandle *AH = (ArchiveHandle *) AHX;
272  RestoreOptions *ropt = AH->public.ropt;
273  TocEntry *te;
274  teSection curSection;
275 
276  /* Decide which TOC entries will be dumped/restored, and mark them */
277  curSection = SECTION_PRE_DATA;
278  for (te = AH->toc->next; te != AH->toc; te = te->next)
279  {
280  /*
281  * When writing an archive, we also take this opportunity to check
282  * that we have generated the entries in a sane order that respects
283  * the section divisions. When reading, don't complain, since buggy
284  * old versions of pg_dump might generate out-of-order archives.
285  */
286  if (AH->mode != archModeRead)
287  {
288  switch (te->section)
289  {
290  case SECTION_NONE:
291  /* ok to be anywhere */
292  break;
293  case SECTION_PRE_DATA:
294  if (curSection != SECTION_PRE_DATA)
296  "WARNING: archive items not in correct section order\n");
297  break;
298  case SECTION_DATA:
299  if (curSection == SECTION_POST_DATA)
301  "WARNING: archive items not in correct section order\n");
302  break;
303  case SECTION_POST_DATA:
304  /* ok no matter which section we were in */
305  break;
306  default:
307  exit_horribly(modulename, "unexpected section code %d\n",
308  (int) te->section);
309  break;
310  }
311  }
312 
313  if (te->section != SECTION_NONE)
314  curSection = te->section;
315 
316  te->reqs = _tocEntryRequired(te, curSection, AH);
317  }
318 
319  /* Enforce strict names checking */
320  if (ropt->strict_names)
321  StrictNamesCheck(ropt);
322 }
struct _tocEntry * next
RestoreOptions * ropt
Definition: pg_backup.h:184
teSection section
struct _tocEntry * toc
static void StrictNamesCheck(RestoreOptions *ropt)
enum _teSection teSection
void write_msg(const char *modulename, const char *fmt,...)
void exit_horribly(const char *modulename, const char *fmt,...)
static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
static const char * modulename

◆ processEncodingEntry()

static void processEncodingEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2723 of file pg_backup_archiver.c.

References _tocEntry::defn, encoding, Archive::encoding, exit_horribly(), free, modulename, pg_char_to_encoding(), pg_strdup(), and _archiveHandle::public.

Referenced by ReadToc().

2724 {
2725  /* te->defn should have the form SET client_encoding = 'foo'; */
2726  char *defn = pg_strdup(te->defn);
2727  char *ptr1;
2728  char *ptr2 = NULL;
2729  int encoding;
2730 
2731  ptr1 = strchr(defn, '\'');
2732  if (ptr1)
2733  ptr2 = strchr(++ptr1, '\'');
2734  if (ptr2)
2735  {
2736  *ptr2 = '\0';
2737  encoding = pg_char_to_encoding(ptr1);
2738  if (encoding < 0)
2739  exit_horribly(modulename, "unrecognized encoding \"%s\"\n",
2740  ptr1);
2741  AH->public.encoding = encoding;
2742  }
2743  else
2744  exit_horribly(modulename, "invalid ENCODING item: %s\n",
2745  te->defn);
2746 
2747  free(defn);
2748 }
int pg_char_to_encoding(const char *name)
Definition: encnames.c:551
int encoding
Definition: pg_backup.h:198
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define free(a)
Definition: header.h:65
int32 encoding
Definition: pg_database.h:33
void exit_horribly(const char *modulename, const char *fmt,...)
static const char * modulename

◆ processSearchPathEntry()

static void processSearchPathEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2767 of file pg_backup_archiver.c.

References _tocEntry::defn, pg_strdup(), _archiveHandle::public, and Archive::searchpath.

Referenced by ReadToc().

2768 {
2769  /*
2770  * te->defn should contain a command to set search_path. We just copy it
2771  * verbatim for use later.
2772  */
2773  AH->public.searchpath = pg_strdup(te->defn);
2774 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
char * searchpath
Definition: pg_backup.h:202

◆ processStdStringsEntry()

static void processStdStringsEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2751 of file pg_backup_archiver.c.

References _tocEntry::defn, exit_horribly(), modulename, _archiveHandle::public, and Archive::std_strings.

Referenced by ReadToc().

2752 {
2753  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2754  char *ptr1;
2755 
2756  ptr1 = strchr(te->defn, '\'');
2757  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2758  AH->public.std_strings = true;
2759  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2760  AH->public.std_strings = false;
2761  else
2762  exit_horribly(modulename, "invalid STDSTRINGS item: %s\n",
2763  te->defn);
2764 }
void exit_horribly(const char *modulename, const char *fmt,...)
static const char * modulename
bool std_strings
Definition: pg_backup.h:199

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 3769 of file pg_backup_archiver.c.

References _archiveHandle::archdbname, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, _archiveHandle::compression, _archiveHandle::createDate, exit_horribly(), _archiveHandle::format, _archiveHandle::intSize, K_VERS_1_0, K_VERS_1_10, K_VERS_1_2, K_VERS_1_4, K_VERS_1_7, K_VERS_MAX, MAKE_ARCHIVE_VERSION, modulename, _archiveHandle::offSize, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, _archiveHandle::readHeader, ReadInt(), ReadStr(), tm, _archiveHandle::version, write_msg(), and Z_DEFAULT_COMPRESSION.

Referenced by InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), and InitArchiveFmt_Tar().

3770 {
3771  char tmpMag[7];
3772  int fmt;
3773  struct tm crtm;
3774 
3775  /*
3776  * If we haven't already read the header, do so.
3777  *
3778  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3779  * way to unify the cases?
3780  */
3781  if (!AH->readHeader)
3782  {
3783  char vmaj,
3784  vmin,
3785  vrev;
3786 
3787  AH->ReadBufPtr(AH, tmpMag, 5);
3788 
3789  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3790  exit_horribly(modulename, "did not find magic string in file header\n");
3791 
3792  vmaj = AH->ReadBytePtr(AH);
3793  vmin = AH->ReadBytePtr(AH);
3794 
3795  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3796  vrev = AH->ReadBytePtr(AH);
3797  else
3798  vrev = 0;
3799 
3800  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3801 
3802  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3803  exit_horribly(modulename, "unsupported version (%d.%d) in file header\n",
3804  vmaj, vmin);
3805 
3806  AH->intSize = AH->ReadBytePtr(AH);
3807  if (AH->intSize > 32)
3808  exit_horribly(modulename, "sanity check on integer size (%lu) failed\n",
3809  (unsigned long) AH->intSize);
3810 
3811  if (AH->intSize > sizeof(int))
3812  write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
3813 
3814  if (AH->version >= K_VERS_1_7)
3815  AH->offSize = AH->ReadBytePtr(AH);
3816  else
3817  AH->offSize = AH->intSize;
3818 
3819  fmt = AH->ReadBytePtr(AH);
3820 
3821  if (AH->format != fmt)
3822  exit_horribly(modulename, "expected format (%d) differs from format found in file (%d)\n",
3823  AH->format, fmt);
3824  }
3825 
3826  if (AH->version >= K_VERS_1_2)
3827  {
3828  if (AH->version < K_VERS_1_4)
3829  AH->compression = AH->ReadBytePtr(AH);
3830  else
3831  AH->compression = ReadInt(AH);
3832  }
3833  else
3835 
3836 #ifndef HAVE_LIBZ
3837  if (AH->compression != 0)
3838  write_msg(modulename, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
3839 #endif
3840 
3841  if (AH->version >= K_VERS_1_4)
3842  {
3843  crtm.tm_sec = ReadInt(AH);
3844  crtm.tm_min = ReadInt(AH);
3845  crtm.tm_hour = ReadInt(AH);
3846  crtm.tm_mday = ReadInt(AH);
3847  crtm.tm_mon = ReadInt(AH);
3848  crtm.tm_year = ReadInt(AH);
3849  crtm.tm_isdst = ReadInt(AH);
3850 
3851  AH->archdbname = ReadStr(AH);
3852 
3853  AH->createDate = mktime(&crtm);
3854 
3855  if (AH->createDate == (time_t) -1)
3856  write_msg(modulename, "WARNING: invalid creation date in header\n");
3857  }
3858 
3859  if (AH->version >= K_VERS_1_10)
3860  {
3861  AH->archiveRemoteVersion = ReadStr(AH);
3862  AH->archiveDumpVersion = ReadStr(AH);
3863  }
3864 }
ReadBufPtrType ReadBufPtr
#define Z_DEFAULT_COMPRESSION
#define K_VERS_1_0
int ReadInt(ArchiveHandle *AH)
#define K_VERS_1_4
ReadBytePtrType ReadBytePtr
static struct pg_tm tm
Definition: localtime.c:106
#define K_VERS_1_7
#define MAKE_ARCHIVE_VERSION(major, minor, rev)
#define K_VERS_1_2
#define K_VERS_1_10
ArchiveFormat format
#define K_VERS_MAX
void write_msg(const char *modulename, const char *fmt,...)
char * ReadStr(ArchiveHandle *AH)
void exit_horribly(const char *modulename, const char *fmt,...)
static const char * modulename

◆ ReadInt()

int ReadInt ( ArchiveHandle AH)

Definition at line 2029 of file pg_backup_archiver.c.

References _archiveHandle::intSize, K_VERS_1_0, _archiveHandle::ReadBytePtr, sign, and _archiveHandle::version.

Referenced by _CustomReadFunc(), _LoadBlobs(), _readBlockHeader(), _ReadExtraToc(), _skipBlobs(), _skipData(), ReadHead(), ReadOffset(), ReadStr(), and ReadToc().

2030 {
2031  int res = 0;
2032  int bv,
2033  b;
2034  int sign = 0; /* Default positive */
2035  int bitShift = 0;
2036 
2037  if (AH->version > K_VERS_1_0)
2038  /* Read a sign byte */
2039  sign = AH->ReadBytePtr(AH);
2040 
2041  for (b = 0; b < AH->intSize; b++)
2042  {
2043  bv = AH->ReadBytePtr(AH) & 0xFF;
2044  if (bv != 0)
2045  res = res + (bv << bitShift);
2046  bitShift += 8;
2047  }
2048 
2049  if (sign)
2050  res = -res;
2051 
2052  return res;
2053 }
#define K_VERS_1_0
ReadBytePtrType ReadBytePtr
char sign
Definition: informix.c:693

◆ ReadOffset()

int ReadOffset ( ArchiveHandle AH,
pgoff_t o 
)

Definition at line 1934 of file pg_backup_archiver.c.

References exit_horribly(), i, K_OFFSET_NO_DATA, K_OFFSET_POS_NOT_SET, K_OFFSET_POS_SET, K_VERS_1_7, modulename, _archiveHandle::offSize, pgoff_t, _archiveHandle::ReadBytePtr, ReadInt(), and _archiveHandle::version.

Referenced by _ReadExtraToc().

1935 {
1936  int i;
1937  int off;
1938  int offsetFlg;
1939 
1940  /* Initialize to zero */
1941  *o = 0;
1942 
1943  /* Check for old version */
1944  if (AH->version < K_VERS_1_7)
1945  {
1946  /* Prior versions wrote offsets using WriteInt */
1947  i = ReadInt(AH);
1948  /* -1 means not set */
1949  if (i < 0)
1950  return K_OFFSET_POS_NOT_SET;
1951  else if (i == 0)
1952  return K_OFFSET_NO_DATA;
1953 
1954  /* Cast to pgoff_t because it was written as an int. */
1955  *o = (pgoff_t) i;
1956  return K_OFFSET_POS_SET;
1957  }
1958 
1959  /*
1960  * Read the flag indicating the state of the data pointer. Check if valid
1961  * and die if not.
1962  *
1963  * This used to be handled by a negative or zero pointer, now we use an
1964  * extra byte specifically for the state.
1965  */
1966  offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
1967 
1968  switch (offsetFlg)
1969  {
1970  case K_OFFSET_POS_NOT_SET:
1971  case K_OFFSET_NO_DATA:
1972  case K_OFFSET_POS_SET:
1973 
1974  break;
1975 
1976  default:
1977  exit_horribly(modulename, "unexpected data offset flag %d\n", offsetFlg);
1978  }
1979 
1980  /*
1981  * Read the bytes
1982  */
1983  for (off = 0; off < AH->offSize; off++)
1984  {
1985  if (off < sizeof(pgoff_t))
1986  *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
1987  else
1988  {
1989  if (AH->ReadBytePtr(AH) != 0)
1990  exit_horribly(modulename, "file offset in dump file is too large\n");
1991  }
1992  }
1993 
1994  return offsetFlg;
1995 }
int ReadInt(ArchiveHandle *AH)
ReadBytePtrType ReadBytePtr
#define K_VERS_1_7
#define pgoff_t
Definition: win32_port.h:206
#define K_OFFSET_NO_DATA
void exit_horribly(const char *modulename, const char *fmt,...)
#define K_OFFSET_POS_SET
int i
static const char * modulename
#define K_OFFSET_POS_NOT_SET

◆ ReadStr()

char* ReadStr ( ArchiveHandle AH)

Definition at line 2075 of file pg_backup_archiver.c.

References buf, pg_malloc(), _archiveHandle::ReadBufPtr, and ReadInt().

Referenced by _ReadExtraToc(), ReadHead(), and ReadToc().

2076 {
2077  char *buf;
2078  int l;
2079 
2080  l = ReadInt(AH);
2081  if (l < 0)
2082  buf = NULL;
2083  else
2084  {
2085  buf = (char *) pg_malloc(l + 1);
2086  AH->ReadBufPtr(AH, (void *) buf, l);
2087 
2088  buf[l] = '\0';
2089  }
2090 
2091  return buf;
2092 }
ReadBufPtrType ReadBufPtr
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int ReadInt(ArchiveHandle *AH)
static char * buf
Definition: pg_test_fsync.c:67

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2564 of file pg_backup_archiver.c.

References ahlog(), _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, exit_horribly(), free, _tocEntry::hadDumper, i, InvalidOid, K_VERS_1_10, K_VERS_1_11, K_VERS_1_3, K_VERS_1_5, K_VERS_1_6, K_VERS_1_8, K_VERS_1_9, _archiveHandle::maxDumpId, modulename, _tocEntry::nDeps, _tocEntry::next, CatalogId::oid, _tocEntry::owner, pg_malloc(), pg_malloc0(), pg_realloc(), _tocEntry::prev, processEncodingEntry(), processSearchPathEntry(), processStdStringsEntry(), _archiveHandle::ReadExtraTocPtr, ReadInt(), ReadStr(), _tocEntry::section, SECTION_DATA, SECTION_NONE, SECTION_POST_DATA, SECTION_PRE_DATA, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocCount, _archiveHandle::version, and _tocEntry::withOids.

Referenced by InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), and InitArchiveFmt_Tar().

2565 {
2566  int i;
2567  char *tmp;
2568  DumpId *deps;
2569  int depIdx;
2570  int depSize;
2571  TocEntry *te;
2572 
2573  AH->tocCount = ReadInt(AH);
2574  AH->maxDumpId = 0;
2575 
2576  for (i = 0; i < AH->tocCount; i++)
2577  {
2578  te = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2579  te->dumpId = ReadInt(AH);
2580 
2581  if (te->dumpId > AH->maxDumpId)
2582  AH->maxDumpId = te->dumpId;
2583 
2584  /* Sanity check */
2585  if (te->dumpId <= 0)
2587  "entry ID %d out of range -- perhaps a corrupt TOC\n",
2588  te->dumpId);
2589 
2590  te->hadDumper = ReadInt(AH);
2591 
2592  if (AH->version >= K_VERS_1_8)
2593  {
2594  tmp = ReadStr(AH);
2595  sscanf(tmp, "%u", &te->catalogId.tableoid);
2596  free(tmp);
2597  }
2598  else
2600  tmp = ReadStr(AH);
2601  sscanf(tmp, "%u", &te->catalogId.oid);
2602  free(tmp);
2603 
2604  te->tag = ReadStr(AH);
2605  te->desc = ReadStr(AH);
2606 
2607  if (AH->version >= K_VERS_1_11)
2608  {
2609  te->section = ReadInt(AH);
2610  }
2611  else
2612  {
2613  /*
2614  * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2615  * the entries into sections. This list need not cover entry
2616  * types added later than 8.4.
2617  */
2618  if (strcmp(te->desc, "COMMENT") == 0 ||
2619  strcmp(te->desc, "ACL") == 0 ||
2620  strcmp(te->desc, "ACL LANGUAGE") == 0)
2621  te->section = SECTION_NONE;
2622  else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2623  strcmp(te->desc, "BLOBS") == 0 ||
2624  strcmp(te->desc, "BLOB COMMENTS") == 0)
2625  te->section = SECTION_DATA;
2626  else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2627  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2628  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2629  strcmp(te->desc, "INDEX") == 0 ||
2630  strcmp(te->desc, "RULE") == 0 ||
2631  strcmp(te->desc, "TRIGGER") == 0)
2632  te->section = SECTION_POST_DATA;
2633  else
2634  te->section = SECTION_PRE_DATA;
2635  }
2636 
2637  te->defn = ReadStr(AH);
2638  te->dropStmt = ReadStr(AH);
2639 
2640  if (AH->version >= K_VERS_1_3)
2641  te->copyStmt = ReadStr(AH);
2642 
2643  if (AH->version >= K_VERS_1_6)
2644  te->namespace = ReadStr(AH);
2645 
2646  if (AH->version >= K_VERS_1_10)
2647  te->tablespace = ReadStr(AH);
2648 
2649  te->owner = ReadStr(AH);
2650  if (AH->version >= K_VERS_1_9)
2651  {
2652  if (strcmp(ReadStr(AH), "true") == 0)
2653  te->withOids = true;
2654  else
2655  te->withOids = false;
2656  }
2657  else
2658  te->withOids = true;
2659 
2660  /* Read TOC entry dependencies */
2661  if (AH->version >= K_VERS_1_5)
2662  {
2663  depSize = 100;
2664  deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize);
2665  depIdx = 0;
2666  for (;;)
2667  {
2668  tmp = ReadStr(AH);
2669  if (!tmp)
2670  break; /* end of list */
2671  if (depIdx >= depSize)
2672  {
2673  depSize *= 2;
2674  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize);
2675  }
2676  sscanf(tmp, "%d", &deps[depIdx]);
2677  free(tmp);
2678  depIdx++;
2679  }
2680 
2681  if (depIdx > 0) /* We have a non-null entry */
2682  {
2683  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx);
2684  te->dependencies = deps;
2685  te->nDeps = depIdx;
2686  }
2687  else
2688  {
2689  free(deps);
2690  te->dependencies = NULL;
2691  te->nDeps = 0;
2692  }
2693  }
2694  else
2695  {
2696  te->dependencies = NULL;
2697  te->nDeps = 0;
2698  }
2699 
2700  if (AH->ReadExtraTocPtr)
2701  AH->ReadExtraTocPtr(AH, te);
2702 
2703  ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
2704  i, te->dumpId, te->desc, te->tag);
2705 
2706  /* link completed entry into TOC circular list */
2707  te->prev = AH->toc->prev;
2708  AH->toc->prev->next = te;
2709  AH->toc->prev = te;
2710  te->next = AH->toc;
2711 
2712  /* special processing immediately upon read for some items */
2713  if (strcmp(te->desc, "ENCODING") == 0)
2714  processEncodingEntry(AH, te);
2715  else if (strcmp(te->desc, "STDSTRINGS") == 0)
2716  processStdStringsEntry(AH, te);
2717  else if (strcmp(te->desc, "SEARCHPATH") == 0)
2718  processSearchPathEntry(AH, te);
2719  }
2720 }
struct _tocEntry * next
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
int DumpId
Definition: pg_backup.h:235
Oid tableoid
Definition: pg_backup.h:231
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
CatalogId catalogId
#define K_VERS_1_9
int ReadInt(ArchiveHandle *AH)
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
teSection section
#define K_VERS_1_5
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
struct _tocEntry * toc
DumpId * dependencies
#define K_VERS_1_8
static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_10
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define K_VERS_1_3
struct _tocEntry * prev
#define InvalidOid
Definition: postgres_ext.h:36
#define free(a)
Definition: header.h:65
char * ReadStr(ArchiveHandle *AH)
void exit_horribly(const char *modulename, const char *fmt,...)
#define K_VERS_1_6
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
int i
#define K_VERS_1_11
static const char * modulename
ReadExtraTocPtrType ReadExtraTocPtr

◆ reduce_dependencies()