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