1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Use getcwd() to construct path when WAL path is relative.

Using pg1-path, as we were doing previously, could lead to WAL being copied to/from unexpected places.  PostgreSQL sets the current working directory to PGDATA so we can use that to resolve relative paths.
This commit is contained in:
David Steele 2019-10-30 14:55:25 +01:00
parent e06db21e35
commit 7168e07440
7 changed files with 22 additions and 40 deletions

View File

@ -6,6 +6,7 @@ Archive Common
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "command/archive/common.h"
#include "common/debug.h"
@ -228,35 +229,25 @@ walIsPartial(const String *walSegment)
}
/***********************************************************************************************************************************
Generates the location of the wal directory using a relative wal path and the supplied pg path
Generates the location of the wal directory using either an absolute path or cwd() and a relative path
***********************************************************************************************************************************/
String *
walPath(const String *walFile, const String *pgPath, const String *command)
walPath(const String *walFile)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, walFile);
FUNCTION_LOG_PARAM(STRING, pgPath);
FUNCTION_LOG_PARAM(STRING, command);
FUNCTION_LOG_END();
ASSERT(walFile != NULL);
ASSERT(command != NULL);
String *result = NULL;
if (!strBeginsWithZ(walFile, "/"))
{
if (pgPath == NULL)
{
THROW_FMT(
OptionRequiredError,
"option '" CFGOPT_PG1_PATH "' must be specified when relative wal paths are used\n"
"HINT: is %%f passed to %s instead of %%p?\n"
"HINT: PostgreSQL may pass relative paths even with %%p depending on the environment.",
strPtr(command));
}
char currentWorkDir[4096];
result = strNewFmt("%s/%s", strPtr(pgPath), strPtr(walFile));
THROW_ON_SYS_ERROR(getcwd(currentWorkDir, sizeof(currentWorkDir)) == NULL, FormatError, "unable to get cwd");
result = strNewFmt("%s/%s", currentWorkDir, strPtr(walFile));
}
else
result = strDup(walFile);

View File

@ -64,7 +64,7 @@ void archiveAsyncStatusErrorWrite(ArchiveMode archiveMode, const String *walSegm
bool walIsPartial(const String *walSegment);
bool walIsSegment(const String *walSegment);
String *walPath(const String *walFile, const String *pgPath, const String *command);
String *walPath(const String *walFile);
String *walSegmentFind(const Storage *storage, const String *archiveId, const String *walSegment, TimeMSec timeout);
String *walSegmentNext(const String *walSegment, size_t walSegmentSize, unsigned int pgVersion);
StringList *walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, unsigned int pgVersion, unsigned int range);

View File

@ -132,8 +132,7 @@ cmdArchiveGet(void)
String *walSegment = strBase(strLstGet(commandParam, 0));
// Destination is wherever we were told to move the WAL segment
const String *walDestination =
walPath(strLstGet(commandParam, 1), cfgOptionStr(cfgOptPgPath), STR(cfgCommandName(cfgCommand())));
const String *walDestination = walPath(strLstGet(commandParam, 1));
// Async get can only be performed on WAL segments, history or other files must use synchronous mode
if (cfgOptionBool(cfgOptArchiveAsync) && walIsSegment(walSegment))

View File

@ -268,7 +268,7 @@ cmdArchivePush(void)
lockStopTest();
// Get the segment name
String *walFile = walPath(strLstGet(commandParam, 0), cfgOptionStr(cfgOptPgPath), STR(cfgCommandName(cfgCommand())));
String *walFile = walPath(strLstGet(commandParam, 0));
String *archiveFile = strBase(walFile);
if (cfgOptionBool(cfgOptArchiveAsync))

View File

@ -172,15 +172,10 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("walPath()"))
{
TEST_RESULT_STR(
strPtr(walPath(strNew("/absolute/path"), strNew("/pg"), strNew("test"))), "/absolute/path", "absolute path");
TEST_RESULT_STR(
strPtr(walPath(strNew("relative/path"), strNew("/pg"), strNew("test"))), "/pg/relative/path", "relative path");
TEST_ERROR(
walPath(strNew("relative/path"), NULL, strNew("test")), OptionRequiredError,
"option 'pg1-path' must be specified when relative wal paths are used\n"
"HINT: is %f passed to test instead of %p?\n"
"HINT: PostgreSQL may pass relative paths even with %p depending on the environment.");
THROW_ON_SYS_ERROR(chdir("/tmp") != 0, PathMissingError, "unable to chdir()");
TEST_RESULT_STR(strPtr(walPath(strNew("/absolute/path"))), "/absolute/path", "absolute path");
TEST_RESULT_STR(strPtr(walPath(strNew("relative/path"))), "/tmp/relative/path", "relative path");
}
// *****************************************************************************************************************************

View File

@ -623,6 +623,8 @@ testRun(void)
// Write out a WAL segment for success
// -------------------------------------------------------------------------------------------------------------------------
THROW_ON_SYS_ERROR(chdir(strPtr(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment))),
BUFSTRDEF("SHOULD-BE-A-REAL-WAL-FILE"));

View File

@ -181,23 +181,12 @@ testRun(void)
TEST_ERROR(cmdArchivePush(), ParamRequiredError, "WAL segment to push required");
// -------------------------------------------------------------------------------------------------------------------------
StringList *argListTemp = strLstDup(argList);
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
harnessCfgLoad(cfgCmdArchivePush, argListTemp);
TEST_ERROR(
cmdArchivePush(), OptionRequiredError,
"option 'pg1-path' must be specified when relative wal paths are used"
"\nHINT: is %f passed to archive-push instead of %p?"
"\nHINT: PostgreSQL may pass relative paths even with %p depending on the environment.");
// Create pg_control and archive.info
// -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath()));
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
argListTemp = strLstDup(argList);
StringList *argListTemp = strLstDup(argList);
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
harnessCfgLoad(cfgCmdArchivePush, argListTemp);
@ -223,6 +212,8 @@ testRun(void)
storagePutNP(storageNewWriteNP(storagePgWrite(), strNew("pg_wal/000000010000000100000001")), walBuffer1);
THROW_ON_SYS_ERROR(chdir(strPtr(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
TEST_ERROR(
cmdArchivePush(), ArchiveMismatchError,
strPtr(
@ -424,6 +415,8 @@ testRun(void)
strLstAddZ(argList, "pg_wal/bogus");
harnessCfgLoadRaw(strLstSize(argList), strLstPtr(argList));
THROW_ON_SYS_ERROR(chdir(testPath()) != 0, PathMissingError, "unable to chdir()");
TEST_ERROR(
cmdArchivePush(), ArchiveTimeoutError,
"unable to push WAL file 'bogus' to the archive asynchronously after 1 second(s)");
@ -475,6 +468,8 @@ testRun(void)
strLstAddZ(argListTemp, "--archive-timeout=1");
harnessCfgLoad(cfgCmdArchivePush, argListTemp);
THROW_ON_SYS_ERROR(chdir(strPtr(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
HARNESS_FORK_BEGIN()
{
HARNESS_FORK_CHILD_BEGIN(0, true)