1 /*-------------------------------------------------------------------------
2  *
3  * pg_backup_directory.c
4  *
5  *	A directory format dump is a directory, which contains a "toc.dat" file
6  *	for the TOC, and a separate file for each data entry, named "<oid>.dat".
7  *	Large objects (BLOBs) are stored in separate files named "blob_<uid>.dat",
8  *	and there's a plain-text TOC file for them called "blobs.toc". If
9  *	compression is used, each data file is individually compressed and the
10  *	".gz" suffix is added to the filenames. The TOC files are never
11  *	compressed by pg_dump, however they are accepted with the .gz suffix too,
12  *	in case the user has manually compressed them with 'gzip'.
13  *
14  *	NOTE: This format is identical to the files written in the tar file in
15  *	the 'tar' format, except that we don't write the restore.sql file (TODO),
16  *	and the tar format doesn't support compression. Please keep the formats in
17  *	sync.
18  *
19  *
20  *	Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
21  *	Portions Copyright (c) 1994, Regents of the University of California
22  *	Portions Copyright (c) 2000, Philip Warner
23  *
24  *	Rights are granted to use this software in any way so long
25  *	as this notice is not removed.
26  *
27  *	The author is not responsible for loss or damages that may
28  *	result from it's use.
29  *
30  * IDENTIFICATION
31  *		src/bin/pg_dump/pg_backup_directory.c
32  *
33  *-------------------------------------------------------------------------
34  */
35 #include "postgres_fe.h"
36 
37 #include "compress_io.h"
38 #include "parallel.h"
39 #include "pg_backup_utils.h"
40 #include "common/file_utils.h"
41 
42 #include <dirent.h>
43 #include <sys/stat.h>
44 
45 typedef struct
46 {
47 	/*
48 	 * Our archive location. This is basically what the user specified as his
49 	 * backup file but of course here it is a directory.
50 	 */
51 	char	   *directory;
52 
53 	cfp		   *dataFH;			/* currently open data file */
54 
55 	cfp		   *blobsTocFH;		/* file handle for blobs.toc */
56 	ParallelState *pstate;		/* for parallel backup / restore */
57 } lclContext;
58 
59 typedef struct
60 {
61 	char	   *filename;		/* filename excluding the directory (basename) */
62 } lclTocEntry;
63 
64 /* translator: this is a module name */
65 static const char *modulename = gettext_noop("directory archiver");
66 
67 /* prototypes for private functions */
68 static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
69 static void _StartData(ArchiveHandle *AH, TocEntry *te);
70 static void _EndData(ArchiveHandle *AH, TocEntry *te);
71 static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
72 static int	_WriteByte(ArchiveHandle *AH, const int i);
73 static int	_ReadByte(ArchiveHandle *);
74 static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
75 static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
76 static void _CloseArchive(ArchiveHandle *AH);
77 static void _ReopenArchive(ArchiveHandle *AH);
78 static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
79 
80 static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
81 static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
82 static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
83 
84 static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
85 static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
86 static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
87 static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
88 static void _LoadBlobs(ArchiveHandle *AH);
89 
90 static void _Clone(ArchiveHandle *AH);
91 static void _DeClone(ArchiveHandle *AH);
92 
93 static int	_WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te);
94 static int	_WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te);
95 
96 static void setFilePath(ArchiveHandle *AH, char *buf,
97 			const char *relativeFilename);
98 
99 /*
100  *	Init routine required by ALL formats. This is a global routine
101  *	and should be declared in pg_backup_archiver.h
102  *
103  *	Its task is to create any extra archive context (using AH->formatData),
104  *	and to initialize the supported function pointers.
105  *
106  *	It should also prepare whatever its input source is for reading/writing,
107  *	and in the case of a read mode connection, it should load the Header & TOC.
108  */
109 void
InitArchiveFmt_Directory(ArchiveHandle * AH)110 InitArchiveFmt_Directory(ArchiveHandle *AH)
111 {
112 	lclContext *ctx;
113 
114 	/* Assuming static functions, this can be copied for each format. */
115 	AH->ArchiveEntryPtr = _ArchiveEntry;
116 	AH->StartDataPtr = _StartData;
117 	AH->WriteDataPtr = _WriteData;
118 	AH->EndDataPtr = _EndData;
119 	AH->WriteBytePtr = _WriteByte;
120 	AH->ReadBytePtr = _ReadByte;
121 	AH->WriteBufPtr = _WriteBuf;
122 	AH->ReadBufPtr = _ReadBuf;
123 	AH->ClosePtr = _CloseArchive;
124 	AH->ReopenPtr = _ReopenArchive;
125 	AH->PrintTocDataPtr = _PrintTocData;
126 	AH->ReadExtraTocPtr = _ReadExtraToc;
127 	AH->WriteExtraTocPtr = _WriteExtraToc;
128 	AH->PrintExtraTocPtr = _PrintExtraToc;
129 
130 	AH->StartBlobsPtr = _StartBlobs;
131 	AH->StartBlobPtr = _StartBlob;
132 	AH->EndBlobPtr = _EndBlob;
133 	AH->EndBlobsPtr = _EndBlobs;
134 
135 	AH->ClonePtr = _Clone;
136 	AH->DeClonePtr = _DeClone;
137 
138 	AH->WorkerJobRestorePtr = _WorkerJobRestoreDirectory;
139 	AH->WorkerJobDumpPtr = _WorkerJobDumpDirectory;
140 
141 	/* Set up our private context */
142 	ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
143 	AH->formatData = (void *) ctx;
144 
145 	ctx->dataFH = NULL;
146 	ctx->blobsTocFH = NULL;
147 
148 	/* Initialize LO buffering */
149 	AH->lo_buf_size = LOBBUFSIZE;
150 	AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
151 
152 	/*
153 	 * Now open the TOC file
154 	 */
155 
156 	if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
157 		exit_horribly(modulename, "no output directory specified\n");
158 
159 	ctx->directory = AH->fSpec;
160 
161 	if (AH->mode == archModeWrite)
162 	{
163 		struct stat st;
164 		bool		is_empty = false;
165 
166 		/* we accept an empty existing directory */
167 		if (stat(ctx->directory, &st) == 0 && S_ISDIR(st.st_mode))
168 		{
169 			DIR		   *dir = opendir(ctx->directory);
170 
171 			if (dir)
172 			{
173 				struct dirent *d;
174 
175 				is_empty = true;
176 				while (errno = 0, (d = readdir(dir)))
177 				{
178 					if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0)
179 					{
180 						is_empty = false;
181 						break;
182 					}
183 				}
184 
185 				if (errno)
186 					exit_horribly(modulename, "could not read directory \"%s\": %s\n",
187 								  ctx->directory, strerror(errno));
188 
189 				if (closedir(dir))
190 					exit_horribly(modulename, "could not close directory \"%s\": %s\n",
191 								  ctx->directory, strerror(errno));
192 			}
193 		}
194 
195 		if (!is_empty && mkdir(ctx->directory, 0700) < 0)
196 			exit_horribly(modulename, "could not create directory \"%s\": %s\n",
197 						  ctx->directory, strerror(errno));
198 	}
199 	else
200 	{							/* Read Mode */
201 		char		fname[MAXPGPATH];
202 		cfp		   *tocFH;
203 
204 		setFilePath(AH, fname, "toc.dat");
205 
206 		tocFH = cfopen_read(fname, PG_BINARY_R);
207 		if (tocFH == NULL)
208 			exit_horribly(modulename,
209 						  "could not open input file \"%s\": %s\n",
210 						  fname, strerror(errno));
211 
212 		ctx->dataFH = tocFH;
213 
214 		/*
215 		 * The TOC of a directory format dump shares the format code of the
216 		 * tar format.
217 		 */
218 		AH->format = archTar;
219 		ReadHead(AH);
220 		AH->format = archDirectory;
221 		ReadToc(AH);
222 
223 		/* Nothing else in the file, so close it again... */
224 		if (cfclose(tocFH) != 0)
225 			exit_horribly(modulename, "could not close TOC file: %s\n",
226 						  strerror(errno));
227 		ctx->dataFH = NULL;
228 	}
229 }
230 
231 /*
232  * Called by the Archiver when the dumper creates a new TOC entry.
233  *
234  * We determine the filename for this entry.
235 */
236 static void
_ArchiveEntry(ArchiveHandle * AH,TocEntry * te)237 _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
238 {
239 	lclTocEntry *tctx;
240 	char		fn[MAXPGPATH];
241 
242 	tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
243 	if (te->dataDumper)
244 	{
245 		snprintf(fn, MAXPGPATH, "%d.dat", te->dumpId);
246 		tctx->filename = pg_strdup(fn);
247 	}
248 	else if (strcmp(te->desc, "BLOBS") == 0)
249 		tctx->filename = pg_strdup("blobs.toc");
250 	else
251 		tctx->filename = NULL;
252 
253 	te->formatData = (void *) tctx;
254 }
255 
256 /*
257  * Called by the Archiver to save any extra format-related TOC entry
258  * data.
259  *
260  * Use the Archiver routines to write data - they are non-endian, and
261  * maintain other important file information.
262  */
263 static void
_WriteExtraToc(ArchiveHandle * AH,TocEntry * te)264 _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
265 {
266 	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
267 
268 	/*
269 	 * A dumpable object has set tctx->filename, any other object has not.
270 	 * (see _ArchiveEntry).
271 	 */
272 	if (tctx->filename)
273 		WriteStr(AH, tctx->filename);
274 	else
275 		WriteStr(AH, "");
276 }
277 
278 /*
279  * Called by the Archiver to read any extra format-related TOC data.
280  *
281  * Needs to match the order defined in _WriteExtraToc, and should also
282  * use the Archiver input routines.
283  */
284 static void
_ReadExtraToc(ArchiveHandle * AH,TocEntry * te)285 _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
286 {
287 	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
288 
289 	if (tctx == NULL)
290 	{
291 		tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
292 		te->formatData = (void *) tctx;
293 	}
294 
295 	tctx->filename = ReadStr(AH);
296 	if (strlen(tctx->filename) == 0)
297 	{
298 		free(tctx->filename);
299 		tctx->filename = NULL;
300 	}
301 }
302 
303 /*
304  * Called by the Archiver when restoring an archive to output a comment
305  * that includes useful information about the TOC entry.
306  */
307 static void
_PrintExtraToc(ArchiveHandle * AH,TocEntry * te)308 _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
309 {
310 	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
311 
312 	if (AH->public.verbose && tctx->filename)
313 		ahprintf(AH, "-- File: %s\n", tctx->filename);
314 }
315 
316 /*
317  * Called by the archiver when saving TABLE DATA (not schema). This routine
318  * should save whatever format-specific information is needed to read
319  * the archive back.
320  *
321  * It is called just prior to the dumper's 'DataDumper' routine being called.
322  *
323  * We create the data file for writing.
324  */
325 static void
_StartData(ArchiveHandle * AH,TocEntry * te)326 _StartData(ArchiveHandle *AH, TocEntry *te)
327 {
328 	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
329 	lclContext *ctx = (lclContext *) AH->formatData;
330 	char		fname[MAXPGPATH];
331 
332 	setFilePath(AH, fname, tctx->filename);
333 
334 	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
335 	if (ctx->dataFH == NULL)
336 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
337 					  fname, strerror(errno));
338 }
339 
340 /*
341  * Called by archiver when dumper calls WriteData. This routine is
342  * called for both BLOB and TABLE data; it is the responsibility of
343  * the format to manage each kind of data using StartBlob/StartData.
344  *
345  * It should only be called from within a DataDumper routine.
346  *
347  * We write the data to the open data file.
348  */
349 static void
_WriteData(ArchiveHandle * AH,const void * data,size_t dLen)350 _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
351 {
352 	lclContext *ctx = (lclContext *) AH->formatData;
353 
354 	errno = 0;
355 	if (dLen > 0 && cfwrite(data, dLen, ctx->dataFH) != dLen)
356 	{
357 		/* if write didn't set errno, assume problem is no disk space */
358 		if (errno == 0)
359 			errno = ENOSPC;
360 		exit_horribly(modulename, "could not write to output file: %s\n",
361 					  get_cfp_error(ctx->dataFH));
362 	}
363 
364 	return;
365 }
366 
367 /*
368  * Called by the archiver when a dumper's 'DataDumper' routine has
369  * finished.
370  *
371  * We close the data file.
372  */
373 static void
_EndData(ArchiveHandle * AH,TocEntry * te)374 _EndData(ArchiveHandle *AH, TocEntry *te)
375 {
376 	lclContext *ctx = (lclContext *) AH->formatData;
377 
378 	/* Close the file */
379 	cfclose(ctx->dataFH);
380 
381 	ctx->dataFH = NULL;
382 }
383 
384 /*
385  * Print data for a given file (can be a BLOB as well)
386  */
387 static void
_PrintFileData(ArchiveHandle * AH,char * filename)388 _PrintFileData(ArchiveHandle *AH, char *filename)
389 {
390 	size_t		cnt;
391 	char	   *buf;
392 	size_t		buflen;
393 	cfp		   *cfp;
394 
395 	if (!filename)
396 		return;
397 
398 	cfp = cfopen_read(filename, PG_BINARY_R);
399 
400 	if (!cfp)
401 		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
402 					  filename, strerror(errno));
403 
404 	buf = pg_malloc(ZLIB_OUT_SIZE);
405 	buflen = ZLIB_OUT_SIZE;
406 
407 	while ((cnt = cfread(buf, buflen, cfp)))
408 	{
409 		ahwrite(buf, 1, cnt, AH);
410 	}
411 
412 	free(buf);
413 	if (cfclose(cfp) !=0)
414 		exit_horribly(modulename, "could not close data file \"%s\": %s\n",
415 					  filename, strerror(errno));
416 }
417 
418 /*
419  * Print data for a given TOC entry
420 */
421 static void
_PrintTocData(ArchiveHandle * AH,TocEntry * te)422 _PrintTocData(ArchiveHandle *AH, TocEntry *te)
423 {
424 	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
425 
426 	if (!tctx->filename)
427 		return;
428 
429 	if (strcmp(te->desc, "BLOBS") == 0)
430 		_LoadBlobs(AH);
431 	else
432 	{
433 		char		fname[MAXPGPATH];
434 
435 		setFilePath(AH, fname, tctx->filename);
436 		_PrintFileData(AH, fname);
437 	}
438 }
439 
440 static void
_LoadBlobs(ArchiveHandle * AH)441 _LoadBlobs(ArchiveHandle *AH)
442 {
443 	Oid			oid;
444 	lclContext *ctx = (lclContext *) AH->formatData;
445 	char		tocfname[MAXPGPATH];
446 	char		line[MAXPGPATH];
447 
448 	StartRestoreBlobs(AH);
449 
450 	setFilePath(AH, tocfname, "blobs.toc");
451 
452 	ctx->blobsTocFH = cfopen_read(tocfname, PG_BINARY_R);
453 
454 	if (ctx->blobsTocFH == NULL)
455 		exit_horribly(modulename, "could not open large object TOC file \"%s\" for input: %s\n",
456 					  tocfname, strerror(errno));
457 
458 	/* Read the blobs TOC file line-by-line, and process each blob */
459 	while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL)
460 	{
461 		char		blobfname[MAXPGPATH + 1];
462 		char		path[MAXPGPATH];
463 
464 		/* Can't overflow because line and blobfname are the same length. */
465 		if (sscanf(line, "%u %" CppAsString2(MAXPGPATH) "s\n", &oid, blobfname) != 2)
466 			exit_horribly(modulename, "invalid line in large object TOC file \"%s\": \"%s\"\n",
467 						  tocfname, line);
468 
469 		StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema);
470 		snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, blobfname);
471 		_PrintFileData(AH, path);
472 		EndRestoreBlob(AH, oid);
473 	}
474 	if (!cfeof(ctx->blobsTocFH))
475 		exit_horribly(modulename, "error reading large object TOC file \"%s\"\n",
476 					  tocfname);
477 
478 	if (cfclose(ctx->blobsTocFH) != 0)
479 		exit_horribly(modulename, "could not close large object TOC file \"%s\": %s\n",
480 					  tocfname, strerror(errno));
481 
482 	ctx->blobsTocFH = NULL;
483 
484 	EndRestoreBlobs(AH);
485 }
486 
487 
488 /*
489  * Write a byte of data to the archive.
490  * Called by the archiver to do integer & byte output to the archive.
491  * These routines are only used to read & write the headers & TOC.
492  */
493 static int
_WriteByte(ArchiveHandle * AH,const int i)494 _WriteByte(ArchiveHandle *AH, const int i)
495 {
496 	unsigned char c = (unsigned char) i;
497 	lclContext *ctx = (lclContext *) AH->formatData;
498 
499 	errno = 0;
500 	if (cfwrite(&c, 1, ctx->dataFH) != 1)
501 	{
502 		/* if write didn't set errno, assume problem is no disk space */
503 		if (errno == 0)
504 			errno = ENOSPC;
505 		exit_horribly(modulename, "could not write to output file: %s\n",
506 					  get_cfp_error(ctx->dataFH));
507 	}
508 
509 	return 1;
510 }
511 
512 /*
513  * Read a byte of data from the archive.
514  * Called by the archiver to read bytes & integers from the archive.
515  * These routines are only used to read & write headers & TOC.
516  * EOF should be treated as a fatal error.
517  */
518 static int
_ReadByte(ArchiveHandle * AH)519 _ReadByte(ArchiveHandle *AH)
520 {
521 	lclContext *ctx = (lclContext *) AH->formatData;
522 
523 	return cfgetc(ctx->dataFH);
524 }
525 
526 /*
527  * Write a buffer of data to the archive.
528  * Called by the archiver to write a block of bytes to the TOC or a data file.
529  */
530 static void
_WriteBuf(ArchiveHandle * AH,const void * buf,size_t len)531 _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
532 {
533 	lclContext *ctx = (lclContext *) AH->formatData;
534 
535 	errno = 0;
536 	if (cfwrite(buf, len, ctx->dataFH) != len)
537 	{
538 		/* if write didn't set errno, assume problem is no disk space */
539 		if (errno == 0)
540 			errno = ENOSPC;
541 		exit_horribly(modulename, "could not write to output file: %s\n",
542 					  get_cfp_error(ctx->dataFH));
543 	}
544 
545 	return;
546 }
547 
548 /*
549  * Read a block of bytes from the archive.
550  *
551  * Called by the archiver to read a block of bytes from the archive
552  */
553 static void
_ReadBuf(ArchiveHandle * AH,void * buf,size_t len)554 _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
555 {
556 	lclContext *ctx = (lclContext *) AH->formatData;
557 
558 	/*
559 	 * If there was an I/O error, we already exited in cfread(), so here we
560 	 * exit on short reads.
561 	 */
562 	if (cfread(buf, len, ctx->dataFH) != len)
563 		exit_horribly(modulename,
564 					  "could not read from input file: end of file\n");
565 
566 	return;
567 }
568 
569 /*
570  * Close the archive.
571  *
572  * When writing the archive, this is the routine that actually starts
573  * the process of saving it to files. No data should be written prior
574  * to this point, since the user could sort the TOC after creating it.
575  *
576  * If an archive is to be written, this routine must call:
577  *		WriteHead			to save the archive header
578  *		WriteToc			to save the TOC entries
579  *		WriteDataChunks		to save all DATA & BLOBs.
580  */
581 static void
_CloseArchive(ArchiveHandle * AH)582 _CloseArchive(ArchiveHandle *AH)
583 {
584 	lclContext *ctx = (lclContext *) AH->formatData;
585 
586 	if (AH->mode == archModeWrite)
587 	{
588 		cfp		   *tocFH;
589 		char		fname[MAXPGPATH];
590 
591 		setFilePath(AH, fname, "toc.dat");
592 
593 		/* this will actually fork the processes for a parallel backup */
594 		ctx->pstate = ParallelBackupStart(AH);
595 
596 		/* The TOC is always created uncompressed */
597 		tocFH = cfopen_write(fname, PG_BINARY_W, 0);
598 		if (tocFH == NULL)
599 			exit_horribly(modulename, "could not open output file \"%s\": %s\n",
600 						  fname, strerror(errno));
601 		ctx->dataFH = tocFH;
602 
603 		/*
604 		 * Write 'tar' in the format field of the toc.dat file. The directory
605 		 * is compatible with 'tar', so there's no point having a different
606 		 * format code for it.
607 		 */
608 		AH->format = archTar;
609 		WriteHead(AH);
610 		AH->format = archDirectory;
611 		WriteToc(AH);
612 		if (cfclose(tocFH) != 0)
613 			exit_horribly(modulename, "could not close TOC file: %s\n",
614 						  strerror(errno));
615 		WriteDataChunks(AH, ctx->pstate);
616 
617 		ParallelBackupEnd(AH, ctx->pstate);
618 
619 		/*
620 		 * In directory mode, there is no need to sync all the entries
621 		 * individually. Just recurse once through all the files generated.
622 		 */
623 		if (AH->dosync)
624 			fsync_dir_recurse(ctx->directory, progname);
625 	}
626 	AH->FH = NULL;
627 }
628 
629 /*
630  * Reopen the archive's file handle.
631  */
632 static void
_ReopenArchive(ArchiveHandle * AH)633 _ReopenArchive(ArchiveHandle *AH)
634 {
635 	/*
636 	 * Our TOC is in memory, our data files are opened by each child anyway as
637 	 * they are separate. We support reopening the archive by just doing
638 	 * nothing.
639 	 */
640 }
641 
642 /*
643  * BLOB support
644  */
645 
646 /*
647  * Called by the archiver when starting to save all BLOB DATA (not schema).
648  * It is called just prior to the dumper's DataDumper routine.
649  *
650  * We open the large object TOC file here, so that we can append a line to
651  * it for each blob.
652  */
653 static void
_StartBlobs(ArchiveHandle * AH,TocEntry * te)654 _StartBlobs(ArchiveHandle *AH, TocEntry *te)
655 {
656 	lclContext *ctx = (lclContext *) AH->formatData;
657 	char		fname[MAXPGPATH];
658 
659 	setFilePath(AH, fname, "blobs.toc");
660 
661 	/* The blob TOC file is never compressed */
662 	ctx->blobsTocFH = cfopen_write(fname, "ab", 0);
663 	if (ctx->blobsTocFH == NULL)
664 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
665 					  fname, strerror(errno));
666 }
667 
668 /*
669  * Called by the archiver when we're about to start dumping a blob.
670  *
671  * We create a file to write the blob to.
672  */
673 static void
_StartBlob(ArchiveHandle * AH,TocEntry * te,Oid oid)674 _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
675 {
676 	lclContext *ctx = (lclContext *) AH->formatData;
677 	char		fname[MAXPGPATH];
678 
679 	snprintf(fname, MAXPGPATH, "%s/blob_%u.dat", ctx->directory, oid);
680 
681 	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
682 
683 	if (ctx->dataFH == NULL)
684 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
685 					  fname, strerror(errno));
686 }
687 
688 /*
689  * Called by the archiver when the dumper is finished writing a blob.
690  *
691  * We close the blob file and write an entry to the blob TOC file for it.
692  */
693 static void
_EndBlob(ArchiveHandle * AH,TocEntry * te,Oid oid)694 _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
695 {
696 	lclContext *ctx = (lclContext *) AH->formatData;
697 	char		buf[50];
698 	int			len;
699 
700 	/* Close the BLOB data file itself */
701 	cfclose(ctx->dataFH);
702 	ctx->dataFH = NULL;
703 
704 	/* register the blob in blobs.toc */
705 	len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid);
706 	if (cfwrite(buf, len, ctx->blobsTocFH) != len)
707 		exit_horribly(modulename, "could not write to blobs TOC file\n");
708 }
709 
710 /*
711  * Called by the archiver when finishing saving all BLOB DATA.
712  *
713  * We close the blobs TOC file.
714  */
715 static void
_EndBlobs(ArchiveHandle * AH,TocEntry * te)716 _EndBlobs(ArchiveHandle *AH, TocEntry *te)
717 {
718 	lclContext *ctx = (lclContext *) AH->formatData;
719 
720 	cfclose(ctx->blobsTocFH);
721 	ctx->blobsTocFH = NULL;
722 }
723 
724 /*
725  * Gets a relative file name and prepends the output directory, writing the
726  * result to buf. The caller needs to make sure that buf is MAXPGPATH bytes
727  * big. Can't use a static char[MAXPGPATH] inside the function because we run
728  * multithreaded on Windows.
729  */
730 static void
setFilePath(ArchiveHandle * AH,char * buf,const char * relativeFilename)731 setFilePath(ArchiveHandle *AH, char *buf, const char *relativeFilename)
732 {
733 	lclContext *ctx = (lclContext *) AH->formatData;
734 	char	   *dname;
735 
736 	dname = ctx->directory;
737 
738 	if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
739 		exit_horribly(modulename, "file name too long: \"%s\"\n", dname);
740 
741 	strcpy(buf, dname);
742 	strcat(buf, "/");
743 	strcat(buf, relativeFilename);
744 }
745 
746 /*
747  * Clone format-specific fields during parallel restoration.
748  */
749 static void
_Clone(ArchiveHandle * AH)750 _Clone(ArchiveHandle *AH)
751 {
752 	lclContext *ctx = (lclContext *) AH->formatData;
753 
754 	AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
755 	memcpy(AH->formatData, ctx, sizeof(lclContext));
756 	ctx = (lclContext *) AH->formatData;
757 
758 	/*
759 	 * Note: we do not make a local lo_buf because we expect at most one BLOBS
760 	 * entry per archive, so no parallelism is possible.  Likewise,
761 	 * TOC-entry-local state isn't an issue because any one TOC entry is
762 	 * touched by just one worker child.
763 	 */
764 
765 	/*
766 	 * We also don't copy the ParallelState pointer (pstate), only the master
767 	 * process ever writes to it.
768 	 */
769 }
770 
771 static void
_DeClone(ArchiveHandle * AH)772 _DeClone(ArchiveHandle *AH)
773 {
774 	lclContext *ctx = (lclContext *) AH->formatData;
775 
776 	free(ctx);
777 }
778 
779 /*
780  * This function is executed in the child of a parallel backup for a
781  * directory-format archive and dumps the actual data for one TOC entry.
782  */
783 static int
_WorkerJobDumpDirectory(ArchiveHandle * AH,TocEntry * te)784 _WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te)
785 {
786 	/*
787 	 * This function returns void. We either fail and die horribly or
788 	 * succeed... A failure will be detected by the parent when the child dies
789 	 * unexpectedly.
790 	 */
791 	WriteDataChunksForTocEntry(AH, te);
792 
793 	return 0;
794 }
795 
796 /*
797  * This function is executed in the child of a parallel restore from a
798  * directory-format archive and restores the actual data for one TOC entry.
799  */
800 static int
_WorkerJobRestoreDirectory(ArchiveHandle * AH,TocEntry * te)801 _WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te)
802 {
803 	return parallel_restore(AH, te);
804 }
805