📄 pg_backup_archiver.c
字号:
return res; } }}/* Common exit code */static void_write_msg(const char *modulename, const char *fmt, va_list ap){ if (modulename) fprintf(stderr, "%s: [%s] ", progname, _(modulename)); else fprintf(stderr, "%s: ", progname); vfprintf(stderr, _(fmt), ap);}voidwrite_msg(const char *modulename, const char *fmt,...){ va_list ap; va_start(ap, fmt); _write_msg(modulename, fmt, ap); va_end(ap);}static void_die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap){ _write_msg(modulename, fmt, ap); if (AH) { if (AH->public.verbose) write_msg(NULL, "*** aborted because of error\n"); if (AH->connection) PQfinish(AH->connection); } exit(1);}/* External use */voidexit_horribly(Archive *AH, const char *modulename, const char *fmt,...){ va_list ap; va_start(ap, fmt); _die_horribly((ArchiveHandle *) AH, modulename, fmt, ap); va_end(ap);}/* Archiver use (just different arg declaration) */voiddie_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...){ va_list ap; va_start(ap, fmt); _die_horribly(AH, modulename, fmt, ap); va_end(ap);}/* on some error, we may decide to go on... */voidwarn_or_die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...){ va_list ap; switch (AH->stage) { case STAGE_NONE: /* Do nothing special */ break; case STAGE_INITIALIZING: if (AH->stage != AH->lastErrorStage) write_msg(modulename, "Error while INITIALIZING:\n"); break; case STAGE_PROCESSING: if (AH->stage != AH->lastErrorStage) write_msg(modulename, "Error while PROCESSING TOC:\n"); break; case STAGE_FINALIZING: if (AH->stage != AH->lastErrorStage) write_msg(modulename, "Error while FINALIZING:\n"); break; } if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE) { write_msg(modulename, "Error from TOC entry %d; %u %u %s %s %s\n", AH->currentTE->dumpId, AH->currentTE->catalogId.tableoid, AH->currentTE->catalogId.oid, AH->currentTE->desc, AH->currentTE->tag, AH->currentTE->owner); } AH->lastErrorStage = AH->stage; AH->lastErrorTE = AH->currentTE; va_start(ap, fmt); if (AH->public.exit_on_error) _die_horribly(AH, modulename, fmt, ap); else { _write_msg(modulename, fmt, ap); AH->public.n_errors++; } va_end(ap);}static void_moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te){ te->prev->next = te->next; te->next->prev = te->prev; te->prev = pos; te->next = pos->next; pos->next->prev = te; pos->next = te;}#ifdef NOT_USEDstatic void_moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te){ te->prev->next = te->next; te->next->prev = te->prev; te->prev = pos->prev; te->next = pos; pos->prev->next = te; pos->prev = te;}#endifstatic TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id){ TocEntry *te; te = AH->toc->next; while (te != AH->toc) { if (te->dumpId == id) return te; te = te->next; } return NULL;}teReqsTocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt){ TocEntry *te = getTocEntryByDumpId(AH, id); if (!te) return 0; return _tocEntryRequired(te, ropt, true);}size_tWriteOffset(ArchiveHandle *AH, off_t o, int wasSet){ int off; /* Save the flag */ (*AH->WriteBytePtr) (AH, wasSet); /* Write out off_t smallest byte first, prevents endian mismatch */ for (off = 0; off < sizeof(off_t); off++) { (*AH->WriteBytePtr) (AH, o & 0xFF); o >>= 8; } return sizeof(off_t) + 1;}intReadOffset(ArchiveHandle *AH, off_t *o){ int i; int off; int offsetFlg; /* Initialize to zero */ *o = 0; /* Check for old version */ if (AH->version < K_VERS_1_7) { /* Prior versions wrote offsets using WriteInt */ i = ReadInt(AH); /* -1 means not set */ if (i < 0) return K_OFFSET_POS_NOT_SET; else if (i == 0) return K_OFFSET_NO_DATA; /* Cast to off_t because it was written as an int. */ *o = (off_t) i; return K_OFFSET_POS_SET; } /* * Read the flag indicating the state of the data pointer. Check if valid * and die if not. * * This used to be handled by a negative or zero pointer, now we use an * extra byte specifically for the state. */ offsetFlg = (*AH->ReadBytePtr) (AH) & 0xFF; switch (offsetFlg) { case K_OFFSET_POS_NOT_SET: case K_OFFSET_NO_DATA: case K_OFFSET_POS_SET: break; default: die_horribly(AH, modulename, "Unexpected data offset flag %d\n", offsetFlg); } /* * Read the bytes */ for (off = 0; off < AH->offSize; off++) { if (off < sizeof(off_t)) *o |= ((off_t) ((*AH->ReadBytePtr) (AH))) << (off * 8); else { if ((*AH->ReadBytePtr) (AH) != 0) die_horribly(AH, modulename, "file offset in dump file is too large\n"); } } return offsetFlg;}size_tWriteInt(ArchiveHandle *AH, int i){ int b; /* * This is a bit yucky, but I don't want to make the binary format very * dependent on representation, and not knowing much about it, I write out * a sign byte. If you change this, don't forget to change the file * version #, and modify readInt to read the new format AS WELL AS the old * formats. */ /* SIGN byte */ if (i < 0) { (*AH->WriteBytePtr) (AH, 1); i = -i; } else (*AH->WriteBytePtr) (AH, 0); for (b = 0; b < AH->intSize; b++) { (*AH->WriteBytePtr) (AH, i & 0xFF); i >>= 8; } return AH->intSize + 1;}intReadInt(ArchiveHandle *AH){ int res = 0; int bv, b; int sign = 0; /* Default positive */ int bitShift = 0; if (AH->version > K_VERS_1_0) /* Read a sign byte */ sign = (*AH->ReadBytePtr) (AH); for (b = 0; b < AH->intSize; b++) { bv = (*AH->ReadBytePtr) (AH) & 0xFF; if (bv != 0) res = res + (bv << bitShift); bitShift += 8; } if (sign) res = -res; return res;}size_tWriteStr(ArchiveHandle *AH, const char *c){ size_t res; if (c) { res = WriteInt(AH, strlen(c)); res += (*AH->WriteBufPtr) (AH, c, strlen(c)); } else res = WriteInt(AH, -1); return res;}char *ReadStr(ArchiveHandle *AH){ char *buf; int l; l = ReadInt(AH); if (l == -1) buf = NULL; else { buf = (char *) malloc(l + 1); if (!buf) die_horribly(AH, modulename, "out of memory\n"); (*AH->ReadBufPtr) (AH, (void *) buf, l); buf[l] = '\0'; } return buf;}static int_discoverArchiveFormat(ArchiveHandle *AH){ FILE *fh; char sig[6]; /* More than enough */ size_t cnt; int wantClose = 0;#if 0 write_msg(modulename, "attempting to ascertain archive format\n");#endif if (AH->lookahead) free(AH->lookahead); AH->lookaheadSize = 512; AH->lookahead = calloc(1, 512); AH->lookaheadLen = 0; AH->lookaheadPos = 0; if (AH->fSpec) { wantClose = 1; fh = fopen(AH->fSpec, PG_BINARY_R); } else fh = stdin; if (!fh) die_horribly(AH, modulename, "could not open input file: %s\n", strerror(errno)); cnt = fread(sig, 1, 5, fh); if (cnt != 5) { if (ferror(fh)) die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno)); else die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n", (unsigned long) cnt); } /* Save it, just in case we need it later */ strncpy(&AH->lookahead[0], sig, 5); AH->lookaheadLen = 5; if (strncmp(sig, "PGDMP", 5) == 0) { AH->vmaj = fgetc(fh); AH->vmin = fgetc(fh); /* Save these too... */ AH->lookahead[AH->lookaheadLen++] = AH->vmaj; AH->lookahead[AH->lookaheadLen++] = AH->vmin; /* Check header version; varies from V1.0 */ if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0))) /* Version > 1.0 */ { AH->vrev = fgetc(fh); AH->lookahead[AH->lookaheadLen++] = AH->vrev; } else AH->vrev = 0; /* Make a convenient integer <maj><min><rev>00 */ AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0; AH->intSize = fgetc(fh); AH->lookahead[AH->lookaheadLen++] = AH->intSize; if (AH->version >= K_VERS_1_7) { AH->offSize = fgetc(fh); AH->lookahead[AH->lookaheadLen++] = AH->offSize; } else AH->offSize = AH->intSize; AH->format = fgetc(fh); AH->lookahead[AH->lookaheadLen++] = AH->format; } else { /* * *Maybe* we have a tar archive format file... So, read first 512 * byte header... */ cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh); AH->lookaheadLen += cnt; if (AH->lookaheadLen != 512) die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n"); if (!isValidTarHeader(AH->lookahead)) die_horribly(AH, modulename, "input file does not appear to be a valid archive\n"); AH->format = archTar; } /* If we can't seek, then mark the header as read */ if (fseeko(fh, 0, SEEK_SET) != 0) { /* * NOTE: Formats that use the lookahead buffer can unset this in their * Init routine. */ AH->readHeader = 1; } else AH->lookaheadLen = 0; /* Don't bother since we've reset the file */#if 0 write_msg(modulename, "read %lu bytes into lookahead buffer\n", (unsigned long) AH->lookaheadLen);#endif /* Close the file */ if (wantClose) if (fclose(fh) != 0) die_horribly(AH, modulename, "could not close the input file after reading header: %s\n", strerror(errno)); return AH->format;}/* * Allocate an archive handle */static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, const int compression, ArchiveMode mode){ ArchiveHandle *AH;#if 0 write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);#endif AH = (ArchiveHandle *) calloc(1, sizeof(ArchiveHandle)); if (!AH) die_horribly(AH, modulename, "out of memory\n"); /* AH->debugLevel = 100; */ AH->vmaj = K_VERS_MAJOR; AH->vmin = K_VERS_MINOR; AH->vrev = K_VERS_REV; AH->createDate = time(NULL); AH->intSize = sizeof(int); AH->offSize = sizeof(off_t); if (FileSpec) { AH->fSpec = strdup(FileSpec); /* * Not used; maybe later.... * * AH->workDir = strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ; * i--) if (AH->workDir[i-1] == '/') */ } else AH->fSpec = NULL; AH->currUser = strdup(""); /* So it's valid, but we can free() it later * if necessary */ AH->currSchema = strdup(""); /* ditto */ AH->currWithOids = -1; /* force SET */ AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry)); if (!AH->toc) die_horribly(AH, modulename, "out of memory\n"); AH->toc->next = AH->toc; AH->toc->prev = AH->toc; AH->mode = mode; AH->compression = compression; AH->pgCopyBuf = createPQExpBuffer(); AH->sqlBuf = createPQExpBuffer(); /* Open stdout with no compression for AH output handle */ AH->gzOut = 0; AH->OF = stdout;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -