1 /*-------------------------------------------------------------------------
5 * This file is copied from the 'files' format file, but dumps data into
6 * one temp file then sends it to the output TAR archive.
8 * The tar format also includes a 'restore.sql' script which is there for
9 * the benefit of humans. This script is never used by pg_restore.
11 * NOTE: If you untar the created 'tar' file, the resulting files are
12 * compatible with the 'directory' format. Please keep the two formats in
15 * See the headers to pg_backup_directory & pg_restore for more details.
17 * Copyright (c) 2000, Philip Warner
18 * Rights are granted to use this software in any way so long
19 * as this notice is not removed.
21 * The author is not responsible for loss or damages that may
22 * result from its use.
26 * src/bin/pg_dump/pg_backup_tar.c
28 *-------------------------------------------------------------------------
30 #include "postgres_fe.h"
37 #include "common/file_utils.h"
38 #include "fe_utils/string_utils.h"
39 #include "pg_backup_archiver.h"
40 #include "pg_backup_tar.h"
41 #include "pg_backup_utils.h"
44 static void _ArchiveEntry(ArchiveHandle
*AH
, TocEntry
*te
);
45 static void _StartData(ArchiveHandle
*AH
, TocEntry
*te
);
46 static void _WriteData(ArchiveHandle
*AH
, const void *data
, size_t dLen
);
47 static void _EndData(ArchiveHandle
*AH
, TocEntry
*te
);
48 static int _WriteByte(ArchiveHandle
*AH
, const int i
);
49 static int _ReadByte(ArchiveHandle
*AH
);
50 static void _WriteBuf(ArchiveHandle
*AH
, const void *buf
, size_t len
);
51 static void _ReadBuf(ArchiveHandle
*AH
, void *buf
, size_t len
);
52 static void _CloseArchive(ArchiveHandle
*AH
);
53 static void _PrintTocData(ArchiveHandle
*AH
, TocEntry
*te
);
54 static void _WriteExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
55 static void _ReadExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
56 static void _PrintExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
58 static void _StartLOs(ArchiveHandle
*AH
, TocEntry
*te
);
59 static void _StartLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
);
60 static void _EndLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
);
61 static void _EndLOs(ArchiveHandle
*AH
, TocEntry
*te
);
63 #define K_STD_BUF_SIZE 1024
85 pgoff_t tarNextMember
;
97 static void _LoadLOs(ArchiveHandle
*AH
, TocEntry
*te
);
99 static TAR_MEMBER
*tarOpen(ArchiveHandle
*AH
, const char *filename
, char mode
);
100 static void tarClose(ArchiveHandle
*AH
, TAR_MEMBER
*th
);
103 static char *tarGets(char *buf
, size_t len
, TAR_MEMBER
*th
);
105 static int tarPrintf(TAR_MEMBER
*th
, const char *fmt
,...) pg_attribute_printf(2, 3);
107 static void _tarAddFile(ArchiveHandle
*AH
, TAR_MEMBER
*th
);
108 static TAR_MEMBER
*_tarPositionTo(ArchiveHandle
*AH
, const char *filename
);
109 static size_t tarRead(void *buf
, size_t len
, TAR_MEMBER
*th
);
110 static size_t tarWrite(const void *buf
, size_t len
, TAR_MEMBER
*th
);
111 static void _tarWriteHeader(TAR_MEMBER
*th
);
112 static int _tarGetHeader(ArchiveHandle
*AH
, TAR_MEMBER
*th
);
113 static size_t _tarReadRaw(ArchiveHandle
*AH
, void *buf
, size_t len
, TAR_MEMBER
*th
, FILE *fh
);
115 static size_t _scriptOut(ArchiveHandle
*AH
, const void *buf
, size_t len
);
121 InitArchiveFmt_Tar(ArchiveHandle
*AH
)
125 /* Assuming static functions, this can be copied for each format. */
126 AH
->ArchiveEntryPtr
= _ArchiveEntry
;
127 AH
->StartDataPtr
= _StartData
;
128 AH
->WriteDataPtr
= _WriteData
;
129 AH
->EndDataPtr
= _EndData
;
130 AH
->WriteBytePtr
= _WriteByte
;
131 AH
->ReadBytePtr
= _ReadByte
;
132 AH
->WriteBufPtr
= _WriteBuf
;
133 AH
->ReadBufPtr
= _ReadBuf
;
134 AH
->ClosePtr
= _CloseArchive
;
135 AH
->ReopenPtr
= NULL
;
136 AH
->PrintTocDataPtr
= _PrintTocData
;
137 AH
->ReadExtraTocPtr
= _ReadExtraToc
;
138 AH
->WriteExtraTocPtr
= _WriteExtraToc
;
139 AH
->PrintExtraTocPtr
= _PrintExtraToc
;
141 AH
->StartLOsPtr
= _StartLOs
;
142 AH
->StartLOPtr
= _StartLO
;
143 AH
->EndLOPtr
= _EndLO
;
144 AH
->EndLOsPtr
= _EndLOs
;
146 AH
->DeClonePtr
= NULL
;
148 AH
->WorkerJobDumpPtr
= NULL
;
149 AH
->WorkerJobRestorePtr
= NULL
;
152 * Set up some special context used in compressing data.
154 ctx
= pg_malloc0_object(lclContext
);
155 AH
->formatData
= ctx
;
157 ctx
->isSpecialScript
= 0;
160 * Now open the tar file, and load the TOC if we're in read mode.
162 if (AH
->mode
== archModeWrite
)
164 if (AH
->fSpec
&& strcmp(AH
->fSpec
, "") != 0)
166 ctx
->tarFH
= fopen(AH
->fSpec
, PG_BINARY_W
);
167 if (ctx
->tarFH
== NULL
)
168 pg_fatal("could not open TOC file \"%s\" for output: %m",
174 if (ctx
->tarFH
== NULL
)
175 pg_fatal("could not open TOC file for output: %m");
181 * Make unbuffered since we will dup() it, and the buffers screw each
184 /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
186 ctx
->hasSeek
= checkSeek(ctx
->tarFH
);
189 * We don't support compression because reading the files back is not
190 * possible since gzdopen uses buffered IO which totally screws file
193 if (AH
->compression_spec
.algorithm
!= PG_COMPRESSION_NONE
)
194 pg_fatal("compression is not supported by tar archive format");
198 if (AH
->fSpec
&& strcmp(AH
->fSpec
, "") != 0)
200 ctx
->tarFH
= fopen(AH
->fSpec
, PG_BINARY_R
);
201 if (ctx
->tarFH
== NULL
)
202 pg_fatal("could not open TOC file \"%s\" for input: %m",
208 if (ctx
->tarFH
== NULL
)
209 pg_fatal("could not open TOC file for input: %m");
213 * Make unbuffered since we will dup() it, and the buffers screw each
216 /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
220 ctx
->hasSeek
= checkSeek(ctx
->tarFH
);
222 ctx
->FH
= tarOpen(AH
, "toc.dat", 'r');
225 tarClose(AH
, ctx
->FH
); /* Nothing else in the file... */
230 * - Start a new TOC entry
231 * Setup the output file name.
234 _ArchiveEntry(ArchiveHandle
*AH
, TocEntry
*te
)
237 char fn
[K_STD_BUF_SIZE
];
239 ctx
= pg_malloc0_object(lclTocEntry
);
240 if (te
->dataDumper
!= NULL
)
242 snprintf(fn
, sizeof(fn
), "%d.dat", te
->dumpId
);
243 ctx
->filename
= pg_strdup(fn
);
247 ctx
->filename
= NULL
;
250 te
->formatData
= ctx
;
254 _WriteExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
256 lclTocEntry
*ctx
= (lclTocEntry
*) te
->formatData
;
259 WriteStr(AH
, ctx
->filename
);
265 _ReadExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
267 lclTocEntry
*ctx
= (lclTocEntry
*) te
->formatData
;
271 ctx
= pg_malloc0_object(lclTocEntry
);
272 te
->formatData
= ctx
;
275 ctx
->filename
= ReadStr(AH
);
276 if (strlen(ctx
->filename
) == 0)
279 ctx
->filename
= NULL
;
285 _PrintExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
287 lclTocEntry
*ctx
= (lclTocEntry
*) te
->formatData
;
289 if (AH
->public.verbose
&& ctx
->filename
!= NULL
)
290 ahprintf(AH
, "-- File: %s\n", ctx
->filename
);
294 _StartData(ArchiveHandle
*AH
, TocEntry
*te
)
296 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
298 tctx
->TH
= tarOpen(AH
, tctx
->filename
, 'w');
302 tarOpen(ArchiveHandle
*AH
, const char *filename
, char mode
)
304 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
309 tm
= _tarPositionTo(AH
, filename
);
310 if (!tm
) /* Not found */
315 * Couldn't find the requested file. Future: do SEEK(0) and
318 pg_fatal("could not find file \"%s\" in archive", filename
);
322 /* Any file OK, none left, so return NULL */
327 if (AH
->compression_spec
.algorithm
== PG_COMPRESSION_NONE
)
328 tm
->nFH
= ctx
->tarFH
;
330 pg_fatal("compression is not supported by tar archive format");
336 tm
= pg_malloc0_object(TAR_MEMBER
);
339 * POSIX does not require, but permits, tmpfile() to restrict file
340 * permissions. Given an OS crash after we write data, the filesystem
341 * might retain the data but forget tmpfile()'s unlink(). If so, the
342 * file mode protects confidentiality of the data written.
344 old_umask
= umask(S_IRWXG
| S_IRWXO
);
347 tm
->tmpFH
= tmpfile();
351 * On WIN32, tmpfile() generates a filename in the root directory,
352 * which requires administrative permissions on certain systems. Loop
353 * until we find a unique file name we can create.
360 name
= _tempnam(NULL
, "pg_temp_");
363 fd
= open(name
, O_RDWR
| O_CREAT
| O_EXCL
| O_BINARY
|
364 O_TEMPORARY
, S_IRUSR
| S_IWUSR
);
367 if (fd
!= -1) /* created a file */
369 tm
->tmpFH
= fdopen(fd
, "w+b");
372 else if (errno
!= EEXIST
) /* failure other than file exists */
377 if (tm
->tmpFH
== NULL
)
378 pg_fatal("could not generate temporary file name: %m");
382 if (AH
->compression_spec
.algorithm
== PG_COMPRESSION_NONE
)
385 pg_fatal("compression is not supported by tar archive format");
388 tm
->targetFile
= pg_strdup(filename
);
392 tm
->tarFH
= ctx
->tarFH
;
398 tarClose(ArchiveHandle
*AH
, TAR_MEMBER
*th
)
400 if (AH
->compression_spec
.algorithm
!= PG_COMPRESSION_NONE
)
401 pg_fatal("compression is not supported by tar archive format");
404 _tarAddFile(AH
, th
); /* This will close the temp file */
407 * else Nothing to do for normal read since we don't dup() normal file
408 * handle, and we don't use temp files.
411 free(th
->targetFile
);
418 tarGets(char *buf
, size_t len
, TAR_MEMBER
*th
)
425 /* Can't read past logical EOF */
426 if (len
> (th
->fileLen
- th
->pos
))
427 len
= th
->fileLen
- th
->pos
;
429 while (cnt
< len
&& c
!= '\n')
431 if (_tarReadRaw(th
->AH
, &c
, 1, th
, NULL
) <= 0)
458 * Just read bytes from the archive. This is the low level read routine
459 * that is used for ALL reads on a tar file.
462 _tarReadRaw(ArchiveHandle
*AH
, void *buf
, size_t len
, TAR_MEMBER
*th
, FILE *fh
)
464 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
471 avail
= AH
->lookaheadLen
- AH
->lookaheadPos
;
474 /* We have some lookahead bytes to use */
475 if (avail
>= len
) /* Just use the lookahead buffer */
480 /* Copy, and adjust buffer pos */
481 memcpy(buf
, AH
->lookahead
+ AH
->lookaheadPos
, used
);
482 AH
->lookaheadPos
+= used
;
484 /* Adjust required length */
488 /* Read the file if len > 0 */
493 res
= fread(&((char *) buf
)[used
], 1, len
, fh
);
494 if (res
!= len
&& !feof(fh
))
499 res
= fread(&((char *) buf
)[used
], 1, len
, th
->nFH
);
500 if (res
!= len
&& !feof(th
->nFH
))
501 READ_ERROR_EXIT(th
->nFH
);
505 ctx
->tarFHpos
+= res
+ used
;
511 tarRead(void *buf
, size_t len
, TAR_MEMBER
*th
)
515 if (th
->pos
+ len
> th
->fileLen
)
516 len
= th
->fileLen
- th
->pos
;
521 res
= _tarReadRaw(th
->AH
, buf
, len
, th
, NULL
);
529 tarWrite(const void *buf
, size_t len
, TAR_MEMBER
*th
)
533 res
= fwrite(buf
, 1, len
, th
->nFH
);
540 _WriteData(ArchiveHandle
*AH
, const void *data
, size_t dLen
)
542 lclTocEntry
*tctx
= (lclTocEntry
*) AH
->currToc
->formatData
;
544 if (tarWrite(data
, dLen
, tctx
->TH
) != dLen
)
549 _EndData(ArchiveHandle
*AH
, TocEntry
*te
)
551 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
554 tarClose(AH
, tctx
->TH
);
559 * Print data for a given file
562 _PrintFileData(ArchiveHandle
*AH
, char *filename
)
564 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
572 th
= tarOpen(AH
, filename
, 'r');
575 while ((cnt
= tarRead(buf
, 4095, th
)) > 0)
578 ahwrite(buf
, 1, cnt
, AH
);
586 * Print data for a given TOC entry
589 _PrintTocData(ArchiveHandle
*AH
, TocEntry
*te
)
591 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
592 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
599 * If we're writing the special restore.sql script, emit a suitable
600 * command to include each table's data from the corresponding file.
602 * In the COPY case this is a bit klugy because the regular COPY command
603 * was already printed before we get control.
605 if (ctx
->isSpecialScript
)
609 /* Abort the COPY FROM stdin */
610 ahprintf(AH
, "\\.\n");
613 * The COPY statement should look like "COPY ... FROM stdin;\n",
614 * see dumpTableData().
616 pos1
= (int) strlen(te
->copyStmt
) - 13;
617 if (pos1
< 6 || strncmp(te
->copyStmt
, "COPY ", 5) != 0 ||
618 strcmp(te
->copyStmt
+ pos1
, " FROM stdin;\n") != 0)
619 pg_fatal("unexpected COPY statement syntax: \"%s\"",
622 /* Emit all but the FROM part ... */
623 ahwrite(te
->copyStmt
, 1, pos1
, AH
);
624 /* ... and insert modified FROM */
625 ahprintf(AH
, " FROM '$$PATH$$/%s';\n\n", tctx
->filename
);
629 /* --inserts mode, no worries, just include the data file */
630 ahprintf(AH
, "\\i $$PATH$$/%s\n\n", tctx
->filename
);
636 if (strcmp(te
->desc
, "BLOBS") == 0)
639 _PrintFileData(AH
, tctx
->filename
);
643 _LoadLOs(ArchiveHandle
*AH
, TocEntry
*te
)
646 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
649 bool foundLO
= false;
655 * The blobs_NNN.toc or blobs.toc file is fairly useless to us because it
656 * will appear only after the associated blob_NNN.dat files. For archive
657 * versions >= 16 we can look at the BLOBS entry's te->tag to discover the
658 * OID of the first blob we want to restore, and then search forward to
659 * find the appropriate blob_<oid>.dat file. For older versions we rely
660 * on the knowledge that there was only one BLOBS entry and just search
661 * for the first blob_<oid>.dat file. Once we find the first blob file to
662 * restore, restore all blobs until we reach the blobs[_NNN].toc file.
664 if (AH
->version
>= K_VERS_1_16
)
666 /* We rely on atooid to not complain about nnnn..nnnn tags */
667 oid
= atooid(te
->tag
);
668 snprintf(buf
, sizeof(buf
), "blob_%u.dat", oid
);
669 th
= tarOpen(AH
, buf
, 'r'); /* Advance to first desired file */
672 th
= tarOpen(AH
, NULL
, 'r'); /* Open next file */
678 if (strncmp(th
->targetFile
, "blob_", 5) == 0)
680 oid
= atooid(&th
->targetFile
[5]);
683 pg_log_info("restoring large object with OID %u", oid
);
685 StartRestoreLO(AH
, oid
, AH
->public.ropt
->dropSchema
);
687 while ((cnt
= tarRead(buf
, 4095, th
)) > 0)
690 ahwrite(buf
, 1, cnt
, AH
);
692 EndRestoreLO(AH
, oid
);
702 * Once we have found the first LO, stop at the first non-LO entry
703 * (which will be 'blobs[_NNN].toc'). This coding would eat all
704 * the rest of the archive if there are no LOs ... but this
705 * function shouldn't be called at all in that case.
711 th
= tarOpen(AH
, NULL
, 'r');
718 _WriteByte(ArchiveHandle
*AH
, const int i
)
720 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
721 char b
= i
; /* Avoid endian problems */
723 if (tarWrite(&b
, 1, ctx
->FH
) != 1)
731 _ReadByte(ArchiveHandle
*AH
)
733 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
737 res
= tarRead(&c
, 1, ctx
->FH
);
739 /* We already would have exited for errors on reads, must be EOF */
740 pg_fatal("could not read from input file: end of file");
746 _WriteBuf(ArchiveHandle
*AH
, const void *buf
, size_t len
)
748 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
750 if (tarWrite(buf
, len
, ctx
->FH
) != len
)
757 _ReadBuf(ArchiveHandle
*AH
, void *buf
, size_t len
)
759 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
761 if (tarRead(buf
, len
, ctx
->FH
) != len
)
762 /* We already would have exited for errors on reads, must be EOF */
763 pg_fatal("could not read from input file: end of file");
769 _CloseArchive(ArchiveHandle
*AH
)
771 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
773 RestoreOptions
*ropt
;
774 RestoreOptions
*savRopt
;
775 DumpOptions
*savDopt
;
779 if (AH
->mode
== archModeWrite
)
782 * Write the Header & TOC to the archive FIRST
784 th
= tarOpen(AH
, "toc.dat", 'w');
788 tarClose(AH
, th
); /* Not needed any more */
791 * Now send the data (tables & LOs)
793 WriteDataChunks(AH
, NULL
);
796 * Now this format wants to append a script which does a full restore
797 * if the files have been extracted.
799 th
= tarOpen(AH
, "restore.sql", 'w');
804 "-- File paths need to be edited. Search for $$PATH$$ and\n"
805 "-- replace it with the path to the directory containing\n"
806 "-- the extracted data files.\n"
809 AH
->CustomOutPtr
= _scriptOut
;
811 ctx
->isSpecialScript
= 1;
814 ropt
= NewRestoreOptions();
815 memcpy(ropt
, AH
->public.ropt
, sizeof(RestoreOptions
));
816 ropt
->filename
= NULL
;
817 ropt
->dropSchema
= 1;
818 ropt
->superuser
= NULL
;
819 ropt
->suppressDumpWarnings
= true;
821 savDopt
= AH
->public.dopt
;
822 savRopt
= AH
->public.ropt
;
824 SetArchiveOptions((Archive
*) AH
, NULL
, ropt
);
826 savVerbose
= AH
->public.verbose
;
827 AH
->public.verbose
= 0;
829 RestoreArchive((Archive
*) AH
);
831 SetArchiveOptions((Archive
*) AH
, savDopt
, savRopt
);
833 AH
->public.verbose
= savVerbose
;
837 ctx
->isSpecialScript
= 0;
840 * EOF marker for tar files is two blocks of NULLs.
842 for (i
= 0; i
< TAR_BLOCK_SIZE
* 2; i
++)
844 if (fputc(0, ctx
->tarFH
) == EOF
)
848 /* Sync the output file if one is defined */
849 if (AH
->dosync
&& AH
->fSpec
)
850 (void) fsync_fname(AH
->fSpec
, false);
857 _scriptOut(ArchiveHandle
*AH
, const void *buf
, size_t len
)
859 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
861 return tarWrite(buf
, len
, ctx
->scriptTH
);
865 * Large Object support
869 * Called by the archiver when starting to save BLOB DATA (not schema).
870 * This routine should save whatever format-specific information is needed
871 * to read the LOs back into memory.
873 * It is called just prior to the dumper's DataDumper routine.
875 * Optional, but strongly recommended.
879 _StartLOs(ArchiveHandle
*AH
, TocEntry
*te
)
881 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
882 char fname
[K_STD_BUF_SIZE
];
884 sprintf(fname
, "blobs_%d.toc", te
->dumpId
);
885 ctx
->loToc
= tarOpen(AH
, fname
, 'w');
889 * Called by the archiver when the dumper calls StartLO.
893 * Must save the passed OID for retrieval at restore-time.
896 _StartLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
)
898 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
899 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
903 pg_fatal("invalid OID for large object (%u)", oid
);
905 if (AH
->compression_spec
.algorithm
!= PG_COMPRESSION_NONE
)
906 pg_fatal("compression is not supported by tar archive format");
908 sprintf(fname
, "blob_%u.dat", oid
);
910 tarPrintf(ctx
->loToc
, "%u %s\n", oid
, fname
);
912 tctx
->TH
= tarOpen(AH
, fname
, 'w');
916 * Called by the archiver when the dumper calls EndLO.
922 _EndLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
)
924 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
926 tarClose(AH
, tctx
->TH
);
930 * Called by the archiver when finishing saving BLOB DATA.
936 _EndLOs(ArchiveHandle
*AH
, TocEntry
*te
)
938 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
940 /* Write out a fake zero OID to mark end-of-LOs. */
941 /* WriteInt(AH, 0); */
943 tarClose(AH
, ctx
->loToc
);
954 tarPrintf(TAR_MEMBER
*th
, const char *fmt
,...)
956 int save_errno
= errno
;
958 size_t len
= 128; /* initial assumption about buffer size */
965 /* Allocate work buffer. */
966 p
= (char *) pg_malloc(len
);
968 /* Try to format the data. */
971 cnt
= pvsnprintf(p
, len
, fmt
, args
);
977 /* Release buffer and loop around to try again with larger len. */
982 cnt
= tarWrite(p
, cnt
, th
);
988 isValidTarHeader(char *header
)
991 int chk
= tarChecksum(header
);
993 sum
= read_tar_number(&header
[TAR_OFFSET_CHECKSUM
], 8);
998 /* POSIX tar format */
999 if (memcmp(&header
[TAR_OFFSET_MAGIC
], "ustar\0", 6) == 0 &&
1000 memcmp(&header
[TAR_OFFSET_VERSION
], "00", 2) == 0)
1002 /* GNU tar format */
1003 if (memcmp(&header
[TAR_OFFSET_MAGIC
], "ustar \0", 8) == 0)
1005 /* not-quite-POSIX format written by pre-9.3 pg_dump */
1006 if (memcmp(&header
[TAR_OFFSET_MAGIC
], "ustar00\0", 8) == 0)
1012 /* Given the member, write the TAR header & copy the file */
1014 _tarAddFile(ArchiveHandle
*AH
, TAR_MEMBER
*th
)
1016 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
1017 FILE *tmp
= th
->tmpFH
; /* Grab it for convenience */
1026 * Find file len & go back to start.
1028 if (fseeko(tmp
, 0, SEEK_END
) != 0)
1029 pg_fatal("error during file seek: %m");
1030 th
->fileLen
= ftello(tmp
);
1031 if (th
->fileLen
< 0)
1032 pg_fatal("could not determine seek position in archive file: %m");
1033 if (fseeko(tmp
, 0, SEEK_SET
) != 0)
1034 pg_fatal("error during file seek: %m");
1036 _tarWriteHeader(th
);
1038 while ((cnt
= fread(buf
, 1, sizeof(buf
), tmp
)) > 0)
1040 if ((res
= fwrite(buf
, 1, cnt
, th
->tarFH
)) != cnt
)
1045 READ_ERROR_EXIT(tmp
);
1047 if (fclose(tmp
) != 0) /* This *should* delete it... */
1048 pg_fatal("could not close temporary file: %m");
1050 if (len
!= th
->fileLen
)
1051 pg_fatal("actual file length (%lld) does not match expected (%lld)",
1052 (long long) len
, (long long) th
->fileLen
);
1054 pad
= tarPaddingBytesRequired(len
);
1055 for (i
= 0; i
< pad
; i
++)
1057 if (fputc('\0', th
->tarFH
) == EOF
)
1061 ctx
->tarFHpos
+= len
+ pad
;
1064 /* Locate the file in the archive, read header and position to data */
1066 _tarPositionTo(ArchiveHandle
*AH
, const char *filename
)
1068 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
1069 TAR_MEMBER
*th
= pg_malloc0_object(TAR_MEMBER
);
1071 char header
[TAR_BLOCK_SIZE
];
1079 /* Go to end of current file, if any */
1080 if (ctx
->tarFHpos
!= 0)
1082 pg_log_debug("moving from position %lld to next member at file position %lld",
1083 (long long) ctx
->tarFHpos
, (long long) ctx
->tarNextMember
);
1085 while (ctx
->tarFHpos
< ctx
->tarNextMember
)
1086 _tarReadRaw(AH
, &c
, 1, NULL
, ctx
->tarFH
);
1089 pg_log_debug("now at file position %lld", (long long) ctx
->tarFHpos
);
1091 /* We are at the start of the file, or at the next member */
1093 /* Get the header */
1094 if (!_tarGetHeader(AH
, th
))
1097 pg_fatal("could not find header for file \"%s\" in tar archive", filename
);
1101 * We're just scanning the archive for the next file, so return
1109 while (filename
!= NULL
&& strcmp(th
->targetFile
, filename
) != 0)
1111 pg_log_debug("skipping tar member %s", th
->targetFile
);
1113 id
= atoi(th
->targetFile
);
1114 if ((TocIDRequired(AH
, id
) & REQ_DATA
) != 0)
1115 pg_fatal("restoring data out of order is not supported in this archive format: "
1116 "\"%s\" is required, but comes before \"%s\" in the archive file.",
1117 th
->targetFile
, filename
);
1119 /* Header doesn't match, so read to next header */
1121 len
+= tarPaddingBytesRequired(th
->fileLen
);
1122 blks
= len
/ TAR_BLOCK_SIZE
; /* # of tar blocks */
1124 for (i
= 0; i
< blks
; i
++)
1125 _tarReadRaw(AH
, &header
[0], TAR_BLOCK_SIZE
, NULL
, ctx
->tarFH
);
1127 if (!_tarGetHeader(AH
, th
))
1128 pg_fatal("could not find header for file \"%s\" in tar archive", filename
);
1131 ctx
->tarNextMember
= ctx
->tarFHpos
+ th
->fileLen
1132 + tarPaddingBytesRequired(th
->fileLen
);
1138 /* Read & verify a header */
1140 _tarGetHeader(ArchiveHandle
*AH
, TAR_MEMBER
*th
)
1142 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
1143 char h
[TAR_BLOCK_SIZE
];
1149 bool gotBlock
= false;
1153 /* Save the pos for reporting purposes */
1154 hPos
= ctx
->tarFHpos
;
1156 /* Read the next tar block, return EOF, exit if short */
1157 len
= _tarReadRaw(AH
, h
, TAR_BLOCK_SIZE
, NULL
, ctx
->tarFH
);
1158 if (len
== 0) /* EOF */
1161 if (len
!= TAR_BLOCK_SIZE
)
1162 pg_fatal(ngettext("incomplete tar header found (%lu byte)",
1163 "incomplete tar header found (%lu bytes)",
1165 (unsigned long) len
);
1168 chk
= tarChecksum(h
);
1169 sum
= read_tar_number(&h
[TAR_OFFSET_CHECKSUM
], 8);
1172 * If the checksum failed, see if it is a null block. If so, silently
1173 * continue to the next block.
1181 for (i
= 0; i
< TAR_BLOCK_SIZE
; i
++)
1192 /* Name field is 100 bytes, might not be null-terminated */
1193 strlcpy(tag
, &h
[TAR_OFFSET_NAME
], 100 + 1);
1195 len
= read_tar_number(&h
[TAR_OFFSET_SIZE
], 12);
1197 pg_log_debug("TOC Entry %s at %llu (length %llu, checksum %d)",
1198 tag
, (unsigned long long) hPos
, (unsigned long long) len
, sum
);
1201 pg_fatal("corrupt tar header found in %s (expected %d, computed %d) file position %llu",
1202 tag
, sum
, chk
, (unsigned long long) ftello(ctx
->tarFH
));
1204 th
->targetFile
= pg_strdup(tag
);
1212 _tarWriteHeader(TAR_MEMBER
*th
)
1214 char h
[TAR_BLOCK_SIZE
];
1216 tarCreateHeader(h
, th
->targetFile
, NULL
, th
->fileLen
,
1217 0600, 04000, 02000, time(NULL
));
1219 /* Now write the completed header. */
1220 if (fwrite(h
, 1, TAR_BLOCK_SIZE
, th
->tarFH
) != TAR_BLOCK_SIZE
)