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:
parent
9421493d09
commit
174cb7b3af
@ -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
|
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
|
$(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
|
$(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
|
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
|
||||||
|
@ -13,6 +13,7 @@ String Handler
|
|||||||
#include "common/macro.h"
|
#include "common/macro.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
#include "common/type/string.h"
|
#include "common/type/string.h"
|
||||||
|
#include "common/type/stringList.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Constant strings that are generally useful
|
Constant strings that are generally useful
|
||||||
@ -21,6 +22,7 @@ STRING_EXTERN(BRACKETL_STR, "[");
|
|||||||
STRING_EXTERN(BRACKETR_STR, "]");
|
STRING_EXTERN(BRACKETR_STR, "]");
|
||||||
STRING_EXTERN(CR_STR, "\r");
|
STRING_EXTERN(CR_STR, "\r");
|
||||||
STRING_EXTERN(DOT_STR, ".");
|
STRING_EXTERN(DOT_STR, ".");
|
||||||
|
STRING_EXTERN(DOTDOT_STR, "..");
|
||||||
STRING_EXTERN(EMPTY_STR, "");
|
STRING_EXTERN(EMPTY_STR, "");
|
||||||
STRING_EXTERN(EQ_STR, "=");
|
STRING_EXTERN(EQ_STR, "=");
|
||||||
STRING_EXTERN(FALSE_STR, "false");
|
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)));
|
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
|
Return string ptr
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -54,6 +54,7 @@ String *strFirstLower(String *this);
|
|||||||
String *strUpper(String *this);
|
String *strUpper(String *this);
|
||||||
String *strLower(String *this);
|
String *strLower(String *this);
|
||||||
String *strPath(const String *this);
|
String *strPath(const String *this);
|
||||||
|
String *strPathAbsolute(const String *this, const String *base);
|
||||||
const char *strPtr(const String *this);
|
const char *strPtr(const String *this);
|
||||||
String *strQuote(const String *this, const String *quote);
|
String *strQuote(const String *this, const String *quote);
|
||||||
String *strQuoteZ(const String *this, const char *quote);
|
String *strQuoteZ(const String *this, const char *quote);
|
||||||
@ -121,6 +122,7 @@ STRING_DECLARE(BRACKETL_STR);
|
|||||||
STRING_DECLARE(BRACKETR_STR);
|
STRING_DECLARE(BRACKETR_STR);
|
||||||
STRING_DECLARE(CR_STR);
|
STRING_DECLARE(CR_STR);
|
||||||
STRING_DECLARE(DOT_STR);
|
STRING_DECLARE(DOT_STR);
|
||||||
|
STRING_DECLARE(DOTDOT_STR);
|
||||||
STRING_DECLARE(EMPTY_STR);
|
STRING_DECLARE(EMPTY_STR);
|
||||||
STRING_DECLARE(EQ_STR);
|
STRING_DECLARE(EQ_STR);
|
||||||
STRING_DECLARE(FALSE_STR);
|
STRING_DECLARE(FALSE_STR);
|
||||||
|
@ -628,6 +628,19 @@ strLstRemove(StringList *this, const String *item)
|
|||||||
FUNCTION_TEST_RETURN(lstRemove((List *)this, &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()
|
Wrapper for lstSize()
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -43,6 +43,7 @@ StringList *strLstMergeAnti(const StringList *this, const StringList *anti);
|
|||||||
StringList *strLstMove(StringList *this, MemContext *parentNew);
|
StringList *strLstMove(StringList *this, MemContext *parentNew);
|
||||||
const char **strLstPtr(const StringList *this);
|
const char **strLstPtr(const StringList *this);
|
||||||
bool strLstRemove(StringList *this, const String *item);
|
bool strLstRemove(StringList *this, const String *item);
|
||||||
|
StringList *strLstRemoveIdx(StringList *this, unsigned int listIdx);
|
||||||
unsigned int strLstSize(const StringList *this);
|
unsigned int strLstSize(const StringList *this);
|
||||||
StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
||||||
|
|
||||||
|
@ -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(""))), "", "empty string");
|
||||||
TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only");
|
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("/"))), "/", "/ only");
|
||||||
TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
|
TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
|
||||||
TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user