]> granicus.if.org Git - postgresql/blob - src/bin/pg_dump/pg_backup_archiver.c
3f858a6b93d3625eeaa9ef778862f558bf309cc7
[postgresql] / src / bin / pg_dump / pg_backup_archiver.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_backup_archiver.c
4  *
5  *      Private implementation of the archiver routines.
6  *
7  *      See the headers to pg_restore for more details.
8  *
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.
12  *
13  *      The author is not responsible for loss or damages that may
14  *      result from its use.
15  *
16  *
17  * IDENTIFICATION
18  *              $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.149 2007/11/15 21:14:41 momjian Exp $
19  *
20  *-------------------------------------------------------------------------
21  */
22
23 #include "pg_backup_db.h"
24 #include "dumputils.h"
25
26 #include <ctype.h>
27
28 #include <unistd.h>
29
30 #ifdef WIN32
31 #include <io.h>
32 #endif
33
34 #include "libpq/libpq-fs.h"
35
36
37 const char *progname;
38
39 static const char *modulename = gettext_noop("archiver");
40
41
42 static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
43                  const int compression, ArchiveMode mode);
44 static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
45                                           ArchiveHandle *AH);
46 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
47
48
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);
65
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);
69
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);
73
74
75 /*
76  *      Wrapper functions.
77  *
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.
80  *
81  */
82
83
84 /* Create a new archive */
85 /* Public */
86 Archive *
87 CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
88                           const int compression, ArchiveMode mode)
89
90 {
91         ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, mode);
92
93         return (Archive *) AH;
94 }
95
96 /* Open an existing archive */
97 /* Public */
98 Archive *
99 OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
100 {
101         ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, archModeRead);
102
103         return (Archive *) AH;
104 }
105
106 /* Public */
107 void
108 CloseArchive(Archive *AHX)
109 {
110         int                     res = 0;
111         ArchiveHandle *AH = (ArchiveHandle *) AHX;
112
113         (*AH->ClosePtr) (AH);
114
115         /* Close the output */
116         if (AH->gzOut)
117                 res = GZCLOSE(AH->OF);
118         else if (AH->OF != stdout)
119                 res = fclose(AH->OF);
120
121         if (res != 0)
122                 die_horribly(AH, modulename, "could not close output file: %s\n",
123                                          strerror(errno));
124 }
125
126 /* Public */
127 void
128 RestoreArchive(Archive *AHX, RestoreOptions *ropt)
129 {
130         ArchiveHandle *AH = (ArchiveHandle *) AHX;
131         TocEntry   *te;
132         teReqs          reqs;
133         OutputContext sav;
134         bool            defnDumped;
135
136         AH->ropt = ropt;
137         AH->stage = STAGE_INITIALIZING;
138
139         /*
140          * Check for nonsensical option combinations.
141          *
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...
146          */
147         if (ropt->create && ropt->dropSchema)
148                 die_horribly(AH, modulename, "-C and -c are incompatible options\n");
149
150         /*
151          * If we're using a DB connection, then connect it.
152          */
153         if (ropt->useDB)
154         {
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");
158
159                 /* XXX Should get this from the archive */
160                 AHX->minRemoteVersion = 070100;
161                 AHX->maxRemoteVersion = 999999;
162
163                 ConnectDatabase(AHX, ropt->dbname,
164                                                 ropt->pghost, ropt->pgport, ropt->username,
165                                                 ropt->requirePassword, ropt->ignoreVersion);
166
167                 /*
168                  * If we're talking to the DB directly, don't send comments since they
169                  * obscure SQL when displaying errors
170                  */
171                 AH->noTocComments = 1;
172         }
173
174         /*
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.
179          *
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).
182          */
183         if (!ropt->dataOnly)
184         {
185                 int                     impliedDataOnly = 1;
186
187                 for (te = AH->toc->next; te != AH->toc; te = te->next)
188                 {
189                         reqs = _tocEntryRequired(te, ropt, true);
190                         if ((reqs & REQ_SCHEMA) != 0)
191                         {                                       /* It's schema, and it's wanted */
192                                 impliedDataOnly = 0;
193                                 break;
194                         }
195                 }
196                 if (impliedDataOnly)
197                 {
198                         ropt->dataOnly = impliedDataOnly;
199                         ahlog(AH, 1, "implied data-only restore\n");
200                 }
201         }
202
203         /*
204          * Setup the output file if necessary.
205          */
206         if (ropt->filename || ropt->compression)
207                 sav = SetOutput(AH, ropt->filename, ropt->compression);
208
209         ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
210
211         if (AH->public.verbose)
212                 dumpTimestamp(AH, "Started on", AH->createDate);
213
214         if (ropt->single_txn)
215         {
216                 if (AH->connection)
217                         StartTransaction(AH);
218                 else
219                         ahprintf(AH, "BEGIN;\n\n");
220         }
221
222         /*
223          * Establish important parameter values right away.
224          */
225         _doSetFixedOutputState(AH);
226
227         AH->stage = STAGE_PROCESSING;
228
229         /*
230          * Drop the items at the start, in reverse order
231          */
232         if (ropt->dropSchema)
233         {
234                 for (te = AH->toc->prev; te != AH->toc; te = te->prev)
235                 {
236                         AH->currentTE = te;
237
238                         reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ );
239                         if (((reqs & REQ_SCHEMA) != 0) && te->dropStmt)
240                         {
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);
246                                 /* Drop it */
247                                 ahprintf(AH, "%s", te->dropStmt);
248                         }
249                 }
250         }
251
252         /*
253          * Now process each non-ACL TOC entry
254          */
255         for (te = AH->toc->next; te != AH->toc; te = te->next)
256         {
257                 AH->currentTE = te;
258
259                 /* Work out what, if anything, we want from this entry */
260                 reqs = _tocEntryRequired(te, ropt, false);
261
262                 /* Dump any relevant dump warnings to stderr */
263                 if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
264                 {
265                         if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
266                                 write_msg(modulename, "warning from original dump file: %s\n", te->defn);
267                         else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
268                                 write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
269                 }
270
271                 defnDumped = false;
272
273                 if ((reqs & REQ_SCHEMA) != 0)   /* We want the schema */
274                 {
275                         ahlog(AH, 1, "creating %s %s\n", te->desc, te->tag);
276
277                         _printTocEntry(AH, te, ropt, false, false);
278                         defnDumped = true;
279
280                         /*
281                          * If we could not create a table and --no-data-for-failed-tables
282                          * was given, ignore the corresponding TABLE DATA
283                          */
284                         if (ropt->noDataForFailedTables &&
285                                 AH->lastErrorTE == te &&
286                                 strcmp(te->desc, "TABLE") == 0)
287                         {
288                                 TocEntry   *tes;
289
290                                 ahlog(AH, 1, "table \"%s\" could not be created, will not restore its data\n",
291                                           te->tag);
292
293                                 for (tes = te->next; tes != AH->toc; tes = tes->next)
294                                 {
295                                         if (strcmp(tes->desc, "TABLE DATA") == 0 &&
296                                                 strcmp(tes->tag, te->tag) == 0 &&
297                                                 strcmp(tes->namespace ? tes->namespace : "",
298                                                            te->namespace ? te->namespace : "") == 0)
299                                         {
300                                                 /* mark it unwanted */
301                                                 ropt->idWanted[tes->dumpId - 1] = false;
302                                                 break;
303                                         }
304                                 }
305                         }
306
307                         /* If we created a DB, connect to it... */
308                         if (strcmp(te->desc, "DATABASE") == 0)
309                         {
310                                 ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag);
311                                 _reconnectToDB(AH, te->tag);
312                         }
313                 }
314
315                 /*
316                  * If we have a data component, then process it
317                  */
318                 if ((reqs & REQ_DATA) != 0)
319                 {
320                         /*
321                          * hadDumper will be set if there is genuine data component for
322                          * this node. Otherwise, we need to check the defn field for
323                          * statements that need to be executed in data-only restores.
324                          */
325                         if (te->hadDumper)
326                         {
327                                 /*
328                                  * If we can output the data, then restore it.
329                                  */
330                                 if (AH->PrintTocDataPtr !=NULL && (reqs & REQ_DATA) != 0)
331                                 {
332 #ifndef HAVE_LIBZ
333                                         if (AH->compression != 0)
334                                                 die_horribly(AH, modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
335 #endif
336
337                                         _printTocEntry(AH, te, ropt, true, false);
338
339                                         if (strcmp(te->desc, "BLOBS") == 0 ||
340                                                 strcmp(te->desc, "BLOB COMMENTS") == 0)
341                                         {
342                                                 ahlog(AH, 1, "restoring %s\n", te->desc);
343
344                                                 _selectOutputSchema(AH, "pg_catalog");
345
346                                                 (*AH->PrintTocDataPtr) (AH, te, ropt);
347                                         }
348                                         else
349                                         {
350                                                 _disableTriggersIfNecessary(AH, te, ropt);
351
352                                                 /* Select owner and schema as necessary */
353                                                 _becomeOwner(AH, te);
354                                                 _selectOutputSchema(AH, te->namespace);
355
356                                                 ahlog(AH, 1, "restoring data for table \"%s\"\n",
357                                                           te->tag);
358
359                                                 /*
360                                                  * If we have a copy statement, use it. As of V1.3,
361                                                  * these are separate to allow easy import from
362                                                  * withing a database connection. Pre 1.3 archives can
363                                                  * not use DB connections and are sent to output only.
364                                                  *
365                                                  * For V1.3+, the table data MUST have a copy
366                                                  * statement so that we can go into appropriate mode
367                                                  * with libpq.
368                                                  */
369                                                 if (te->copyStmt && strlen(te->copyStmt) > 0)
370                                                 {
371                                                         ahprintf(AH, "%s", te->copyStmt);
372                                                         AH->writingCopyData = true;
373                                                 }
374
375                                                 (*AH->PrintTocDataPtr) (AH, te, ropt);
376
377                                                 AH->writingCopyData = false;
378
379                                                 _enableTriggersIfNecessary(AH, te, ropt);
380                                         }
381                                 }
382                         }
383                         else if (!defnDumped)
384                         {
385                                 /* If we haven't already dumped the defn part, do so now */
386                                 ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
387                                 _printTocEntry(AH, te, ropt, false, false);
388                         }
389                 }
390         }                                                       /* end loop over TOC entries */
391
392         /*
393          * Scan TOC again to output ownership commands and ACLs
394          */
395         for (te = AH->toc->next; te != AH->toc; te = te->next)
396         {
397                 AH->currentTE = te;
398
399                 /* Work out what, if anything, we want from this entry */
400                 reqs = _tocEntryRequired(te, ropt, true);
401
402                 if ((reqs & REQ_SCHEMA) != 0)   /* We want the schema */
403                 {
404                         ahlog(AH, 1, "setting owner and privileges for %s %s\n",
405                                   te->desc, te->tag);
406                         _printTocEntry(AH, te, ropt, false, true);
407                 }
408         }
409
410         if (ropt->single_txn)
411         {
412                 if (AH->connection)
413                         CommitTransaction(AH);
414                 else
415                         ahprintf(AH, "COMMIT;\n\n");
416         }
417
418         if (AH->public.verbose)
419                 dumpTimestamp(AH, "Completed on", time(NULL));
420
421         ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
422
423         /*
424          * Clean up & we're done.
425          */
426         AH->stage = STAGE_FINALIZING;
427
428         if (ropt->filename || ropt->compression)
429                 ResetOutput(AH, sav);
430
431         if (ropt->useDB)
432         {
433                 PQfinish(AH->connection);
434                 AH->connection = NULL;
435         }
436 }
437
438 /*
439  * Allocate a new RestoreOptions block.
440  * This is mainly so we can initialize it, but also for future expansion,
441  */
442 RestoreOptions *
443 NewRestoreOptions(void)
444 {
445         RestoreOptions *opts;
446
447         opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions));
448
449         opts->format = archUnknown;
450         opts->suppressDumpWarnings = false;
451         opts->exit_on_error = false;
452
453         return opts;
454 }
455
456 static void
457 _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
458 {
459         /* This hack is only needed in a data-only restore */
460         if (!ropt->dataOnly || !ropt->disable_triggers)
461                 return;
462
463         ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
464
465         /*
466          * Become superuser if possible, since they are the only ones who can
467          * disable constraint triggers.  If -S was not given, assume the initial
468          * user identity is a superuser.  (XXX would it be better to become the
469          * table owner?)
470          */
471         _becomeUser(AH, ropt->superuser);
472
473         /*
474          * Disable them.
475          */
476         _selectOutputSchema(AH, te->namespace);
477
478         ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
479                          fmtId(te->tag));
480 }
481
482 static void
483 _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
484 {
485         /* This hack is only needed in a data-only restore */
486         if (!ropt->dataOnly || !ropt->disable_triggers)
487                 return;
488
489         ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
490
491         /*
492          * Become superuser if possible, since they are the only ones who can
493          * disable constraint triggers.  If -S was not given, assume the initial
494          * user identity is a superuser.  (XXX would it be better to become the
495          * table owner?)
496          */
497         _becomeUser(AH, ropt->superuser);
498
499         /*
500          * Enable them.
501          */
502         _selectOutputSchema(AH, te->namespace);
503
504         ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
505                          fmtId(te->tag));
506 }
507
508 /*
509  * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
510  */
511
512 /* Public */
513 size_t
514 WriteData(Archive *AHX, const void *data, size_t dLen)
515 {
516         ArchiveHandle *AH = (ArchiveHandle *) AHX;
517
518         if (!AH->currToc)
519                 die_horribly(AH, modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
520
521         return (*AH->WriteDataPtr) (AH, data, dLen);
522 }
523
524 /*
525  * Create a new TOC entry. The TOC was designed as a TOC, but is now the
526  * repository for all metadata. But the name has stuck.
527  */
528
529 /* Public */
530 void
531 ArchiveEntry(Archive *AHX,
532                          CatalogId catalogId, DumpId dumpId,
533                          const char *tag,
534                          const char *namespace,
535                          const char *tablespace,
536                          const char *owner, bool withOids,
537                          const char *desc, const char *defn,
538                          const char *dropStmt, const char *copyStmt,
539                          const DumpId *deps, int nDeps,
540                          DataDumperPtr dumpFn, void *dumpArg)
541 {
542         ArchiveHandle *AH = (ArchiveHandle *) AHX;
543         TocEntry   *newToc;
544
545         newToc = (TocEntry *) calloc(1, sizeof(TocEntry));
546         if (!newToc)
547                 die_horribly(AH, modulename, "out of memory\n");
548
549         AH->tocCount++;
550         if (dumpId > AH->maxDumpId)
551                 AH->maxDumpId = dumpId;
552
553         newToc->prev = AH->toc->prev;
554         newToc->next = AH->toc;
555         AH->toc->prev->next = newToc;
556         AH->toc->prev = newToc;
557
558         newToc->catalogId = catalogId;
559         newToc->dumpId = dumpId;
560
561         newToc->tag = strdup(tag);
562         newToc->namespace = namespace ? strdup(namespace) : NULL;
563         newToc->tablespace = tablespace ? strdup(tablespace) : NULL;
564         newToc->owner = strdup(owner);
565         newToc->withOids = withOids;
566         newToc->desc = strdup(desc);
567         newToc->defn = strdup(defn);
568         newToc->dropStmt = strdup(dropStmt);
569         newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
570
571         if (nDeps > 0)
572         {
573                 newToc->dependencies = (DumpId *) malloc(nDeps * sizeof(DumpId));
574                 memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
575                 newToc->nDeps = nDeps;
576         }
577         else
578         {
579                 newToc->dependencies = NULL;
580                 newToc->nDeps = 0;
581         }
582
583         newToc->dataDumper = dumpFn;
584         newToc->dataDumperArg = dumpArg;
585         newToc->hadDumper = dumpFn ? true : false;
586
587         newToc->formatData = NULL;
588
589         if (AH->ArchiveEntryPtr !=NULL)
590                 (*AH->ArchiveEntryPtr) (AH, newToc);
591 }
592
593 /* Public */
594 void
595 PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
596 {
597         ArchiveHandle *AH = (ArchiveHandle *) AHX;
598         TocEntry   *te = AH->toc->next;
599         OutputContext sav;
600         char       *fmtName;
601
602         if (ropt->filename)
603                 sav = SetOutput(AH, ropt->filename, 0 /* no compression */ );
604
605         ahprintf(AH, ";\n; Archive created at %s", ctime(&AH->createDate));
606         ahprintf(AH, ";     dbname: %s\n;     TOC Entries: %d\n;     Compression: %d\n",
607                          AH->archdbname, AH->tocCount, AH->compression);
608
609         switch (AH->format)
610         {
611                 case archFiles:
612                         fmtName = "FILES";
613                         break;
614                 case archCustom:
615                         fmtName = "CUSTOM";
616                         break;
617                 case archTar:
618                         fmtName = "TAR";
619                         break;
620                 default:
621                         fmtName = "UNKNOWN";
622         }
623
624         ahprintf(AH, ";     Dump Version: %d.%d-%d\n", AH->vmaj, AH->vmin, AH->vrev);
625         ahprintf(AH, ";     Format: %s\n", fmtName);
626         ahprintf(AH, ";     Integer: %d bytes\n", (int) AH->intSize);
627         ahprintf(AH, ";     Offset: %d bytes\n", (int) AH->offSize);
628         if (AH->archiveRemoteVersion)
629                 ahprintf(AH, ";     Dumped from database version: %s\n",
630                                  AH->archiveRemoteVersion);
631         if (AH->archiveDumpVersion)
632                 ahprintf(AH, ";     Dumped by pg_dump version: %s\n",
633                                  AH->archiveDumpVersion);
634
635         ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
636
637         while (te != AH->toc)
638         {
639                 if (_tocEntryRequired(te, ropt, true) != 0)
640                         ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
641                                          te->catalogId.tableoid, te->catalogId.oid,
642                                          te->desc, te->namespace ? te->namespace : "-",
643                                          te->tag, te->owner);
644                 te = te->next;
645         }
646
647         if (ropt->filename)
648                 ResetOutput(AH, sav);
649 }
650
651 /***********
652  * BLOB Archival
653  ***********/
654
655 /* Called by a dumper to signal start of a BLOB */
656 int
657 StartBlob(Archive *AHX, Oid oid)
658 {
659         ArchiveHandle *AH = (ArchiveHandle *) AHX;
660
661         if (!AH->StartBlobPtr)
662                 die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
663
664         (*AH->StartBlobPtr) (AH, AH->currToc, oid);
665
666         return 1;
667 }
668
669 /* Called by a dumper to signal end of a BLOB */
670 int
671 EndBlob(Archive *AHX, Oid oid)
672 {
673         ArchiveHandle *AH = (ArchiveHandle *) AHX;
674
675         if (AH->EndBlobPtr)
676                 (*AH->EndBlobPtr) (AH, AH->currToc, oid);
677
678         return 1;
679 }
680
681 /**********
682  * BLOB Restoration
683  **********/
684
685 /*
686  * Called by a format handler before any blobs are restored
687  */
688 void
689 StartRestoreBlobs(ArchiveHandle *AH)
690 {
691         if (!AH->ropt->single_txn)
692         {
693                 if (AH->connection)
694                         StartTransaction(AH);
695                 else
696                         ahprintf(AH, "BEGIN;\n\n");
697         }
698
699         AH->blobCount = 0;
700 }
701
702 /*
703  * Called by a format handler after all blobs are restored
704  */
705 void
706 EndRestoreBlobs(ArchiveHandle *AH)
707 {
708         if (!AH->ropt->single_txn)
709         {
710                 if (AH->connection)
711                         CommitTransaction(AH);
712                 else
713                         ahprintf(AH, "COMMIT;\n\n");
714         }
715
716         ahlog(AH, 1, "restored %d large objects\n", AH->blobCount);
717 }
718
719
720 /*
721  * Called by a format handler to initiate restoration of a blob
722  */
723 void
724 StartRestoreBlob(ArchiveHandle *AH, Oid oid)
725 {
726         Oid                     loOid;
727
728         AH->blobCount++;
729
730         /* Initialize the LO Buffer */
731         AH->lo_buf_used = 0;
732
733         ahlog(AH, 2, "restoring large object with OID %u\n", oid);
734
735         if (AH->connection)
736         {
737                 loOid = lo_create(AH->connection, oid);
738                 if (loOid == 0 || loOid != oid)
739                         die_horribly(AH, modulename, "could not create large object %u\n",
740                                                  oid);
741
742                 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
743                 if (AH->loFd == -1)
744                         die_horribly(AH, modulename, "could not open large object\n");
745         }
746         else
747         {
748                 ahprintf(AH, "SELECT lo_open(lo_create(%u), %d);\n", oid, INV_WRITE);
749         }
750
751         AH->writingBlob = 1;
752 }
753
754 void
755 EndRestoreBlob(ArchiveHandle *AH, Oid oid)
756 {
757         if (AH->lo_buf_used > 0)
758         {
759                 /* Write remaining bytes from the LO buffer */
760                 dump_lo_buf(AH);
761         }
762
763         AH->writingBlob = 0;
764
765         if (AH->connection)
766         {
767                 lo_close(AH->connection, AH->loFd);
768                 AH->loFd = -1;
769         }
770         else
771         {
772                 ahprintf(AH, "SELECT lo_close(0);\n\n");
773         }
774 }
775
776 /***********
777  * Sorting and Reordering
778  ***********/
779
780 void
781 SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
782 {
783         ArchiveHandle *AH = (ArchiveHandle *) AHX;
784         FILE       *fh;
785         char            buf[1024];
786         char       *cmnt;
787         char       *endptr;
788         DumpId          id;
789         TocEntry   *te;
790         TocEntry   *tePrev;
791
792         /* Allocate space for the 'wanted' array, and init it */
793         ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);
794         memset(ropt->idWanted, 0, sizeof(bool) * AH->maxDumpId);
795
796         /* Set prev entry as head of list */
797         tePrev = AH->toc;
798
799         /* Setup the file */
800         fh = fopen(ropt->tocFile, PG_BINARY_R);
801         if (!fh)
802                 die_horribly(AH, modulename, "could not open TOC file \"%s\": %s\n",
803                                          ropt->tocFile, strerror(errno));
804
805         while (fgets(buf, sizeof(buf), fh) != NULL)
806         {
807                 /* Truncate line at comment, if any */
808                 cmnt = strchr(buf, ';');
809                 if (cmnt != NULL)
810                         cmnt[0] = '\0';
811
812                 /* Ignore if all blank */
813                 if (strspn(buf, " \t\r") == strlen(buf))
814                         continue;
815
816                 /* Get an ID, check it's valid and not already seen */
817                 id = strtol(buf, &endptr, 10);
818                 if (endptr == buf || id <= 0 || id > AH->maxDumpId ||
819                         ropt->idWanted[id - 1])
820                 {
821                         write_msg(modulename, "WARNING: line ignored: %s\n", buf);
822                         continue;
823                 }
824
825                 /* Find TOC entry */
826                 te = getTocEntryByDumpId(AH, id);
827                 if (!te)
828                         die_horribly(AH, modulename, "could not find entry for ID %d\n",
829                                                  id);
830
831                 ropt->idWanted[id - 1] = true;
832
833                 _moveAfter(AH, tePrev, te);
834                 tePrev = te;
835         }
836
837         if (fclose(fh) != 0)
838                 die_horribly(AH, modulename, "could not close TOC file: %s\n",
839                                          strerror(errno));
840 }
841
842 /*
843  * Set up a dummy ID filter that selects all dump IDs
844  */
845 void
846 InitDummyWantedList(Archive *AHX, RestoreOptions *ropt)
847 {
848         ArchiveHandle *AH = (ArchiveHandle *) AHX;
849
850         /* Allocate space for the 'wanted' array, and init it to 1's */
851         ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);
852         memset(ropt->idWanted, 1, sizeof(bool) * AH->maxDumpId);
853 }
854
855 /**********************
856  * 'Convenience functions that look like standard IO functions
857  * for writing data when in dump mode.
858  **********************/
859
860 /* Public */
861 int
862 archputs(const char *s, Archive *AH)
863 {
864         return WriteData(AH, s, strlen(s));
865 }
866
867 /* Public */
868 int
869 archprintf(Archive *AH, const char *fmt,...)
870 {
871         char       *p = NULL;
872         va_list         ap;
873         int                     bSize = strlen(fmt) + 256;
874         int                     cnt = -1;
875
876         /*
877          * This is paranoid: deal with the possibility that vsnprintf is willing
878          * to ignore trailing null or returns > 0 even if string does not fit. It
879          * may be the case that it returns cnt = bufsize
880          */
881         while (cnt < 0 || cnt >= (bSize - 1))
882         {
883                 if (p != NULL)
884                         free(p);
885                 bSize *= 2;
886                 p = (char *) malloc(bSize);
887                 if (p == NULL)
888                         exit_horribly(AH, modulename, "out of memory\n");
889                 va_start(ap, fmt);
890                 cnt = vsnprintf(p, bSize, fmt, ap);
891                 va_end(ap);
892         }
893         WriteData(AH, p, cnt);
894         free(p);
895         return cnt;
896 }
897
898
899 /*******************************
900  * Stuff below here should be 'private' to the archiver routines
901  *******************************/
902
903 static OutputContext
904 SetOutput(ArchiveHandle *AH, char *filename, int compression)
905 {
906         OutputContext sav;
907         int                     fn;
908
909         /* Replace the AH output file handle */
910         sav.OF = AH->OF;
911         sav.gzOut = AH->gzOut;
912
913         if (filename)
914                 fn = -1;
915         else if (AH->FH)
916                 fn = fileno(AH->FH);
917         else if (AH->fSpec)
918         {
919                 fn = -1;
920                 filename = AH->fSpec;
921         }
922         else
923                 fn = fileno(stdout);
924
925         /* If compression explicitly requested, use gzopen */
926 #ifdef HAVE_LIBZ
927         if (compression != 0)
928         {
929                 char            fmode[10];
930
931                 /* Don't use PG_BINARY_x since this is zlib */
932                 sprintf(fmode, "wb%d", compression);
933                 if (fn >= 0)
934                         AH->OF = gzdopen(dup(fn), fmode);
935                 else
936                         AH->OF = gzopen(filename, fmode);
937                 AH->gzOut = 1;
938         }
939         else
940 #endif
941         {                                                       /* Use fopen */
942                 if (AH->mode == archModeAppend)
943                 {
944                         if (fn >= 0)
945                                 AH->OF = fdopen(dup(fn), PG_BINARY_A);
946                         else
947                                 AH->OF = fopen(filename, PG_BINARY_A);
948                 }
949                 else
950                 {
951                         if (fn >= 0)
952                                 AH->OF = fdopen(dup(fn), PG_BINARY_W);
953                         else
954                                 AH->OF = fopen(filename, PG_BINARY_W);
955                 }
956                 AH->gzOut = 0;
957         }
958
959         if (!AH->OF)
960         {
961                 if (filename)
962                         die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
963                                                  filename, strerror(errno));
964                 else
965                         die_horribly(AH, modulename, "could not open output file: %s\n",
966                                                  strerror(errno));
967         }
968
969         return sav;
970 }
971
972 static void
973 ResetOutput(ArchiveHandle *AH, OutputContext sav)
974 {
975         int                     res;
976
977         if (AH->gzOut)
978                 res = GZCLOSE(AH->OF);
979         else
980                 res = fclose(AH->OF);
981
982         if (res != 0)
983                 die_horribly(AH, modulename, "could not close output file: %s\n",
984                                          strerror(errno));
985
986         AH->gzOut = sav.gzOut;
987         AH->OF = sav.OF;
988 }
989
990
991
992 /*
993  *      Print formatted text to the output file (usually stdout).
994  */
995 int
996 ahprintf(ArchiveHandle *AH, const char *fmt,...)
997 {
998         char       *p = NULL;
999         va_list         ap;
1000         int                     bSize = strlen(fmt) + 256;              /* Should be enough */
1001         int                     cnt = -1;
1002
1003         /*
1004          * This is paranoid: deal with the possibility that vsnprintf is willing
1005          * to ignore trailing null
1006          */
1007
1008         /*
1009          * or returns > 0 even if string does not fit. It may be the case that it
1010          * returns cnt = bufsize
1011          */
1012         while (cnt < 0 || cnt >= (bSize - 1))
1013         {
1014                 if (p != NULL)
1015                         free(p);
1016                 bSize *= 2;
1017                 p = (char *) malloc(bSize);
1018                 if (p == NULL)
1019                         die_horribly(AH, modulename, "out of memory\n");
1020                 va_start(ap, fmt);
1021                 cnt = vsnprintf(p, bSize, fmt, ap);
1022                 va_end(ap);
1023         }
1024         ahwrite(p, 1, cnt, AH);
1025         free(p);
1026         return cnt;
1027 }
1028
1029 void
1030 ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
1031 {
1032         va_list         ap;
1033
1034         if (AH->debugLevel < level && (!AH->public.verbose || level > 1))
1035                 return;
1036
1037         va_start(ap, fmt);
1038         _write_msg(NULL, fmt, ap);
1039         va_end(ap);
1040 }
1041
1042 /*
1043  * Single place for logic which says 'We are restoring to a direct DB connection'.
1044  */
1045 static int
1046 RestoringToDB(ArchiveHandle *AH)
1047 {
1048         return (AH->ropt && AH->ropt->useDB && AH->connection);
1049 }
1050
1051 /*
1052  * Dump the current contents of the LO data buffer while writing a BLOB
1053  */
1054 static void
1055 dump_lo_buf(ArchiveHandle *AH)
1056 {
1057         if (AH->connection)
1058         {
1059                 size_t          res;
1060
1061                 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1062                 ahlog(AH, 5, "wrote %lu bytes of large object data (result = %lu)\n",
1063                           (unsigned long) AH->lo_buf_used, (unsigned long) res);
1064                 if (res != AH->lo_buf_used)
1065                         die_horribly(AH, modulename,
1066                         "could not write to large object (result: %lu, expected: %lu)\n",
1067                                            (unsigned long) res, (unsigned long) AH->lo_buf_used);
1068         }
1069         else
1070         {
1071                 unsigned char *str;
1072                 size_t          len;
1073
1074                 str = PQescapeBytea((const unsigned char *) AH->lo_buf,
1075                                                         AH->lo_buf_used, &len);
1076                 if (!str)
1077                         die_horribly(AH, modulename, "out of memory\n");
1078
1079                 /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1080                 AH->writingBlob = 0;
1081                 ahprintf(AH, "SELECT lowrite(0, '%s');\n", str);
1082                 AH->writingBlob = 1;
1083
1084                 free(str);
1085         }
1086         AH->lo_buf_used = 0;
1087 }
1088
1089
1090 /*
1091  *      Write buffer to the output file (usually stdout). This is user for
1092  *      outputting 'restore' scripts etc. It is even possible for an archive
1093  *      format to create a custom output routine to 'fake' a restore if it
1094  *      wants to generate a script (see TAR output).
1095  */
1096 int
1097 ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
1098 {
1099         size_t          res;
1100
1101         if (AH->writingBlob)
1102         {
1103                 size_t          remaining = size * nmemb;
1104
1105                 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1106                 {
1107                         size_t          avail = AH->lo_buf_size - AH->lo_buf_used;
1108
1109                         memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1110                         ptr = (const void *) ((const char *) ptr + avail);
1111                         remaining -= avail;
1112                         AH->lo_buf_used += avail;
1113                         dump_lo_buf(AH);
1114                 }
1115
1116                 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1117                 AH->lo_buf_used += remaining;
1118
1119                 return size * nmemb;
1120         }
1121         else if (AH->gzOut)
1122         {
1123                 res = GZWRITE((void *) ptr, size, nmemb, AH->OF);
1124                 if (res != (nmemb * size))
1125                         die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
1126                 return res;
1127         }
1128         else if (AH->CustomOutPtr)
1129         {
1130                 res = AH->CustomOutPtr (AH, ptr, size * nmemb);
1131
1132                 if (res != (nmemb * size))
1133                         die_horribly(AH, modulename, "could not write to custom output routine\n");
1134                 return res;
1135         }
1136         else
1137         {
1138                 /*
1139                  * If we're doing a restore, and it's direct to DB, and we're
1140                  * connected then send it to the DB.
1141                  */
1142                 if (RestoringToDB(AH))
1143                         return ExecuteSqlCommandBuf(AH, (void *) ptr, size * nmemb);            /* Always 1, currently */
1144                 else
1145                 {
1146                         res = fwrite((void *) ptr, size, nmemb, AH->OF);
1147                         if (res != nmemb)
1148                                 die_horribly(AH, modulename, "could not write to output file: %s\n",
1149                                                          strerror(errno));
1150                         return res;
1151                 }
1152         }
1153 }
1154
1155 /* Common exit code */
1156 static void
1157 _write_msg(const char *modulename, const char *fmt, va_list ap)
1158 {
1159         if (modulename)
1160                 fprintf(stderr, "%s: [%s] ", progname, _(modulename));
1161         else
1162                 fprintf(stderr, "%s: ", progname);
1163         vfprintf(stderr, _(fmt), ap);
1164 }
1165
1166 void
1167 write_msg(const char *modulename, const char *fmt,...)
1168 {
1169         va_list         ap;
1170
1171         va_start(ap, fmt);
1172         _write_msg(modulename, fmt, ap);
1173         va_end(ap);
1174 }
1175
1176
1177 static void
1178 _die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap)
1179 {
1180         _write_msg(modulename, fmt, ap);
1181
1182         if (AH)
1183         {
1184                 if (AH->public.verbose)
1185                         write_msg(NULL, "*** aborted because of error\n");
1186                 if (AH->connection)
1187                         PQfinish(AH->connection);
1188         }
1189
1190         exit(1);
1191 }
1192
1193 /* External use */
1194 void
1195 exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
1196 {
1197         va_list         ap;
1198
1199         va_start(ap, fmt);
1200         _die_horribly((ArchiveHandle *) AH, modulename, fmt, ap);
1201         va_end(ap);
1202 }
1203
1204 /* Archiver use (just different arg declaration) */
1205 void
1206 die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
1207 {
1208         va_list         ap;
1209
1210         va_start(ap, fmt);
1211         _die_horribly(AH, modulename, fmt, ap);
1212         va_end(ap);
1213 }
1214
1215 /* on some error, we may decide to go on... */
1216 void
1217 warn_or_die_horribly(ArchiveHandle *AH,
1218                                          const char *modulename, const char *fmt,...)
1219 {
1220         va_list         ap;
1221
1222         switch (AH->stage)
1223         {
1224
1225                 case STAGE_NONE:
1226                         /* Do nothing special */
1227                         break;
1228
1229                 case STAGE_INITIALIZING:
1230                         if (AH->stage != AH->lastErrorStage)
1231                                 write_msg(modulename, "Error while INITIALIZING:\n");
1232                         break;
1233
1234                 case STAGE_PROCESSING:
1235                         if (AH->stage != AH->lastErrorStage)
1236                                 write_msg(modulename, "Error while PROCESSING TOC:\n");
1237                         break;
1238
1239                 case STAGE_FINALIZING:
1240                         if (AH->stage != AH->lastErrorStage)
1241                                 write_msg(modulename, "Error while FINALIZING:\n");
1242                         break;
1243         }
1244         if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1245         {
1246                 write_msg(modulename, "Error from TOC entry %d; %u %u %s %s %s\n",
1247                                   AH->currentTE->dumpId,
1248                          AH->currentTE->catalogId.tableoid, AH->currentTE->catalogId.oid,
1249                           AH->currentTE->desc, AH->currentTE->tag, AH->currentTE->owner);
1250         }
1251         AH->lastErrorStage = AH->stage;
1252         AH->lastErrorTE = AH->currentTE;
1253
1254         va_start(ap, fmt);
1255         if (AH->public.exit_on_error)
1256                 _die_horribly(AH, modulename, fmt, ap);
1257         else
1258         {
1259                 _write_msg(modulename, fmt, ap);
1260                 AH->public.n_errors++;
1261         }
1262         va_end(ap);
1263 }
1264
1265 static void
1266 _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1267 {
1268         te->prev->next = te->next;
1269         te->next->prev = te->prev;
1270
1271         te->prev = pos;
1272         te->next = pos->next;
1273
1274         pos->next->prev = te;
1275         pos->next = te;
1276 }
1277
1278 #ifdef NOT_USED
1279
1280 static void
1281 _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1282 {
1283         te->prev->next = te->next;
1284         te->next->prev = te->prev;
1285
1286         te->prev = pos->prev;
1287         te->next = pos;
1288         pos->prev->next = te;
1289         pos->prev = te;
1290 }
1291 #endif
1292
1293 static TocEntry *
1294 getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
1295 {
1296         TocEntry   *te;
1297
1298         te = AH->toc->next;
1299         while (te != AH->toc)
1300         {
1301                 if (te->dumpId == id)
1302                         return te;
1303                 te = te->next;
1304         }
1305         return NULL;
1306 }
1307
1308 teReqs
1309 TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
1310 {
1311         TocEntry   *te = getTocEntryByDumpId(AH, id);
1312
1313         if (!te)
1314                 return 0;
1315
1316         return _tocEntryRequired(te, ropt, true);
1317 }
1318
1319 size_t
1320 WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
1321 {
1322         int                     off;
1323
1324         /* Save the flag */
1325         (*AH->WriteBytePtr) (AH, wasSet);
1326
1327         /* Write out pgoff_t smallest byte first, prevents endian mismatch */
1328         for (off = 0; off < sizeof(pgoff_t); off++)
1329         {
1330                 (*AH->WriteBytePtr) (AH, o & 0xFF);
1331                 o >>= 8;
1332         }
1333         return sizeof(pgoff_t) + 1;
1334 }
1335
1336 int
1337 ReadOffset(ArchiveHandle *AH, pgoff_t * o)
1338 {
1339         int                     i;
1340         int                     off;
1341         int                     offsetFlg;
1342
1343         /* Initialize to zero */
1344         *o = 0;
1345
1346         /* Check for old version */
1347         if (AH->version < K_VERS_1_7)
1348         {
1349                 /* Prior versions wrote offsets using WriteInt */
1350                 i = ReadInt(AH);
1351                 /* -1 means not set */
1352                 if (i < 0)
1353                         return K_OFFSET_POS_NOT_SET;
1354                 else if (i == 0)
1355                         return K_OFFSET_NO_DATA;
1356
1357                 /* Cast to pgoff_t because it was written as an int. */
1358                 *o = (pgoff_t) i;
1359                 return K_OFFSET_POS_SET;
1360         }
1361
1362         /*
1363          * Read the flag indicating the state of the data pointer. Check if valid
1364          * and die if not.
1365          *
1366          * This used to be handled by a negative or zero pointer, now we use an
1367          * extra byte specifically for the state.
1368          */
1369         offsetFlg = (*AH->ReadBytePtr) (AH) & 0xFF;
1370
1371         switch (offsetFlg)
1372         {
1373                 case K_OFFSET_POS_NOT_SET:
1374                 case K_OFFSET_NO_DATA:
1375                 case K_OFFSET_POS_SET:
1376
1377                         break;
1378
1379                 default:
1380                         die_horribly(AH, modulename, "unexpected data offset flag %d\n", offsetFlg);
1381         }
1382
1383         /*
1384          * Read the bytes
1385          */
1386         for (off = 0; off < AH->offSize; off++)
1387         {
1388                 if (off < sizeof(pgoff_t))
1389                         *o |= ((pgoff_t) ((*AH->ReadBytePtr) (AH))) << (off * 8);
1390                 else
1391                 {
1392                         if ((*AH->ReadBytePtr) (AH) != 0)
1393                                 die_horribly(AH, modulename, "file offset in dump file is too large\n");
1394                 }
1395         }
1396
1397         return offsetFlg;
1398 }
1399
1400 size_t
1401 WriteInt(ArchiveHandle *AH, int i)
1402 {
1403         int                     b;
1404
1405         /*
1406          * This is a bit yucky, but I don't want to make the binary format very
1407          * dependent on representation, and not knowing much about it, I write out
1408          * a sign byte. If you change this, don't forget to change the file
1409          * version #, and modify readInt to read the new format AS WELL AS the old
1410          * formats.
1411          */
1412
1413         /* SIGN byte */
1414         if (i < 0)
1415         {
1416                 (*AH->WriteBytePtr) (AH, 1);
1417                 i = -i;
1418         }
1419         else
1420                 (*AH->WriteBytePtr) (AH, 0);
1421
1422         for (b = 0; b < AH->intSize; b++)
1423         {
1424                 (*AH->WriteBytePtr) (AH, i & 0xFF);
1425                 i >>= 8;
1426         }
1427
1428         return AH->intSize + 1;
1429 }
1430
1431 int
1432 ReadInt(ArchiveHandle *AH)
1433 {
1434         int                     res = 0;
1435         int                     bv,
1436                                 b;
1437         int                     sign = 0;               /* Default positive */
1438         int                     bitShift = 0;
1439
1440         if (AH->version > K_VERS_1_0)
1441                 /* Read a sign byte */
1442                 sign = (*AH->ReadBytePtr) (AH);
1443
1444         for (b = 0; b < AH->intSize; b++)
1445         {
1446                 bv = (*AH->ReadBytePtr) (AH) & 0xFF;
1447                 if (bv != 0)
1448                         res = res + (bv << bitShift);
1449                 bitShift += 8;
1450         }
1451
1452         if (sign)
1453                 res = -res;
1454
1455         return res;
1456 }
1457
1458 size_t
1459 WriteStr(ArchiveHandle *AH, const char *c)
1460 {
1461         size_t          res;
1462
1463         if (c)
1464         {
1465                 res = WriteInt(AH, strlen(c));
1466                 res += (*AH->WriteBufPtr) (AH, c, strlen(c));
1467         }
1468         else
1469                 res = WriteInt(AH, -1);
1470
1471         return res;
1472 }
1473
1474 char *
1475 ReadStr(ArchiveHandle *AH)
1476 {
1477         char       *buf;
1478         int                     l;
1479
1480         l = ReadInt(AH);
1481         if (l < 0)
1482                 buf = NULL;
1483         else
1484         {
1485                 buf = (char *) malloc(l + 1);
1486                 if (!buf)
1487                         die_horribly(AH, modulename, "out of memory\n");
1488
1489                 if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
1490                         die_horribly(AH, modulename, "unexpected end of file\n");
1491
1492                 buf[l] = '\0';
1493         }
1494
1495         return buf;
1496 }
1497
1498 static int
1499 _discoverArchiveFormat(ArchiveHandle *AH)
1500 {
1501         FILE       *fh;
1502         char            sig[6];                 /* More than enough */
1503         size_t          cnt;
1504         int                     wantClose = 0;
1505
1506 #if 0
1507         write_msg(modulename, "attempting to ascertain archive format\n");
1508 #endif
1509
1510         if (AH->lookahead)
1511                 free(AH->lookahead);
1512
1513         AH->lookaheadSize = 512;
1514         AH->lookahead = calloc(1, 512);
1515         AH->lookaheadLen = 0;
1516         AH->lookaheadPos = 0;
1517
1518         if (AH->fSpec)
1519         {
1520                 wantClose = 1;
1521                 fh = fopen(AH->fSpec, PG_BINARY_R);
1522                 if (!fh)
1523                         die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
1524                                                  AH->fSpec, strerror(errno));
1525         }
1526         else
1527         {
1528                 fh = stdin;
1529                 if (!fh)
1530                         die_horribly(AH, modulename, "could not open input file: %s\n",
1531                                                  strerror(errno));
1532         }
1533
1534         cnt = fread(sig, 1, 5, fh);
1535
1536         if (cnt != 5)
1537         {
1538                 if (ferror(fh))
1539                         die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno));
1540                 else
1541                         die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n",
1542                                                  (unsigned long) cnt);
1543         }
1544
1545         /* Save it, just in case we need it later */
1546         strncpy(&AH->lookahead[0], sig, 5);
1547         AH->lookaheadLen = 5;
1548
1549         if (strncmp(sig, "PGDMP", 5) == 0)
1550         {
1551                 AH->vmaj = fgetc(fh);
1552                 AH->vmin = fgetc(fh);
1553
1554                 /* Save these too... */
1555                 AH->lookahead[AH->lookaheadLen++] = AH->vmaj;
1556                 AH->lookahead[AH->lookaheadLen++] = AH->vmin;
1557
1558                 /* Check header version; varies from V1.0 */
1559                 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0)))                /* Version > 1.0 */
1560                 {
1561                         AH->vrev = fgetc(fh);
1562                         AH->lookahead[AH->lookaheadLen++] = AH->vrev;
1563                 }
1564                 else
1565                         AH->vrev = 0;
1566
1567                 /* Make a convenient integer <maj><min><rev>00 */
1568                 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
1569
1570                 AH->intSize = fgetc(fh);
1571                 AH->lookahead[AH->lookaheadLen++] = AH->intSize;
1572
1573                 if (AH->version >= K_VERS_1_7)
1574                 {
1575                         AH->offSize = fgetc(fh);
1576                         AH->lookahead[AH->lookaheadLen++] = AH->offSize;
1577                 }
1578                 else
1579                         AH->offSize = AH->intSize;
1580
1581                 AH->format = fgetc(fh);
1582                 AH->lookahead[AH->lookaheadLen++] = AH->format;
1583         }
1584         else
1585         {
1586                 /*
1587                  * *Maybe* we have a tar archive format file... So, read first 512
1588                  * byte header...
1589                  */
1590                 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
1591                 AH->lookaheadLen += cnt;
1592
1593                 if (AH->lookaheadLen != 512)
1594                         die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n");
1595
1596                 if (!isValidTarHeader(AH->lookahead))
1597                         die_horribly(AH, modulename, "input file does not appear to be a valid archive\n");
1598
1599                 AH->format = archTar;
1600         }
1601
1602         /* If we can't seek, then mark the header as read */
1603         if (fseeko(fh, 0, SEEK_SET) != 0)
1604         {
1605                 /*
1606                  * NOTE: Formats that use the lookahead buffer can unset this in their
1607                  * Init routine.
1608                  */
1609                 AH->readHeader = 1;
1610         }
1611         else
1612                 AH->lookaheadLen = 0;   /* Don't bother since we've reset the file */
1613
1614 #if 0
1615         write_msg(modulename, "read %lu bytes into lookahead buffer\n",
1616                           (unsigned long) AH->lookaheadLen);
1617 #endif
1618
1619         /* Close the file */
1620         if (wantClose)
1621                 if (fclose(fh) != 0)
1622                         die_horribly(AH, modulename, "could not close input file: %s\n",
1623                                                  strerror(errno));
1624
1625         return AH->format;
1626 }
1627
1628
1629 /*
1630  * Allocate an archive handle
1631  */
1632 static ArchiveHandle *
1633 _allocAH(const char *FileSpec, const ArchiveFormat fmt,
1634                  const int compression, ArchiveMode mode)
1635 {
1636         ArchiveHandle *AH;
1637
1638 #if 0
1639         write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);
1640 #endif
1641
1642         AH = (ArchiveHandle *) calloc(1, sizeof(ArchiveHandle));
1643         if (!AH)
1644                 die_horribly(AH, modulename, "out of memory\n");
1645
1646         /* AH->debugLevel = 100; */
1647
1648         AH->vmaj = K_VERS_MAJOR;
1649         AH->vmin = K_VERS_MINOR;
1650         AH->vrev = K_VERS_REV;
1651
1652         /* initialize for backwards compatible string processing */
1653         AH->public.encoding = 0;        /* PG_SQL_ASCII */
1654         AH->public.std_strings = false;
1655
1656         /* sql error handling */
1657         AH->public.exit_on_error = true;
1658         AH->public.n_errors = 0;
1659
1660         AH->createDate = time(NULL);
1661
1662         AH->intSize = sizeof(int);
1663         AH->offSize = sizeof(pgoff_t);
1664         if (FileSpec)
1665         {
1666                 AH->fSpec = strdup(FileSpec);
1667
1668                 /*
1669                  * Not used; maybe later....
1670                  *
1671                  * AH->workDir = strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
1672                  * i--) if (AH->workDir[i-1] == '/')
1673                  */
1674         }
1675         else
1676                 AH->fSpec = NULL;
1677
1678         AH->currUser = strdup("");      /* So it's valid, but we can free() it later
1679                                                                  * if necessary */
1680         AH->currSchema = strdup("");    /* ditto */
1681         AH->currWithOids = -1;          /* force SET */
1682
1683         AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
1684         if (!AH->toc)
1685                 die_horribly(AH, modulename, "out of memory\n");
1686
1687         AH->toc->next = AH->toc;
1688         AH->toc->prev = AH->toc;
1689
1690         AH->mode = mode;
1691         AH->compression = compression;
1692
1693         AH->pgCopyBuf = createPQExpBuffer();
1694         AH->sqlBuf = createPQExpBuffer();
1695
1696         /* Open stdout with no compression for AH output handle */
1697         AH->gzOut = 0;
1698         AH->OF = stdout;
1699
1700         /*
1701          * On Windows, we need to use binary mode to read/write non-text archive
1702          * formats.  Force stdin/stdout into binary mode if that is what we are
1703          * using.
1704          */
1705 #ifdef WIN32
1706         if (fmt != archNull &&
1707                 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
1708         {
1709                 if (mode == archModeWrite)
1710                         setmode(fileno(stdout), O_BINARY);
1711                 else
1712                         setmode(fileno(stdin), O_BINARY);
1713         }
1714 #endif
1715
1716 #if 0
1717         write_msg(modulename, "archive format is %d\n", fmt);
1718 #endif
1719
1720         if (fmt == archUnknown)
1721                 AH->format = _discoverArchiveFormat(AH);
1722         else
1723                 AH->format = fmt;
1724
1725         switch (AH->format)
1726         {
1727                 case archCustom:
1728                         InitArchiveFmt_Custom(AH);
1729                         break;
1730
1731                 case archFiles:
1732                         InitArchiveFmt_Files(AH);
1733                         break;
1734
1735                 case archNull:
1736                         InitArchiveFmt_Null(AH);
1737                         break;
1738
1739                 case archTar:
1740                         InitArchiveFmt_Tar(AH);
1741                         break;
1742
1743                 default:
1744                         die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
1745         }
1746
1747         return AH;
1748 }
1749
1750
1751 void
1752 WriteDataChunks(ArchiveHandle *AH)
1753 {
1754         TocEntry   *te = AH->toc->next;
1755         StartDataPtr startPtr;
1756         EndDataPtr      endPtr;
1757
1758         while (te != AH->toc)
1759         {
1760                 if (te->dataDumper != NULL)
1761                 {
1762                         AH->currToc = te;
1763                         /* printf("Writing data for %d (%x)\n", te->id, te); */
1764
1765                         if (strcmp(te->desc, "BLOBS") == 0)
1766                         {
1767                                 startPtr = AH->StartBlobsPtr;
1768                                 endPtr = AH->EndBlobsPtr;
1769                         }
1770                         else
1771                         {
1772                                 startPtr = AH->StartDataPtr;
1773                                 endPtr = AH->EndDataPtr;
1774                         }
1775
1776                         if (startPtr != NULL)
1777                                 (*startPtr) (AH, te);
1778
1779                         /*
1780                          * printf("Dumper arg for %d is %x\n", te->id, te->dataDumperArg);
1781                          */
1782
1783                         /*
1784                          * The user-provided DataDumper routine needs to call
1785                          * AH->WriteData
1786                          */
1787                         (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);
1788
1789                         if (endPtr != NULL)
1790                                 (*endPtr) (AH, te);
1791                         AH->currToc = NULL;
1792                 }
1793                 te = te->next;
1794         }
1795 }
1796
1797 void
1798 WriteToc(ArchiveHandle *AH)
1799 {
1800         TocEntry   *te;
1801         char            workbuf[32];
1802         int                     i;
1803
1804         /* printf("%d TOC Entries to save\n", AH->tocCount); */
1805
1806         WriteInt(AH, AH->tocCount);
1807
1808         for (te = AH->toc->next; te != AH->toc; te = te->next)
1809         {
1810                 WriteInt(AH, te->dumpId);
1811                 WriteInt(AH, te->dataDumper ? 1 : 0);
1812
1813                 /* OID is recorded as a string for historical reasons */
1814                 sprintf(workbuf, "%u", te->catalogId.tableoid);
1815                 WriteStr(AH, workbuf);
1816                 sprintf(workbuf, "%u", te->catalogId.oid);
1817                 WriteStr(AH, workbuf);
1818
1819                 WriteStr(AH, te->tag);
1820                 WriteStr(AH, te->desc);
1821                 WriteStr(AH, te->defn);
1822                 WriteStr(AH, te->dropStmt);
1823                 WriteStr(AH, te->copyStmt);
1824                 WriteStr(AH, te->namespace);
1825                 WriteStr(AH, te->tablespace);
1826                 WriteStr(AH, te->owner);
1827                 WriteStr(AH, te->withOids ? "true" : "false");
1828
1829                 /* Dump list of dependencies */
1830                 for (i = 0; i < te->nDeps; i++)
1831                 {
1832                         sprintf(workbuf, "%d", te->dependencies[i]);
1833                         WriteStr(AH, workbuf);
1834                 }
1835                 WriteStr(AH, NULL);             /* Terminate List */
1836
1837                 if (AH->WriteExtraTocPtr)
1838                         (*AH->WriteExtraTocPtr) (AH, te);
1839         }
1840 }
1841
1842 void
1843 ReadToc(ArchiveHandle *AH)
1844 {
1845         int                     i;
1846         char       *tmp;
1847         DumpId     *deps;
1848         int                     depIdx;
1849         int                     depSize;
1850
1851         TocEntry   *te = AH->toc->next;
1852
1853         AH->tocCount = ReadInt(AH);
1854         AH->maxDumpId = 0;
1855
1856         for (i = 0; i < AH->tocCount; i++)
1857         {
1858                 te = (TocEntry *) calloc(1, sizeof(TocEntry));
1859                 te->dumpId = ReadInt(AH);
1860
1861                 if (te->dumpId > AH->maxDumpId)
1862                         AH->maxDumpId = te->dumpId;
1863
1864                 /* Sanity check */
1865                 if (te->dumpId <= 0)
1866                         die_horribly(AH, modulename,
1867                                            "entry ID %d out of range -- perhaps a corrupt TOC\n",
1868                                                  te->dumpId);
1869
1870                 te->hadDumper = ReadInt(AH);
1871
1872                 if (AH->version >= K_VERS_1_8)
1873                 {
1874                         tmp = ReadStr(AH);
1875                         sscanf(tmp, "%u", &te->catalogId.tableoid);
1876                         free(tmp);
1877                 }
1878                 else
1879                         te->catalogId.tableoid = InvalidOid;
1880                 tmp = ReadStr(AH);
1881                 sscanf(tmp, "%u", &te->catalogId.oid);
1882                 free(tmp);
1883
1884                 te->tag = ReadStr(AH);
1885                 te->desc = ReadStr(AH);
1886                 te->defn = ReadStr(AH);
1887                 te->dropStmt = ReadStr(AH);
1888
1889                 if (AH->version >= K_VERS_1_3)
1890                         te->copyStmt = ReadStr(AH);
1891
1892                 if (AH->version >= K_VERS_1_6)
1893                         te->namespace = ReadStr(AH);
1894
1895                 if (AH->version >= K_VERS_1_10)
1896                         te->tablespace = ReadStr(AH);
1897
1898                 te->owner = ReadStr(AH);
1899                 if (AH->version >= K_VERS_1_9)
1900                 {
1901                         if (strcmp(ReadStr(AH), "true") == 0)
1902                                 te->withOids = true;
1903                         else
1904                                 te->withOids = false;
1905                 }
1906                 else
1907                         te->withOids = true;
1908
1909                 /* Read TOC entry dependencies */
1910                 if (AH->version >= K_VERS_1_5)
1911                 {
1912                         depSize = 100;
1913                         deps = (DumpId *) malloc(sizeof(DumpId) * depSize);
1914                         depIdx = 0;
1915                         for (;;)
1916                         {
1917                                 tmp = ReadStr(AH);
1918                                 if (!tmp)
1919                                         break;          /* end of list */
1920                                 if (depIdx >= depSize)
1921                                 {
1922                                         depSize *= 2;
1923                                         deps = (DumpId *) realloc(deps, sizeof(DumpId) * depSize);
1924                                 }
1925                                 sscanf(tmp, "%d", &deps[depIdx]);
1926                                 free(tmp);
1927                                 depIdx++;
1928                         }
1929
1930                         if (depIdx > 0)         /* We have a non-null entry */
1931                         {
1932                                 deps = (DumpId *) realloc(deps, sizeof(DumpId) * depIdx);
1933                                 te->dependencies = deps;
1934                                 te->nDeps = depIdx;
1935                         }
1936                         else
1937                         {
1938                                 free(deps);
1939                                 te->dependencies = NULL;
1940                                 te->nDeps = 0;
1941                         }
1942                 }
1943                 else
1944                 {
1945                         te->dependencies = NULL;
1946                         te->nDeps = 0;
1947                 }
1948
1949                 if (AH->ReadExtraTocPtr)
1950                         (*AH->ReadExtraTocPtr) (AH, te);
1951
1952                 ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
1953                           i, te->dumpId, te->desc, te->tag);
1954
1955                 /* link completed entry into TOC circular list */
1956                 te->prev = AH->toc->prev;
1957                 AH->toc->prev->next = te;
1958                 AH->toc->prev = te;
1959                 te->next = AH->toc;
1960
1961                 /* special processing immediately upon read for some items */
1962                 if (strcmp(te->desc, "ENCODING") == 0)
1963                         processEncodingEntry(AH, te);
1964                 else if (strcmp(te->desc, "STDSTRINGS") == 0)
1965                         processStdStringsEntry(AH, te);
1966         }
1967 }
1968
1969 static void
1970 processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
1971 {
1972         /* te->defn should have the form SET client_encoding = 'foo'; */
1973         char       *defn = strdup(te->defn);
1974         char       *ptr1;
1975         char       *ptr2 = NULL;
1976         int                     encoding;
1977
1978         ptr1 = strchr(defn, '\'');
1979         if (ptr1)
1980                 ptr2 = strchr(++ptr1, '\'');
1981         if (ptr2)
1982         {
1983                 *ptr2 = '\0';
1984                 encoding = pg_char_to_encoding(ptr1);
1985                 if (encoding < 0)
1986                         die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
1987                                                  ptr1);
1988                 AH->public.encoding = encoding;
1989         }
1990         else
1991                 die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
1992                                          te->defn);
1993
1994         free(defn);
1995 }
1996
1997 static void
1998 processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
1999 {
2000         /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2001         char       *ptr1;
2002
2003         ptr1 = strchr(te->defn, '\'');
2004         if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2005                 AH->public.std_strings = true;
2006         else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2007                 AH->public.std_strings = false;
2008         else
2009                 die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
2010                                          te->defn);
2011 }
2012
2013 static teReqs
2014 _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
2015 {
2016         teReqs          res = REQ_ALL;
2017
2018         /* ENCODING and STDSTRINGS items are dumped specially, so always reject */
2019         if (strcmp(te->desc, "ENCODING") == 0 ||
2020                 strcmp(te->desc, "STDSTRINGS") == 0)
2021                 return 0;
2022
2023         /* If it's an ACL, maybe ignore it */
2024         if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
2025                 return 0;
2026
2027         if (!ropt->create && strcmp(te->desc, "DATABASE") == 0)
2028                 return 0;
2029
2030         /* Check options for selective dump/restore */
2031         if (ropt->schemaNames)
2032         {
2033                 /* If no namespace is specified, it means all. */
2034                 if (!te->namespace)
2035                         return 0;
2036                 if (strcmp(ropt->schemaNames, te->namespace) != 0)
2037                         return 0;
2038         }
2039
2040         if (ropt->selTypes)
2041         {
2042                 if (strcmp(te->desc, "TABLE") == 0 ||
2043                         strcmp(te->desc, "TABLE DATA") == 0)
2044                 {
2045                         if (!ropt->selTable)
2046                                 return 0;
2047                         if (ropt->tableNames && strcmp(ropt->tableNames, te->tag) != 0)
2048                                 return 0;
2049                 }
2050                 else if (strcmp(te->desc, "INDEX") == 0)
2051                 {
2052                         if (!ropt->selIndex)
2053                                 return 0;
2054                         if (ropt->indexNames && strcmp(ropt->indexNames, te->tag) != 0)
2055                                 return 0;
2056                 }
2057                 else if (strcmp(te->desc, "FUNCTION") == 0)
2058                 {
2059                         if (!ropt->selFunction)
2060                                 return 0;
2061                         if (ropt->functionNames && strcmp(ropt->functionNames, te->tag) != 0)
2062                                 return 0;
2063                 }
2064                 else if (strcmp(te->desc, "TRIGGER") == 0)
2065                 {
2066                         if (!ropt->selTrigger)
2067                                 return 0;
2068                         if (ropt->triggerNames && strcmp(ropt->triggerNames, te->tag) != 0)
2069                                 return 0;
2070                 }
2071                 else
2072                         return 0;
2073         }
2074
2075         /*
2076          * Check if we had a dataDumper. Indicates if the entry is schema or data
2077          */
2078         if (!te->hadDumper)
2079         {
2080                 /*
2081                  * Special Case: If 'SEQUENCE SET' then it is considered a data entry
2082                  */
2083                 if (strcmp(te->desc, "SEQUENCE SET") == 0)
2084                         res = res & REQ_DATA;
2085                 else
2086                         res = res & ~REQ_DATA;
2087         }
2088
2089         /*
2090          * Special case: <Init> type with <Max OID> tag; this is obsolete and we
2091          * always ignore it.
2092          */
2093         if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
2094                 return 0;
2095
2096         /* Mask it if we only want schema */
2097         if (ropt->schemaOnly)
2098                 res = res & REQ_SCHEMA;
2099
2100         /* Mask it we only want data */
2101         if (ropt->dataOnly)
2102                 res = res & REQ_DATA;
2103
2104         /* Mask it if we don't have a schema contribution */
2105         if (!te->defn || strlen(te->defn) == 0)
2106                 res = res & ~REQ_SCHEMA;
2107
2108         /* Finally, if there's a per-ID filter, limit based on that as well */
2109         if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2110                 return 0;
2111
2112         return res;
2113 }
2114
2115 /*
2116  * Issue SET commands for parameters that we want to have set the same way
2117  * at all times during execution of a restore script.
2118  */
2119 static void
2120 _doSetFixedOutputState(ArchiveHandle *AH)
2121 {
2122         /* Select the correct character set encoding */
2123         ahprintf(AH, "SET client_encoding = '%s';\n",
2124                          pg_encoding_to_char(AH->public.encoding));
2125
2126         /* Select the correct string literal syntax */
2127         ahprintf(AH, "SET standard_conforming_strings = %s;\n",
2128                          AH->public.std_strings ? "on" : "off");
2129
2130         /* Make sure function checking is disabled */
2131         ahprintf(AH, "SET check_function_bodies = false;\n");
2132
2133         /* Avoid annoying notices etc */
2134         ahprintf(AH, "SET client_min_messages = warning;\n");
2135         if (!AH->public.std_strings)
2136                 ahprintf(AH, "SET escape_string_warning = off;\n");
2137
2138         ahprintf(AH, "\n");
2139 }
2140
2141 /*
2142  * Issue a SET SESSION AUTHORIZATION command.  Caller is responsible
2143  * for updating state if appropriate.  If user is NULL or an empty string,
2144  * the specification DEFAULT will be used.
2145  */
2146 static void
2147 _doSetSessionAuth(ArchiveHandle *AH, const char *user)
2148 {
2149         PQExpBuffer cmd = createPQExpBuffer();
2150
2151         appendPQExpBuffer(cmd, "SET SESSION AUTHORIZATION ");
2152
2153         /*
2154          * SQL requires a string literal here.  Might as well be correct.
2155          */
2156         if (user && *user)
2157                 appendStringLiteralAHX(cmd, user, AH);
2158         else
2159                 appendPQExpBuffer(cmd, "DEFAULT");
2160         appendPQExpBuffer(cmd, ";");
2161
2162         if (RestoringToDB(AH))
2163         {
2164                 PGresult   *res;
2165
2166                 res = PQexec(AH->connection, cmd->data);
2167
2168                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2169                         /* NOT warn_or_die_horribly... use -O instead to skip this. */
2170                         die_horribly(AH, modulename, "could not set session user to \"%s\": %s",
2171                                                  user, PQerrorMessage(AH->connection));
2172
2173                 PQclear(res);
2174         }
2175         else
2176                 ahprintf(AH, "%s\n\n", cmd->data);
2177
2178         destroyPQExpBuffer(cmd);
2179 }
2180
2181
2182 /*
2183  * Issue a SET default_with_oids command.  Caller is responsible
2184  * for updating state if appropriate.
2185  */
2186 static void
2187 _doSetWithOids(ArchiveHandle *AH, const bool withOids)
2188 {
2189         PQExpBuffer cmd = createPQExpBuffer();
2190
2191         appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?
2192                                           "true" : "false");
2193
2194         if (RestoringToDB(AH))
2195         {
2196                 PGresult   *res;
2197
2198                 res = PQexec(AH->connection, cmd->data);
2199
2200                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2201                         warn_or_die_horribly(AH, modulename,
2202                                                                  "could not set default_with_oids: %s",
2203                                                                  PQerrorMessage(AH->connection));
2204
2205                 PQclear(res);
2206         }
2207         else
2208                 ahprintf(AH, "%s\n\n", cmd->data);
2209
2210         destroyPQExpBuffer(cmd);
2211 }
2212
2213
2214 /*
2215  * Issue the commands to connect to the specified database.
2216  *
2217  * If we're currently restoring right into a database, this will
2218  * actually establish a connection. Otherwise it puts a \connect into
2219  * the script output.
2220  *
2221  * NULL dbname implies reconnecting to the current DB (pretty useless).
2222  */
2223 static void
2224 _reconnectToDB(ArchiveHandle *AH, const char *dbname)
2225 {
2226         if (RestoringToDB(AH))
2227                 ReconnectToServer(AH, dbname, NULL);
2228         else
2229         {
2230                 PQExpBuffer qry = createPQExpBuffer();
2231
2232                 appendPQExpBuffer(qry, "\\connect %s\n\n",
2233                                                   dbname ? fmtId(dbname) : "-");
2234                 ahprintf(AH, "%s", qry->data);
2235                 destroyPQExpBuffer(qry);
2236         }
2237
2238         /*
2239          * NOTE: currUser keeps track of what the imaginary session user in our
2240          * script is.  It's now effectively reset to the original userID.
2241          */
2242         if (AH->currUser)
2243                 free(AH->currUser);
2244
2245         AH->currUser = strdup("");
2246
2247         /* don't assume we still know the output schema */
2248         if (AH->currSchema)
2249                 free(AH->currSchema);
2250         AH->currSchema = strdup("");
2251         AH->currWithOids = -1;
2252
2253         /* re-establish fixed state */
2254         _doSetFixedOutputState(AH);
2255 }
2256
2257 /*
2258  * Become the specified user, and update state to avoid redundant commands
2259  *
2260  * NULL or empty argument is taken to mean restoring the session default
2261  */
2262 static void
2263 _becomeUser(ArchiveHandle *AH, const char *user)
2264 {
2265         if (!user)
2266                 user = "";                              /* avoid null pointers */
2267
2268         if (AH->currUser && strcmp(AH->currUser, user) == 0)
2269                 return;                                 /* no need to do anything */
2270
2271         _doSetSessionAuth(AH, user);
2272
2273         /*
2274          * NOTE: currUser keeps track of what the imaginary session user in our
2275          * script is
2276          */
2277         if (AH->currUser)
2278                 free(AH->currUser);
2279
2280         AH->currUser = strdup(user);
2281 }
2282
2283 /*
2284  * Become the owner of the the given TOC entry object.  If
2285  * changes in ownership are not allowed, this doesn't do anything.
2286  */
2287 static void
2288 _becomeOwner(ArchiveHandle *AH, TocEntry *te)
2289 {
2290         if (AH->ropt && (AH->ropt->noOwner || !AH->ropt->use_setsessauth))
2291                 return;
2292
2293         _becomeUser(AH, te->owner);
2294 }
2295
2296
2297 /*
2298  * Set the proper default_with_oids value for the table.
2299  */
2300 static void
2301 _setWithOids(ArchiveHandle *AH, TocEntry *te)
2302 {
2303         if (AH->currWithOids != te->withOids)
2304         {
2305                 _doSetWithOids(AH, te->withOids);
2306                 AH->currWithOids = te->withOids;
2307         }
2308 }
2309
2310
2311 /*
2312  * Issue the commands to select the specified schema as the current schema
2313  * in the target database.
2314  */
2315 static void
2316 _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
2317 {
2318         PQExpBuffer qry;
2319
2320         if (!schemaName || *schemaName == '\0' ||
2321                 (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
2322                 return;                                 /* no need to do anything */
2323
2324         qry = createPQExpBuffer();
2325
2326         appendPQExpBuffer(qry, "SET search_path = %s",
2327                                           fmtId(schemaName));
2328         if (strcmp(schemaName, "pg_catalog") != 0)
2329                 appendPQExpBuffer(qry, ", pg_catalog");
2330
2331         if (RestoringToDB(AH))
2332         {
2333                 PGresult   *res;
2334
2335                 res = PQexec(AH->connection, qry->data);
2336
2337                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2338                         warn_or_die_horribly(AH, modulename,
2339                                                                  "could not set search_path to \"%s\": %s",
2340                                                                  schemaName, PQerrorMessage(AH->connection));
2341
2342                 PQclear(res);
2343         }
2344         else
2345                 ahprintf(AH, "%s;\n\n", qry->data);
2346
2347         if (AH->currSchema)
2348                 free(AH->currSchema);
2349         AH->currSchema = strdup(schemaName);
2350
2351         destroyPQExpBuffer(qry);
2352 }
2353
2354 /*
2355  * Issue the commands to select the specified tablespace as the current one
2356  * in the target database.
2357  */
2358 static void
2359 _selectTablespace(ArchiveHandle *AH, const char *tablespace)
2360 {
2361         PQExpBuffer qry;
2362         const char *want,
2363                            *have;
2364
2365         have = AH->currTablespace;
2366         want = tablespace;
2367
2368         /* no need to do anything for non-tablespace object */
2369         if (!want)
2370                 return;
2371
2372         if (have && strcmp(want, have) == 0)
2373                 return;                                 /* no need to do anything */
2374
2375         qry = createPQExpBuffer();
2376
2377         if (strcmp(want, "") == 0)
2378         {
2379                 /* We want the tablespace to be the database's default */
2380                 appendPQExpBuffer(qry, "SET default_tablespace = ''");
2381         }
2382         else
2383         {
2384                 /* We want an explicit tablespace */
2385                 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
2386         }
2387
2388         if (RestoringToDB(AH))
2389         {
2390                 PGresult   *res;
2391
2392                 res = PQexec(AH->connection, qry->data);
2393
2394                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2395                         warn_or_die_horribly(AH, modulename,
2396                                                                  "could not set default_tablespace to %s: %s",
2397                                                                  fmtId(want), PQerrorMessage(AH->connection));
2398
2399                 PQclear(res);
2400         }
2401         else
2402                 ahprintf(AH, "%s;\n\n", qry->data);
2403
2404         if (AH->currTablespace)
2405                 free(AH->currTablespace);
2406         AH->currTablespace = strdup(want);
2407
2408         destroyPQExpBuffer(qry);
2409 }
2410
2411 /*
2412  * Extract an object description for a TOC entry, and append it to buf.
2413  *
2414  * This is not quite as general as it may seem, since it really only
2415  * handles constructing the right thing to put into ALTER ... OWNER TO.
2416  *
2417  * The whole thing is pretty grotty, but we are kind of stuck since the
2418  * information used is all that's available in older dump files.
2419  */
2420 static void
2421 _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
2422 {
2423         const char *type = te->desc;
2424
2425         /* Use ALTER TABLE for views and sequences */
2426         if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0)
2427                 type = "TABLE";
2428
2429         /* objects named by a schema and name */
2430         if (strcmp(type, "CONVERSION") == 0 ||
2431                 strcmp(type, "DOMAIN") == 0 ||
2432                 strcmp(type, "TABLE") == 0 ||
2433                 strcmp(type, "TYPE") == 0 ||
2434                 strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
2435                 strcmp(type, "TEXT SEARCH CONFIGURATION") == 0)
2436         {
2437                 appendPQExpBuffer(buf, "%s ", type);
2438                 if (te->namespace && te->namespace[0])  /* is null pre-7.3 */
2439                         appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
2440
2441                 /*
2442                  * Pre-7.3 pg_dump would sometimes (not always) put a fmtId'd name
2443                  * into te->tag for an index. This check is heuristic, so make its
2444                  * scope as narrow as possible.
2445                  */
2446                 if (AH->version < K_VERS_1_7 &&
2447                         te->tag[0] == '"' &&
2448                         te->tag[strlen(te->tag) - 1] == '"' &&
2449                         strcmp(type, "INDEX") == 0)
2450                         appendPQExpBuffer(buf, "%s", te->tag);
2451                 else
2452                         appendPQExpBuffer(buf, "%s", fmtId(te->tag));
2453                 return;
2454         }
2455
2456         /* objects named by just a name */
2457         if (strcmp(type, "DATABASE") == 0 ||
2458                 strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
2459                 strcmp(type, "SCHEMA") == 0)
2460         {
2461                 appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
2462                 return;
2463         }
2464
2465         /*
2466          * These object types require additional decoration.  Fortunately, the
2467          * information needed is exactly what's in the DROP command.
2468          */
2469         if (strcmp(type, "AGGREGATE") == 0 ||
2470                 strcmp(type, "FUNCTION") == 0 ||
2471                 strcmp(type, "OPERATOR") == 0 ||
2472                 strcmp(type, "OPERATOR CLASS") == 0 ||
2473                 strcmp(type, "OPERATOR FAMILY") == 0)
2474         {
2475                 /* Chop "DROP " off the front and make a modifiable copy */
2476                 char       *first = strdup(te->dropStmt + 5);
2477                 char       *last;
2478
2479                 /* point to last character in string */
2480                 last = first + strlen(first) - 1;
2481
2482                 /* Strip off any ';' or '\n' at the end */
2483                 while (last >= first && (*last == '\n' || *last == ';'))
2484                         last--;
2485                 *(last + 1) = '\0';
2486
2487                 appendPQExpBufferStr(buf, first);
2488
2489                 free(first);
2490                 return;
2491         }
2492
2493         write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2494                           type);
2495 }
2496
2497 static void
2498 _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass)
2499 {
2500         /* ACLs are dumped only during acl pass */
2501         if (acl_pass)
2502         {
2503                 if (strcmp(te->desc, "ACL") != 0)
2504                         return;
2505         }
2506         else
2507         {
2508                 if (strcmp(te->desc, "ACL") == 0)
2509                         return;
2510         }
2511
2512         /*
2513          * Avoid dumping the public schema, as it will already be created ...
2514          * unless we are using --clean mode, in which case it's been deleted and
2515          * we'd better recreate it.
2516          */
2517         if (!ropt->dropSchema &&
2518                 strcmp(te->desc, "SCHEMA") == 0 && strcmp(te->tag, "public") == 0)
2519                 return;
2520
2521         /* Select owner, schema, and tablespace as necessary */
2522         _becomeOwner(AH, te);
2523         _selectOutputSchema(AH, te->namespace);
2524         _selectTablespace(AH, te->tablespace);
2525
2526         /* Set up OID mode too */
2527         if (strcmp(te->desc, "TABLE") == 0)
2528                 _setWithOids(AH, te);
2529
2530         /* Emit header comment for item */
2531         if (!AH->noTocComments)
2532         {
2533                 const char *pfx;
2534
2535                 if (isData)
2536                         pfx = "Data for ";
2537                 else
2538                         pfx = "";
2539
2540                 ahprintf(AH, "--\n");
2541                 if (AH->public.verbose)
2542                 {
2543                         ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
2544                                          te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
2545                         if (te->nDeps > 0)
2546                         {
2547                                 int                     i;
2548
2549                                 ahprintf(AH, "-- Dependencies:");
2550                                 for (i = 0; i < te->nDeps; i++)
2551                                         ahprintf(AH, " %d", te->dependencies[i]);
2552                                 ahprintf(AH, "\n");
2553                         }
2554                 }
2555                 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
2556                                  pfx, te->tag, te->desc,
2557                                  te->namespace ? te->namespace : "-",
2558                                  ropt->noOwner ? "-" : te->owner);
2559                 if (te->tablespace)
2560                         ahprintf(AH, "; Tablespace: %s", te->tablespace);
2561                 ahprintf(AH, "\n");
2562
2563                 if (AH->PrintExtraTocPtr !=NULL)
2564                         (*AH->PrintExtraTocPtr) (AH, te);
2565                 ahprintf(AH, "--\n\n");
2566         }
2567
2568         /*
2569          * Actually print the definition.
2570          *
2571          * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
2572          * versions put into CREATE SCHEMA.  We have to do this when --no-owner
2573          * mode is selected.  This is ugly, but I see no other good way ...
2574          */
2575         if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
2576         {
2577                 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
2578         }
2579         else
2580         {
2581                 if (strlen(te->defn) > 0)
2582                         ahprintf(AH, "%s\n\n", te->defn);
2583         }
2584
2585         /*
2586          * If we aren't using SET SESSION AUTH to determine ownership, we must
2587          * instead issue an ALTER OWNER command.  We assume that anything without
2588          * a DROP command is not a separately ownable object.  All the categories
2589          * with DROP commands must appear in one list or the other.
2590          */
2591         if (!ropt->noOwner && !ropt->use_setsessauth &&
2592                 strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
2593         {
2594                 if (strcmp(te->desc, "AGGREGATE") == 0 ||
2595                         strcmp(te->desc, "CONVERSION") == 0 ||
2596                         strcmp(te->desc, "DATABASE") == 0 ||
2597                         strcmp(te->desc, "DOMAIN") == 0 ||
2598                         strcmp(te->desc, "FUNCTION") == 0 ||
2599                         strcmp(te->desc, "OPERATOR") == 0 ||
2600                         strcmp(te->desc, "OPERATOR CLASS") == 0 ||
2601                         strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
2602                         strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
2603                         strcmp(te->desc, "SCHEMA") == 0 ||
2604                         strcmp(te->desc, "TABLE") == 0 ||
2605                         strcmp(te->desc, "TYPE") == 0 ||
2606                         strcmp(te->desc, "VIEW") == 0 ||
2607                         strcmp(te->desc, "SEQUENCE") == 0 ||
2608                         strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
2609                         strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0)
2610                 {
2611                         PQExpBuffer temp = createPQExpBuffer();
2612
2613                         appendPQExpBuffer(temp, "ALTER ");
2614                         _getObjectDescription(temp, te, AH);
2615                         appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
2616                         ahprintf(AH, "%s\n\n", temp->data);
2617                         destroyPQExpBuffer(temp);
2618                 }
2619                 else if (strcmp(te->desc, "CAST") == 0 ||
2620                                  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2621                                  strcmp(te->desc, "CONSTRAINT") == 0 ||
2622                                  strcmp(te->desc, "DEFAULT") == 0 ||
2623                                  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2624                                  strcmp(te->desc, "INDEX") == 0 ||
2625                                  strcmp(te->desc, "RULE") == 0 ||
2626                                  strcmp(te->desc, "TRIGGER") == 0)
2627                 {
2628                         /* these object types don't have separate owners */
2629                 }
2630                 else
2631                 {
2632                         write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2633                                           te->desc);
2634                 }
2635         }
2636
2637         /*
2638          * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
2639          * commands, so we can no longer assume we know the current auth setting.
2640          */
2641         if (strncmp(te->desc, "ACL", 3) == 0)
2642         {
2643                 if (AH->currUser)
2644                         free(AH->currUser);
2645                 AH->currUser = NULL;
2646         }
2647 }
2648
2649 void
2650 WriteHead(ArchiveHandle *AH)
2651 {
2652         struct tm       crtm;
2653
2654         (*AH->WriteBufPtr) (AH, "PGDMP", 5);            /* Magic code */
2655         (*AH->WriteBytePtr) (AH, AH->vmaj);
2656         (*AH->WriteBytePtr) (AH, AH->vmin);
2657         (*AH->WriteBytePtr) (AH, AH->vrev);
2658         (*AH->WriteBytePtr) (AH, AH->intSize);
2659         (*AH->WriteBytePtr) (AH, AH->offSize);
2660         (*AH->WriteBytePtr) (AH, AH->format);
2661
2662 #ifndef HAVE_LIBZ
2663         if (AH->compression != 0)
2664                 write_msg(modulename, "WARNING: requested compression not available in this "
2665                                   "installation -- archive will be uncompressed\n");
2666
2667         AH->compression = 0;
2668 #endif
2669
2670         WriteInt(AH, AH->compression);
2671
2672         crtm = *localtime(&AH->createDate);
2673         WriteInt(AH, crtm.tm_sec);
2674         WriteInt(AH, crtm.tm_min);
2675         WriteInt(AH, crtm.tm_hour);
2676         WriteInt(AH, crtm.tm_mday);
2677         WriteInt(AH, crtm.tm_mon);
2678         WriteInt(AH, crtm.tm_year);
2679         WriteInt(AH, crtm.tm_isdst);
2680         WriteStr(AH, PQdb(AH->connection));
2681         WriteStr(AH, AH->public.remoteVersionStr);
2682         WriteStr(AH, PG_VERSION);
2683 }
2684
2685 void
2686 ReadHead(ArchiveHandle *AH)
2687 {
2688         char            tmpMag[7];
2689         int                     fmt;
2690         struct tm       crtm;
2691
2692         /* If we haven't already read the header... */
2693         if (!AH->readHeader)
2694         {
2695                 if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
2696                         die_horribly(AH, modulename, "unexpected end of file\n");
2697
2698                 if (strncmp(tmpMag, "PGDMP", 5) != 0)
2699                         die_horribly(AH, modulename, "did not find magic string in file header\n");
2700
2701                 AH->vmaj = (*AH->ReadBytePtr) (AH);
2702                 AH->vmin = (*AH->ReadBytePtr) (AH);
2703
2704                 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0)))                /* Version > 1.0 */
2705                         AH->vrev = (*AH->ReadBytePtr) (AH);
2706                 else
2707                         AH->vrev = 0;
2708
2709                 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
2710
2711
2712                 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
2713                         die_horribly(AH, modulename, "unsupported version (%d.%d) in file header\n",
2714                                                  AH->vmaj, AH->vmin);
2715
2716                 AH->intSize = (*AH->ReadBytePtr) (AH);
2717                 if (AH->intSize > 32)
2718                         die_horribly(AH, modulename, "sanity check on integer size (%lu) failed\n",
2719                                                  (unsigned long) AH->intSize);
2720
2721                 if (AH->intSize > sizeof(int))
2722                         write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
2723
2724                 if (AH->version >= K_VERS_1_7)
2725                         AH->offSize = (*AH->ReadBytePtr) (AH);
2726                 else
2727                         AH->offSize = AH->intSize;
2728
2729                 fmt = (*AH->ReadBytePtr) (AH);
2730
2731                 if (AH->format != fmt)
2732                         die_horribly(AH, modulename, "expected format (%d) differs from format found in file (%d)\n",
2733                                                  AH->format, fmt);
2734         }
2735
2736         if (AH->version >= K_VERS_1_2)
2737         {
2738                 if (AH->version < K_VERS_1_4)
2739                         AH->compression = (*AH->ReadBytePtr) (AH);
2740                 else
2741                         AH->compression = ReadInt(AH);
2742         }
2743         else
2744                 AH->compression = Z_DEFAULT_COMPRESSION;
2745
2746 #ifndef HAVE_LIBZ
2747         if (AH->compression != 0)
2748                 write_msg(modulename, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
2749 #endif
2750
2751         if (AH->version >= K_VERS_1_4)
2752         {
2753                 crtm.tm_sec = ReadInt(AH);
2754                 crtm.tm_min = ReadInt(AH);
2755                 crtm.tm_hour = ReadInt(AH);
2756                 crtm.tm_mday = ReadInt(AH);
2757                 crtm.tm_mon = ReadInt(AH);
2758                 crtm.tm_year = ReadInt(AH);
2759                 crtm.tm_isdst = ReadInt(AH);
2760
2761                 AH->archdbname = ReadStr(AH);
2762
2763                 AH->createDate = mktime(&crtm);
2764
2765                 if (AH->createDate == (time_t) -1)
2766                         write_msg(modulename, "WARNING: invalid creation date in header\n");
2767         }
2768
2769         if (AH->version >= K_VERS_1_10)
2770         {
2771                 AH->archiveRemoteVersion = ReadStr(AH);
2772                 AH->archiveDumpVersion = ReadStr(AH);
2773         }
2774
2775 }
2776
2777
2778 /*
2779  * checkSeek
2780  *        check to see if fseek can be performed.
2781  */
2782
2783 bool
2784 checkSeek(FILE *fp)
2785 {
2786
2787         if (fseeko(fp, 0, SEEK_CUR) != 0)
2788                 return false;
2789         else if (sizeof(pgoff_t) > sizeof(long))
2790
2791                 /*
2792                  * At this point, pgoff_t is too large for long, so we return based on
2793                  * whether an pgoff_t version of fseek is available.
2794                  */
2795 #ifdef HAVE_FSEEKO
2796                 return true;
2797 #else
2798                 return false;
2799 #endif
2800         else
2801                 return true;
2802 }
2803
2804
2805 /*
2806  * dumpTimestamp
2807  */
2808 static void
2809 dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
2810 {
2811         char            buf[256];
2812
2813         /*
2814          * We don't print the timezone on Win32, because the names are long and
2815          * localized, which means they may contain characters in various random
2816          * encodings; this has been seen to cause encoding errors when reading the
2817          * dump script.
2818          */
2819         if (strftime(buf, sizeof(buf),
2820 #ifndef WIN32
2821                                  "%Y-%m-%d %H:%M:%S %Z",
2822 #else
2823                                  "%Y-%m-%d %H:%M:%S",
2824 #endif
2825                                  localtime(&tim)) != 0)
2826                 ahprintf(AH, "-- %s %s\n\n", msg, buf);
2827 }