1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Add strPathAbsolute() and strLstRemoveIdx().

strPathAbsolute() generates an absolute path from an absolute base path and an absolute/relative path.

strLstRemoveIdx() is a support function based on lstRemoveIdx().
This commit is contained in:
David Steele 2019-09-19 22:42:28 -04:00
parent 9421493d09
commit 174cb7b3af
6 changed files with 110 additions and 2 deletions

View File

@ -429,7 +429,7 @@ common/type/list.o: common/type/list.c build.auto.h common/assert.h common/debug
common/type/mcv.o: common/type/mcv.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/mcv.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/type/mcv.c -o common/type/mcv.o
common/type/string.o: common/type/string.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/macro.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h
common/type/string.o: common/type/string.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/macro.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/type/string.c -o common/type/string.o
common/type/stringList.o: common/type/stringList.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h

View File

@ -13,6 +13,7 @@ String Handler
#include "common/macro.h"
#include "common/memContext.h"
#include "common/type/string.h"
#include "common/type/stringList.h"
/***********************************************************************************************************************************
Constant strings that are generally useful
@ -21,6 +22,7 @@ STRING_EXTERN(BRACKETL_STR, "[");
STRING_EXTERN(BRACKETR_STR, "]");
STRING_EXTERN(CR_STR, "\r");
STRING_EXTERN(DOT_STR, ".");
STRING_EXTERN(DOTDOT_STR, "..");
STRING_EXTERN(EMPTY_STR, "");
STRING_EXTERN(EQ_STR, "=");
STRING_EXTERN(FALSE_STR, "false");
@ -594,6 +596,85 @@ strPath(const String *this)
end - this->buffer <= 1 ? (size_t)(end - this->buffer) : (size_t)(end - this->buffer - 1)));
}
/***********************************************************************************************************************************
Combine with a base path to get an absolute path
***********************************************************************************************************************************/
String *
strPathAbsolute(const String *this, const String *base)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, this);
FUNCTION_TEST_PARAM(STRING, base);
FUNCTION_TEST_END();
ASSERT(this != NULL);
String *result = NULL;
// Path is already absolute so just return it
if (strBeginsWith(this, FSLASH_STR))
{
result = strDup(this);
}
// Else we'll need to construct the absolute path. You would hope we could use realpath() here but it is so broken in the
// Posix spec that is seems best avoided.
else
{
ASSERT(base != NULL);
// Base must be absolute to start
if (!strBeginsWith(base, FSLASH_STR))
THROW_FMT(AssertError, "base path '%s' is not absolute", strPtr(base));
MEM_CONTEXT_TEMP_BEGIN()
{
StringList *baseList = strLstNewSplit(base, FSLASH_STR);
StringList *pathList = strLstNewSplit(this, FSLASH_STR);
while (strLstSize(pathList) > 0)
{
const String *pathPart = strLstGet(pathList, 0);
if (strSize(pathPart) == 0)
THROW_FMT(AssertError, "'%s' is not a valid relative path", strPtr(this));
if (strEq(pathPart, DOTDOT_STR))
{
const String *basePart = strLstGet(baseList, strLstSize(baseList) - 1);
if (strSize(basePart) == 0)
{
THROW_FMT(
AssertError, "relative path '%s' goes back too far in base path '%s'", strPtr(this), strPtr(base));
}
strLstRemoveIdx(baseList, strLstSize(baseList) - 1);
}
else
strLstAdd(baseList, pathPart);
strLstRemoveIdx(pathList, 0);
}
memContextSwitch(MEM_CONTEXT_OLD());
if (strLstSize(baseList) == 1)
result = strDup(FSLASH_STR);
else
result = strLstJoin(baseList, "/");
memContextSwitch(MEM_CONTEXT_TEMP());
}
MEM_CONTEXT_TEMP_END();
}
// There should not be any stray .. or // in the final result
if (strstr(strPtr(result), "/..") != NULL || strstr(strPtr(result), "//") != NULL)
THROW_FMT(AssertError, "result path '%s' is not absolute", strPtr(result));
FUNCTION_TEST_RETURN(result);
}
/***********************************************************************************************************************************
Return string ptr
***********************************************************************************************************************************/

View File

@ -54,6 +54,7 @@ String *strFirstLower(String *this);
String *strUpper(String *this);
String *strLower(String *this);
String *strPath(const String *this);
String *strPathAbsolute(const String *this, const String *base);
const char *strPtr(const String *this);
String *strQuote(const String *this, const String *quote);
String *strQuoteZ(const String *this, const char *quote);
@ -121,6 +122,7 @@ STRING_DECLARE(BRACKETL_STR);
STRING_DECLARE(BRACKETR_STR);
STRING_DECLARE(CR_STR);
STRING_DECLARE(DOT_STR);
STRING_DECLARE(DOTDOT_STR);
STRING_DECLARE(EMPTY_STR);
STRING_DECLARE(EQ_STR);
STRING_DECLARE(FALSE_STR);

View File

@ -628,6 +628,19 @@ strLstRemove(StringList *this, const String *item)
FUNCTION_TEST_RETURN(lstRemove((List *)this, &item));
}
StringList *
strLstRemoveIdx(StringList *this, unsigned int listIdx)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING_LIST, this);
FUNCTION_TEST_PARAM(UINT, listIdx);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN((StringList *)lstRemoveIdx((List *)this, listIdx));
}
/***********************************************************************************************************************************
Wrapper for lstSize()
***********************************************************************************************************************************/

View File

@ -43,6 +43,7 @@ StringList *strLstMergeAnti(const StringList *this, const StringList *anti);
StringList *strLstMove(StringList *this, MemContext *parentNew);
const char **strLstPtr(const StringList *this);
bool strLstRemove(StringList *this, const String *item);
StringList *strLstRemoveIdx(StringList *this, unsigned int listIdx);
unsigned int strLstSize(const StringList *this);
StringList *strLstSort(StringList *this, SortOrder sortOrder);

View File

@ -61,7 +61,7 @@ testRun(void)
}
// *****************************************************************************************************************************
if (testBegin("strBase() and strPath()"))
if (testBegin("strBase(), strPath(), and strPathAbsolute()"))
{
TEST_RESULT_STR(strPtr(strBase(STRDEF(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only");
@ -72,6 +72,17 @@ testRun(void)
TEST_RESULT_STR(strPtr(strPath(STRDEF("/"))), "/", "/ only");
TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
TEST_ERROR(strPathAbsolute(STRDEF("/.."), NULL), AssertError, "result path '/..' is not absolute");
TEST_ERROR(strPathAbsolute(STRDEF("//"), NULL), AssertError, "result path '//' is not absolute");
TEST_ERROR(strPathAbsolute(STRDEF(".."), STRDEF("path1")), AssertError, "base path 'path1' is not absolute");
TEST_ERROR(
strPathAbsolute(STRDEF(".."), STRDEF("/")), AssertError, "relative path '..' goes back too far in base path '/'");
TEST_ERROR(strPathAbsolute(STRDEF("path1/"), STRDEF("/")), AssertError, "'path1/' is not a valid relative path");
TEST_RESULT_STR_Z(strPathAbsolute(STRDEF("/"), NULL), "/", "path is already absolute");
TEST_RESULT_STR_Z(strPathAbsolute(STRDEF(".."), STRDEF("/path1")), "/", "simple relative path");
TEST_RESULT_STR_Z(
strPathAbsolute(STRDEF("../path2/../path3"), STRDEF("/base1/base2")), "/base1/path3", "complex relative path");
}
// *****************************************************************************************************************************