PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_backup_custom.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_backup_custom.c
4  *
5  * Implements the custom output format.
6  *
7  * The comments with the routined in this code are a good place to
8  * understand how to write a new format.
9  *
10  * See the headers to pg_restore for more details.
11  *
12  * Copyright (c) 2000, Philip Warner
13  * Rights are granted to use this software in any way so long
14  * as this notice is not removed.
15  *
16  * The author is not responsible for loss or damages that may
17  * and any liability will be limited to the time taken to fix any
18  * related bug.
19  *
20  *
21  * IDENTIFICATION
22  * src/bin/pg_dump/pg_backup_custom.c
23  *
24  *-------------------------------------------------------------------------
25  */
26 #include "postgres_fe.h"
27 
28 #include "compress_io.h"
29 #include "parallel.h"
30 #include "pg_backup_utils.h"
31 
32 /*--------
33  * Routines in the format interface
34  *--------
35  */
36 
37 static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
38 static void _StartData(ArchiveHandle *AH, TocEntry *te);
39 static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
40 static void _EndData(ArchiveHandle *AH, TocEntry *te);
41 static int _WriteByte(ArchiveHandle *AH, const int i);
42 static int _ReadByte(ArchiveHandle *);
43 static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
44 static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
45 static void _CloseArchive(ArchiveHandle *AH);
46 static void _ReopenArchive(ArchiveHandle *AH);
47 static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
48 static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
49 static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
50 static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
51 
52 static void _PrintData(ArchiveHandle *AH);
53 static void _skipData(ArchiveHandle *AH);
54 static void _skipBlobs(ArchiveHandle *AH);
55 
56 static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
57 static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
58 static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
59 static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
60 static void _LoadBlobs(ArchiveHandle *AH, bool drop);
61 static void _Clone(ArchiveHandle *AH);
62 static void _DeClone(ArchiveHandle *AH);
63 
65 
66 typedef struct
67 {
69  int hasSeek;
72 } lclContext;
73 
74 typedef struct
75 {
76  int dataState;
78 } lclTocEntry;
79 
80 
81 /*------
82  * Static declarations
83  *------
84  */
85 static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id);
87 
88 static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len);
89 static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen);
90 
91 /* translator: this is a module name */
92 static const char *modulename = gettext_noop("custom archiver");
93 
94 
95 
96 /*
97  * Init routine required by ALL formats. This is a global routine
98  * and should be declared in pg_backup_archiver.h
99  *
100  * It's task is to create any extra archive context (using AH->formatData),
101  * and to initialize the supported function pointers.
102  *
103  * It should also prepare whatever it's input source is for reading/writing,
104  * and in the case of a read mode connection, it should load the Header & TOC.
105  */
106 void
108 {
109  lclContext *ctx;
110 
111  /* Assuming static functions, this can be copied for each format. */
113  AH->StartDataPtr = _StartData;
114  AH->WriteDataPtr = _WriteData;
115  AH->EndDataPtr = _EndData;
116  AH->WriteBytePtr = _WriteByte;
117  AH->ReadBytePtr = _ReadByte;
118  AH->WriteBufPtr = _WriteBuf;
119  AH->ReadBufPtr = _ReadBuf;
120  AH->ClosePtr = _CloseArchive;
126 
128  AH->StartBlobPtr = _StartBlob;
129  AH->EndBlobPtr = _EndBlob;
130  AH->EndBlobsPtr = _EndBlobs;
131  AH->ClonePtr = _Clone;
132  AH->DeClonePtr = _DeClone;
133 
134  /* no parallel dump in the custom archive, only parallel restore */
135  AH->WorkerJobDumpPtr = NULL;
137 
138  /* Set up a private area. */
139  ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
140  AH->formatData = (void *) ctx;
141 
142  /* Initialize LO buffering */
143  AH->lo_buf_size = LOBBUFSIZE;
144  AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
145 
146  ctx->filePos = 0;
147 
148  /*
149  * Now open the file
150  */
151  if (AH->mode == archModeWrite)
152  {
153  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
154  {
155  AH->FH = fopen(AH->fSpec, PG_BINARY_W);
156  if (!AH->FH)
157  exit_horribly(modulename, "could not open output file \"%s\": %s\n",
158  AH->fSpec, strerror(errno));
159  }
160  else
161  {
162  AH->FH = stdout;
163  if (!AH->FH)
164  exit_horribly(modulename, "could not open output file: %s\n",
165  strerror(errno));
166  }
167 
168  ctx->hasSeek = checkSeek(AH->FH);
169  }
170  else
171  {
172  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
173  {
174  AH->FH = fopen(AH->fSpec, PG_BINARY_R);
175  if (!AH->FH)
176  exit_horribly(modulename, "could not open input file \"%s\": %s\n",
177  AH->fSpec, strerror(errno));
178  }
179  else
180  {
181  AH->FH = stdin;
182  if (!AH->FH)
183  exit_horribly(modulename, "could not open input file: %s\n",
184  strerror(errno));
185  }
186 
187  ctx->hasSeek = checkSeek(AH->FH);
188 
189  ReadHead(AH);
190  ReadToc(AH);
191  ctx->dataStart = _getFilePos(AH, ctx);
192  }
193 
194 }
195 
196 /*
197  * Called by the Archiver when the dumper creates a new TOC entry.
198  *
199  * Optional.
200  *
201  * Set up extract format-related TOC data.
202 */
203 static void
205 {
206  lclTocEntry *ctx;
207 
208  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
209  if (te->dataDumper)
211  else
213 
214  te->formatData = (void *) ctx;
215 }
216 
217 /*
218  * Called by the Archiver to save any extra format-related TOC entry
219  * data.
220  *
221  * Optional.
222  *
223  * Use the Archiver routines to write data - they are non-endian, and
224  * maintain other important file information.
225  */
226 static void
228 {
229  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
230 
231  WriteOffset(AH, ctx->dataPos, ctx->dataState);
232 }
233 
234 /*
235  * Called by the Archiver to read any extra format-related TOC data.
236  *
237  * Optional.
238  *
239  * Needs to match the order defined in _WriteExtraToc, and should also
240  * use the Archiver input routines.
241  */
242 static void
244 {
245  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
246 
247  if (ctx == NULL)
248  {
249  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
250  te->formatData = (void *) ctx;
251  }
252 
253  ctx->dataState = ReadOffset(AH, &(ctx->dataPos));
254 
255  /*
256  * Prior to V1.7 (pg7.3), we dumped the data size as an int now we don't
257  * dump it at all.
258  */
259  if (AH->version < K_VERS_1_7)
260  ReadInt(AH);
261 }
262 
263 /*
264  * Called by the Archiver when restoring an archive to output a comment
265  * that includes useful information about the TOC entry.
266  *
267  * Optional.
268  *
269  */
270 static void
272 {
273  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
274 
275  if (AH->public.verbose)
276  ahprintf(AH, "-- Data Pos: " INT64_FORMAT "\n",
277  (int64) ctx->dataPos);
278 }
279 
280 /*
281  * Called by the archiver when saving TABLE DATA (not schema). This routine
282  * should save whatever format-specific information is needed to read
283  * the archive back.
284  *
285  * It is called just prior to the dumper's 'DataDumper' routine being called.
286  *
287  * Optional, but strongly recommended.
288  *
289  */
290 static void
292 {
293  lclContext *ctx = (lclContext *) AH->formatData;
294  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
295 
296  tctx->dataPos = _getFilePos(AH, ctx);
297  tctx->dataState = K_OFFSET_POS_SET;
298 
299  _WriteByte(AH, BLK_DATA); /* Block type */
300  WriteInt(AH, te->dumpId); /* For sanity check */
301 
303 }
304 
305 /*
306  * Called by archiver when dumper calls WriteData. This routine is
307  * called for both BLOB and TABLE data; it is the responsibility of
308  * the format to manage each kind of data using StartBlob/StartData.
309  *
310  * It should only be called from within a DataDumper routine.
311  *
312  * Mandatory.
313  */
314 static void
315 _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
316 {
317  lclContext *ctx = (lclContext *) AH->formatData;
318  CompressorState *cs = ctx->cs;
319 
320  if (dLen > 0)
321  /* WriteDataToArchive() internally throws write errors */
322  WriteDataToArchive(AH, cs, data, dLen);
323 
324  return;
325 }
326 
327 /*
328  * Called by the archiver when a dumper's 'DataDumper' routine has
329  * finished.
330  *
331  * Optional.
332  *
333  */
334 static void
336 {
337  lclContext *ctx = (lclContext *) AH->formatData;
338 
339  EndCompressor(AH, ctx->cs);
340  /* Send the end marker */
341  WriteInt(AH, 0);
342 }
343 
344 /*
345  * Called by the archiver when starting to save all BLOB DATA (not schema).
346  * This routine should save whatever format-specific information is needed
347  * to read the BLOBs back into memory.
348  *
349  * It is called just prior to the dumper's DataDumper routine.
350  *
351  * Optional, but strongly recommended.
352  */
353 static void
355 {
356  lclContext *ctx = (lclContext *) AH->formatData;
357  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
358 
359  tctx->dataPos = _getFilePos(AH, ctx);
360  tctx->dataState = K_OFFSET_POS_SET;
361 
362  _WriteByte(AH, BLK_BLOBS); /* Block type */
363  WriteInt(AH, te->dumpId); /* For sanity check */
364 }
365 
366 /*
367  * Called by the archiver when the dumper calls StartBlob.
368  *
369  * Mandatory.
370  *
371  * Must save the passed OID for retrieval at restore-time.
372  */
373 static void
375 {
376  lclContext *ctx = (lclContext *) AH->formatData;
377 
378  if (oid == 0)
379  exit_horribly(modulename, "invalid OID for large object\n");
380 
381  WriteInt(AH, oid);
382 
384 }
385 
386 /*
387  * Called by the archiver when the dumper calls EndBlob.
388  *
389  * Optional.
390  */
391 static void
393 {
394  lclContext *ctx = (lclContext *) AH->formatData;
395 
396  EndCompressor(AH, ctx->cs);
397  /* Send the end marker */
398  WriteInt(AH, 0);
399 }
400 
401 /*
402  * Called by the archiver when finishing saving all BLOB DATA.
403  *
404  * Optional.
405  */
406 static void
408 {
409  /* Write out a fake zero OID to mark end-of-blobs. */
410  WriteInt(AH, 0);
411 }
412 
413 /*
414  * Print data for a given TOC entry
415  */
416 static void
418 {
419  lclContext *ctx = (lclContext *) AH->formatData;
420  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
421  int blkType;
422  int id;
423 
424  if (tctx->dataState == K_OFFSET_NO_DATA)
425  return;
426 
427  if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
428  {
429  /*
430  * We cannot seek directly to the desired block. Instead, skip over
431  * block headers until we find the one we want. This could fail if we
432  * are asked to restore items out-of-order.
433  */
434  _readBlockHeader(AH, &blkType, &id);
435 
436  while (blkType != EOF && id != te->dumpId)
437  {
438  switch (blkType)
439  {
440  case BLK_DATA:
441  _skipData(AH);
442  break;
443 
444  case BLK_BLOBS:
445  _skipBlobs(AH);
446  break;
447 
448  default: /* Always have a default */
450  "unrecognized data block type (%d) while searching archive\n",
451  blkType);
452  break;
453  }
454  _readBlockHeader(AH, &blkType, &id);
455  }
456  }
457  else
458  {
459  /* We can just seek to the place we need to be. */
460  if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
461  exit_horribly(modulename, "error during file seek: %s\n",
462  strerror(errno));
463 
464  _readBlockHeader(AH, &blkType, &id);
465  }
466 
467  /* Produce suitable failure message if we fell off end of file */
468  if (blkType == EOF)
469  {
470  if (tctx->dataState == K_OFFSET_POS_NOT_SET)
471  exit_horribly(modulename, "could not find block ID %d in archive -- "
472  "possibly due to out-of-order restore request, "
473  "which cannot be handled due to lack of data offsets in archive\n",
474  te->dumpId);
475  else if (!ctx->hasSeek)
476  exit_horribly(modulename, "could not find block ID %d in archive -- "
477  "possibly due to out-of-order restore request, "
478  "which cannot be handled due to non-seekable input file\n",
479  te->dumpId);
480  else /* huh, the dataPos led us to EOF? */
481  exit_horribly(modulename, "could not find block ID %d in archive -- "
482  "possibly corrupt archive\n",
483  te->dumpId);
484  }
485 
486  /* Are we sane? */
487  if (id != te->dumpId)
488  exit_horribly(modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
489  id, te->dumpId);
490 
491  switch (blkType)
492  {
493  case BLK_DATA:
494  _PrintData(AH);
495  break;
496 
497  case BLK_BLOBS:
498  _LoadBlobs(AH, AH->public.ropt->dropSchema);
499  break;
500 
501  default: /* Always have a default */
502  exit_horribly(modulename, "unrecognized data block type %d while restoring archive\n",
503  blkType);
504  break;
505  }
506 }
507 
508 /*
509  * Print data from current file position.
510 */
511 static void
513 {
515 }
516 
517 static void
518 _LoadBlobs(ArchiveHandle *AH, bool drop)
519 {
520  Oid oid;
521 
522  StartRestoreBlobs(AH);
523 
524  oid = ReadInt(AH);
525  while (oid != 0)
526  {
527  StartRestoreBlob(AH, oid, drop);
528  _PrintData(AH);
529  EndRestoreBlob(AH, oid);
530  oid = ReadInt(AH);
531  }
532 
533  EndRestoreBlobs(AH);
534 }
535 
536 /*
537  * Skip the BLOBs from the current file position.
538  * BLOBS are written sequentially as data blocks (see below).
539  * Each BLOB is preceded by it's original OID.
540  * A zero OID indicated the end of the BLOBS
541  */
542 static void
544 {
545  Oid oid;
546 
547  oid = ReadInt(AH);
548  while (oid != 0)
549  {
550  _skipData(AH);
551  oid = ReadInt(AH);
552  }
553 }
554 
555 /*
556  * Skip data from current file position.
557  * Data blocks are formatted as an integer length, followed by data.
558  * A zero length denoted the end of the block.
559 */
560 static void
562 {
563  lclContext *ctx = (lclContext *) AH->formatData;
564  size_t blkLen;
565  char *buf = NULL;
566  int buflen = 0;
567  size_t cnt;
568 
569  blkLen = ReadInt(AH);
570  while (blkLen != 0)
571  {
572  if (blkLen > buflen)
573  {
574  if (buf)
575  free(buf);
576  buf = (char *) pg_malloc(blkLen);
577  buflen = blkLen;
578  }
579  if ((cnt = fread(buf, 1, blkLen, AH->FH)) != blkLen)
580  {
581  if (feof(AH->FH))
583  "could not read from input file: end of file\n");
584  else
586  "could not read from input file: %s\n", strerror(errno));
587  }
588 
589  ctx->filePos += blkLen;
590 
591  blkLen = ReadInt(AH);
592  }
593 
594  if (buf)
595  free(buf);
596 }
597 
598 /*
599  * Write a byte of data to the archive.
600  *
601  * Mandatory.
602  *
603  * Called by the archiver to do integer & byte output to the archive.
604  */
605 static int
606 _WriteByte(ArchiveHandle *AH, const int i)
607 {
608  lclContext *ctx = (lclContext *) AH->formatData;
609  int res;
610 
611  if ((res = fputc(i, AH->FH)) == EOF)
613  ctx->filePos += 1;
614 
615  return 1;
616 }
617 
618 /*
619  * Read a byte of data from the archive.
620  *
621  * Mandatory
622  *
623  * Called by the archiver to read bytes & integers from the archive.
624  * EOF should be treated as a fatal error.
625  */
626 static int
628 {
629  lclContext *ctx = (lclContext *) AH->formatData;
630  int res;
631 
632  res = getc(AH->FH);
633  if (res == EOF)
634  READ_ERROR_EXIT(AH->FH);
635  ctx->filePos += 1;
636  return res;
637 }
638 
639 /*
640  * Write a buffer of data to the archive.
641  *
642  * Mandatory.
643  *
644  * Called by the archiver to write a block of bytes to the archive.
645  */
646 static void
647 _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
648 {
649  lclContext *ctx = (lclContext *) AH->formatData;
650 
651  if (fwrite(buf, 1, len, AH->FH) != len)
653  ctx->filePos += len;
654 
655  return;
656 }
657 
658 /*
659  * Read a block of bytes from the archive.
660  *
661  * Mandatory.
662  *
663  * Called by the archiver to read a block of bytes from the archive
664  */
665 static void
666 _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
667 {
668  lclContext *ctx = (lclContext *) AH->formatData;
669 
670  if (fread(buf, 1, len, AH->FH) != len)
671  READ_ERROR_EXIT(AH->FH);
672  ctx->filePos += len;
673 
674  return;
675 }
676 
677 /*
678  * Close the archive.
679  *
680  * Mandatory.
681  *
682  * When writing the archive, this is the routine that actually starts
683  * the process of saving it to files. No data should be written prior
684  * to this point, since the user could sort the TOC after creating it.
685  *
686  * If an archive is to be written, this routine must call:
687  * WriteHead to save the archive header
688  * WriteToc to save the TOC entries
689  * WriteDataChunks to save all DATA & BLOBs.
690  *
691  */
692 static void
694 {
695  lclContext *ctx = (lclContext *) AH->formatData;
696  pgoff_t tpos;
697 
698  if (AH->mode == archModeWrite)
699  {
700  WriteHead(AH);
701  /* Remember TOC's seek position for use below */
702  tpos = ftello(AH->FH);
703  if (tpos < 0 && ctx->hasSeek)
704  exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
705  strerror(errno));
706  WriteToc(AH);
707  ctx->dataStart = _getFilePos(AH, ctx);
708  WriteDataChunks(AH, NULL);
709 
710  /*
711  * If possible, re-write the TOC in order to update the data offset
712  * information. This is not essential, as pg_restore can cope in most
713  * cases without it; but it can make pg_restore significantly faster
714  * in some situations (especially parallel restore).
715  */
716  if (ctx->hasSeek &&
717  fseeko(AH->FH, tpos, SEEK_SET) == 0)
718  WriteToc(AH);
719  }
720 
721  if (fclose(AH->FH) != 0)
722  exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
723 
724  AH->FH = NULL;
725 }
726 
727 /*
728  * Reopen the archive's file handle.
729  *
730  * We close the original file handle, except on Windows. (The difference
731  * is because on Windows, this is used within a multithreading context,
732  * and we don't want a thread closing the parent file handle.)
733  */
734 static void
736 {
737  lclContext *ctx = (lclContext *) AH->formatData;
738  pgoff_t tpos;
739 
740  if (AH->mode == archModeWrite)
741  exit_horribly(modulename, "can only reopen input archives\n");
742 
743  /*
744  * These two cases are user-facing errors since they represent unsupported
745  * (but not invalid) use-cases. Word the error messages appropriately.
746  */
747  if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
748  exit_horribly(modulename, "parallel restore from standard input is not supported\n");
749  if (!ctx->hasSeek)
750  exit_horribly(modulename, "parallel restore from non-seekable file is not supported\n");
751 
752  tpos = ftello(AH->FH);
753  if (tpos < 0)
754  exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
755  strerror(errno));
756 
757 #ifndef WIN32
758  if (fclose(AH->FH) != 0)
759  exit_horribly(modulename, "could not close archive file: %s\n",
760  strerror(errno));
761 #endif
762 
763  AH->FH = fopen(AH->fSpec, PG_BINARY_R);
764  if (!AH->FH)
765  exit_horribly(modulename, "could not open input file \"%s\": %s\n",
766  AH->fSpec, strerror(errno));
767 
768  if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
769  exit_horribly(modulename, "could not set seek position in archive file: %s\n",
770  strerror(errno));
771 }
772 
773 /*
774  * Clone format-specific fields during parallel restoration.
775  */
776 static void
778 {
779  lclContext *ctx = (lclContext *) AH->formatData;
780 
781  AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
782  memcpy(AH->formatData, ctx, sizeof(lclContext));
783  ctx = (lclContext *) AH->formatData;
784 
785  /* sanity check, shouldn't happen */
786  if (ctx->cs != NULL)
787  exit_horribly(modulename, "compressor active\n");
788 
789  /*
790  * Note: we do not make a local lo_buf because we expect at most one BLOBS
791  * entry per archive, so no parallelism is possible. Likewise,
792  * TOC-entry-local state isn't an issue because any one TOC entry is
793  * touched by just one worker child.
794  */
795 }
796 
797 static void
799 {
800  lclContext *ctx = (lclContext *) AH->formatData;
801 
802  free(ctx);
803 }
804 
805 /*
806  * This function is executed in the child of a parallel restore from a
807  * custom-format archive and restores the actual data for one TOC entry.
808  */
809 static int
811 {
812  return parallel_restore(AH, te);
813 }
814 
815 /*--------------------------------------------------
816  * END OF FORMAT CALLBACKS
817  *--------------------------------------------------
818  */
819 
820 /*
821  * Get the current position in the archive file.
822  */
823 static pgoff_t
825 {
826  pgoff_t pos;
827 
828  if (ctx->hasSeek)
829  {
830  /*
831  * Prior to 1.7 (pg7.3) we relied on the internally maintained
832  * pointer. Now we rely on ftello() always, unless the file has been
833  * found to not support it. For debugging purposes, print a warning
834  * if the internal pointer disagrees, so that we're more likely to
835  * notice if something's broken about the internal position tracking.
836  */
837  pos = ftello(AH->FH);
838  if (pos < 0)
839  exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
840  strerror(errno));
841 
842  if (pos != ctx->filePos)
843  write_msg(modulename, "WARNING: ftell mismatch with expected position -- ftell used\n");
844  }
845  else
846  pos = ctx->filePos;
847  return pos;
848 }
849 
850 /*
851  * Read a data block header. The format changed in V1.3, so we
852  * centralize the code here for simplicity. Returns *type = EOF
853  * if at EOF.
854  */
855 static void
856 _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
857 {
858  lclContext *ctx = (lclContext *) AH->formatData;
859  int byt;
860 
861  /*
862  * Note: if we are at EOF with a pre-1.3 input file, we'll exit_horribly
863  * inside ReadInt rather than returning EOF. It doesn't seem worth
864  * jumping through hoops to deal with that case better, because no such
865  * files are likely to exist in the wild: only some 7.1 development
866  * versions of pg_dump ever generated such files.
867  */
868  if (AH->version < K_VERS_1_3)
869  *type = BLK_DATA;
870  else
871  {
872  byt = getc(AH->FH);
873  *type = byt;
874  if (byt == EOF)
875  {
876  *id = 0; /* don't return an uninitialized value */
877  return;
878  }
879  ctx->filePos += 1;
880  }
881 
882  *id = ReadInt(AH);
883 }
884 
885 /*
886  * Callback function for WriteDataToArchive. Writes one block of (compressed)
887  * data to the archive.
888  */
889 static void
890 _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)
891 {
892  /* never write 0-byte blocks (this should not happen) */
893  if (len > 0)
894  {
895  WriteInt(AH, len);
896  _WriteBuf(AH, buf, len);
897  }
898  return;
899 }
900 
901 /*
902  * Callback function for ReadDataFromArchive. To keep things simple, we
903  * always read one compressed block at a time.
904  */
905 static size_t
906 _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
907 {
908  size_t blkLen;
909 
910  /* Read length */
911  blkLen = ReadInt(AH);
912  if (blkLen == 0)
913  return 0;
914 
915  /* If the caller's buffer is not large enough, allocate a bigger one */
916  if (blkLen > *buflen)
917  {
918  free(*buf);
919  *buf = (char *) pg_malloc(blkLen);
920  *buflen = blkLen;
921  }
922 
923  /* exits app on read errors */
924  _ReadBuf(AH, *buf, blkLen);
925 
926  return blkLen;
927 }
static void _ReopenArchive(ArchiveHandle *AH)
void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, const void *data, size_t dLen)
Definition: compress_io.c:183
void ReadToc(ArchiveHandle *AH)
static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
StartBlobsPtr StartBlobsPtr
int parallel_restore(ArchiveHandle *AH, TocEntry *te)
void ReadHead(ArchiveHandle *AH)
static void _Clone(ArchiveHandle *AH)
#define BLK_DATA
static void _StartData(ArchiveHandle *AH, TocEntry *te)
static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
CompressorState * AllocateCompressor(int compression, WriteFunc writeF)
Definition: compress_io.c:128
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
RestoreOptions * ropt
Definition: pg_backup.h:179
#define BLK_BLOBS
PrintTocDataPtr PrintTocDataPtr
static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
void WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
WorkerJobDumpPtr WorkerJobDumpPtr
static void _skipBlobs(ArchiveHandle *AH)
static int _WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te)
#define gettext_noop(x)
Definition: c.h:139
WriteBufPtr WriteBufPtr
WriteExtraTocPtr WriteExtraTocPtr
#define PG_BINARY_W
Definition: c.h:1040
void WriteToc(ArchiveHandle *AH)
DataDumperPtr dataDumper
int ReadInt(ArchiveHandle *AH)
static void _PrintTocData(ArchiveHandle *AH, TocEntry *te)
static void _CloseArchive(ArchiveHandle *AH)
unsigned int Oid
Definition: postgres_ext.h:31
#define fseeko(stream, offset, origin)
Definition: win32.h:247
#define PG_BINARY_R
Definition: c.h:1039
void StartRestoreBlobs(ArchiveHandle *AH)
void ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF)
Definition: compress_io.c:161
static void _PrintData(ArchiveHandle *AH)
CompressorState * cs
#define K_VERS_1_7
static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static void _StartBlobs(ArchiveHandle *AH, TocEntry *te)
PrintExtraTocPtr PrintExtraTocPtr
void StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
WriteBytePtr WriteBytePtr
static char * buf
Definition: pg_test_fsync.c:65
WorkerJobRestorePtr WorkerJobRestorePtr
ArchiveEntryPtr ArchiveEntryPtr
ReadBytePtr ReadBytePtr
static void _LoadBlobs(ArchiveHandle *AH, bool drop)
#define K_OFFSET_NO_DATA
static void _EndData(ArchiveHandle *AH, TocEntry *te)
static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_3
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
size_t WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
static void _skipData(ArchiveHandle *AH)
void EndRestoreBlobs(ArchiveHandle *AH)
#define pgoff_t
Definition: win32.h:241
int ReadOffset(ArchiveHandle *AH, pgoff_t *o)
static int _ReadByte(ArchiveHandle *)
int verbose
Definition: pg_backup.h:181
static const char * modulename
#define free(a)
Definition: header.h:60
void write_msg(const char *modulename, const char *fmt,...)
#define NULL
Definition: c.h:226
static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx)
static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
static void _EndBlobs(ArchiveHandle *AH, TocEntry *te)
#define ftello(stream)
Definition: win32.h:250
WriteDataPtr WriteDataPtr
size_t WriteInt(ArchiveHandle *AH, int i)
static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
#define INT64_FORMAT
Definition: c.h:312
void WriteHead(ArchiveHandle *AH)
#define WRITE_ERROR_EXIT
void exit_horribly(const char *modulename, const char *fmt,...)
pgoff_t dataStart
StartDataPtr StartDataPtr
EndBlobsPtr EndBlobsPtr
void EndRestoreBlob(ArchiveHandle *AH, Oid oid)
#define K_OFFSET_POS_SET
int i
const char * strerror(int errnum)
Definition: strerror.c:19
void InitArchiveFmt_Custom(ArchiveHandle *AH)
#define READ_ERROR_EXIT(fd)
static void _DeClone(ArchiveHandle *AH)
static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)
bool checkSeek(FILE *fp)
pgoff_t filePos
static int _WriteByte(ArchiveHandle *AH, const int i)
ReadExtraTocPtr ReadExtraTocPtr
void EndCompressor(ArchiveHandle *AH, CompressorState *cs)
Definition: compress_io.c:206
#define LOBBUFSIZE
static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
#define K_OFFSET_POS_NOT_SET
static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
StartBlobPtr StartBlobPtr