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 * See the headers to pg_backup_files & pg_restore for more details.
10 * Copyright (c) 2000, Philip Warner
11 * Rights are granted to use this software in any way so long
12 * as this notice is not removed.
14 * The author is not responsible for loss or damages that may
15 * result from it's use.
19 * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.67 2010/01/07 04:53:35 tgl Exp $
21 *-------------------------------------------------------------------------
24 #include "pg_backup.h"
25 #include "pg_backup_archiver.h"
26 #include "pg_backup_tar.h"
33 static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
34 static void _StartData(ArchiveHandle *AH, TocEntry *te);
35 static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
36 static void _EndData(ArchiveHandle *AH, TocEntry *te);
37 static int _WriteByte(ArchiveHandle *AH, const int i);
38 static int _ReadByte(ArchiveHandle *);
39 static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
40 static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
41 static void _CloseArchive(ArchiveHandle *AH);
42 static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
43 static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
44 static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
45 static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
47 static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
48 static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
49 static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
50 static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
52 #define K_STD_BUF_SIZE 1024
56 /* typedef gzFile ThingFile; */
57 typedef FILE ThingFile;
59 typedef FILE ThingFile;
76 * Maximum file size for a tar member: The limit inherent in the
77 * format is 2^33-1 bytes (nearly 8 GB). But we don't want to exceed
78 * what we can represent in pgoff_t.
80 #define MAX_TAR_MEMBER_FILELEN (((int64) 1 << Min(33, sizeof(pgoff_t)*8 - 1)) - 1)
89 pgoff_t tarNextMember;
101 static const char *modulename = gettext_noop("tar archiver");
103 static void _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt);
105 static TAR_MEMBER *tarOpen(ArchiveHandle *AH, const char *filename, char mode);
106 static void tarClose(ArchiveHandle *AH, TAR_MEMBER *TH);
109 static char *tarGets(char *buf, size_t len, TAR_MEMBER *th);
111 static int tarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...);
113 static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th);
114 static int _tarChecksum(char *th);
115 static TAR_MEMBER *_tarPositionTo(ArchiveHandle *AH, const char *filename);
116 static size_t tarRead(void *buf, size_t len, TAR_MEMBER *th);
117 static size_t tarWrite(const void *buf, size_t len, TAR_MEMBER *th);
118 static void _tarWriteHeader(TAR_MEMBER *th);
119 static int _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th);
120 static size_t _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh);
122 static size_t _scriptOut(ArchiveHandle *AH, const void *buf, size_t len);
128 InitArchiveFmt_Tar(ArchiveHandle *AH)
132 /* Assuming static functions, this can be copied for each format. */
133 AH->ArchiveEntryPtr = _ArchiveEntry;
134 AH->StartDataPtr = _StartData;
135 AH->WriteDataPtr = _WriteData;
136 AH->EndDataPtr = _EndData;
137 AH->WriteBytePtr = _WriteByte;
138 AH->ReadBytePtr = _ReadByte;
139 AH->WriteBufPtr = _WriteBuf;
140 AH->ReadBufPtr = _ReadBuf;
141 AH->ClosePtr = _CloseArchive;
142 AH->ReopenPtr = NULL;
143 AH->PrintTocDataPtr = _PrintTocData;
144 AH->ReadExtraTocPtr = _ReadExtraToc;
145 AH->WriteExtraTocPtr = _WriteExtraToc;
146 AH->PrintExtraTocPtr = _PrintExtraToc;
148 AH->StartBlobsPtr = _StartBlobs;
149 AH->StartBlobPtr = _StartBlob;
150 AH->EndBlobPtr = _EndBlob;
151 AH->EndBlobsPtr = _EndBlobs;
153 AH->DeClonePtr = NULL;
156 * Set up some special context used in compressing data.
158 ctx = (lclContext *) calloc(1, sizeof(lclContext));
159 AH->formatData = (void *) ctx;
161 ctx->isSpecialScript = 0;
163 /* Initialize LO buffering */
164 AH->lo_buf_size = LOBBUFSIZE;
165 AH->lo_buf = (void *) malloc(LOBBUFSIZE);
166 if (AH->lo_buf == NULL)
167 die_horribly(AH, modulename, "out of memory\n");
170 * Now open the TOC file
172 if (AH->mode == archModeWrite)
174 if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
176 ctx->tarFH = fopen(AH->fSpec, PG_BINARY_W);
177 if (ctx->tarFH == NULL)
178 die_horribly(NULL, modulename,
179 "could not open TOC file \"%s\" for output: %s\n",
180 AH->fSpec, strerror(errno));
185 if (ctx->tarFH == NULL)
186 die_horribly(NULL, modulename,
187 "could not open TOC file for output: %s\n",
194 * Make unbuffered since we will dup() it, and the buffers screw each
197 /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
199 ctx->hasSeek = checkSeek(ctx->tarFH);
201 if (AH->compression < 0 || AH->compression > 9)
202 AH->compression = Z_DEFAULT_COMPRESSION;
204 /* Don't compress into tar files unless asked to do so */
205 if (AH->compression == Z_DEFAULT_COMPRESSION)
209 * We don't support compression because reading the files back is not
210 * possible since gzdopen uses buffered IO which totally screws file
213 if (AH->compression != 0)
214 die_horribly(NULL, modulename, "compression not supported by tar output format\n");
219 if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
221 ctx->tarFH = fopen(AH->fSpec, PG_BINARY_R);
222 if (ctx->tarFH == NULL)
223 die_horribly(NULL, modulename, "could not open TOC file \"%s\" for input: %s\n",
224 AH->fSpec, strerror(errno));
229 if (ctx->tarFH == NULL)
230 die_horribly(NULL, modulename, "could not open TOC file for input: %s\n",
235 * Make unbuffered since we will dup() it, and the buffers screw each
238 /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
242 ctx->hasSeek = checkSeek(ctx->tarFH);
245 * Forcibly unmark the header as read since we use the lookahead
250 ctx->FH = (void *) tarOpen(AH, "toc.dat", 'r');
253 tarClose(AH, ctx->FH); /* Nothing else in the file... */
258 * - Start a new TOC entry
259 * Setup the output file name.
262 _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
265 char fn[K_STD_BUF_SIZE];
267 ctx = (lclTocEntry *) calloc(1, sizeof(lclTocEntry));
268 if (te->dataDumper != NULL)
271 if (AH->compression == 0)
272 sprintf(fn, "%d.dat", te->dumpId);
274 sprintf(fn, "%d.dat.gz", te->dumpId);
276 sprintf(fn, "%d.dat", te->dumpId);
278 ctx->filename = strdup(fn);
282 ctx->filename = NULL;
285 te->formatData = (void *) ctx;
289 _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
291 lclTocEntry *ctx = (lclTocEntry *) te->formatData;
294 WriteStr(AH, ctx->filename);
300 _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
302 lclTocEntry *ctx = (lclTocEntry *) te->formatData;
306 ctx = (lclTocEntry *) calloc(1, sizeof(lclTocEntry));
307 te->formatData = (void *) ctx;
310 ctx->filename = ReadStr(AH);
311 if (strlen(ctx->filename) == 0)
314 ctx->filename = NULL;
320 _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
322 lclTocEntry *ctx = (lclTocEntry *) te->formatData;
324 if (AH->public.verbose && ctx->filename != NULL)
325 ahprintf(AH, "-- File: %s\n", ctx->filename);
329 _StartData(ArchiveHandle *AH, TocEntry *te)
331 lclTocEntry *tctx = (lclTocEntry *) te->formatData;
333 tctx->TH = tarOpen(AH, tctx->filename, 'w');
337 tarOpen(ArchiveHandle *AH, const char *filename, char mode)
339 lclContext *ctx = (lclContext *) AH->formatData;
348 tm = _tarPositionTo(AH, filename);
349 if (!tm) /* Not found */
351 if (filename) /* Couldn't find the requested file. Future:
352 * DO SEEK(0) and retry. */
353 die_horribly(AH, modulename, "could not find file %s in archive\n", filename);
355 /* Any file OK, non left, so return NULL */
361 if (AH->compression == 0)
362 tm->nFH = ctx->tarFH;
364 die_horribly(AH, modulename, "compression support is disabled in this format\n");
365 /* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */
367 tm->nFH = ctx->tarFH;
373 tm = calloc(1, sizeof(TAR_MEMBER));
376 tm->tmpFH = tmpfile();
380 * On WIN32, tmpfile() generates a filename in the root directory,
381 * which requires administrative permissions on certain systems. Loop
382 * until we find a unique file name we can create.
389 name = _tempnam(NULL, "pg_temp_");
392 fd = open(name, O_RDWR | O_CREAT | O_EXCL | O_BINARY |
393 O_TEMPORARY, S_IRUSR | S_IWUSR);
396 if (fd != -1) /* created a file */
398 tm->tmpFH = fdopen(fd, "w+b");
401 else if (errno != EEXIST) /* failure other than file exists */
406 if (tm->tmpFH == NULL)
407 die_horribly(AH, modulename, "could not generate temporary file name: %s\n", strerror(errno));
411 if (AH->compression != 0)
413 sprintf(fmode, "wb%d", AH->compression);
414 tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
416 die_horribly(AH, modulename, "could not open temporary file\n");
427 tm->targetFile = strdup(filename);
431 tm->tarFH = ctx->tarFH;
438 tarClose(ArchiveHandle *AH, TAR_MEMBER *th)
441 * Close the GZ file since we dup'd. This will flush the buffers.
443 if (AH->compression != 0)
444 if (GZCLOSE(th->zFH) != 0)
445 die_horribly(AH, modulename, "could not close tar member\n");
448 _tarAddFile(AH, th); /* This will close the temp file */
451 * else Nothing to do for normal read since we don't dup() normal file
452 * handle, and we don't use temp files.
456 free(th->targetFile);
464 tarGets(char *buf, size_t len, TAR_MEMBER *th)
471 /* Can't read past logical EOF */
472 if (len > (th->fileLen - th->pos))
473 len = th->fileLen - th->pos;
475 while (cnt < len && c != '\n')
477 if (_tarReadRaw(th->AH, &c, 1, th, NULL) <= 0)
504 * Just read bytes from the archive. This is the low level read routine
505 * that is used for ALL reads on a tar file.
508 _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh)
510 lclContext *ctx = (lclContext *) AH->formatData;
515 avail = AH->lookaheadLen - AH->lookaheadPos;
518 /* We have some lookahead bytes to use */
519 if (avail >= len) /* Just use the lookahead buffer */
524 /* Copy, and adjust buffer pos */
525 memcpy(buf, AH->lookahead + AH->lookaheadPos, used);
526 AH->lookaheadPos += used;
528 /* Adjust required length */
532 /* Read the file if len > 0 */
536 res = fread(&((char *) buf)[used], 1, len, fh);
540 res = GZREAD(&((char *) buf)[used], 1, len, th->zFH);
542 res = fread(&((char *) buf)[used], 1, len, th->nFH);
545 die_horribly(AH, modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
548 ctx->tarFHpos += res + used;
554 tarRead(void *buf, size_t len, TAR_MEMBER *th)
558 if (th->pos + len > th->fileLen)
559 len = th->fileLen - th->pos;
564 res = _tarReadRaw(th->AH, buf, len, th, NULL);
572 tarWrite(const void *buf, size_t len, TAR_MEMBER *th)
577 res = GZWRITE((void *) buf, 1, len, th->zFH);
579 res = fwrite(buf, 1, len, th->nFH);
582 die_horribly(th->AH, modulename,
583 "could not write to output file: %s\n", strerror(errno));
590 _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
592 lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData;
594 dLen = tarWrite((void *) data, dLen, tctx->TH);
600 _EndData(ArchiveHandle *AH, TocEntry *te)
602 lclTocEntry *tctx = (lclTocEntry *) te->formatData;
605 tarClose(AH, tctx->TH);
610 * Print data for a given file
613 _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
615 lclContext *ctx = (lclContext *) AH->formatData;
623 th = tarOpen(AH, filename, 'r');
626 while ((cnt = tarRead(buf, 4095, th)) > 0)
629 ahwrite(buf, 1, cnt, AH);
637 * Print data for a given TOC entry
640 _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
642 lclContext *ctx = (lclContext *) AH->formatData;
643 lclTocEntry *tctx = (lclTocEntry *) te->formatData;
652 if (ctx->isSpecialScript)
657 /* Abort the default COPY */
658 ahprintf(AH, "\\.\n");
660 /* Get a copy of the COPY statement and clean it up */
661 tmpCopy = strdup(te->copyStmt);
662 for (i = 0; i < strlen(tmpCopy); i++)
663 tmpCopy[i] = pg_tolower((unsigned char) tmpCopy[i]);
666 * This is very nasty; we don't know if the archive used WITH OIDS, so
667 * we search the string for it in a paranoid sort of way.
669 if (strncmp(tmpCopy, "copy ", 5) != 0)
670 die_horribly(AH, modulename,
671 "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
674 for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
675 if (tmpCopy[pos1] != ' ')
678 if (tmpCopy[pos1] == '"')
681 pos1 += strlen(te->tag);
683 for (pos2 = pos1; pos2 < strlen(tmpCopy); pos2++)
684 if (strncmp(&tmpCopy[pos2], "from stdin", 10) == 0)
687 if (pos2 >= strlen(tmpCopy))
688 die_horribly(AH, modulename,
689 "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
690 tmpCopy, (unsigned long) pos1);
692 ahwrite(tmpCopy, 1, pos2, AH); /* 'copy "table" [with oids]' */
693 ahprintf(AH, " from '$$PATH$$/%s' %s", tctx->filename, &tmpCopy[pos2 + 10]);
698 if (strcmp(te->desc, "BLOBS") == 0)
699 _LoadBlobs(AH, ropt);
701 _PrintFileData(AH, tctx->filename, ropt);
705 _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
708 lclContext *ctx = (lclContext *) AH->formatData;
711 bool foundBlob = false;
714 StartRestoreBlobs(AH);
716 th = tarOpen(AH, NULL, 'r'); /* Open next file */
721 if (strncmp(th->targetFile, "blob_", 5) == 0)
723 oid = atooid(&th->targetFile[5]);
726 ahlog(AH, 1, "restoring large object OID %u\n", oid);
728 StartRestoreBlob(AH, oid, ropt->dropSchema);
730 while ((cnt = tarRead(buf, 4095, th)) > 0)
733 ahwrite(buf, 1, cnt, AH);
735 EndRestoreBlob(AH, oid);
745 * Once we have found the first blob, stop at the first non-blob
746 * entry (which will be 'blobs.toc'). This coding would eat all
747 * the rest of the archive if there are no blobs ... but this
748 * function shouldn't be called at all in that case.
754 th = tarOpen(AH, NULL, 'r');
761 _WriteByte(ArchiveHandle *AH, const int i)
763 lclContext *ctx = (lclContext *) AH->formatData;
765 char b = i; /* Avoid endian problems */
767 res = tarWrite(&b, 1, ctx->FH);
774 _ReadByte(ArchiveHandle *AH)
776 lclContext *ctx = (lclContext *) AH->formatData;
780 res = tarRead(&c, 1, ctx->FH);
782 die_horribly(AH, modulename, "unexpected end of file\n");
788 _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
790 lclContext *ctx = (lclContext *) AH->formatData;
793 res = tarWrite((void *) buf, len, ctx->FH);
799 _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
801 lclContext *ctx = (lclContext *) AH->formatData;
804 res = tarRead(buf, len, ctx->FH);
810 _CloseArchive(ArchiveHandle *AH)
812 lclContext *ctx = (lclContext *) AH->formatData;
814 RestoreOptions *ropt;
818 if (AH->mode == archModeWrite)
821 * Write the Header & TOC to the archive FIRST
823 th = tarOpen(AH, "toc.dat", 'w');
827 tarClose(AH, th); /* Not needed any more */
830 * Now send the data (tables & blobs)
835 * Now this format wants to append a script which does a full restore
836 * if the files have been extracted.
838 th = tarOpen(AH, "restore.sql", 'w');
839 tarPrintf(AH, th, "create temporary table pgdump_restore_path(p text);\n");
840 tarPrintf(AH, th, "--\n"
843 "-- File paths need to be edited. Search for $$PATH$$ and\n"
844 "-- replace it with the path to the directory containing\n"
845 "-- the extracted data files.\n"
847 "-- Edit the following to match the path where the\n"
848 "-- tar archive has been extracted.\n"
850 tarPrintf(AH, th, "insert into pgdump_restore_path values('/tmp');\n\n");
852 AH->CustomOutPtr = _scriptOut;
854 ctx->isSpecialScript = 1;
857 ropt = NewRestoreOptions();
858 ropt->dropSchema = 1;
859 ropt->compression = 0;
860 ropt->superuser = NULL;
861 ropt->suppressDumpWarnings = true;
863 savVerbose = AH->public.verbose;
864 AH->public.verbose = 0;
866 RestoreArchive((Archive *) AH, ropt);
868 AH->public.verbose = savVerbose;
872 /* Add a block of NULLs since it's de-rigeur. */
873 for (i = 0; i < 512; i++)
875 if (fputc(0, ctx->tarFH) == EOF)
876 die_horribly(AH, modulename,
877 "could not write null block at end of tar archive\n");
885 _scriptOut(ArchiveHandle *AH, const void *buf, size_t len)
887 lclContext *ctx = (lclContext *) AH->formatData;
889 return tarWrite(buf, len, ctx->scriptTH);
897 * Called by the archiver when starting to save all BLOB DATA (not schema).
898 * This routine should save whatever format-specific information is needed
899 * to read the BLOBs back into memory.
901 * It is called just prior to the dumper's DataDumper routine.
903 * Optional, but strongly recommended.
907 _StartBlobs(ArchiveHandle *AH, TocEntry *te)
909 lclContext *ctx = (lclContext *) AH->formatData;
910 char fname[K_STD_BUF_SIZE];
912 sprintf(fname, "blobs.toc");
913 ctx->blobToc = tarOpen(AH, fname, 'w');
917 * Called by the archiver when the dumper calls StartBlob.
921 * Must save the passed OID for retrieval at restore-time.
924 _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
926 lclContext *ctx = (lclContext *) AH->formatData;
927 lclTocEntry *tctx = (lclTocEntry *) te->formatData;
932 die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
934 if (AH->compression != 0)
939 sprintf(fname, "blob_%u.dat%s", oid, sfx);
941 tarPrintf(AH, ctx->blobToc, "%u %s\n", oid, fname);
943 tctx->TH = tarOpen(AH, fname, 'w');
947 * Called by the archiver when the dumper calls EndBlob.
953 _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
955 lclTocEntry *tctx = (lclTocEntry *) te->formatData;
957 tarClose(AH, tctx->TH);
961 * Called by the archiver when finishing saving all BLOB DATA.
967 _EndBlobs(ArchiveHandle *AH, TocEntry *te)
969 lclContext *ctx = (lclContext *) AH->formatData;
971 /* Write out a fake zero OID to mark end-of-blobs. */
972 /* WriteInt(AH, 0); */
974 tarClose(AH, ctx->blobToc);
985 tarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...)
989 size_t bSize = strlen(fmt) + 256; /* Should be enough */
993 * This is paranoid: deal with the possibility that vsnprintf is willing
994 * to ignore trailing null
998 * or returns > 0 even if string does not fit. It may be the case that it
999 * returns cnt = bufsize
1001 while (cnt < 0 || cnt >= (bSize - 1))
1006 p = (char *) malloc(bSize);
1008 die_horribly(AH, modulename, "out of memory\n");
1010 cnt = vsnprintf(p, bSize, fmt, ap);
1013 cnt = tarWrite(p, cnt, th);
1019 _tarChecksum(char *header)
1025 for (i = 0; i < 512; i++)
1026 if (i < 148 || i >= 156)
1027 sum += 0xFF & header[i];
1028 return sum + 256; /* Assume 8 blanks in checksum field */
1032 isValidTarHeader(char *header)
1035 int chk = _tarChecksum(header);
1037 sscanf(&header[148], "%8o", &sum);
1043 if (strncmp(&header[257], "ustar00", 7) == 0)
1046 if (strncmp(&header[257], "ustar ", 7) == 0)
1052 /* Given the member, write the TAR header & copy the file */
1054 _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
1056 lclContext *ctx = (lclContext *) AH->formatData;
1057 FILE *tmp = th->tmpFH; /* Grab it for convenience */
1066 * Find file len & go back to start.
1068 fseeko(tmp, 0, SEEK_END);
1069 th->fileLen = ftello(tmp);
1070 fseeko(tmp, 0, SEEK_SET);
1073 * Some compilers will throw a warning knowing this test can never be true
1074 * because pgoff_t can't exceed the compared maximum on their platform.
1076 if (th->fileLen > MAX_TAR_MEMBER_FILELEN)
1077 die_horribly(AH, modulename, "archive member too large for tar format\n");
1079 _tarWriteHeader(th);
1081 while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0)
1083 res = fwrite(buf, 1, cnt, th->tarFH);
1085 die_horribly(AH, modulename,
1086 "could not write to output file: %s\n",
1091 if (fclose(tmp) != 0) /* This *should* delete it... */
1092 die_horribly(AH, modulename, "could not close temporary file: %s\n",
1095 if (len != th->fileLen)
1100 snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);
1101 snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen);
1102 die_horribly(AH, modulename, "actual file length (%s) does not match expected (%s)\n",
1106 pad = ((len + 511) & ~511) - len;
1107 for (i = 0; i < pad; i++)
1109 if (fputc('\0', th->tarFH) == EOF)
1110 die_horribly(AH, modulename, "could not output padding at end of tar member\n");
1113 ctx->tarFHpos += len + pad;
1116 /* Locate the file in the archive, read header and position to data */
1118 _tarPositionTo(ArchiveHandle *AH, const char *filename)
1120 lclContext *ctx = (lclContext *) AH->formatData;
1121 TAR_MEMBER *th = calloc(1, sizeof(TAR_MEMBER));
1131 /* Go to end of current file, if any */
1132 if (ctx->tarFHpos != 0)
1137 snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ctx->tarFHpos);
1138 snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ctx->tarNextMember);
1139 ahlog(AH, 4, "moving from position %s to next member at file position %s\n",
1142 while (ctx->tarFHpos < ctx->tarNextMember)
1143 _tarReadRaw(AH, &c, 1, NULL, ctx->tarFH);
1149 snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ctx->tarFHpos);
1150 ahlog(AH, 4, "now at file position %s\n", buf);
1153 /* We are at the start of the file. or at the next member */
1155 /* Get the header */
1156 if (!_tarGetHeader(AH, th))
1159 die_horribly(AH, modulename, "could not find header for file %s in tar archive\n", filename);
1163 * We're just scanning the archibe for the next file, so return
1172 while (filename != NULL && strcmp(th->targetFile, filename) != 0)
1174 ahlog(AH, 4, "skipping tar member %s\n", th->targetFile);
1176 id = atoi(th->targetFile);
1177 if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0)
1178 die_horribly(AH, modulename, "dumping data out of order is not supported in this archive format: "
1179 "%s is required, but comes before %s in the archive file.\n",
1180 th->targetFile, filename);
1182 /* Header doesn't match, so read to next header */
1183 len = ((th->fileLen + 511) & ~511); /* Padded length */
1184 blks = len >> 9; /* # of 512 byte blocks */
1186 for (i = 0; i < blks; i++)
1187 _tarReadRaw(AH, &header[0], 512, NULL, ctx->tarFH);
1189 if (!_tarGetHeader(AH, th))
1190 die_horribly(AH, modulename, "could not find header for file %s in tar archive\n", filename);
1194 ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);
1200 /* Read & verify a header */
1202 _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
1204 lclContext *ctx = (lclContext *) AH->formatData;
1210 unsigned long ullen;
1212 bool gotBlock = false;
1217 if (ftello(ctx->tarFH) != ctx->tarFHpos)
1222 snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));
1223 snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));
1224 die_horribly(AH, modulename,
1225 "mismatch in actual vs. predicted file position (%s vs. %s)\n",
1230 /* Save the pos for reporting purposes */
1231 hPos = ctx->tarFHpos;
1233 /* Read a 512 byte block, return EOF, exit if short */
1234 len = _tarReadRaw(AH, h, 512, NULL, ctx->tarFH);
1235 if (len == 0) /* EOF */
1239 die_horribly(AH, modulename,
1240 ngettext("incomplete tar header found (%lu byte)\n",
1241 "incomplete tar header found (%lu bytes)\n",
1243 (unsigned long) len);
1246 chk = _tarChecksum(h);
1247 sscanf(&h[148], "%8o", &sum);
1250 * If the checksum failed, see if it is a null block. If so, silently
1251 * continue to the next block.
1259 for (i = 0; i < 512; i++)
1270 sscanf(&h[0], "%99s", tag);
1271 sscanf(&h[124], "%12lo", &ullen);
1272 len = (size_t) ullen;
1277 snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) hPos);
1278 ahlog(AH, 3, "TOC Entry %s at %s (length %lu, checksum %d)\n",
1279 tag, buf, (unsigned long) len, sum);
1286 snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ftello(ctx->tarFH));
1287 die_horribly(AH, modulename,
1288 "corrupt tar header found in %s "
1289 "(expected %d, computed %d) file position %s\n",
1290 tag, sum, chk, buf);
1293 th->targetFile = strdup(tag);
1301 * Utility routine to print possibly larger than 32 bit integers in a
1302 * portable fashion. Filled with zeros.
1305 print_val(char *s, uint64 val, unsigned int base, size_t len)
1309 for (i = len; i > 0; i--)
1311 int digit = val % base;
1313 s[i - 1] = '0' + digit;
1320 _tarWriteHeader(TAR_MEMBER *th)
1326 memset(h, 0, sizeof(h));
1329 sprintf(&h[0], "%.99s", th->targetFile);
1332 sprintf(&h[100], "100600 ");
1335 sprintf(&h[108], "004000 ");
1338 sprintf(&h[116], "002000 ");
1340 /* File size 12 - 11 digits, 1 space, no NUL */
1341 print_val(&h[124], th->fileLen, 8, 11);
1342 sprintf(&h[135], " ");
1345 sprintf(&h[136], "%011o ", (int) time(NULL));
1348 sprintf(&h[148], "%06o ", lastSum);
1350 /* Type - regular file */
1351 sprintf(&h[156], "0");
1353 /* Link tag 100 (NULL) */
1355 /* Magic 6 + Version 2 */
1356 sprintf(&h[257], "ustar00");
1360 sprintf(&h[265], "%.31s", ""); /* How do I get username reliably? Do
1364 sprintf(&h[297], "%.31s", ""); /* How do I get group reliably? Do I
1368 sprintf(&h[329], "%6o ", 0);
1371 sprintf(&h[337], "%6o ", 0);
1374 while ((sum = _tarChecksum(h)) != lastSum)
1376 sprintf(&h[148], "%06o ", sum);
1380 if (fwrite(h, 1, 512, th->tarFH) != 512)
1381 die_horribly(th->AH, modulename, "could not write to output file: %s\n", strerror(errno));