1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-05-22 10:15:16 +02:00
Files
pgbackrest/libc/xs/storage/storage.xsh
T
David Steele 3f77a83e73 Remove raw option for gz compression.
This was a minor optimization used in protocol layer compression.  Even though it was slightly faster, it omitted the crc-32 that is generated during normal compression which could lead to corrupt data after a bad network transmission.  This would be caught on restore by our checksum but it seems better to catch an issue like this early.

The raw option also made the function signature different than future compression formats which may not support raw, or require different code to support raw.

In general, it doesn't seem worth the extra testing to support a format that has minimal benefit and is seldom used, since protocol compression is only enabled when the transmitted data is uncompressed.
2020-02-27 12:19:40 -05:00

208 lines
7.2 KiB
Plaintext

/***********************************************************************************************************************************
Storage XS Header
***********************************************************************************************************************************/
#include "common/assert.h"
#include "common/compress/gz/compress.h"
#include "common/compress/gz/decompress.h"
#include "common/crypto/cipherBlock.h"
#include "common/io/filter/size.h"
#include "common/memContext.h"
#include "common/type/convert.h"
#include "common/type/json.h"
#include "postgres/interface.h"
#include "storage/helper.h"
#include "storage/s3/storage.intern.h"
#include "storage/storage.intern.h"
typedef Storage *pgBackRest__LibC__Storage;
/***********************************************************************************************************************************
Manifest callback
***********************************************************************************************************************************/
typedef struct StorageManifestXsCallbackData
{
const Storage *storage;
const String *pathRoot;
const String *path;
String *json;
const String *filter;
} StorageManifestXsCallbackData;
String *
storageManifestXsInfo(const String *path, const StorageInfo *info)
{
String *json = strNew("");
if (info->name != NULL)
{
strCatFmt(
json, "%s:", strPtr(jsonFromStr(path == NULL ? info->name : strNewFmt("%s/%s", strPtr(path), strPtr(info->name)))));
}
strCatFmt(json, "{\"group\":%s,\"user\":%s,\"type\":\"", strPtr(jsonFromStr(info->group)), strPtr(jsonFromStr(info->user)));
switch (info->type)
{
case storageTypeFile:
{
strCatFmt(
json, "f\",\"mode\":\"%04o\",\"modification_time\":%" PRId64 ",\"size\":%" PRIu64 "}", info->mode,
(int64_t)info->timeModified, info->size);
break;
}
case storageTypeLink:
{
strCatFmt(json, "l\",\"link_destination\":%s}", strPtr(jsonFromStr(info->linkDestination)));
break;
}
case storageTypePath:
{
strCatFmt(json, "d\",\"mode\":\"%04o\"}", info->mode);
break;
}
case storageTypeSpecial:
{
strCatFmt(json, "s\",\"mode\":\"%04o\"}", info->mode);
break;
}
}
return json;
}
void
storageManifestXsCallback(void *callbackData, const StorageInfo *info)
{
StorageManifestXsCallbackData *data = (StorageManifestXsCallbackData *)callbackData;
if (data->path == NULL || !strEqZ(info->name, "."))
{
if (!strEqZ(info->name, ".") && data->filter && !strEq(data->filter, info->name))
return;
if (strSize(data->json) != 1)
strCat(data->json, ",");
strCat(data->json, strPtr(storageManifestXsInfo(data->path, info)));
if (info->type == storageTypePath)
{
if (!strEqZ(info->name, "."))
{
StorageManifestXsCallbackData dataSub =
{
.storage = data->storage,
.json = data->json,
.pathRoot = data->pathRoot,
.path = data->path == NULL ? info->name : strNewFmt("%s/%s", strPtr(data->path), strPtr(info->name)),
};
storageInfoListP(
dataSub.storage, strNewFmt("%s/%s", strPtr(dataSub.pathRoot), strPtr(dataSub.path)), storageManifestXsCallback,
&dataSub);
}
}
}
}
/***********************************************************************************************************************************
Add IO filter
***********************************************************************************************************************************/
void
storageFilterXsAdd(IoFilterGroup *filterGroup, const String *filter, const String *paramJson)
{
VariantList *paramList = paramJson ? jsonToVarLst(paramJson) : NULL;
if (strEqZ(filter, "pgBackRest::Storage::Filter::CipherBlock"))
{
ioFilterGroupAdd(
filterGroup,
cipherBlockNew(
varUInt64Force(varLstGet(paramList, 0)) ? cipherModeEncrypt : cipherModeDecrypt,
cipherType(varStr(varLstGet(paramList, 1))), BUFSTR(varStr(varLstGet(paramList, 2))), NULL));
}
else if (strEqZ(filter, "pgBackRest::Storage::Filter::Sha"))
{
ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR));
}
else if (strEqZ(filter, "pgBackRest::Common::Io::Handle"))
{
ioFilterGroupAdd(filterGroup, ioSizeNew());
}
else if (strEqZ(filter, "pgBackRest::Storage::Filter::Gz"))
{
if (strEqZ(varStr(varLstGet(paramList, 0)), "compress"))
ioFilterGroupAdd(filterGroup, gzCompressNew(varUIntForce(varLstGet(paramList, 1))));
else
ioFilterGroupAdd(filterGroup, gzDecompressNew());
}
else
THROW_FMT(AssertError, "unable to add invalid filter '%s'", strPtr(filter));
}
/***********************************************************************************************************************************
Get result from IO filter
***********************************************************************************************************************************/
String *
storageFilterXsResult(const IoFilterGroup *filterGroup, const String *filter)
{
const Variant *result;
if (strEqZ(filter, "pgBackRest::Storage::Filter::Sha"))
{
result = ioFilterGroupResult(filterGroup, CRYPTO_HASH_FILTER_TYPE_STR);
}
else if (strEqZ(filter, "pgBackRest::Common::Io::Handle"))
{
result = ioFilterGroupResult(filterGroup, SIZE_FILTER_TYPE_STR);
}
else
THROW_FMT(AssertError, "unable to get result for invalid filter '%s'", strPtr(filter));
if (result == NULL)
THROW_FMT(AssertError, "unable to find result for filter '%s'", strPtr(filter));
return jsonFromVar(result);
}
/***********************************************************************************************************************************
Get results from all IO filters
***********************************************************************************************************************************/
String *
storageFilterXsResultAll(const IoFilterGroup *filterGroup)
{
const VariantList *filterList = kvKeyList(varKv(ioFilterGroupResultAll(filterGroup)));
String *result = strNew("{");
for (unsigned int filterIdx = 0; filterIdx < varLstSize(filterList); filterIdx++)
{
const String *filter = varStr(varLstGet(filterList, filterIdx));
const String *filterPerl = NULL;
if (strEq(filter, CRYPTO_HASH_FILTER_TYPE_STR))
{
filterPerl = strNew("pgBackRest::Storage::Filter::Sha");
}
else if (strEq(filter, SIZE_FILTER_TYPE_STR))
{
filterPerl = strNew("pgBackRest::Common::Io::Handle");
}
if (filterPerl != NULL)
{
if (strSize(result) > 1)
strCat(result, ",");
strCatFmt(
result, "%s:%s", strPtr(jsonFromStr(filterPerl)), strPtr(storageFilterXsResult(filterGroup, filterPerl)));
}
}
strCat(result, "}");
return result;
}