1 /*-------------------------------------------------------------------------
5 * Private implementation of the archiver routines.
7 * See the headers to pg_restore for more details.
9 * Copyright (c) 2000, Philip Warner
10 * Rights are granted to use this software in any way so long
11 * as this notice is not removed.
13 * The author is not responsible for loss or damages that may
14 * result from its use.
20 *-------------------------------------------------------------------------
23 #include "pg_backup_db.h"
24 #include "dumputils.h"
34 #include "libpq/libpq-fs.h"
39 static const char *modulename
= gettext_noop("archiver");
42 static ArchiveHandle
*_allocAH(const char *FileSpec
, const ArchiveFormat fmt
,
43 const int compression
, ArchiveMode mode
);
44 static void _getObjectDescription(PQExpBuffer buf
, TocEntry
*te
,
46 static void _printTocEntry(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
, bool isData
, bool acl_pass
);
49 static void _doSetFixedOutputState(ArchiveHandle
*AH
);
50 static void _doSetSessionAuth(ArchiveHandle
*AH
, const char *user
);
51 static void _doSetWithOids(ArchiveHandle
*AH
, const bool withOids
);
52 static void _reconnectToDB(ArchiveHandle
*AH
, const char *dbname
);
53 static void _becomeUser(ArchiveHandle
*AH
, const char *user
);
54 static void _becomeOwner(ArchiveHandle
*AH
, TocEntry
*te
);
55 static void _selectOutputSchema(ArchiveHandle
*AH
, const char *schemaName
);
56 static void _selectTablespace(ArchiveHandle
*AH
, const char *tablespace
);
57 static void processEncodingEntry(ArchiveHandle
*AH
, TocEntry
*te
);
58 static void processStdStringsEntry(ArchiveHandle
*AH
, TocEntry
*te
);
59 static teReqs
_tocEntryRequired(TocEntry
*te
, RestoreOptions
*ropt
, bool include_acls
);
60 static void _disableTriggersIfNecessary(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
);
61 static void _enableTriggersIfNecessary(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
);
62 static TocEntry
*getTocEntryByDumpId(ArchiveHandle
*AH
, DumpId id
);
63 static void _moveAfter(ArchiveHandle
*AH
, TocEntry
*pos
, TocEntry
*te
);
64 static int _discoverArchiveFormat(ArchiveHandle
*AH
);
66 static void dump_lo_buf(ArchiveHandle
*AH
);
67 static void _write_msg(const char *modulename
, const char *fmt
, va_list ap
);
68 static void _die_horribly(ArchiveHandle
*AH
, const char *modulename
, const char *fmt
, va_list ap
);
70 static void dumpTimestamp(ArchiveHandle
*AH
, const char *msg
, time_t tim
);
71 static OutputContext
SetOutput(ArchiveHandle
*AH
, char *filename
, int compression
);
72 static void ResetOutput(ArchiveHandle
*AH
, OutputContext savedContext
);
78 * The objective it to make writing new formats and dumpers as simple
79 * as possible, if necessary at the expense of extra function calls etc.
84 /* Create a new archive */
87 CreateArchive(const char *FileSpec
, const ArchiveFormat fmt
,
88 const int compression
, ArchiveMode mode
)
91 ArchiveHandle
*AH
= _allocAH(FileSpec
, fmt
, compression
, mode
);
93 return (Archive
*) AH
;
96 /* Open an existing archive */
99 OpenArchive(const char *FileSpec
, const ArchiveFormat fmt
)
101 ArchiveHandle
*AH
= _allocAH(FileSpec
, fmt
, 0, archModeRead
);
103 return (Archive
*) AH
;
108 CloseArchive(Archive
*AHX
)
111 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
113 (*AH
->ClosePtr
) (AH
);
115 /* Close the output */
117 res
= GZCLOSE(AH
->OF
);
118 else if (AH
->OF
!= stdout
)
119 res
= fclose(AH
->OF
);
122 die_horribly(AH
, modulename
, "could not close output file: %s\n",
128 RestoreArchive(Archive
*AHX
, RestoreOptions
*ropt
)
130 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
137 AH
->stage
= STAGE_INITIALIZING
;
140 * Check for nonsensical option combinations.
142 * NB: create+dropSchema is useless because if you're creating the DB,
143 * there's no need to drop individual items in it. Moreover, if we tried
144 * to do that then we'd issue the drops in the database initially
145 * connected to, not the one we will create, which is very bad...
147 if (ropt
->create
&& ropt
->dropSchema
)
148 die_horribly(AH
, modulename
, "-C and -c are incompatible options\n");
151 * If we're using a DB connection, then connect it.
155 ahlog(AH
, 1, "connecting to database for restore\n");
156 if (AH
->version
< K_VERS_1_3
)
157 die_horribly(AH
, modulename
, "direct database connections are not supported in pre-1.3 archives\n");
159 /* XXX Should get this from the archive */
160 AHX
->minRemoteVersion
= 070100;
161 AHX
->maxRemoteVersion
= 999999;
163 ConnectDatabase(AHX
, ropt
->dbname
,
164 ropt
->pghost
, ropt
->pgport
, ropt
->username
,
165 ropt
->requirePassword
);
168 * If we're talking to the DB directly, don't send comments since they
169 * obscure SQL when displaying errors
171 AH
->noTocComments
= 1;
175 * Work out if we have an implied data-only restore. This can happen if
176 * the dump was data only or if the user has used a toc list to exclude
177 * all of the schema data. All we do is look for schema entries - if none
178 * are found then we set the dataOnly flag.
180 * We could scan for wanted TABLE entries, but that is not the same as
181 * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
185 int impliedDataOnly
= 1;
187 for (te
= AH
->toc
->next
; te
!= AH
->toc
; te
= te
->next
)
189 reqs
= _tocEntryRequired(te
, ropt
, true);
190 if ((reqs
& REQ_SCHEMA
) != 0)
191 { /* It's schema, and it's wanted */
198 ropt
->dataOnly
= impliedDataOnly
;
199 ahlog(AH
, 1, "implied data-only restore\n");
204 * Setup the output file if necessary.
206 if (ropt
->filename
|| ropt
->compression
)
207 sav
= SetOutput(AH
, ropt
->filename
, ropt
->compression
);
209 ahprintf(AH
, "--\n-- PostgreSQL database dump\n--\n\n");
211 if (AH
->public.verbose
)
212 dumpTimestamp(AH
, "Started on", AH
->createDate
);
214 if (ropt
->single_txn
)
217 StartTransaction(AH
);
219 ahprintf(AH
, "BEGIN;\n\n");
223 * Establish important parameter values right away.
225 _doSetFixedOutputState(AH
);
227 AH
->stage
= STAGE_PROCESSING
;
230 * Drop the items at the start, in reverse order
232 if (ropt
->dropSchema
)
234 for (te
= AH
->toc
->prev
; te
!= AH
->toc
; te
= te
->prev
)
238 reqs
= _tocEntryRequired(te
, ropt
, false /* needn't drop ACLs */ );
239 if (((reqs
& REQ_SCHEMA
) != 0) && te
->dropStmt
)
241 /* We want the schema */
242 ahlog(AH
, 1, "dropping %s %s\n", te
->desc
, te
->tag
);
243 /* Select owner and schema as necessary */
244 _becomeOwner(AH
, te
);
245 _selectOutputSchema(AH
, te
->namespace);
247 ahprintf(AH
, "%s", te
->dropStmt
);
252 * _selectOutputSchema may have set currSchema to reflect the effect
253 * of a "SET search_path" command it emitted. However, by now we may
254 * have dropped that schema; or it might not have existed in the first
255 * place. In either case the effective value of search_path will not
256 * be what we think. Forcibly reset currSchema so that we will
257 * re-establish the search_path setting when needed (after creating
260 * If we treated users as pg_dump'able objects then we'd need to reset
264 free(AH
->currSchema
);
265 AH
->currSchema
= strdup("");
269 * Now process each non-ACL TOC entry
271 for (te
= AH
->toc
->next
; te
!= AH
->toc
; te
= te
->next
)
275 /* Work out what, if anything, we want from this entry */
276 reqs
= _tocEntryRequired(te
, ropt
, false);
278 /* Dump any relevant dump warnings to stderr */
279 if (!ropt
->suppressDumpWarnings
&& strcmp(te
->desc
, "WARNING") == 0)
281 if (!ropt
->dataOnly
&& te
->defn
!= NULL
&& strlen(te
->defn
) != 0)
282 write_msg(modulename
, "warning from original dump file: %s\n", te
->defn
);
283 else if (te
->copyStmt
!= NULL
&& strlen(te
->copyStmt
) != 0)
284 write_msg(modulename
, "warning from original dump file: %s\n", te
->copyStmt
);
289 if ((reqs
& REQ_SCHEMA
) != 0) /* We want the schema */
291 ahlog(AH
, 1, "creating %s %s\n", te
->desc
, te
->tag
);
293 _printTocEntry(AH
, te
, ropt
, false, false);
297 * If we could not create a table and --no-data-for-failed-tables
298 * was given, ignore the corresponding TABLE DATA
300 if (ropt
->noDataForFailedTables
&&
301 AH
->lastErrorTE
== te
&&
302 strcmp(te
->desc
, "TABLE") == 0)
306 ahlog(AH
, 1, "table \"%s\" could not be created, will not restore its data\n",
309 for (tes
= te
->next
; tes
!= AH
->toc
; tes
= tes
->next
)
311 if (strcmp(tes
->desc
, "TABLE DATA") == 0 &&
312 strcmp(tes
->tag
, te
->tag
) == 0 &&
313 strcmp(tes
->namespace ? tes
->namespace : "",
314 te
->namespace ? te
->namespace : "") == 0)
316 /* mark it unwanted */
317 ropt
->idWanted
[tes
->dumpId
- 1] = false;
323 /* If we created a DB, connect to it... */
324 if (strcmp(te
->desc
, "DATABASE") == 0)
326 ahlog(AH
, 1, "connecting to new database \"%s\"\n", te
->tag
);
327 _reconnectToDB(AH
, te
->tag
);
332 * If we have a data component, then process it
334 if ((reqs
& REQ_DATA
) != 0)
337 * hadDumper will be set if there is genuine data component for
338 * this node. Otherwise, we need to check the defn field for
339 * statements that need to be executed in data-only restores.
344 * If we can output the data, then restore it.
346 if (AH
->PrintTocDataPtr
!=NULL
&& (reqs
& REQ_DATA
) != 0)
349 if (AH
->compression
!= 0)
350 die_horribly(AH
, modulename
, "cannot restore from compressed archive (compression not supported in this installation)\n");
353 _printTocEntry(AH
, te
, ropt
, true, false);
355 if (strcmp(te
->desc
, "BLOBS") == 0 ||
356 strcmp(te
->desc
, "BLOB COMMENTS") == 0)
358 ahlog(AH
, 1, "restoring %s\n", te
->desc
);
360 _selectOutputSchema(AH
, "pg_catalog");
362 (*AH
->PrintTocDataPtr
) (AH
, te
, ropt
);
366 _disableTriggersIfNecessary(AH
, te
, ropt
);
368 /* Select owner and schema as necessary */
369 _becomeOwner(AH
, te
);
370 _selectOutputSchema(AH
, te
->namespace);
372 ahlog(AH
, 1, "restoring data for table \"%s\"\n",
376 * If we have a copy statement, use it. As of V1.3,
377 * these are separate to allow easy import from
378 * withing a database connection. Pre 1.3 archives can
379 * not use DB connections and are sent to output only.
381 * For V1.3+, the table data MUST have a copy
382 * statement so that we can go into appropriate mode
385 if (te
->copyStmt
&& strlen(te
->copyStmt
) > 0)
387 ahprintf(AH
, "%s", te
->copyStmt
);
388 AH
->writingCopyData
= true;
391 (*AH
->PrintTocDataPtr
) (AH
, te
, ropt
);
393 AH
->writingCopyData
= false;
395 _enableTriggersIfNecessary(AH
, te
, ropt
);
399 else if (!defnDumped
)
401 /* If we haven't already dumped the defn part, do so now */
402 ahlog(AH
, 1, "executing %s %s\n", te
->desc
, te
->tag
);
403 _printTocEntry(AH
, te
, ropt
, false, false);
406 } /* end loop over TOC entries */
409 * Scan TOC again to output ownership commands and ACLs
411 for (te
= AH
->toc
->next
; te
!= AH
->toc
; te
= te
->next
)
415 /* Work out what, if anything, we want from this entry */
416 reqs
= _tocEntryRequired(te
, ropt
, true);
418 if ((reqs
& REQ_SCHEMA
) != 0) /* We want the schema */
420 ahlog(AH
, 1, "setting owner and privileges for %s %s\n",
422 _printTocEntry(AH
, te
, ropt
, false, true);
426 if (ropt
->single_txn
)
429 CommitTransaction(AH
);
431 ahprintf(AH
, "COMMIT;\n\n");
434 if (AH
->public.verbose
)
435 dumpTimestamp(AH
, "Completed on", time(NULL
));
437 ahprintf(AH
, "--\n-- PostgreSQL database dump complete\n--\n\n");
440 * Clean up & we're done.
442 AH
->stage
= STAGE_FINALIZING
;
444 if (ropt
->filename
|| ropt
->compression
)
445 ResetOutput(AH
, sav
);
449 PQfinish(AH
->connection
);
450 AH
->connection
= NULL
;
455 * Allocate a new RestoreOptions block.
456 * This is mainly so we can initialize it, but also for future expansion,
459 NewRestoreOptions(void)
461 RestoreOptions
*opts
;
463 opts
= (RestoreOptions
*) calloc(1, sizeof(RestoreOptions
));
465 opts
->format
= archUnknown
;
466 opts
->suppressDumpWarnings
= false;
467 opts
->exit_on_error
= false;
473 _disableTriggersIfNecessary(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
)
475 /* This hack is only needed in a data-only restore */
476 if (!ropt
->dataOnly
|| !ropt
->disable_triggers
)
479 ahlog(AH
, 1, "disabling triggers for %s\n", te
->tag
);
482 * Become superuser if possible, since they are the only ones who can
483 * disable constraint triggers. If -S was not given, assume the initial
484 * user identity is a superuser. (XXX would it be better to become the
487 _becomeUser(AH
, ropt
->superuser
);
492 _selectOutputSchema(AH
, te
->namespace);
494 ahprintf(AH
, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
499 _enableTriggersIfNecessary(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
)
501 /* This hack is only needed in a data-only restore */
502 if (!ropt
->dataOnly
|| !ropt
->disable_triggers
)
505 ahlog(AH
, 1, "enabling triggers for %s\n", te
->tag
);
508 * Become superuser if possible, since they are the only ones who can
509 * disable constraint triggers. If -S was not given, assume the initial
510 * user identity is a superuser. (XXX would it be better to become the
513 _becomeUser(AH
, ropt
->superuser
);
518 _selectOutputSchema(AH
, te
->namespace);
520 ahprintf(AH
, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
525 * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
530 WriteData(Archive
*AHX
, const void *data
, size_t dLen
)
532 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
535 die_horribly(AH
, modulename
, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
537 return (*AH
->WriteDataPtr
) (AH
, data
, dLen
);
541 * Create a new TOC entry. The TOC was designed as a TOC, but is now the
542 * repository for all metadata. But the name has stuck.
547 ArchiveEntry(Archive
*AHX
,
548 CatalogId catalogId
, DumpId dumpId
,
550 const char *namespace,
551 const char *tablespace
,
552 const char *owner
, bool withOids
,
553 const char *desc
, const char *defn
,
554 const char *dropStmt
, const char *copyStmt
,
555 const DumpId
*deps
, int nDeps
,
556 DataDumperPtr dumpFn
, void *dumpArg
)
558 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
561 newToc
= (TocEntry
*) calloc(1, sizeof(TocEntry
));
563 die_horribly(AH
, modulename
, "out of memory\n");
566 if (dumpId
> AH
->maxDumpId
)
567 AH
->maxDumpId
= dumpId
;
569 newToc
->prev
= AH
->toc
->prev
;
570 newToc
->next
= AH
->toc
;
571 AH
->toc
->prev
->next
= newToc
;
572 AH
->toc
->prev
= newToc
;
574 newToc
->catalogId
= catalogId
;
575 newToc
->dumpId
= dumpId
;
577 newToc
->tag
= strdup(tag
);
578 newToc
->namespace = namespace ? strdup(namespace) : NULL
;
579 newToc
->tablespace
= tablespace
? strdup(tablespace
) : NULL
;
580 newToc
->owner
= strdup(owner
);
581 newToc
->withOids
= withOids
;
582 newToc
->desc
= strdup(desc
);
583 newToc
->defn
= strdup(defn
);
584 newToc
->dropStmt
= strdup(dropStmt
);
585 newToc
->copyStmt
= copyStmt
? strdup(copyStmt
) : NULL
;
589 newToc
->dependencies
= (DumpId
*) malloc(nDeps
* sizeof(DumpId
));
590 memcpy(newToc
->dependencies
, deps
, nDeps
* sizeof(DumpId
));
591 newToc
->nDeps
= nDeps
;
595 newToc
->dependencies
= NULL
;
599 newToc
->dataDumper
= dumpFn
;
600 newToc
->dataDumperArg
= dumpArg
;
601 newToc
->hadDumper
= dumpFn
? true : false;
603 newToc
->formatData
= NULL
;
605 if (AH
->ArchiveEntryPtr
!=NULL
)
606 (*AH
->ArchiveEntryPtr
) (AH
, newToc
);
611 PrintTOCSummary(Archive
*AHX
, RestoreOptions
*ropt
)
613 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
614 TocEntry
*te
= AH
->toc
->next
;
619 sav
= SetOutput(AH
, ropt
->filename
, 0 /* no compression */ );
621 ahprintf(AH
, ";\n; Archive created at %s", ctime(&AH
->createDate
));
622 ahprintf(AH
, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
623 AH
->archdbname
, AH
->tocCount
, AH
->compression
);
640 ahprintf(AH
, "; Dump Version: %d.%d-%d\n", AH
->vmaj
, AH
->vmin
, AH
->vrev
);
641 ahprintf(AH
, "; Format: %s\n", fmtName
);
642 ahprintf(AH
, "; Integer: %d bytes\n", (int) AH
->intSize
);
643 ahprintf(AH
, "; Offset: %d bytes\n", (int) AH
->offSize
);
644 if (AH
->archiveRemoteVersion
)
645 ahprintf(AH
, "; Dumped from database version: %s\n",
646 AH
->archiveRemoteVersion
);
647 if (AH
->archiveDumpVersion
)
648 ahprintf(AH
, "; Dumped by pg_dump version: %s\n",
649 AH
->archiveDumpVersion
);
651 ahprintf(AH
, ";\n;\n; Selected TOC Entries:\n;\n");
653 while (te
!= AH
->toc
)
655 if (_tocEntryRequired(te
, ropt
, true) != 0)
656 ahprintf(AH
, "%d; %u %u %s %s %s %s\n", te
->dumpId
,
657 te
->catalogId
.tableoid
, te
->catalogId
.oid
,
658 te
->desc
, te
->namespace ? te
->namespace : "-",
664 ResetOutput(AH
, sav
);
671 /* Called by a dumper to signal start of a BLOB */
673 StartBlob(Archive
*AHX
, Oid oid
)
675 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
677 if (!AH
->StartBlobPtr
)
678 die_horribly(AH
, modulename
, "large-object output not supported in chosen format\n");
680 (*AH
->StartBlobPtr
) (AH
, AH
->currToc
, oid
);
685 /* Called by a dumper to signal end of a BLOB */
687 EndBlob(Archive
*AHX
, Oid oid
)
689 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
692 (*AH
->EndBlobPtr
) (AH
, AH
->currToc
, oid
);
702 * Called by a format handler before any blobs are restored
705 StartRestoreBlobs(ArchiveHandle
*AH
)
707 if (!AH
->ropt
->single_txn
)
710 StartTransaction(AH
);
712 ahprintf(AH
, "BEGIN;\n\n");
719 * Called by a format handler after all blobs are restored
722 EndRestoreBlobs(ArchiveHandle
*AH
)
724 if (!AH
->ropt
->single_txn
)
727 CommitTransaction(AH
);
729 ahprintf(AH
, "COMMIT;\n\n");
732 ahlog(AH
, 1, "restored %d large objects\n", AH
->blobCount
);
737 * Called by a format handler to initiate restoration of a blob
740 StartRestoreBlob(ArchiveHandle
*AH
, Oid oid
)
746 /* Initialize the LO Buffer */
749 ahlog(AH
, 2, "restoring large object with OID %u\n", oid
);
753 loOid
= lo_create(AH
->connection
, oid
);
754 if (loOid
== 0 || loOid
!= oid
)
755 die_horribly(AH
, modulename
, "could not create large object %u\n",
758 AH
->loFd
= lo_open(AH
->connection
, oid
, INV_WRITE
);
760 die_horribly(AH
, modulename
, "could not open large object\n");
764 ahprintf(AH
, "SELECT lo_open(lo_create(%u), %d);\n", oid
, INV_WRITE
);
771 EndRestoreBlob(ArchiveHandle
*AH
, Oid oid
)
773 if (AH
->lo_buf_used
> 0)
775 /* Write remaining bytes from the LO buffer */
783 lo_close(AH
->connection
, AH
->loFd
);
788 ahprintf(AH
, "SELECT lo_close(0);\n\n");
793 * Sorting and Reordering
797 SortTocFromFile(Archive
*AHX
, RestoreOptions
*ropt
)
799 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
808 /* Allocate space for the 'wanted' array, and init it */
809 ropt
->idWanted
= (bool *) malloc(sizeof(bool) * AH
->maxDumpId
);
810 memset(ropt
->idWanted
, 0, sizeof(bool) * AH
->maxDumpId
);
812 /* Set prev entry as head of list */
816 fh
= fopen(ropt
->tocFile
, PG_BINARY_R
);
818 die_horribly(AH
, modulename
, "could not open TOC file \"%s\": %s\n",
819 ropt
->tocFile
, strerror(errno
));
821 while (fgets(buf
, sizeof(buf
), fh
) != NULL
)
823 /* Truncate line at comment, if any */
824 cmnt
= strchr(buf
, ';');
828 /* Ignore if all blank */
829 if (strspn(buf
, " \t\r") == strlen(buf
))
832 /* Get an ID, check it's valid and not already seen */
833 id
= strtol(buf
, &endptr
, 10);
834 if (endptr
== buf
|| id
<= 0 || id
> AH
->maxDumpId
||
835 ropt
->idWanted
[id
- 1])
837 write_msg(modulename
, "WARNING: line ignored: %s\n", buf
);
842 te
= getTocEntryByDumpId(AH
, id
);
844 die_horribly(AH
, modulename
, "could not find entry for ID %d\n",
847 ropt
->idWanted
[id
- 1] = true;
849 _moveAfter(AH
, tePrev
, te
);
854 die_horribly(AH
, modulename
, "could not close TOC file: %s\n",
859 * Set up a dummy ID filter that selects all dump IDs
862 InitDummyWantedList(Archive
*AHX
, RestoreOptions
*ropt
)
864 ArchiveHandle
*AH
= (ArchiveHandle
*) AHX
;
866 /* Allocate space for the 'wanted' array, and init it to 1's */
867 ropt
->idWanted
= (bool *) malloc(sizeof(bool) * AH
->maxDumpId
);
868 memset(ropt
->idWanted
, 1, sizeof(bool) * AH
->maxDumpId
);
871 /**********************
872 * 'Convenience functions that look like standard IO functions
873 * for writing data when in dump mode.
874 **********************/
878 archputs(const char *s
, Archive
*AH
)
880 return WriteData(AH
, s
, strlen(s
));
885 archprintf(Archive
*AH
, const char *fmt
,...)
889 int bSize
= strlen(fmt
) + 256;
893 * This is paranoid: deal with the possibility that vsnprintf is willing
894 * to ignore trailing null or returns > 0 even if string does not fit. It
895 * may be the case that it returns cnt = bufsize
897 while (cnt
< 0 || cnt
>= (bSize
- 1))
902 p
= (char *) malloc(bSize
);
904 exit_horribly(AH
, modulename
, "out of memory\n");
906 cnt
= vsnprintf(p
, bSize
, fmt
, ap
);
909 WriteData(AH
, p
, cnt
);
915 /*******************************
916 * Stuff below here should be 'private' to the archiver routines
917 *******************************/
920 SetOutput(ArchiveHandle
*AH
, char *filename
, int compression
)
925 /* Replace the AH output file handle */
927 sav
.gzOut
= AH
->gzOut
;
936 filename
= AH
->fSpec
;
941 /* If compression explicitly requested, use gzopen */
943 if (compression
!= 0)
947 /* Don't use PG_BINARY_x since this is zlib */
948 sprintf(fmode
, "wb%d", compression
);
950 AH
->OF
= gzdopen(dup(fn
), fmode
);
952 AH
->OF
= gzopen(filename
, fmode
);
958 if (AH
->mode
== archModeAppend
)
961 AH
->OF
= fdopen(dup(fn
), PG_BINARY_A
);
963 AH
->OF
= fopen(filename
, PG_BINARY_A
);
968 AH
->OF
= fdopen(dup(fn
), PG_BINARY_W
);
970 AH
->OF
= fopen(filename
, PG_BINARY_W
);
978 die_horribly(AH
, modulename
, "could not open output file \"%s\": %s\n",
979 filename
, strerror(errno
));
981 die_horribly(AH
, modulename
, "could not open output file: %s\n",
989 ResetOutput(ArchiveHandle
*AH
, OutputContext sav
)
994 res
= GZCLOSE(AH
->OF
);
996 res
= fclose(AH
->OF
);
999 die_horribly(AH
, modulename
, "could not close output file: %s\n",
1002 AH
->gzOut
= sav
.gzOut
;
1009 * Print formatted text to the output file (usually stdout).
1012 ahprintf(ArchiveHandle
*AH
, const char *fmt
,...)
1016 int bSize
= strlen(fmt
) + 256; /* Should be enough */
1020 * This is paranoid: deal with the possibility that vsnprintf is willing
1021 * to ignore trailing null
1025 * or returns > 0 even if string does not fit. It may be the case that it
1026 * returns cnt = bufsize
1028 while (cnt
< 0 || cnt
>= (bSize
- 1))
1033 p
= (char *) malloc(bSize
);
1035 die_horribly(AH
, modulename
, "out of memory\n");
1037 cnt
= vsnprintf(p
, bSize
, fmt
, ap
);
1040 ahwrite(p
, 1, cnt
, AH
);
1046 ahlog(ArchiveHandle
*AH
, int level
, const char *fmt
,...)
1050 if (AH
->debugLevel
< level
&& (!AH
->public.verbose
|| level
> 1))
1054 _write_msg(NULL
, fmt
, ap
);
1059 * Single place for logic which says 'We are restoring to a direct DB connection'.
1062 RestoringToDB(ArchiveHandle
*AH
)
1064 return (AH
->ropt
&& AH
->ropt
->useDB
&& AH
->connection
);
1068 * Dump the current contents of the LO data buffer while writing a BLOB
1071 dump_lo_buf(ArchiveHandle
*AH
)
1077 res
= lo_write(AH
->connection
, AH
->loFd
, AH
->lo_buf
, AH
->lo_buf_used
);
1078 ahlog(AH
, 5, "wrote %lu bytes of large object data (result = %lu)\n",
1079 (unsigned long) AH
->lo_buf_used
, (unsigned long) res
);
1080 if (res
!= AH
->lo_buf_used
)
1081 die_horribly(AH
, modulename
,
1082 "could not write to large object (result: %lu, expected: %lu)\n",
1083 (unsigned long) res
, (unsigned long) AH
->lo_buf_used
);
1090 str
= PQescapeBytea((const unsigned char *) AH
->lo_buf
,
1091 AH
->lo_buf_used
, &len
);
1093 die_horribly(AH
, modulename
, "out of memory\n");
1095 /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1096 AH
->writingBlob
= 0;
1097 ahprintf(AH
, "SELECT lowrite(0, '%s');\n", str
);
1098 AH
->writingBlob
= 1;
1102 AH
->lo_buf_used
= 0;
1107 * Write buffer to the output file (usually stdout). This is user for
1108 * outputting 'restore' scripts etc. It is even possible for an archive
1109 * format to create a custom output routine to 'fake' a restore if it
1110 * wants to generate a script (see TAR output).
1113 ahwrite(const void *ptr
, size_t size
, size_t nmemb
, ArchiveHandle
*AH
)
1117 if (AH
->writingBlob
)
1119 size_t remaining
= size
* nmemb
;
1121 while (AH
->lo_buf_used
+ remaining
> AH
->lo_buf_size
)
1123 size_t avail
= AH
->lo_buf_size
- AH
->lo_buf_used
;
1125 memcpy((char *) AH
->lo_buf
+ AH
->lo_buf_used
, ptr
, avail
);
1126 ptr
= (const void *) ((const char *) ptr
+ avail
);
1128 AH
->lo_buf_used
+= avail
;
1132 memcpy((char *) AH
->lo_buf
+ AH
->lo_buf_used
, ptr
, remaining
);
1133 AH
->lo_buf_used
+= remaining
;
1135 return size
* nmemb
;
1139 res
= GZWRITE((void *) ptr
, size
, nmemb
, AH
->OF
);
1140 if (res
!= (nmemb
* size
))
1141 die_horribly(AH
, modulename
, "could not write to output file: %s\n", strerror(errno
));
1144 else if (AH
->CustomOutPtr
)
1146 res
= AH
->CustomOutPtr (AH
, ptr
, size
* nmemb
);
1148 if (res
!= (nmemb
* size
))
1149 die_horribly(AH
, modulename
, "could not write to custom output routine\n");
1155 * If we're doing a restore, and it's direct to DB, and we're
1156 * connected then send it to the DB.
1158 if (RestoringToDB(AH
))
1159 return ExecuteSqlCommandBuf(AH
, (void *) ptr
, size
* nmemb
); /* Always 1, currently */
1162 res
= fwrite((void *) ptr
, size
, nmemb
, AH
->OF
);
1164 die_horribly(AH
, modulename
, "could not write to output file: %s\n",
1171 /* Common exit code */
1173 _write_msg(const char *modulename
, const char *fmt
, va_list ap
)
1176 fprintf(stderr
, "%s: [%s] ", progname
, _(modulename
));
1178 fprintf(stderr
, "%s: ", progname
);
1179 vfprintf(stderr
, _(fmt
), ap
);
1183 write_msg(const char *modulename
, const char *fmt
,...)
1188 _write_msg(modulename
, fmt
, ap
);
1194 _die_horribly(ArchiveHandle
*AH
, const char *modulename
, const char *fmt
, va_list ap
)
1196 _write_msg(modulename
, fmt
, ap
);
1200 if (AH
->public.verbose
)
1201 write_msg(NULL
, "*** aborted because of error\n");
1203 PQfinish(AH
->connection
);
1211 exit_horribly(Archive
*AH
, const char *modulename
, const char *fmt
,...)
1216 _die_horribly((ArchiveHandle
*) AH
, modulename
, fmt
, ap
);
1220 /* Archiver use (just different arg declaration) */
1222 die_horribly(ArchiveHandle
*AH
, const char *modulename
, const char *fmt
,...)
1227 _die_horribly(AH
, modulename
, fmt
, ap
);
1231 /* on some error, we may decide to go on... */
1233 warn_or_die_horribly(ArchiveHandle
*AH
,
1234 const char *modulename
, const char *fmt
,...)
1242 /* Do nothing special */
1245 case STAGE_INITIALIZING
:
1246 if (AH
->stage
!= AH
->lastErrorStage
)
1247 write_msg(modulename
, "Error while INITIALIZING:\n");
1250 case STAGE_PROCESSING
:
1251 if (AH
->stage
!= AH
->lastErrorStage
)
1252 write_msg(modulename
, "Error while PROCESSING TOC:\n");
1255 case STAGE_FINALIZING
:
1256 if (AH
->stage
!= AH
->lastErrorStage
)
1257 write_msg(modulename
, "Error while FINALIZING:\n");
1260 if (AH
->currentTE
!= NULL
&& AH
->currentTE
!= AH
->lastErrorTE
)
1262 write_msg(modulename
, "Error from TOC entry %d; %u %u %s %s %s\n",
1263 AH
->currentTE
->dumpId
,
1264 AH
->currentTE
->catalogId
.tableoid
, AH
->currentTE
->catalogId
.oid
,
1265 AH
->currentTE
->desc
, AH
->currentTE
->tag
, AH
->currentTE
->owner
);
1267 AH
->lastErrorStage
= AH
->stage
;
1268 AH
->lastErrorTE
= AH
->currentTE
;
1271 if (AH
->public.exit_on_error
)
1272 _die_horribly(AH
, modulename
, fmt
, ap
);
1275 _write_msg(modulename
, fmt
, ap
);
1276 AH
->public.n_errors
++;
1282 _moveAfter(ArchiveHandle
*AH
, TocEntry
*pos
, TocEntry
*te
)
1284 te
->prev
->next
= te
->next
;
1285 te
->next
->prev
= te
->prev
;
1288 te
->next
= pos
->next
;
1290 pos
->next
->prev
= te
;
1297 _moveBefore(ArchiveHandle
*AH
, TocEntry
*pos
, TocEntry
*te
)
1299 te
->prev
->next
= te
->next
;
1300 te
->next
->prev
= te
->prev
;
1302 te
->prev
= pos
->prev
;
1304 pos
->prev
->next
= te
;
1310 getTocEntryByDumpId(ArchiveHandle
*AH
, DumpId id
)
1315 while (te
!= AH
->toc
)
1317 if (te
->dumpId
== id
)
1325 TocIDRequired(ArchiveHandle
*AH
, DumpId id
, RestoreOptions
*ropt
)
1327 TocEntry
*te
= getTocEntryByDumpId(AH
, id
);
1332 return _tocEntryRequired(te
, ropt
, true);
1336 WriteOffset(ArchiveHandle
*AH
, pgoff_t o
, int wasSet
)
1341 (*AH
->WriteBytePtr
) (AH
, wasSet
);
1343 /* Write out pgoff_t smallest byte first, prevents endian mismatch */
1344 for (off
= 0; off
< sizeof(pgoff_t
); off
++)
1346 (*AH
->WriteBytePtr
) (AH
, o
& 0xFF);
1349 return sizeof(pgoff_t
) + 1;
1353 ReadOffset(ArchiveHandle
*AH
, pgoff_t
* o
)
1359 /* Initialize to zero */
1362 /* Check for old version */
1363 if (AH
->version
< K_VERS_1_7
)
1365 /* Prior versions wrote offsets using WriteInt */
1367 /* -1 means not set */
1369 return K_OFFSET_POS_NOT_SET
;
1371 return K_OFFSET_NO_DATA
;
1373 /* Cast to pgoff_t because it was written as an int. */
1375 return K_OFFSET_POS_SET
;
1379 * Read the flag indicating the state of the data pointer. Check if valid
1382 * This used to be handled by a negative or zero pointer, now we use an
1383 * extra byte specifically for the state.
1385 offsetFlg
= (*AH
->ReadBytePtr
) (AH
) & 0xFF;
1389 case K_OFFSET_POS_NOT_SET
:
1390 case K_OFFSET_NO_DATA
:
1391 case K_OFFSET_POS_SET
:
1396 die_horribly(AH
, modulename
, "unexpected data offset flag %d\n", offsetFlg
);
1402 for (off
= 0; off
< AH
->offSize
; off
++)
1404 if (off
< sizeof(pgoff_t
))
1405 *o
|= ((pgoff_t
) ((*AH
->ReadBytePtr
) (AH
))) << (off
* 8);
1408 if ((*AH
->ReadBytePtr
) (AH
) != 0)
1409 die_horribly(AH
, modulename
, "file offset in dump file is too large\n");
1417 WriteInt(ArchiveHandle
*AH
, int i
)
1422 * This is a bit yucky, but I don't want to make the binary format very
1423 * dependent on representation, and not knowing much about it, I write out
1424 * a sign byte. If you change this, don't forget to change the file
1425 * version #, and modify readInt to read the new format AS WELL AS the old
1432 (*AH
->WriteBytePtr
) (AH
, 1);
1436 (*AH
->WriteBytePtr
) (AH
, 0);
1438 for (b
= 0; b
< AH
->intSize
; b
++)
1440 (*AH
->WriteBytePtr
) (AH
, i
& 0xFF);
1444 return AH
->intSize
+ 1;
1448 ReadInt(ArchiveHandle
*AH
)
1453 int sign
= 0; /* Default positive */
1456 if (AH
->version
> K_VERS_1_0
)
1457 /* Read a sign byte */
1458 sign
= (*AH
->ReadBytePtr
) (AH
);
1460 for (b
= 0; b
< AH
->intSize
; b
++)
1462 bv
= (*AH
->ReadBytePtr
) (AH
) & 0xFF;
1464 res
= res
+ (bv
<< bitShift
);
1475 WriteStr(ArchiveHandle
*AH
, const char *c
)
1481 res
= WriteInt(AH
, strlen(c
));
1482 res
+= (*AH
->WriteBufPtr
) (AH
, c
, strlen(c
));
1485 res
= WriteInt(AH
, -1);
1491 ReadStr(ArchiveHandle
*AH
)
1501 buf
= (char *) malloc(l
+ 1);
1503 die_horribly(AH
, modulename
, "out of memory\n");
1505 if ((*AH
->ReadBufPtr
) (AH
, (void *) buf
, l
) != l
)
1506 die_horribly(AH
, modulename
, "unexpected end of file\n");
1515 _discoverArchiveFormat(ArchiveHandle
*AH
)
1518 char sig
[6]; /* More than enough */
1523 write_msg(modulename
, "attempting to ascertain archive format\n");
1527 free(AH
->lookahead
);
1529 AH
->lookaheadSize
= 512;
1530 AH
->lookahead
= calloc(1, 512);
1531 AH
->lookaheadLen
= 0;
1532 AH
->lookaheadPos
= 0;
1537 fh
= fopen(AH
->fSpec
, PG_BINARY_R
);
1539 die_horribly(AH
, modulename
, "could not open input file \"%s\": %s\n",
1540 AH
->fSpec
, strerror(errno
));
1546 die_horribly(AH
, modulename
, "could not open input file: %s\n",
1550 cnt
= fread(sig
, 1, 5, fh
);
1555 die_horribly(AH
, modulename
, "could not read input file: %s\n", strerror(errno
));
1557 die_horribly(AH
, modulename
, "input file is too short (read %lu, expected 5)\n",
1558 (unsigned long) cnt
);
1561 /* Save it, just in case we need it later */
1562 strncpy(&AH
->lookahead
[0], sig
, 5);
1563 AH
->lookaheadLen
= 5;
1565 if (strncmp(sig
, "PGDMP", 5) == 0)
1567 AH
->vmaj
= fgetc(fh
);
1568 AH
->vmin
= fgetc(fh
);
1570 /* Save these too... */
1571 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->vmaj
;
1572 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->vmin
;
1574 /* Check header version; varies from V1.0 */
1575 if (AH
->vmaj
> 1 || ((AH
->vmaj
== 1) && (AH
->vmin
> 0))) /* Version > 1.0 */
1577 AH
->vrev
= fgetc(fh
);
1578 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->vrev
;
1583 /* Make a convenient integer <maj><min><rev>00 */
1584 AH
->version
= ((AH
->vmaj
* 256 + AH
->vmin
) * 256 + AH
->vrev
) * 256 + 0;
1586 AH
->intSize
= fgetc(fh
);
1587 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->intSize
;
1589 if (AH
->version
>= K_VERS_1_7
)
1591 AH
->offSize
= fgetc(fh
);
1592 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->offSize
;
1595 AH
->offSize
= AH
->intSize
;
1597 AH
->format
= fgetc(fh
);
1598 AH
->lookahead
[AH
->lookaheadLen
++] = AH
->format
;
1603 * *Maybe* we have a tar archive format file... So, read first 512
1606 cnt
= fread(&AH
->lookahead
[AH
->lookaheadLen
], 1, 512 - AH
->lookaheadLen
, fh
);
1607 AH
->lookaheadLen
+= cnt
;
1609 if (AH
->lookaheadLen
!= 512)
1610 die_horribly(AH
, modulename
, "input file does not appear to be a valid archive (too short?)\n");
1612 if (!isValidTarHeader(AH
->lookahead
))
1613 die_horribly(AH
, modulename
, "input file does not appear to be a valid archive\n");
1615 AH
->format
= archTar
;
1618 /* If we can't seek, then mark the header as read */
1619 if (fseeko(fh
, 0, SEEK_SET
) != 0)
1622 * NOTE: Formats that use the lookahead buffer can unset this in their
1628 AH
->lookaheadLen
= 0; /* Don't bother since we've reset the file */
1631 write_msg(modulename
, "read %lu bytes into lookahead buffer\n",
1632 (unsigned long) AH
->lookaheadLen
);
1635 /* Close the file */
1637 if (fclose(fh
) != 0)
1638 die_horribly(AH
, modulename
, "could not close input file: %s\n",
1646 * Allocate an archive handle
1648 static ArchiveHandle
*
1649 _allocAH(const char *FileSpec
, const ArchiveFormat fmt
,
1650 const int compression
, ArchiveMode mode
)
1655 write_msg(modulename
, "allocating AH for %s, format %d\n", FileSpec
, fmt
);
1658 AH
= (ArchiveHandle
*) calloc(1, sizeof(ArchiveHandle
));
1660 die_horribly(AH
, modulename
, "out of memory\n");
1662 /* AH->debugLevel = 100; */
1664 AH
->vmaj
= K_VERS_MAJOR
;
1665 AH
->vmin
= K_VERS_MINOR
;
1666 AH
->vrev
= K_VERS_REV
;
1668 /* initialize for backwards compatible string processing */
1669 AH
->public.encoding
= 0; /* PG_SQL_ASCII */
1670 AH
->public.std_strings
= false;
1672 /* sql error handling */
1673 AH
->public.exit_on_error
= true;
1674 AH
->public.n_errors
= 0;
1676 AH
->createDate
= time(NULL
);
1678 AH
->intSize
= sizeof(int);
1679 AH
->offSize
= sizeof(pgoff_t
);
1682 AH
->fSpec
= strdup(FileSpec
);
1685 * Not used; maybe later....
1687 * AH->workDir = strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
1688 * i--) if (AH->workDir[i-1] == '/')
1694 AH
->currUser
= strdup(""); /* So it's valid, but we can free() it later
1696 AH
->currSchema
= strdup(""); /* ditto */
1697 AH
->currWithOids
= -1; /* force SET */
1699 AH
->toc
= (TocEntry
*) calloc(1, sizeof(TocEntry
));
1701 die_horribly(AH
, modulename
, "out of memory\n");
1703 AH
->toc
->next
= AH
->toc
;
1704 AH
->toc
->prev
= AH
->toc
;
1707 AH
->compression
= compression
;
1709 AH
->pgCopyBuf
= createPQExpBuffer();
1710 AH
->sqlBuf
= createPQExpBuffer();
1712 /* Open stdout with no compression for AH output handle */
1717 * On Windows, we need to use binary mode to read/write non-text archive
1718 * formats. Force stdin/stdout into binary mode if that is what we are
1722 if (fmt
!= archNull
&&
1723 (AH
->fSpec
== NULL
|| strcmp(AH
->fSpec
, "") == 0))
1725 if (mode
== archModeWrite
)
1726 setmode(fileno(stdout
), O_BINARY
);
1728 setmode(fileno(stdin
), O_BINARY
);
1733 write_msg(modulename
, "archive format is %d\n", fmt
);
1736 if (fmt
== archUnknown
)
1737 AH
->format
= _discoverArchiveFormat(AH
);
1744 InitArchiveFmt_Custom(AH
);
1748 InitArchiveFmt_Files(AH
);
1752 InitArchiveFmt_Null(AH
);
1756 InitArchiveFmt_Tar(AH
);
1760 die_horribly(AH
, modulename
, "unrecognized file format \"%d\"\n", fmt
);
1768 WriteDataChunks(ArchiveHandle
*AH
)
1770 TocEntry
*te
= AH
->toc
->next
;
1771 StartDataPtr startPtr
;
1774 while (te
!= AH
->toc
)
1776 if (te
->dataDumper
!= NULL
)
1779 /* printf("Writing data for %d (%x)\n", te->id, te); */
1781 if (strcmp(te
->desc
, "BLOBS") == 0)
1783 startPtr
= AH
->StartBlobsPtr
;
1784 endPtr
= AH
->EndBlobsPtr
;
1788 startPtr
= AH
->StartDataPtr
;
1789 endPtr
= AH
->EndDataPtr
;
1792 if (startPtr
!= NULL
)
1793 (*startPtr
) (AH
, te
);
1796 * printf("Dumper arg for %d is %x\n", te->id, te->dataDumperArg);
1800 * The user-provided DataDumper routine needs to call
1803 (*te
->dataDumper
) ((Archive
*) AH
, te
->dataDumperArg
);
1814 WriteToc(ArchiveHandle
*AH
)
1820 /* printf("%d TOC Entries to save\n", AH->tocCount); */
1822 WriteInt(AH
, AH
->tocCount
);
1824 for (te
= AH
->toc
->next
; te
!= AH
->toc
; te
= te
->next
)
1826 WriteInt(AH
, te
->dumpId
);
1827 WriteInt(AH
, te
->dataDumper
? 1 : 0);
1829 /* OID is recorded as a string for historical reasons */
1830 sprintf(workbuf
, "%u", te
->catalogId
.tableoid
);
1831 WriteStr(AH
, workbuf
);
1832 sprintf(workbuf
, "%u", te
->catalogId
.oid
);
1833 WriteStr(AH
, workbuf
);
1835 WriteStr(AH
, te
->tag
);
1836 WriteStr(AH
, te
->desc
);
1837 WriteStr(AH
, te
->defn
);
1838 WriteStr(AH
, te
->dropStmt
);
1839 WriteStr(AH
, te
->copyStmt
);
1840 WriteStr(AH
, te
->namespace);
1841 WriteStr(AH
, te
->tablespace
);
1842 WriteStr(AH
, te
->owner
);
1843 WriteStr(AH
, te
->withOids
? "true" : "false");
1845 /* Dump list of dependencies */
1846 for (i
= 0; i
< te
->nDeps
; i
++)
1848 sprintf(workbuf
, "%d", te
->dependencies
[i
]);
1849 WriteStr(AH
, workbuf
);
1851 WriteStr(AH
, NULL
); /* Terminate List */
1853 if (AH
->WriteExtraTocPtr
)
1854 (*AH
->WriteExtraTocPtr
) (AH
, te
);
1859 ReadToc(ArchiveHandle
*AH
)
1867 TocEntry
*te
= AH
->toc
->next
;
1869 AH
->tocCount
= ReadInt(AH
);
1872 for (i
= 0; i
< AH
->tocCount
; i
++)
1874 te
= (TocEntry
*) calloc(1, sizeof(TocEntry
));
1875 te
->dumpId
= ReadInt(AH
);
1877 if (te
->dumpId
> AH
->maxDumpId
)
1878 AH
->maxDumpId
= te
->dumpId
;
1881 if (te
->dumpId
<= 0)
1882 die_horribly(AH
, modulename
,
1883 "entry ID %d out of range -- perhaps a corrupt TOC\n",
1886 te
->hadDumper
= ReadInt(AH
);
1888 if (AH
->version
>= K_VERS_1_8
)
1891 sscanf(tmp
, "%u", &te
->catalogId
.tableoid
);
1895 te
->catalogId
.tableoid
= InvalidOid
;
1897 sscanf(tmp
, "%u", &te
->catalogId
.oid
);
1900 te
->tag
= ReadStr(AH
);
1901 te
->desc
= ReadStr(AH
);
1902 te
->defn
= ReadStr(AH
);
1903 te
->dropStmt
= ReadStr(AH
);
1905 if (AH
->version
>= K_VERS_1_3
)
1906 te
->copyStmt
= ReadStr(AH
);
1908 if (AH
->version
>= K_VERS_1_6
)
1909 te
->namespace = ReadStr(AH
);
1911 if (AH
->version
>= K_VERS_1_10
)
1912 te
->tablespace
= ReadStr(AH
);
1914 te
->owner
= ReadStr(AH
);
1915 if (AH
->version
>= K_VERS_1_9
)
1917 if (strcmp(ReadStr(AH
), "true") == 0)
1918 te
->withOids
= true;
1920 te
->withOids
= false;
1923 te
->withOids
= true;
1925 /* Read TOC entry dependencies */
1926 if (AH
->version
>= K_VERS_1_5
)
1929 deps
= (DumpId
*) malloc(sizeof(DumpId
) * depSize
);
1935 break; /* end of list */
1936 if (depIdx
>= depSize
)
1939 deps
= (DumpId
*) realloc(deps
, sizeof(DumpId
) * depSize
);
1941 sscanf(tmp
, "%d", &deps
[depIdx
]);
1946 if (depIdx
> 0) /* We have a non-null entry */
1948 deps
= (DumpId
*) realloc(deps
, sizeof(DumpId
) * depIdx
);
1949 te
->dependencies
= deps
;
1955 te
->dependencies
= NULL
;
1961 te
->dependencies
= NULL
;
1965 if (AH
->ReadExtraTocPtr
)
1966 (*AH
->ReadExtraTocPtr
) (AH
, te
);
1968 ahlog(AH
, 3, "read TOC entry %d (ID %d) for %s %s\n",
1969 i
, te
->dumpId
, te
->desc
, te
->tag
);
1971 /* link completed entry into TOC circular list */
1972 te
->prev
= AH
->toc
->prev
;
1973 AH
->toc
->prev
->next
= te
;
1977 /* special processing immediately upon read for some items */
1978 if (strcmp(te
->desc
, "ENCODING") == 0)
1979 processEncodingEntry(AH
, te
);
1980 else if (strcmp(te
->desc
, "STDSTRINGS") == 0)
1981 processStdStringsEntry(AH
, te
);
1986 processEncodingEntry(ArchiveHandle
*AH
, TocEntry
*te
)
1988 /* te->defn should have the form SET client_encoding = 'foo'; */
1989 char *defn
= strdup(te
->defn
);
1994 ptr1
= strchr(defn
, '\'');
1996 ptr2
= strchr(++ptr1
, '\'');
2000 encoding
= pg_char_to_encoding(ptr1
);
2002 die_horribly(AH
, modulename
, "unrecognized encoding \"%s\"\n",
2004 AH
->public.encoding
= encoding
;
2007 die_horribly(AH
, modulename
, "invalid ENCODING item: %s\n",
2014 processStdStringsEntry(ArchiveHandle
*AH
, TocEntry
*te
)
2016 /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2019 ptr1
= strchr(te
->defn
, '\'');
2020 if (ptr1
&& strncmp(ptr1
, "'on'", 4) == 0)
2021 AH
->public.std_strings
= true;
2022 else if (ptr1
&& strncmp(ptr1
, "'off'", 5) == 0)
2023 AH
->public.std_strings
= false;
2025 die_horribly(AH
, modulename
, "invalid STDSTRINGS item: %s\n",
2030 _tocEntryRequired(TocEntry
*te
, RestoreOptions
*ropt
, bool include_acls
)
2032 teReqs res
= REQ_ALL
;
2034 /* ENCODING and STDSTRINGS items are dumped specially, so always reject */
2035 if (strcmp(te
->desc
, "ENCODING") == 0 ||
2036 strcmp(te
->desc
, "STDSTRINGS") == 0)
2039 /* If it's an ACL, maybe ignore it */
2040 if ((!include_acls
|| ropt
->aclsSkip
) && strcmp(te
->desc
, "ACL") == 0)
2043 if (!ropt
->create
&& strcmp(te
->desc
, "DATABASE") == 0)
2046 /* Check options for selective dump/restore */
2047 if (ropt
->schemaNames
)
2049 /* If no namespace is specified, it means all. */
2052 if (strcmp(ropt
->schemaNames
, te
->namespace) != 0)
2058 if (strcmp(te
->desc
, "TABLE") == 0 ||
2059 strcmp(te
->desc
, "TABLE DATA") == 0)
2061 if (!ropt
->selTable
)
2063 if (ropt
->tableNames
&& strcmp(ropt
->tableNames
, te
->tag
) != 0)
2066 else if (strcmp(te
->desc
, "INDEX") == 0)
2068 if (!ropt
->selIndex
)
2070 if (ropt
->indexNames
&& strcmp(ropt
->indexNames
, te
->tag
) != 0)
2073 else if (strcmp(te
->desc
, "FUNCTION") == 0)
2075 if (!ropt
->selFunction
)
2077 if (ropt
->functionNames
&& strcmp(ropt
->functionNames
, te
->tag
) != 0)
2080 else if (strcmp(te
->desc
, "TRIGGER") == 0)
2082 if (!ropt
->selTrigger
)
2084 if (ropt
->triggerNames
&& strcmp(ropt
->triggerNames
, te
->tag
) != 0)
2092 * Check if we had a dataDumper. Indicates if the entry is schema or data
2097 * Special Case: If 'SEQUENCE SET' then it is considered a data entry
2099 if (strcmp(te
->desc
, "SEQUENCE SET") == 0)
2100 res
= res
& REQ_DATA
;
2102 res
= res
& ~REQ_DATA
;
2106 * Special case: <Init> type with <Max OID> tag; this is obsolete and we
2109 if ((strcmp(te
->desc
, "<Init>") == 0) && (strcmp(te
->tag
, "Max OID") == 0))
2112 /* Mask it if we only want schema */
2113 if (ropt
->schemaOnly
)
2114 res
= res
& REQ_SCHEMA
;
2116 /* Mask it we only want data */
2118 res
= res
& REQ_DATA
;
2120 /* Mask it if we don't have a schema contribution */
2121 if (!te
->defn
|| strlen(te
->defn
) == 0)
2122 res
= res
& ~REQ_SCHEMA
;
2124 /* Finally, if there's a per-ID filter, limit based on that as well */
2125 if (ropt
->idWanted
&& !ropt
->idWanted
[te
->dumpId
- 1])
2132 * Issue SET commands for parameters that we want to have set the same way
2133 * at all times during execution of a restore script.
2136 _doSetFixedOutputState(ArchiveHandle
*AH
)
2138 /* Disable statement_timeout in archive for pg_restore/psql */
2139 ahprintf(AH
, "SET statement_timeout = 0;\n");
2141 /* Select the correct character set encoding */
2142 ahprintf(AH
, "SET client_encoding = '%s';\n",
2143 pg_encoding_to_char(AH
->public.encoding
));
2145 /* Select the correct string literal syntax */
2146 ahprintf(AH
, "SET standard_conforming_strings = %s;\n",
2147 AH
->public.std_strings
? "on" : "off");
2149 /* Make sure function checking is disabled */
2150 ahprintf(AH
, "SET check_function_bodies = false;\n");
2152 /* Avoid annoying notices etc */
2153 ahprintf(AH
, "SET client_min_messages = warning;\n");
2154 if (!AH
->public.std_strings
)
2155 ahprintf(AH
, "SET escape_string_warning = off;\n");
2161 * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
2162 * for updating state if appropriate. If user is NULL or an empty string,
2163 * the specification DEFAULT will be used.
2166 _doSetSessionAuth(ArchiveHandle
*AH
, const char *user
)
2168 PQExpBuffer cmd
= createPQExpBuffer();
2170 appendPQExpBuffer(cmd
, "SET SESSION AUTHORIZATION ");
2173 * SQL requires a string literal here. Might as well be correct.
2176 appendStringLiteralAHX(cmd
, user
, AH
);
2178 appendPQExpBuffer(cmd
, "DEFAULT");
2179 appendPQExpBuffer(cmd
, ";");
2181 if (RestoringToDB(AH
))
2185 res
= PQexec(AH
->connection
, cmd
->data
);
2187 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
)
2188 /* NOT warn_or_die_horribly... use -O instead to skip this. */
2189 die_horribly(AH
, modulename
, "could not set session user to \"%s\": %s",
2190 user
, PQerrorMessage(AH
->connection
));
2195 ahprintf(AH
, "%s\n\n", cmd
->data
);
2197 destroyPQExpBuffer(cmd
);
2202 * Issue a SET default_with_oids command. Caller is responsible
2203 * for updating state if appropriate.
2206 _doSetWithOids(ArchiveHandle
*AH
, const bool withOids
)
2208 PQExpBuffer cmd
= createPQExpBuffer();
2210 appendPQExpBuffer(cmd
, "SET default_with_oids = %s;", withOids
?
2213 if (RestoringToDB(AH
))
2217 res
= PQexec(AH
->connection
, cmd
->data
);
2219 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
)
2220 warn_or_die_horribly(AH
, modulename
,
2221 "could not set default_with_oids: %s",
2222 PQerrorMessage(AH
->connection
));
2227 ahprintf(AH
, "%s\n\n", cmd
->data
);
2229 destroyPQExpBuffer(cmd
);
2234 * Issue the commands to connect to the specified database.
2236 * If we're currently restoring right into a database, this will
2237 * actually establish a connection. Otherwise it puts a \connect into
2238 * the script output.
2240 * NULL dbname implies reconnecting to the current DB (pretty useless).
2243 _reconnectToDB(ArchiveHandle
*AH
, const char *dbname
)
2245 if (RestoringToDB(AH
))
2246 ReconnectToServer(AH
, dbname
, NULL
);
2249 PQExpBuffer qry
= createPQExpBuffer();
2251 appendPQExpBuffer(qry
, "\\connect %s\n\n",
2252 dbname
? fmtId(dbname
) : "-");
2253 ahprintf(AH
, "%s", qry
->data
);
2254 destroyPQExpBuffer(qry
);
2258 * NOTE: currUser keeps track of what the imaginary session user in our
2259 * script is. It's now effectively reset to the original userID.
2264 AH
->currUser
= strdup("");
2266 /* don't assume we still know the output schema */
2268 free(AH
->currSchema
);
2269 AH
->currSchema
= strdup("");
2270 AH
->currWithOids
= -1;
2272 /* re-establish fixed state */
2273 _doSetFixedOutputState(AH
);
2277 * Become the specified user, and update state to avoid redundant commands
2279 * NULL or empty argument is taken to mean restoring the session default
2282 _becomeUser(ArchiveHandle
*AH
, const char *user
)
2285 user
= ""; /* avoid null pointers */
2287 if (AH
->currUser
&& strcmp(AH
->currUser
, user
) == 0)
2288 return; /* no need to do anything */
2290 _doSetSessionAuth(AH
, user
);
2293 * NOTE: currUser keeps track of what the imaginary session user in our
2299 AH
->currUser
= strdup(user
);
2303 * Become the owner of the the given TOC entry object. If
2304 * changes in ownership are not allowed, this doesn't do anything.
2307 _becomeOwner(ArchiveHandle
*AH
, TocEntry
*te
)
2309 if (AH
->ropt
&& (AH
->ropt
->noOwner
|| !AH
->ropt
->use_setsessauth
))
2312 _becomeUser(AH
, te
->owner
);
2317 * Set the proper default_with_oids value for the table.
2320 _setWithOids(ArchiveHandle
*AH
, TocEntry
*te
)
2322 if (AH
->currWithOids
!= te
->withOids
)
2324 _doSetWithOids(AH
, te
->withOids
);
2325 AH
->currWithOids
= te
->withOids
;
2331 * Issue the commands to select the specified schema as the current schema
2332 * in the target database.
2335 _selectOutputSchema(ArchiveHandle
*AH
, const char *schemaName
)
2339 if (!schemaName
|| *schemaName
== '\0' ||
2340 (AH
->currSchema
&& strcmp(AH
->currSchema
, schemaName
) == 0))
2341 return; /* no need to do anything */
2343 qry
= createPQExpBuffer();
2345 appendPQExpBuffer(qry
, "SET search_path = %s",
2347 if (strcmp(schemaName
, "pg_catalog") != 0)
2348 appendPQExpBuffer(qry
, ", pg_catalog");
2350 if (RestoringToDB(AH
))
2354 res
= PQexec(AH
->connection
, qry
->data
);
2356 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
)
2357 warn_or_die_horribly(AH
, modulename
,
2358 "could not set search_path to \"%s\": %s",
2359 schemaName
, PQerrorMessage(AH
->connection
));
2364 ahprintf(AH
, "%s;\n\n", qry
->data
);
2367 free(AH
->currSchema
);
2368 AH
->currSchema
= strdup(schemaName
);
2370 destroyPQExpBuffer(qry
);
2374 * Issue the commands to select the specified tablespace as the current one
2375 * in the target database.
2378 _selectTablespace(ArchiveHandle
*AH
, const char *tablespace
)
2384 /* do nothing in --no-tablespaces mode */
2385 if (AH
->ropt
->noTablespace
)
2388 have
= AH
->currTablespace
;
2391 /* no need to do anything for non-tablespace object */
2395 if (have
&& strcmp(want
, have
) == 0)
2396 return; /* no need to do anything */
2398 qry
= createPQExpBuffer();
2400 if (strcmp(want
, "") == 0)
2402 /* We want the tablespace to be the database's default */
2403 appendPQExpBuffer(qry
, "SET default_tablespace = ''");
2407 /* We want an explicit tablespace */
2408 appendPQExpBuffer(qry
, "SET default_tablespace = %s", fmtId(want
));
2411 if (RestoringToDB(AH
))
2415 res
= PQexec(AH
->connection
, qry
->data
);
2417 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
)
2418 warn_or_die_horribly(AH
, modulename
,
2419 "could not set default_tablespace to %s: %s",
2420 fmtId(want
), PQerrorMessage(AH
->connection
));
2425 ahprintf(AH
, "%s;\n\n", qry
->data
);
2427 if (AH
->currTablespace
)
2428 free(AH
->currTablespace
);
2429 AH
->currTablespace
= strdup(want
);
2431 destroyPQExpBuffer(qry
);
2435 * Extract an object description for a TOC entry, and append it to buf.
2437 * This is not quite as general as it may seem, since it really only
2438 * handles constructing the right thing to put into ALTER ... OWNER TO.
2440 * The whole thing is pretty grotty, but we are kind of stuck since the
2441 * information used is all that's available in older dump files.
2444 _getObjectDescription(PQExpBuffer buf
, TocEntry
*te
, ArchiveHandle
*AH
)
2446 const char *type
= te
->desc
;
2448 /* Use ALTER TABLE for views and sequences */
2449 if (strcmp(type
, "VIEW") == 0 || strcmp(type
, "SEQUENCE") == 0)
2452 /* objects named by a schema and name */
2453 if (strcmp(type
, "CONVERSION") == 0 ||
2454 strcmp(type
, "DOMAIN") == 0 ||
2455 strcmp(type
, "TABLE") == 0 ||
2456 strcmp(type
, "TYPE") == 0 ||
2457 strcmp(type
, "TEXT SEARCH DICTIONARY") == 0 ||
2458 strcmp(type
, "TEXT SEARCH CONFIGURATION") == 0)
2460 appendPQExpBuffer(buf
, "%s ", type
);
2461 if (te
->namespace && te
->namespace[0]) /* is null pre-7.3 */
2462 appendPQExpBuffer(buf
, "%s.", fmtId(te
->namespace));
2465 * Pre-7.3 pg_dump would sometimes (not always) put a fmtId'd name
2466 * into te->tag for an index. This check is heuristic, so make its
2467 * scope as narrow as possible.
2469 if (AH
->version
< K_VERS_1_7
&&
2470 te
->tag
[0] == '"' &&
2471 te
->tag
[strlen(te
->tag
) - 1] == '"' &&
2472 strcmp(type
, "INDEX") == 0)
2473 appendPQExpBuffer(buf
, "%s", te
->tag
);
2475 appendPQExpBuffer(buf
, "%s", fmtId(te
->tag
));
2479 /* objects named by just a name */
2480 if (strcmp(type
, "DATABASE") == 0 ||
2481 strcmp(type
, "PROCEDURAL LANGUAGE") == 0 ||
2482 strcmp(type
, "SCHEMA") == 0)
2484 appendPQExpBuffer(buf
, "%s %s", type
, fmtId(te
->tag
));
2489 * These object types require additional decoration. Fortunately, the
2490 * information needed is exactly what's in the DROP command.
2492 if (strcmp(type
, "AGGREGATE") == 0 ||
2493 strcmp(type
, "FUNCTION") == 0 ||
2494 strcmp(type
, "OPERATOR") == 0 ||
2495 strcmp(type
, "OPERATOR CLASS") == 0 ||
2496 strcmp(type
, "OPERATOR FAMILY") == 0)
2498 /* Chop "DROP " off the front and make a modifiable copy */
2499 char *first
= strdup(te
->dropStmt
+ 5);
2502 /* point to last character in string */
2503 last
= first
+ strlen(first
) - 1;
2505 /* Strip off any ';' or '\n' at the end */
2506 while (last
>= first
&& (*last
== '\n' || *last
== ';'))
2510 appendPQExpBufferStr(buf
, first
);
2516 write_msg(modulename
, "WARNING: don't know how to set owner for object type %s\n",
2521 _printTocEntry(ArchiveHandle
*AH
, TocEntry
*te
, RestoreOptions
*ropt
, bool isData
, bool acl_pass
)
2523 /* ACLs are dumped only during acl pass */
2526 if (strcmp(te
->desc
, "ACL") != 0)
2531 if (strcmp(te
->desc
, "ACL") == 0)
2536 * Avoid dumping the public schema, as it will already be created ...
2537 * unless we are using --clean mode, in which case it's been deleted and
2538 * we'd better recreate it. Likewise for its comment, if any.
2540 if (!ropt
->dropSchema
)
2542 if (strcmp(te
->desc
, "SCHEMA") == 0 &&
2543 strcmp(te
->tag
, "public") == 0)
2545 /* The comment restore would require super-user privs, so avoid it. */
2546 if (strcmp(te
->desc
, "COMMENT") == 0 &&
2547 strcmp(te
->tag
, "SCHEMA public") == 0)
2551 /* Select owner, schema, and tablespace as necessary */
2552 _becomeOwner(AH
, te
);
2553 _selectOutputSchema(AH
, te
->namespace);
2554 _selectTablespace(AH
, te
->tablespace
);
2556 /* Set up OID mode too */
2557 if (strcmp(te
->desc
, "TABLE") == 0)
2558 _setWithOids(AH
, te
);
2560 /* Emit header comment for item */
2561 if (!AH
->noTocComments
)
2570 ahprintf(AH
, "--\n");
2571 if (AH
->public.verbose
)
2573 ahprintf(AH
, "-- TOC entry %d (class %u OID %u)\n",
2574 te
->dumpId
, te
->catalogId
.tableoid
, te
->catalogId
.oid
);
2579 ahprintf(AH
, "-- Dependencies:");
2580 for (i
= 0; i
< te
->nDeps
; i
++)
2581 ahprintf(AH
, " %d", te
->dependencies
[i
]);
2585 ahprintf(AH
, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
2586 pfx
, te
->tag
, te
->desc
,
2587 te
->namespace ? te
->namespace : "-",
2588 ropt
->noOwner
? "-" : te
->owner
);
2589 if (te
->tablespace
&& !ropt
->noTablespace
)
2590 ahprintf(AH
, "; Tablespace: %s", te
->tablespace
);
2593 if (AH
->PrintExtraTocPtr
!=NULL
)
2594 (*AH
->PrintExtraTocPtr
) (AH
, te
);
2595 ahprintf(AH
, "--\n\n");
2599 * Actually print the definition.
2601 * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
2602 * versions put into CREATE SCHEMA. We have to do this when --no-owner
2603 * mode is selected. This is ugly, but I see no other good way ...
2605 if (ropt
->noOwner
&& strcmp(te
->desc
, "SCHEMA") == 0)
2607 ahprintf(AH
, "CREATE SCHEMA %s;\n\n\n", fmtId(te
->tag
));
2611 if (strlen(te
->defn
) > 0)
2612 ahprintf(AH
, "%s\n\n", te
->defn
);
2616 * If we aren't using SET SESSION AUTH to determine ownership, we must
2617 * instead issue an ALTER OWNER command. We assume that anything without
2618 * a DROP command is not a separately ownable object. All the categories
2619 * with DROP commands must appear in one list or the other.
2621 if (!ropt
->noOwner
&& !ropt
->use_setsessauth
&&
2622 strlen(te
->owner
) > 0 && strlen(te
->dropStmt
) > 0)
2624 if (strcmp(te
->desc
, "AGGREGATE") == 0 ||
2625 strcmp(te
->desc
, "CONVERSION") == 0 ||
2626 strcmp(te
->desc
, "DATABASE") == 0 ||
2627 strcmp(te
->desc
, "DOMAIN") == 0 ||
2628 strcmp(te
->desc
, "FUNCTION") == 0 ||
2629 strcmp(te
->desc
, "OPERATOR") == 0 ||
2630 strcmp(te
->desc
, "OPERATOR CLASS") == 0 ||
2631 strcmp(te
->desc
, "OPERATOR FAMILY") == 0 ||
2632 strcmp(te
->desc
, "PROCEDURAL LANGUAGE") == 0 ||
2633 strcmp(te
->desc
, "SCHEMA") == 0 ||
2634 strcmp(te
->desc
, "TABLE") == 0 ||
2635 strcmp(te
->desc
, "TYPE") == 0 ||
2636 strcmp(te
->desc
, "VIEW") == 0 ||
2637 strcmp(te
->desc
, "SEQUENCE") == 0 ||
2638 strcmp(te
->desc
, "TEXT SEARCH DICTIONARY") == 0 ||
2639 strcmp(te
->desc
, "TEXT SEARCH CONFIGURATION") == 0)
2641 PQExpBuffer temp
= createPQExpBuffer();
2643 appendPQExpBuffer(temp
, "ALTER ");
2644 _getObjectDescription(temp
, te
, AH
);
2645 appendPQExpBuffer(temp
, " OWNER TO %s;", fmtId(te
->owner
));
2646 ahprintf(AH
, "%s\n\n", temp
->data
);
2647 destroyPQExpBuffer(temp
);
2649 else if (strcmp(te
->desc
, "CAST") == 0 ||
2650 strcmp(te
->desc
, "CHECK CONSTRAINT") == 0 ||
2651 strcmp(te
->desc
, "CONSTRAINT") == 0 ||
2652 strcmp(te
->desc
, "DEFAULT") == 0 ||
2653 strcmp(te
->desc
, "FK CONSTRAINT") == 0 ||
2654 strcmp(te
->desc
, "INDEX") == 0 ||
2655 strcmp(te
->desc
, "RULE") == 0 ||
2656 strcmp(te
->desc
, "TRIGGER") == 0)
2658 /* these object types don't have separate owners */
2662 write_msg(modulename
, "WARNING: don't know how to set owner for object type %s\n",
2668 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
2669 * commands, so we can no longer assume we know the current auth setting.
2671 if (strncmp(te
->desc
, "ACL", 3) == 0)
2675 AH
->currUser
= NULL
;
2680 WriteHead(ArchiveHandle
*AH
)
2684 (*AH
->WriteBufPtr
) (AH
, "PGDMP", 5); /* Magic code */
2685 (*AH
->WriteBytePtr
) (AH
, AH
->vmaj
);
2686 (*AH
->WriteBytePtr
) (AH
, AH
->vmin
);
2687 (*AH
->WriteBytePtr
) (AH
, AH
->vrev
);
2688 (*AH
->WriteBytePtr
) (AH
, AH
->intSize
);
2689 (*AH
->WriteBytePtr
) (AH
, AH
->offSize
);
2690 (*AH
->WriteBytePtr
) (AH
, AH
->format
);
2693 if (AH
->compression
!= 0)
2694 write_msg(modulename
, "WARNING: requested compression not available in this "
2695 "installation -- archive will be uncompressed\n");
2697 AH
->compression
= 0;
2700 WriteInt(AH
, AH
->compression
);
2702 crtm
= *localtime(&AH
->createDate
);
2703 WriteInt(AH
, crtm
.tm_sec
);
2704 WriteInt(AH
, crtm
.tm_min
);
2705 WriteInt(AH
, crtm
.tm_hour
);
2706 WriteInt(AH
, crtm
.tm_mday
);
2707 WriteInt(AH
, crtm
.tm_mon
);
2708 WriteInt(AH
, crtm
.tm_year
);
2709 WriteInt(AH
, crtm
.tm_isdst
);
2710 WriteStr(AH
, PQdb(AH
->connection
));
2711 WriteStr(AH
, AH
->public.remoteVersionStr
);
2712 WriteStr(AH
, PG_VERSION
);
2716 ReadHead(ArchiveHandle
*AH
)
2722 /* If we haven't already read the header... */
2723 if (!AH
->readHeader
)
2725 if ((*AH
->ReadBufPtr
) (AH
, tmpMag
, 5) != 5)
2726 die_horribly(AH
, modulename
, "unexpected end of file\n");
2728 if (strncmp(tmpMag
, "PGDMP", 5) != 0)
2729 die_horribly(AH
, modulename
, "did not find magic string in file header\n");
2731 AH
->vmaj
= (*AH
->ReadBytePtr
) (AH
);
2732 AH
->vmin
= (*AH
->ReadBytePtr
) (AH
);
2734 if (AH
->vmaj
> 1 || ((AH
->vmaj
== 1) && (AH
->vmin
> 0))) /* Version > 1.0 */
2735 AH
->vrev
= (*AH
->ReadBytePtr
) (AH
);
2739 AH
->version
= ((AH
->vmaj
* 256 + AH
->vmin
) * 256 + AH
->vrev
) * 256 + 0;
2742 if (AH
->version
< K_VERS_1_0
|| AH
->version
> K_VERS_MAX
)
2743 die_horribly(AH
, modulename
, "unsupported version (%d.%d) in file header\n",
2744 AH
->vmaj
, AH
->vmin
);
2746 AH
->intSize
= (*AH
->ReadBytePtr
) (AH
);
2747 if (AH
->intSize
> 32)
2748 die_horribly(AH
, modulename
, "sanity check on integer size (%lu) failed\n",
2749 (unsigned long) AH
->intSize
);
2751 if (AH
->intSize
> sizeof(int))
2752 write_msg(modulename
, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
2754 if (AH
->version
>= K_VERS_1_7
)
2755 AH
->offSize
= (*AH
->ReadBytePtr
) (AH
);
2757 AH
->offSize
= AH
->intSize
;
2759 fmt
= (*AH
->ReadBytePtr
) (AH
);
2761 if (AH
->format
!= fmt
)
2762 die_horribly(AH
, modulename
, "expected format (%d) differs from format found in file (%d)\n",
2766 if (AH
->version
>= K_VERS_1_2
)
2768 if (AH
->version
< K_VERS_1_4
)
2769 AH
->compression
= (*AH
->ReadBytePtr
) (AH
);
2771 AH
->compression
= ReadInt(AH
);
2774 AH
->compression
= Z_DEFAULT_COMPRESSION
;
2777 if (AH
->compression
!= 0)
2778 write_msg(modulename
, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
2781 if (AH
->version
>= K_VERS_1_4
)
2783 crtm
.tm_sec
= ReadInt(AH
);
2784 crtm
.tm_min
= ReadInt(AH
);
2785 crtm
.tm_hour
= ReadInt(AH
);
2786 crtm
.tm_mday
= ReadInt(AH
);
2787 crtm
.tm_mon
= ReadInt(AH
);
2788 crtm
.tm_year
= ReadInt(AH
);
2789 crtm
.tm_isdst
= ReadInt(AH
);
2791 AH
->archdbname
= ReadStr(AH
);
2793 AH
->createDate
= mktime(&crtm
);
2795 if (AH
->createDate
== (time_t) -1)
2796 write_msg(modulename
, "WARNING: invalid creation date in header\n");
2799 if (AH
->version
>= K_VERS_1_10
)
2801 AH
->archiveRemoteVersion
= ReadStr(AH
);
2802 AH
->archiveDumpVersion
= ReadStr(AH
);
2810 * check to see if fseek can be performed.
2817 if (fseeko(fp
, 0, SEEK_CUR
) != 0)
2819 else if (sizeof(pgoff_t
) > sizeof(long))
2822 * At this point, pgoff_t is too large for long, so we return based on
2823 * whether an pgoff_t version of fseek is available.
2839 dumpTimestamp(ArchiveHandle
*AH
, const char *msg
, time_t tim
)
2844 * We don't print the timezone on Win32, because the names are long and
2845 * localized, which means they may contain characters in various random
2846 * encodings; this has been seen to cause encoding errors when reading the
2849 if (strftime(buf
, sizeof(buf
),
2851 "%Y-%m-%d %H:%M:%S %Z",
2853 "%Y-%m-%d %H:%M:%S",
2855 localtime(&tim
)) != 0)
2856 ahprintf(AH
, "-- %s %s\n\n", msg
, buf
);