1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-30 05:39:12 +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 <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "command/archive/common.h" #include "command/archive/common.h"
#include "common/debug.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 * String *
walPath(const String *walFile, const String *pgPath, const String *command) walPath(const String *walFile)
{ {
FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, walFile); FUNCTION_LOG_PARAM(STRING, walFile);
FUNCTION_LOG_PARAM(STRING, pgPath);
FUNCTION_LOG_PARAM(STRING, command);
FUNCTION_LOG_END(); FUNCTION_LOG_END();
ASSERT(walFile != NULL); ASSERT(walFile != NULL);
ASSERT(command != NULL);
String *result = NULL; String *result = NULL;
if (!strBeginsWithZ(walFile, "/")) if (!strBeginsWithZ(walFile, "/"))
{ {
if (pgPath == NULL) char currentWorkDir[4096];
{
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));
}
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 else
result = strDup(walFile); result = strDup(walFile);

View File

@ -64,7 +64,7 @@ void archiveAsyncStatusErrorWrite(ArchiveMode archiveMode, const String *walSegm
bool walIsPartial(const String *walSegment); bool walIsPartial(const String *walSegment);
bool walIsSegment(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 *walSegmentFind(const Storage *storage, const String *archiveId, const String *walSegment, TimeMSec timeout);
String *walSegmentNext(const String *walSegment, size_t walSegmentSize, unsigned int pgVersion); 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); 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)); String *walSegment = strBase(strLstGet(commandParam, 0));
// Destination is wherever we were told to move the WAL segment // Destination is wherever we were told to move the WAL segment
const String *walDestination = const String *walDestination = walPath(strLstGet(commandParam, 1));
walPath(strLstGet(commandParam, 1), cfgOptionStr(cfgOptPgPath), STR(cfgCommandName(cfgCommand())));
// Async get can only be performed on WAL segments, history or other files must use synchronous mode // Async get can only be performed on WAL segments, history or other files must use synchronous mode
if (cfgOptionBool(cfgOptArchiveAsync) && walIsSegment(walSegment)) if (cfgOptionBool(cfgOptArchiveAsync) && walIsSegment(walSegment))

View File

@ -268,7 +268,7 @@ cmdArchivePush(void)
lockStopTest(); lockStopTest();
// Get the segment name // 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); String *archiveFile = strBase(walFile);
if (cfgOptionBool(cfgOptArchiveAsync)) if (cfgOptionBool(cfgOptArchiveAsync))

View File

@ -172,15 +172,10 @@ testRun(void)
// ***************************************************************************************************************************** // *****************************************************************************************************************************
if (testBegin("walPath()")) if (testBegin("walPath()"))
{ {
TEST_RESULT_STR( THROW_ON_SYS_ERROR(chdir("/tmp") != 0, PathMissingError, "unable to chdir()");
strPtr(walPath(strNew("/absolute/path"), strNew("/pg"), strNew("test"))), "/absolute/path", "absolute path");
TEST_RESULT_STR( TEST_RESULT_STR(strPtr(walPath(strNew("/absolute/path"))), "/absolute/path", "absolute path");
strPtr(walPath(strNew("relative/path"), strNew("/pg"), strNew("test"))), "/pg/relative/path", "relative path"); TEST_RESULT_STR(strPtr(walPath(strNew("relative/path"))), "/tmp/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.");
} }
// ***************************************************************************************************************************** // *****************************************************************************************************************************

View File

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

View File

@ -181,23 +181,12 @@ testRun(void)
TEST_ERROR(cmdArchivePush(), ParamRequiredError, "WAL segment to push required"); 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 // Create pg_control and archive.info
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath())); strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath()));
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath())); strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
argListTemp = strLstDup(argList); StringList *argListTemp = strLstDup(argList);
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001"); strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
harnessCfgLoad(cfgCmdArchivePush, argListTemp); harnessCfgLoad(cfgCmdArchivePush, argListTemp);
@ -223,6 +212,8 @@ testRun(void)
storagePutNP(storageNewWriteNP(storagePgWrite(), strNew("pg_wal/000000010000000100000001")), walBuffer1); storagePutNP(storageNewWriteNP(storagePgWrite(), strNew("pg_wal/000000010000000100000001")), walBuffer1);
THROW_ON_SYS_ERROR(chdir(strPtr(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
TEST_ERROR( TEST_ERROR(
cmdArchivePush(), ArchiveMismatchError, cmdArchivePush(), ArchiveMismatchError,
strPtr( strPtr(
@ -424,6 +415,8 @@ testRun(void)
strLstAddZ(argList, "pg_wal/bogus"); strLstAddZ(argList, "pg_wal/bogus");
harnessCfgLoadRaw(strLstSize(argList), strLstPtr(argList)); harnessCfgLoadRaw(strLstSize(argList), strLstPtr(argList));
THROW_ON_SYS_ERROR(chdir(testPath()) != 0, PathMissingError, "unable to chdir()");
TEST_ERROR( TEST_ERROR(
cmdArchivePush(), ArchiveTimeoutError, cmdArchivePush(), ArchiveTimeoutError,
"unable to push WAL file 'bogus' to the archive asynchronously after 1 second(s)"); "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"); strLstAddZ(argListTemp, "--archive-timeout=1");
harnessCfgLoad(cfgCmdArchivePush, argListTemp); harnessCfgLoad(cfgCmdArchivePush, argListTemp);
THROW_ON_SYS_ERROR(chdir(strPtr(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
HARNESS_FORK_BEGIN() HARNESS_FORK_BEGIN()
{ {
HARNESS_FORK_CHILD_BEGIN(0, true) HARNESS_FORK_CHILD_BEGIN(0, true)