⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pg_backup_tar.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
}static void_LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt){	Oid			oid;	lclContext *ctx = (lclContext *) AH->formatData;	TAR_MEMBER *th;	size_t		cnt;	char		buf[4096];	StartRestoreBlobs(AH);	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)			{				ahlog(AH, 1, "restoring large object OID %u\n", oid);				StartRestoreBlob(AH, oid);				while ((cnt = tarRead(buf, 4095, th)) > 0)				{					buf[cnt] = '\0';					ahwrite(buf, 1, cnt, AH);				}				EndRestoreBlob(AH, oid);			}		}		tarClose(AH, th);		th = tarOpen(AH, NULL, 'r');	}	EndRestoreBlobs(AH);}static int_WriteByte(ArchiveHandle *AH, const int i){	lclContext *ctx = (lclContext *) AH->formatData;	int			res;	char		b = i;			/* Avoid endian problems */	res = tarWrite(&b, 1, ctx->FH);	if (res != EOF)		ctx->filePos += res;	return res;}static int_ReadByte(ArchiveHandle *AH){	lclContext *ctx = (lclContext *) AH->formatData;	int			res;	char		c = '\0';	res = tarRead(&c, 1, ctx->FH);	if (res != EOF)		ctx->filePos += res;	return c;}static size_t_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len){	lclContext *ctx = (lclContext *) AH->formatData;	size_t		res;	res = tarWrite((void *) buf, len, ctx->FH);	ctx->filePos += res;	return res;}static size_t_ReadBuf(ArchiveHandle *AH, void *buf, size_t len){	lclContext *ctx = (lclContext *) AH->formatData;	size_t		res;	res = tarRead(buf, len, ctx->FH);	ctx->filePos += res;	return res;}static void_CloseArchive(ArchiveHandle *AH){	lclContext *ctx = (lclContext *) AH->formatData;	TAR_MEMBER *th;	RestoreOptions *ropt;	int			savVerbose,				i;	if (AH->mode == archModeWrite)	{		/*		 * Write the Header & TOC to the archive FIRST		 */		th = tarOpen(AH, "toc.dat", 'w');		ctx->FH = th;		WriteHead(AH);		WriteToc(AH);		tarClose(AH, th);		/* Not needed any more */		/*		 * Now send the data (tables & blobs)		 */		WriteDataChunks(AH);		/*		 * Now this format wants to append a script which does a full restore		 * if the files have been extracted.		 */		th = tarOpen(AH, "restore.sql", 'w');		tarPrintf(AH, th, "create temporary table pgdump_restore_path(p text);\n");		tarPrintf(AH, 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"				  "-- Edit the following to match the path where the\n"				  "-- tar archive has been extracted.\n"				  "--\n");		tarPrintf(AH, th, "insert into pgdump_restore_path values('/tmp');\n\n");		AH->CustomOutPtr = _scriptOut;		ctx->isSpecialScript = 1;		ctx->scriptTH = th;		ropt = NewRestoreOptions();		ropt->dropSchema = 1;		ropt->compression = 0;		ropt->superuser = NULL;		ropt->suppressDumpWarnings = true;		savVerbose = AH->public.verbose;		AH->public.verbose = 0;		RestoreArchive((Archive *) AH, ropt);		AH->public.verbose = savVerbose;		tarClose(AH, th);		/* Add a block of NULLs since it's de-rigeur. */		for (i = 0; i < 512; i++)		{			if (fputc(0, ctx->tarFH) == EOF)				die_horribly(AH, modulename,					   "could not write null block at end of tar archive\n");		}	}	AH->FH = NULL;}static size_t_scriptOut(ArchiveHandle *AH, const void *buf, size_t len){	lclContext *ctx = (lclContext *) AH->formatData;	return tarWrite(buf, len, ctx->scriptTH);}/* * BLOB support *//* * Called by the archiver when starting to save all BLOB DATA (not schema). * This routine should save whatever format-specific information is needed * to read the BLOBs back into memory. * * It is called just prior to the dumper's DataDumper routine. * * Optional, but strongly recommended. * */static void_StartBlobs(ArchiveHandle *AH, TocEntry *te){	lclContext *ctx = (lclContext *) AH->formatData;	char		fname[K_STD_BUF_SIZE];	sprintf(fname, "blobs.toc");	ctx->blobToc = tarOpen(AH, fname, 'w');}/* * Called by the archiver when the dumper calls StartBlob. * * Mandatory. * * Must save the passed OID for retrieval at restore-time. */static void_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid){	lclContext *ctx = (lclContext *) AH->formatData;	lclTocEntry *tctx = (lclTocEntry *) te->formatData;	char		fname[255];	char	   *sfx;	if (oid == 0)		die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);	if (AH->compression != 0)		sfx = ".gz";	else		sfx = "";	sprintf(fname, "blob_%u.dat%s", oid, sfx);	tarPrintf(AH, ctx->blobToc, "%u %s\n", oid, fname);	tctx->TH = tarOpen(AH, fname, 'w');}/* * Called by the archiver when the dumper calls EndBlob. * * Optional. * */static void_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid){	lclTocEntry *tctx = (lclTocEntry *) te->formatData;	tarClose(AH, tctx->TH);}/* * Called by the archiver when finishing saving all BLOB DATA. * * Optional. * */static void_EndBlobs(ArchiveHandle *AH, TocEntry *te){	lclContext *ctx = (lclContext *) AH->formatData;	/* Write out a fake zero OID to mark end-of-blobs. */	/* WriteInt(AH, 0); */	tarClose(AH, ctx->blobToc);}/*------------ * TAR Support *------------ */static inttarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...){	char	   *p = NULL;	va_list		ap;	size_t		bSize = strlen(fmt) + 256;		/* Should be enough */	int			cnt = -1;	/*	 * This is paranoid: deal with the possibility that vsnprintf is willing	 * to ignore trailing null	 */	/*	 * or returns > 0 even if string does not fit. It may be the case that it	 * returns cnt = bufsize	 */	while (cnt < 0 || cnt >= (bSize - 1))	{		if (p != NULL)			free(p);		bSize *= 2;		p = (char *) malloc(bSize);		if (p == NULL)			die_horribly(AH, modulename, "out of memory\n");		va_start(ap, fmt);		cnt = vsnprintf(p, bSize, fmt, ap);		va_end(ap);	}	cnt = tarWrite(p, cnt, th);	free(p);	return cnt;}static int_tarChecksum(char *header){	int			i,				sum;	sum = 0;	for (i = 0; i < 512; i++)		if (i < 148 || i >= 156)			sum += 0xFF & header[i];	return sum + 256;			/* Assume 8 blanks in checksum field */}boolisValidTarHeader(char *header){	int			sum;	int			chk = _tarChecksum(header);	sscanf(&header[148], "%8o", &sum);	if (sum != chk)		return false;	/* POSIX format */	if (strncmp(&header[257], "ustar00", 7) == 0)		return true;	/* older format */	if (strncmp(&header[257], "ustar  ", 7) == 0)		return true;	return false;}/* Given the member, write the TAR header & copy the file */static void_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;	off_t		len = 0;	size_t		res;	size_t		i,				pad;	/*	 * Find file len & go back to start.	 */	fseeko(tmp, 0, SEEK_END);	th->fileLen = ftello(tmp);	/*	 * Some compilers with throw a warning knowing this test can never be true	 * because off_t can't exceed the compared maximum.	 */	if (th->fileLen > MAX_TAR_MEMBER_FILELEN)		die_horribly(AH, modulename, "archive member too large for tar format\n");	fseeko(tmp, 0, SEEK_SET);	_tarWriteHeader(th);	while ((cnt = fread(&buf[0], 1, 32767, tmp)) > 0)	{		res = fwrite(&buf[0], 1, cnt, th->tarFH);		if (res != cnt)			die_horribly(AH, modulename,						 "write error appending to tar archive (wrote %lu, attempted %lu)\n",						 (unsigned long) res, (unsigned long) cnt);		len += res;	}	if (fclose(tmp) != 0)		/* This *should* delete it... */		die_horribly(AH, modulename, "could not close tar member: %s\n", strerror(errno));	if (len != th->fileLen)	{		char		buf1[100],					buf2[100];		snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);		snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->pos);		die_horribly(AH, modulename, "actual file length (%s) does not match expected (%s)\n",					 buf1, buf2);	}	pad = ((len + 511) & ~511) - len;	for (i = 0; i < pad; i++)	{		if (fputc('\0', th->tarFH) == EOF)			die_horribly(AH, modulename, "could not output padding at end of tar member\n");	}	ctx->tarFHpos += len + pad;}/* Locate the file in the archive, read header and position to data */static TAR_MEMBER *_tarPositionTo(ArchiveHandle *AH, const char *filename){	lclContext *ctx = (lclContext *) AH->formatData;	TAR_MEMBER *th = calloc(1, sizeof(TAR_MEMBER));	char		c;	char		header[512];	size_t		i,				len,				blks;	int			id;	th->AH = AH;	/* Go to end of current file, if any */	if (ctx->tarFHpos != 0)	{		char		buf1[100],					buf2[100];		snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ctx->tarFHpos);		snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ctx->tarNextMember);		ahlog(AH, 4, "moving from position %s to next member at file position %s\n",			  buf1, buf2);		while (ctx->tarFHpos < ctx->tarNextMember)			_tarReadRaw(AH, &c, 1, NULL, ctx->tarFH);	}	{		char		buf[100];		snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ctx->tarFHpos);		ahlog(AH, 4, "now at file position %s\n", buf);	}	/* We are at the start of the file. or at the next member */	/* Get the header */	if (!_tarGetHeader(AH, th))	{		if (filename)			die_horribly(AH, modulename, "could not find header for file %s in tar archive\n", filename);		else			/*			 * We're just scanning the archibe for the next file, so return			 * null			 */		{			free(th);			return NULL;		}	}	while (filename != NULL && strcmp(th->targetFile, filename) != 0)	{		ahlog(AH, 4, "skipping tar member %s\n", th->targetFile);		id = atoi(th->targetFile);		if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0)			die_horribly(AH, modulename, "dumping data out of order is not supported in this archive format: "				"%s is required, but comes before %s in the archive file.\n",						 th->targetFile, filename);		/* Header doesn't match, so read to next header */		len = ((th->fileLen + 511) & ~511);		/* Padded length */		blks = len >> 9;		/* # of 512 byte blocks */		for (i = 0; i < blks; i++)			_tarReadRaw(AH, &header[0], 512, NULL, ctx->tarFH);		if (!_tarGetHeader(AH, th))			die_horribly(AH, modulename, "could not find header for file %s in tar archive\n", filename);	}	ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);	th->pos = 0;	return th;}/* Read & verify a header */static int_tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th){	lclContext *ctx = (lclContext *) AH->formatData;	char		h[512];	char		tag[100];	int			sum,				chk;	size_t		len;	unsigned long ullen;	off_t		hPos;	bool		gotBlock = false;	while (!gotBlock)	{#if 0		if (ftello(ctx->tarFH) != ctx->tarFHpos)		{			char		buf1[100],						buf2[100];			snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));			snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));			die_horribly(AH, modulename,			  "mismatch in actual vs. predicted file position (%s vs. %s)\n",						 buf1, buf2);		}#endif		/* Save the pos for reporting purposes */		hPos = ctx->tarFHpos;		/* Read a 512 byte block, return EOF, exit if short */		len = _tarReadRaw(AH, h, 512, NULL, ctx->tarFH);		if (len == 0)			/* EOF */			return 0;		if (len != 512)			die_horribly(AH, modulename,						 "incomplete tar header found (%lu bytes)\n",						 (unsigned long) len);		/* Calc checksum */		chk = _tarChecksum(h);		sscanf(&h[148], "%8o", &sum);		/*		 * If the checksum failed, see if it is a null block. If so, silently		 * continue to the next block.		 */		if (chk == sum)			gotBlock = true;		else		{			int			i;			for (i = 0; i < 512; i++)			{				if (h[i] != 0)				{					gotBlock = true;					break;				}			}		}	}	sscanf(&h[0], "%99s", tag);	sscanf(&h[124], "%12lo", &ullen);	len = (size_t) ullen;	{		char		buf[100];		snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) hPos);		ahlog(AH, 3, "TOC Entry %s at %s (length %lu, checksum %d)\n",			  tag, buf, (unsigned long) len, sum);	}	if (chk != sum)	{		char		buf[100];		snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ftello(ctx->tarFH));		die_horribly(AH, modulename,					 "corrupt tar header found in %s "					 "(expected %d, computed %d) file position %s\n",					 tag, sum, chk, buf);	}	th->targetFile = strdup(tag);	th->fileLen = len;	return 1;}/* * Utility routine to print possibly larger than 32 bit integers in a * portable fashion.  Filled with zeros. */static voidprint_val(char *s, uint64 val, unsigned int base, size_t len){	int			i;	for (i = len; i > 0; i--)	{		int			digit = val % base;		s[i - 1] = '0' + digit;		val = val / base;	}}static void_tarWriteHeader(TAR_MEMBER *th){	char		h[512];	int			lastSum = 0;	int			sum;	memset(h, 0, sizeof(h));	/* Name 100 */	sprintf(&h[0], "%.99s", th->targetFile);	/* Mode 8 */	sprintf(&h[100], "100600 ");	/* User ID 8 */	sprintf(&h[108], "004000 ");	/* Group 8 */	sprintf(&h[116], "002000 ");	/* File size 12 - 11 digits, 1 space, no NUL */	print_val(&h[124], th->fileLen, 8, 11);	sprintf(&h[135], " ");	/* Mod Time 12 */	sprintf(&h[136], "%011o ", (int) time(NULL));	/* Checksum 8 */	sprintf(&h[148], "%06o ", lastSum);	/* Type - regular file */	sprintf(&h[156], "0");	/* Link tag 100 (NULL) */	/* Magic 6 + Version 2 */	sprintf(&h[257], "ustar00");#if 0	/* User 32 */	sprintf(&h[265], "%.31s", "");		/* How do I get username reliably? Do										 * I need to? */	/* Group 32 */	sprintf(&h[297], "%.31s", "");		/* How do I get group reliably? Do I										 * need to? */	/* Maj Dev 8 */	sprintf(&h[329], "%6o ", 0);	/* Min Dev 8 */	sprintf(&h[337], "%6o ", 0);#endif	while ((sum = _tarChecksum(h)) != lastSum)	{		sprintf(&h[148], "%06o ", sum);		lastSum = sum;	}	if (fwrite(h, 1, 512, th->tarFH) != 512)		die_horribly(th->AH, modulename, "could not write tar header\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -