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:
parent
e06db21e35
commit
7168e07440
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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))
|
||||||
|
@ -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))
|
||||||
|
@ -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.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
|
@ -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"));
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user