/* *Wedon'tsupportcompressionbecausereadingthefilesbackisnot *possiblesincegzdopenusesbufferedIOwhichtotallyscrewsfile *positioning.
*/ if (AH->compression_spec.algorithm != PG_COMPRESSION_NONE)
pg_fatal("compression is not supported by tar archive format");
} else
{ /* Read Mode */ if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
{
ctx->tarFH = fopen(AH->fSpec, PG_BINARY_R); if (ctx->tarFH == NULL)
pg_fatal("could not open TOC file \"%s\" for input: %m",
AH->fSpec);
} else
{
ctx->tarFH = stdin; if (ctx->tarFH == NULL)
pg_fatal("could not open TOC file for input: %m");
}
if (mode == 'r')
{
tm = _tarPositionTo(AH, filename); if (!tm) /* Not found */
{ if (filename)
{ /* *Couldn'tfindtherequestedfile.Future:doSEEK(0)and *retry.
*/
pg_fatal("could not find file \"%s\" in archive", filename);
} else
{ /* Any file OK, none left, so return NULL */ return NULL;
}
}
if (AH->compression_spec.algorithm == PG_COMPRESSION_NONE)
tm->nFH = ctx->tarFH; else
pg_fatal("compression is not supported by tar archive format");
} else
{ int old_umask;
staticvoid
tarClose(ArchiveHandle *AH, TAR_MEMBER *th)
{ if (AH->compression_spec.algorithm != PG_COMPRESSION_NONE)
pg_fatal("compression is not supported by tar archive format");
if (th->mode == 'w')
_tarAddFile(AH, th); /* This will close the temp file */
avail = AH->lookaheadLen - AH->lookaheadPos; if (avail > 0)
{ /* We have some lookahead bytes to use */ if (avail >= len) /* Just use the lookahead buffer */
used = len; else
used = avail;
/* Read the file if len > 0 */ if (len > 0)
{ if (fh)
{
res = fread(&((char *) buf)[used], 1, len, fh); if (res != len && !feof(fh))
READ_ERROR_EXIT(fh);
} elseif (th)
{
res = fread(&((char *) buf)[used], 1, len, th->nFH); if (res != len && !feof(th->nFH))
READ_ERROR_EXIT(th->nFH);
}
}
/* Emit all but the FROM part ... */
ahwrite(te->copyStmt, 1, pos1, AH); /* ... and insert modified FROM */
ahprintf(AH, " FROM '$$PATH$$/%s';\n\n", tctx->filename);
} else
{ /* --inserts mode, no worries, just include the data file */
ahprintf(AH, "\\i $$PATH$$/%s\n\n", tctx->filename);
}
/* *Theblobs_NNN.tocorblobs.tocfileisfairlyuselesstousbecauseit *willappearonlyaftertheassociatedblob_NNN.datfiles.Forarchive *versions>=16wecanlookattheBLOBSentry'ste->tagtodiscoverthe *OIDofthefirstblobwewanttorestore,andthensearchforwardto *findtheappropriateblob_<oid>.datfile.Forolderversionswerely *ontheknowledgethattherewasonlyoneBLOBSentryandjustsearch *forthefirstblob_<oid>.datfile.Oncewefindthefirstblobfileto *restore,restoreallblobsuntilwereachtheblobs[_NNN].tocfile.
*/ if (AH->version >= K_VERS_1_16)
{ /* We rely on atooid to not complain about nnnn..nnnn tags */
oid = atooid(te->tag);
snprintf(buf, sizeof(buf), "blob_%u.dat", oid);
th = tarOpen(AH, buf, 'r'); /* Advance to first desired file */
} else
th = tarOpen(AH, NULL, 'r'); /* Open next file */
while (th != NULL)
{
ctx->FH = th;
if (strncmp(th->targetFile, "blob_", 5) == 0)
{
oid = atooid(&th->targetFile[5]); if (oid != 0)
{
pg_log_info("restoring large object with OID %u", oid);
res = tarRead(&c, 1, ctx->FH); if (res != 1) /* We already would have exited for errors on reads, must be EOF */
pg_fatal("could not read from input file: end of file");
ctx->filePos += 1; return c;
}
if (tarRead(buf, len, ctx->FH) != len) /* We already would have exited for errors on reads, must be EOF */
pg_fatal("could not read from input file: end of file");
tarPrintf(th, "--\n" "-- NOTE:\n" "--\n" "-- File paths need to be edited. Search for $$PATH$$ and\n" "-- replace it with the path to the directory containing\n" "-- the extracted data files.\n" "--\n");
/* Given the member, write the TAR header & copy the file */ staticvoid
_tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
{
lclContext *ctx = (lclContext *) AH->formatData;
FILE *tmp = th->tmpFH; /* Grab it for convenience */ char buf[32768];
size_t cnt;
pgoff_t len = 0;
size_t res;
size_t i,
pad;
/* *Findfilelen&gobacktostart.
*/ if (fseeko(tmp, 0, SEEK_END) != 0)
pg_fatal("error during file seek: %m");
th->fileLen = ftello(tmp); if (th->fileLen < 0)
pg_fatal("could not determine seek position in archive file: %m"); if (fseeko(tmp, 0, SEEK_SET) != 0)
pg_fatal("error during file seek: %m");
_tarWriteHeader(th);
while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0)
{ if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt)
WRITE_ERROR_EXIT;
len += res;
} if (!feof(tmp))
READ_ERROR_EXIT(tmp);
if (fclose(tmp) != 0) /* This *should* delete it... */
pg_fatal("could not close temporary file: %m");
if (len != th->fileLen)
pg_fatal("actual file length (%lld) does not match expected (%lld)",
(longlong) len, (longlong) th->fileLen);
pad = tarPaddingBytesRequired(len); for (i = 0; i < pad; i++)
{ if (fputc('\0', th->tarFH) == EOF)
WRITE_ERROR_EXIT;
}
ctx->tarFHpos += len + pad;
}
/* Locate the file in the archive, read header and position to data */ static TAR_MEMBER *
_tarPositionTo(ArchiveHandle *AH, constchar *filename)
{
lclContext *ctx = (lclContext *) AH->formatData;
TAR_MEMBER *th = pg_malloc0_object(TAR_MEMBER); char c; char header[TAR_BLOCK_SIZE];
size_t i,
len,
blks; int id;
th->AH = AH;
/* Go to end of current file, if any */ if (ctx->tarFHpos != 0)
{
pg_log_debug("moving from position %lld to next member at file position %lld",
(longlong) ctx->tarFHpos, (longlong) ctx->tarNextMember);
while (ctx->tarFHpos < ctx->tarNextMember)
_tarReadRaw(AH, &c, 1, NULL, ctx->tarFH);
}
pg_log_debug("now at file position %lld", (longlong) ctx->tarFHpos);
/* We are at the start of the file, or at the next member */
/* Get the header */ if (!_tarGetHeader(AH, th))
{ if (filename)
pg_fatal("could not find header for file \"%s\" in tar archive", filename); else
{ /* *We'rejustscanningthearchiveforthenextfile,soreturn *null
*/
free(th); return NULL;
}
}
while (filename != NULL && strcmp(th->targetFile, filename) != 0)
{
pg_log_debug("skipping tar member %s", th->targetFile);
id = atoi(th->targetFile); if ((TocIDRequired(AH, id) & REQ_DATA) != 0)
pg_fatal("restoring data out of order is not supported in this archive format: " "\"%s\" is required, but comes before \"%s\" in the archive file.",
th->targetFile, filename);
/* Header doesn't match, so read to next header */
len = th->fileLen;
len += tarPaddingBytesRequired(th->fileLen);
blks = len / TAR_BLOCK_SIZE; /* # of tar blocks */
for (i = 0; i < blks; i++)
_tarReadRaw(AH, &header[0], TAR_BLOCK_SIZE, NULL, ctx->tarFH);
if (!_tarGetHeader(AH, th))
pg_fatal("could not find header for file \"%s\" in tar archive", filename);
}
while (!gotBlock)
{ /* Save the pos for reporting purposes */
hPos = ctx->tarFHpos;
/* Read the next tar block, return EOF, exit if short */
len = _tarReadRaw(AH, h, TAR_BLOCK_SIZE, NULL, ctx->tarFH); if (len == 0) /* EOF */ return0;
if (len != TAR_BLOCK_SIZE)
pg_fatal(ngettext("incomplete tar header found (%lu byte)", "incomplete tar header found (%lu bytes)",
len),
(unsignedlong) len);
if (chk != sum)
pg_fatal("corrupt tar header found in %s (expected %d, computed %d) file position %llu",
tag, sum, chk, (unsignedlonglong) ftello(ctx->tarFH));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.