2018-04-11 14:21:09 +02:00
|
|
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
# Storage Exports
|
|
|
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-06-26 14:24:58 +02:00
|
|
|
MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC::Storage
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
pgBackRest::LibC::Storage
|
|
|
|
new(class, type, path)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
const String *class = STR_NEW_SV($arg);
|
|
|
|
const String *type = STR_NEW_SV($arg);
|
|
|
|
const String *path = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
|
|
|
CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::Storage"));
|
|
|
|
|
|
|
|
if (strEqZ(type, "<LOCAL>"))
|
|
|
|
{
|
|
|
|
memContextSwitch(MEM_CONTEXT_XS_OLD());
|
|
|
|
RETVAL = storagePosixNew(
|
|
|
|
path == NULL ? STRDEF("/") : path, STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
|
|
|
storagePathEnforceSet((Storage *)RETVAL, false);
|
|
|
|
memContextSwitch(MEM_CONTEXT_XS_TEMP());
|
|
|
|
}
|
|
|
|
else if (strEqZ(type, "<REPO>"))
|
|
|
|
{
|
|
|
|
CHECK(path == NULL);
|
|
|
|
RETVAL = (Storage *)storageRepoWrite();
|
|
|
|
}
|
|
|
|
else if (strEqZ(type, "<DB>"))
|
|
|
|
{
|
|
|
|
CHECK(path == NULL);
|
|
|
|
|
|
|
|
memContextSwitch(MEM_CONTEXT_XS_OLD());
|
|
|
|
RETVAL = storagePosixNew(cfgOptionStr(cfgOptPgPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
|
|
|
storagePathEnforceSet((Storage *)RETVAL, false);
|
|
|
|
memContextSwitch(MEM_CONTEXT_XS_TEMP());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
THROW_FMT(AssertError, "unexpected storage type '%s'", strPtr(type));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
2019-06-26 21:02:30 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
void
|
|
|
|
bucketCreate(self)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
CODE:
|
|
|
|
if (strEq(storageType(self), STORAGE_S3_TYPE_STR))
|
|
|
|
storageS3Request((StorageS3 *)storageDriver(self), HTTP_VERB_PUT_STR, FSLASH_STR, NULL, NULL, true, false);
|
|
|
|
else
|
|
|
|
THROW_FMT(AssertError, "unable to create bucket on '%s' storage", strPtr(storageType(self)));
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
2019-06-26 14:24:58 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
bool
|
|
|
|
copy(self, source, destination)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::StorageRead source
|
|
|
|
pgBackRest::LibC::StorageWrite destination
|
|
|
|
CODE:
|
2019-11-17 22:10:40 +02:00
|
|
|
RETVAL = storageCopyP(source, destination);
|
2019-06-26 14:24:58 +02:00
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
bool
|
|
|
|
exists(self, fileExp)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *fileExp = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
2019-11-17 22:10:40 +02:00
|
|
|
RETVAL = storageExistsP(self, fileExp);
|
2019-06-26 14:24:58 +02:00
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
SV *
|
|
|
|
get(self, read)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::StorageRead read
|
|
|
|
CODE:
|
|
|
|
RETVAL = NULL;
|
2019-11-17 22:10:40 +02:00
|
|
|
Buffer *buffer = storageGetP(read);
|
2019-06-26 14:24:58 +02:00
|
|
|
|
|
|
|
if (buffer != NULL)
|
|
|
|
{
|
|
|
|
if (bufUsed(buffer) == 0)
|
|
|
|
RETVAL = newSVpv("", 0);
|
|
|
|
else
|
|
|
|
RETVAL = newSVpv((char *)bufPtr(buffer), bufUsed(buffer));
|
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
SV *
|
|
|
|
info(self, pathExp, ignoreMissing)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
bool ignoreMissing
|
|
|
|
CODE:
|
|
|
|
RETVAL = NULL;
|
|
|
|
|
|
|
|
StorageInfo info = storageInfoP(self, pathExp, .ignoreMissing = ignoreMissing);
|
|
|
|
|
|
|
|
if (info.exists)
|
|
|
|
{
|
|
|
|
String *json = storageManifestXsInfo(NULL, &info);
|
|
|
|
RETVAL = newSVpv((char *)strPtr(json), strSize(json));
|
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
SV *
|
|
|
|
list(self, pathExp, ignoreMissing, sortAsc, expression)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
bool ignoreMissing
|
|
|
|
bool sortAsc
|
|
|
|
const String *expression = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
|
|
|
StringList *fileList = strLstSort(
|
|
|
|
storageListP(self, pathExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false,
|
|
|
|
.expression = expression), sortAsc ? sortOrderAsc : sortOrderDesc);
|
|
|
|
|
2019-10-11 19:03:52 +02:00
|
|
|
const String *fileListJson = jsonFromVar(varNewVarLst(varLstNewStrLst(fileList)));
|
2019-06-26 14:24:58 +02:00
|
|
|
|
|
|
|
RETVAL = newSVpv(strPtr(fileListJson), strSize(fileListJson));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
SV *
|
|
|
|
manifest(self, pathExp, filter=NULL)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
const String *filter = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
|
|
|
StorageManifestXsCallbackData data = {.storage = self, .json = strNew("{"), .pathRoot = pathExp, .filter = filter};
|
|
|
|
|
|
|
|
// If a path is specified
|
|
|
|
StorageInfo info = storageInfoP(self, pathExp, .ignoreMissing = true);
|
|
|
|
|
|
|
|
if (!info.exists || info.type == storageTypePath)
|
|
|
|
{
|
|
|
|
storageInfoListP(
|
|
|
|
self, data.pathRoot, storageManifestXsCallback, &data,
|
|
|
|
.errorOnMissing = storageFeature(self, storageFeaturePath) ? true : false);
|
|
|
|
}
|
|
|
|
// Else a file is specified
|
|
|
|
else
|
|
|
|
{
|
2019-11-21 17:21:35 +02:00
|
|
|
info.name = strBase(storagePathP(self, pathExp));
|
2019-06-26 14:24:58 +02:00
|
|
|
strCat(data.json, strPtr(storageManifestXsInfo(NULL, &info)));
|
|
|
|
}
|
|
|
|
|
|
|
|
strCat(data.json, "}");
|
|
|
|
|
|
|
|
RETVAL = newSVpv((char *)strPtr(data.json), strSize(data.json));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
void
|
|
|
|
pathCreate(self, pathExp, mode, ignoreExists, createParent)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
const String *mode = STR_NEW_SV($arg);
|
|
|
|
bool ignoreExists
|
|
|
|
bool createParent
|
|
|
|
CODE:
|
|
|
|
if (storageFeature(self, storageFeaturePath))
|
|
|
|
storagePathCreateP(
|
2019-08-17 23:52:00 +02:00
|
|
|
self, pathExp, .mode = mode ? cvtZToMode(strPtr(mode)) : 0, .errorOnExists = !ignoreExists,
|
2019-06-26 14:24:58 +02:00
|
|
|
.noParentCreate = !createParent);
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
bool
|
|
|
|
pathExists(self, pathExp)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
|
|
|
RETVAL = true;
|
|
|
|
|
|
|
|
if (storageFeature(self, storageFeaturePath))
|
2019-11-17 22:10:40 +02:00
|
|
|
RETVAL = storagePathExistsP(self, pathExp);
|
2019-06-26 14:24:58 +02:00
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
SV *
|
|
|
|
pathGet(self, pathExp)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
2019-11-17 22:10:40 +02:00
|
|
|
String *path = storagePathP(self, pathExp);
|
2019-06-26 14:24:58 +02:00
|
|
|
RETVAL = newSVpv((char *)strPtr(path), strSize(path));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
2018-04-11 14:21:09 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
void
|
2019-06-26 14:24:58 +02:00
|
|
|
pathRemove(self, pathExp, ignoreMissing, recurse)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
bool ignoreMissing
|
2018-04-11 14:21:09 +02:00
|
|
|
bool recurse
|
|
|
|
CODE:
|
2019-06-26 14:24:58 +02:00
|
|
|
storagePathRemoveP(
|
|
|
|
self, pathExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false, .recurse = recurse);
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
void
|
|
|
|
pathSync(self, pathExp)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *pathExp = STR_NEW_SV($arg);
|
|
|
|
CODE:
|
2019-11-17 22:10:40 +02:00
|
|
|
storagePathSyncP(self, pathExp);
|
2019-06-26 14:24:58 +02:00
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
UV
|
|
|
|
put(self, write, buffer)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::StorageWrite write
|
|
|
|
const Buffer *buffer = BUF_CONST_SV($arg);
|
|
|
|
CODE:
|
2019-11-17 22:10:40 +02:00
|
|
|
storagePutP(write, buffer);
|
2019-06-26 14:24:58 +02:00
|
|
|
RETVAL = buffer ? bufUsed(buffer) : 0;
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
bool
|
|
|
|
readDrain(self, read)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::StorageRead read
|
|
|
|
CODE:
|
|
|
|
RETVAL = false;
|
|
|
|
|
|
|
|
// Read and discard all IO (this is useful for processing filters)
|
|
|
|
if (ioReadOpen(storageReadIo(read)))
|
|
|
|
{
|
|
|
|
Buffer *buffer = bufNew(ioBufferSize());
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ioRead(storageReadIo(read), buffer);
|
|
|
|
bufUsedZero(buffer);
|
|
|
|
}
|
|
|
|
while (!ioReadEof(storageReadIo(read)));
|
|
|
|
|
|
|
|
ioReadClose(storageReadIo(read));
|
|
|
|
RETVAL = true;
|
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
void
|
|
|
|
remove(self, fileExp, ignoreMissing)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
const String *fileExp = STR_NEW_SV($arg);
|
|
|
|
bool ignoreMissing
|
|
|
|
CODE:
|
|
|
|
storageRemoveP(self, fileExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false);
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
const char *
|
|
|
|
cipherType(self)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
CODE:
|
|
|
|
if (cfgOptionStr(cfgOptRepoCipherType) == NULL || cipherType(cfgOptionStr(cfgOptRepoCipherType)) == cipherTypeNone)
|
|
|
|
RETVAL = NULL;
|
|
|
|
else
|
|
|
|
RETVAL = strPtr(cfgOptionStr(cfgOptRepoCipherType));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
const char *
|
|
|
|
cipherPass(self)
|
|
|
|
PREINIT:
|
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
|
|
|
CODE:
|
|
|
|
RETVAL = strPtr(cfgOptionStr(cfgOptRepoCipherPass));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
const char *
|
|
|
|
type(self)
|
|
|
|
PREINIT:
|
2018-04-11 14:21:09 +02:00
|
|
|
MEM_CONTEXT_XS_TEMP_BEGIN()
|
|
|
|
{
|
2019-06-26 14:24:58 +02:00
|
|
|
INPUT:
|
|
|
|
pgBackRest::LibC::Storage self
|
|
|
|
CODE:
|
|
|
|
RETVAL = strPtr(storageType(self));
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
CLEANUP:
|
2018-04-11 14:21:09 +02:00
|
|
|
}
|
|
|
|
MEM_CONTEXT_XS_TEMP_END();
|
2019-06-26 14:24:58 +02:00
|
|
|
|
|
|
|
MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
void
|
|
|
|
storageRepoFree()
|
|
|
|
CODE:
|
|
|
|
storageHelperFree();
|