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

Use structs to pass optional parameters to storage drivers.

New optional parameters can be added without breaking the interface and this reduces noise in the function prototypes.
This commit is contained in:
David Steele 2019-11-17 14:17:03 -05:00
parent 09e129886e
commit 5c65d88f62
8 changed files with 377 additions and 250 deletions

View File

@ -42,17 +42,16 @@ struct StoragePosix
StorageInterface interface; // Storage interface
};
/***********************************************************************************************************************************
Does a file exist? This function is only for files, not paths.
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storagePosixExists(THIS_VOID, const String *file)
storagePosixExists(THIS_VOID, const String *file, StorageInterfaceExistsParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, file);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -76,18 +75,16 @@ storagePosixExists(THIS_VOID, const String *file)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
File/path info
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageInfo
storagePosixInfo(THIS_VOID, const String *file, bool followLink)
storagePosixInfo(THIS_VOID, const String *file, StorageInterfaceInfoParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, followLink);
FUNCTION_LOG_PARAM(BOOL, param.followLink);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -98,7 +95,7 @@ storagePosixInfo(THIS_VOID, const String *file, bool followLink)
// Attempt to stat the file
struct stat statFile;
if ((followLink ? stat(strPtr(file), &statFile) : lstat(strPtr(file), &statFile)) == -1)
if ((param.followLink ? stat(strPtr(file), &statFile) : lstat(strPtr(file), &statFile)) == -1)
{
if (errno != ENOENT)
THROW_SYS_ERROR_FMT(FileOpenError, STORAGE_ERROR_INFO, strPtr(file));
@ -142,9 +139,7 @@ storagePosixInfo(THIS_VOID, const String *file, bool followLink)
FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}
/***********************************************************************************************************************************
Info for all files/paths in a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storagePosixInfoListEntry(
StoragePosix *this, const String *path, const String *name, StorageInfoListCallback callback, void *callbackData)
@ -166,7 +161,7 @@ storagePosixInfoListEntry(
{
String *pathInfo = strEqZ(name, ".") ? strDup(path) : strNewFmt("%s/%s", strPtr(path), strPtr(name));
StorageInfo storageInfo = storagePosixInfo(this, pathInfo, false);
StorageInfo storageInfo = storagePosixInfo(this, pathInfo, (StorageInterfaceInfoParam){.followLink = false});
if (storageInfo.exists)
{
@ -179,7 +174,8 @@ storagePosixInfoListEntry(
}
static bool
storagePosixInfoList(THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData)
storagePosixInfoList(
THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData, StorageInterfaceInfoListParam param)
{
THIS(StoragePosix);
@ -188,6 +184,7 @@ storagePosixInfoList(THIS_VOID, const String *path, StorageInfoListCallback call
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(FUNCTIONP, callback);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -241,18 +238,16 @@ storagePosixInfoList(THIS_VOID, const String *path, StorageInfoListCallback call
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Get a list of files from a directory
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StringList *
storagePosixList(THIS_VOID, const String *path, const String *expression)
storagePosixList(THIS_VOID, const String *path, StorageInterfaceListParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(STRING, expression);
FUNCTION_LOG_PARAM(STRING, param.expression);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -277,7 +272,7 @@ storagePosixList(THIS_VOID, const String *path, const String *expression)
MEM_CONTEXT_TEMP_BEGIN()
{
// Prepare regexp if an expression was passed
RegExp *regExp = expression == NULL ? NULL : regExpNew(expression);
RegExp *regExp = param.expression == NULL ? NULL : regExpNew(param.expression);
// Create the string list now that we know the directory is valid
result = strLstNew();
@ -312,11 +307,9 @@ storagePosixList(THIS_VOID, const String *path, const String *expression)
FUNCTION_LOG_RETURN(STRING_LIST, result);
}
/***********************************************************************************************************************************
Move a path/file
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination, StorageInterfaceMoveParam param)
{
THIS(StoragePosix);
@ -324,6 +317,7 @@ storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STORAGE_READ, source);
FUNCTION_LOG_PARAM(STORAGE_WRITE, destination);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -341,10 +335,10 @@ storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
// Attempt to move the file
if (rename(strPtr(sourceFile), strPtr(destinationFile)) == -1)
{
// Detemine which file/path is missing
// Determine which file/path is missing
if (errno == ENOENT)
{
if (!storagePosixExists(this, sourceFile))
if (!storagePosixExists(this, sourceFile, (StorageInterfaceExistsParam){false}))
THROW_SYS_ERROR_FMT(FileMissingError, "unable to move missing file '%s'", strPtr(sourceFile));
if (!storageWriteCreatePath(destination))
@ -353,8 +347,10 @@ storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
PathMissingError, "unable to move '%s' to missing path '%s'", strPtr(sourceFile), strPtr(destinationPath));
}
storagePosixPathCreate(this, destinationPath, false, false, storageWriteModePath(destination));
result = storagePosixMove(this, source, destination);
storagePosixPathCreate(
this, destinationPath, false, false, storageWriteModePath(destination),
(StorageInterfacePathCreateParam){false});
result = storagePosixMove(this, source, destination, (StorageInterfaceMoveParam){false});
}
// Else the destination is on a different device so a copy will be needed
else if (errno == EXDEV)
@ -373,7 +369,7 @@ storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
String *sourcePath = strPath(sourceFile);
if (!strEq(destinationPath, sourcePath))
storagePosixPathSync(this, sourcePath);
storagePosixPathSync(this, sourcePath, (StorageInterfacePathSyncParam){false});
}
}
}
@ -382,11 +378,9 @@ storagePosixMove(THIS_VOID, StorageRead *source, StorageWrite *destination)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
New file read object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageRead *
storagePosixNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool compressible)
storagePosixNewRead(THIS_VOID, const String *file, bool ignoreMissing, StorageInterfaceNewReadParam param)
{
THIS(StoragePosix);
@ -394,7 +388,7 @@ storagePosixNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool comp
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, ignoreMissing);
(void)compressible;
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -403,29 +397,24 @@ storagePosixNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool comp
FUNCTION_LOG_RETURN(STORAGE_READ, storageReadPosixNew(this, file, ignoreMissing));
}
/***********************************************************************************************************************************
New file write object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageWrite *
storagePosixNewWrite(
THIS_VOID, const String *file, mode_t modeFile, mode_t modePath, const String *user, const String *group, time_t timeModified,
bool createPath, bool syncFile, bool syncPath, bool atomic, bool compressible)
storagePosixNewWrite(THIS_VOID, const String *file, StorageInterfaceNewWriteParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(MODE, modeFile);
FUNCTION_LOG_PARAM(MODE, modePath);
FUNCTION_LOG_PARAM(STRING, user);
FUNCTION_LOG_PARAM(STRING, group);
FUNCTION_LOG_PARAM(TIME, timeModified);
FUNCTION_LOG_PARAM(BOOL, createPath);
FUNCTION_LOG_PARAM(BOOL, syncFile);
FUNCTION_LOG_PARAM(BOOL, syncPath);
FUNCTION_LOG_PARAM(BOOL, atomic);
(void)compressible;
FUNCTION_LOG_PARAM(MODE, param.modeFile);
FUNCTION_LOG_PARAM(MODE, param.modePath);
FUNCTION_LOG_PARAM(STRING, param.user);
FUNCTION_LOG_PARAM(STRING, param.group);
FUNCTION_LOG_PARAM(TIME, param.timeModified);
FUNCTION_LOG_PARAM(BOOL, param.createPath);
FUNCTION_LOG_PARAM(BOOL, param.syncFile);
FUNCTION_LOG_PARAM(BOOL, param.syncPath);
FUNCTION_LOG_PARAM(BOOL, param.atomic);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -434,15 +423,14 @@ storagePosixNewWrite(
FUNCTION_LOG_RETURN(
STORAGE_WRITE,
storageWritePosixNew(
this, file, modeFile, modePath, user, group, timeModified, createPath, syncFile,
this->interface.pathSync != NULL ? syncPath : false, atomic));
this, file, param.modeFile, param.modePath, param.user, param.group, param.timeModified, param.createPath,
param.syncFile, this->interface.pathSync != NULL ? param.syncPath : false, param.atomic));
}
/***********************************************************************************************************************************
Create a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
void
storagePosixPathCreate(THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode)
storagePosixPathCreate(
THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode, StorageInterfacePathCreateParam param)
{
THIS(StoragePosix);
@ -452,6 +440,7 @@ storagePosixPathCreate(THIS_VOID, const String *path, bool errorOnExists, bool n
FUNCTION_LOG_PARAM(BOOL, errorOnExists);
FUNCTION_LOG_PARAM(BOOL, noParentCreate);
FUNCTION_LOG_PARAM(MODE, mode);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -463,8 +452,9 @@ storagePosixPathCreate(THIS_VOID, const String *path, bool errorOnExists, bool n
// If the parent path does not exist then create it if allowed
if (errno == ENOENT && !noParentCreate)
{
storagePosixPathCreate(this, strPath(path), errorOnExists, noParentCreate, mode);
storagePosixPathCreate(this, path, errorOnExists, noParentCreate, mode);
storagePosixPathCreate(
this, strPath(path), errorOnExists, noParentCreate, mode, (StorageInterfacePathCreateParam){false});
storagePosixPathCreate(this, path, errorOnExists, noParentCreate, mode, (StorageInterfacePathCreateParam){false});
}
// Ignore path exists if allowed
else if (errno != EEXIST || errorOnExists)
@ -474,17 +464,16 @@ storagePosixPathCreate(THIS_VOID, const String *path, bool errorOnExists, bool n
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Does a path exist?
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storagePosixPathExists(THIS_VOID, const String *path)
storagePosixPathExists(THIS_VOID, const String *path, StorageInterfacePathExistsParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -508,11 +497,9 @@ storagePosixPathExists(THIS_VOID, const String *path)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storagePosixPathRemove(THIS_VOID, const String *path, bool recurse)
storagePosixPathRemove(THIS_VOID, const String *path, bool recurse, StorageInterfacePathRemoveParam param)
{
THIS(StoragePosix);
@ -520,6 +507,7 @@ storagePosixPathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(BOOL, recurse);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -533,7 +521,7 @@ storagePosixPathRemove(THIS_VOID, const String *path, bool recurse)
if (recurse)
{
// Get a list of files in this path
StringList *fileList = storagePosixList(this, path, NULL);
StringList *fileList = storagePosixList(this, path, (StorageInterfaceListParam){.expression = NULL});
// Only continue if the path exists
if (fileList != NULL)
@ -548,7 +536,7 @@ storagePosixPathRemove(THIS_VOID, const String *path, bool recurse)
{
// These errors indicate that the entry is actually a path so we'll try to delete it that way
if (errno == EPERM || errno == EISDIR) // {uncovered_branch - no EPERM on tested systems}
storagePosixPathRemove(this, file, true);
storagePosixPathRemove(this, file, true, (StorageInterfacePathRemoveParam){false});
// Else error
else
THROW_SYS_ERROR_FMT(PathRemoveError, STORAGE_ERROR_PATH_REMOVE_FILE, strPtr(file));
@ -572,17 +560,16 @@ storagePosixPathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Sync a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
void
storagePosixPathSync(THIS_VOID, const String *path)
storagePosixPathSync(THIS_VOID, const String *path, StorageInterfacePathSyncParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -618,18 +605,16 @@ storagePosixPathSync(THIS_VOID, const String *path)
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Remove a file
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storagePosixRemove(THIS_VOID, const String *file, bool errorOnMissing)
storagePosixRemove(THIS_VOID, const String *file, StorageInterfaceRemoveParam param)
{
THIS(StoragePosix);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, errorOnMissing);
FUNCTION_LOG_PARAM(BOOL, param.errorOnMissing);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -638,7 +623,7 @@ storagePosixRemove(THIS_VOID, const String *file, bool errorOnMissing)
// Attempt to unlink the file
if (unlink(strPtr(file)) == -1)
{
if (errorOnMissing || errno != ENOENT)
if (param.errorOnMissing || errno != ENOENT)
THROW_SYS_ERROR_FMT(FileRemoveError, "unable to remove '%s'", strPtr(file));
}

View File

@ -17,8 +17,9 @@ Storage *storagePosixNewInternal(
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
void storagePosixPathCreate(THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode);
void storagePosixPathSync(THIS_VOID, const String *path);
void storagePosixPathCreate(
THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode, StorageInterfacePathCreateParam param);
void storagePosixPathSync(THIS_VOID, const String *path, StorageInterfacePathSyncParam param);
/***********************************************************************************************************************************
Macros for function logging

View File

@ -82,7 +82,8 @@ storageWritePosixOpen(THIS_VOID)
if (this->handle == -1 && errno == ENOENT && this->interface.createPath)
{
// Create the path
storagePosixPathCreate(this->storage, this->path, false, false, this->interface.modePath);
storagePosixPathCreate(
this->storage, this->path, false, false, this->interface.modePath, (StorageInterfacePathCreateParam){false});
// Open file again
this->handle = open(strPtr(this->nameTmp), FILE_OPEN_FLAGS, this->interface.modeFile);
@ -193,7 +194,7 @@ storageWritePosixClose(THIS_VOID)
// Sync the path
if (this->interface.syncPath)
storagePosixPathSync(this->storage, this->path);
storagePosixPathSync(this->storage, this->path, (StorageInterfacePathSyncParam){false});
}
FUNCTION_LOG_RETURN_VOID();

View File

@ -202,7 +202,9 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
{
if (strEq(command, PROTOCOL_COMMAND_STORAGE_EXISTS_STR))
{
protocolServerResponse(server, VARBOOL(interface.exists(driver, varStr(varLstGet(paramList, 0)))));
protocolServerResponse(
server,
VARBOOL(interface.exists(driver, varStr(varLstGet(paramList, 0)), (StorageInterfaceExistsParam){false})));
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_FEATURE_STR))
{
@ -213,7 +215,9 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_INFO_STR))
{
StorageInfo info = interface.info(driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)));
StorageInfo info = interface.info(
driver, varStr(varLstGet(paramList, 0)),
(StorageInterfaceInfoParam){.followLink = varBool(varLstGet(paramList, 1))});
protocolServerResponse(server, VARBOOL(info.exists));
@ -226,7 +230,8 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_INFO_LIST_STR))
{
bool result = interface.infoList(
driver, varStr(varLstGet(paramList, 0)), storageRemoteProtocolInfoListCallback, server);
driver, varStr(varLstGet(paramList, 0)), storageRemoteProtocolInfoListCallback, server,
(StorageInterfaceInfoListParam){false});
protocolServerWriteLine(server, NULL);
protocolServerResponse(server, VARBOOL(result));
@ -236,13 +241,18 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
protocolServerResponse(
server,
varNewVarLst(
varLstNewStrLst(interface.list(driver, varStr(varLstGet(paramList, 0)), varStr(varLstGet(paramList, 1))))));
varLstNewStrLst(
interface.list(
driver, varStr(varLstGet(paramList, 0)),
(StorageInterfaceListParam){.expression = varStr(varLstGet(paramList, 1))}))));
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_OPEN_READ_STR))
{
// Create the read object
IoRead *fileRead = storageReadIo(
interface.newRead(driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)), false));
interface.newRead(
driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)),
(StorageInterfaceNewReadParam){.compressible = false}));
// Set filter group based on passed filters
storageRemoteFilterGroup(ioReadFilterGroup(fileRead), varLstGet(paramList, 2));
@ -287,10 +297,13 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
// Create the write object
IoWrite *fileWrite = storageWriteIo(
interface.newWrite(
driver, varStr(varLstGet(paramList, 0)), varUIntForce(varLstGet(paramList, 1)),
varUIntForce(varLstGet(paramList, 2)), varStr(varLstGet(paramList, 3)), varStr(varLstGet(paramList, 4)),
(time_t)varIntForce(varLstGet(paramList, 5)), varBool(varLstGet(paramList, 6)),
varBool(varLstGet(paramList, 7)), varBool(varLstGet(paramList, 8)), varBool(varLstGet(paramList, 9)), false));
driver, varStr(varLstGet(paramList, 0)),
(StorageInterfaceNewWriteParam){
.modeFile = varUIntForce(varLstGet(paramList, 1)), .modePath = varUIntForce(varLstGet(paramList, 2)),
.user = varStr(varLstGet(paramList, 3)), .group = varStr(varLstGet(paramList, 4)),
.timeModified = (time_t)varUInt64Force(varLstGet(paramList, 5)),
.createPath = varBool(varLstGet(paramList, 6)), .syncFile = varBool(varLstGet(paramList, 7)),
.syncPath = varBool(varLstGet(paramList, 8)), .atomic = varBool(varLstGet(paramList, 9))}));
// Set filter group based on passed filters
storageRemoteFilterGroup(ioWriteFilterGroup(fileWrite), varLstGet(paramList, 10));
@ -348,7 +361,7 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
{
interface.pathCreate(
driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)), varBool(varLstGet(paramList, 2)),
varUIntForce(varLstGet(paramList, 3)));
varUIntForce(varLstGet(paramList, 3)), (StorageInterfacePathCreateParam){false});
protocolServerResponse(server, NULL);
}
@ -357,22 +370,29 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto
// Not all drivers implement pathExists()
CHECK(interface.pathExists != NULL);
protocolServerResponse(server, VARBOOL(interface.pathExists(driver, varStr(varLstGet(paramList, 0)))));
protocolServerResponse(
server,
VARBOOL(interface.pathExists(driver, varStr(varLstGet(paramList, 0)), (StorageInterfacePathExistsParam){false})));
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_PATH_REMOVE_STR))
{
protocolServerResponse(server,
VARBOOL(interface.pathRemove(driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)))));
VARBOOL(
interface.pathRemove(
driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)),
(StorageInterfacePathRemoveParam){false})));
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_PATH_SYNC_STR))
{
interface.pathSync(driver, varStr(varLstGet(paramList, 0)));
interface.pathSync(driver, varStr(varLstGet(paramList, 0)), (StorageInterfacePathSyncParam){false});
protocolServerResponse(server, NULL);
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_REMOVE_STR))
{
interface.remove(driver, varStr(varLstGet(paramList, 0)), varBool(varLstGet(paramList, 1)));
interface.remove(
driver, varStr(varLstGet(paramList, 0)),
(StorageInterfaceRemoveParam){.errorOnMissing = varBool(varLstGet(paramList, 1))});
protocolServerResponse(server, NULL);
}

View File

@ -28,17 +28,16 @@ struct StorageRemote
unsigned int compressLevel; // Protocol compression level
};
/***********************************************************************************************************************************
Does a file exist? This function is only for files, not paths.
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storageRemoteExists(THIS_VOID, const String *file)
storageRemoteExists(THIS_VOID, const String *file, StorageInterfaceExistsParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, file);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -58,9 +57,7 @@ storageRemoteExists(THIS_VOID, const String *file)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
File/path info
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
// Helper to convert protocol storage type to an enum
static StorageType
storageRemoteInfoParseType(const char type)
@ -114,14 +111,14 @@ storageRemoteInfoParse(ProtocolClient *client, StorageInfo *info)
}
static StorageInfo
storageRemoteInfo(THIS_VOID, const String *file, bool followLink)
storageRemoteInfo(THIS_VOID, const String *file, StorageInterfaceInfoParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, followLink);
FUNCTION_LOG_PARAM(BOOL, param.followLink);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -132,7 +129,7 @@ storageRemoteInfo(THIS_VOID, const String *file, bool followLink)
{
ProtocolCommand *command = protocolCommandNew(PROTOCOL_COMMAND_STORAGE_INFO_STR);
protocolCommandParamAdd(command, VARSTR(file));
protocolCommandParamAdd(command, VARBOOL(followLink));
protocolCommandParamAdd(command, VARBOOL(param.followLink));
result.exists = varBool(protocolClientExecute(this->client, command, true));
@ -158,11 +155,10 @@ storageRemoteInfo(THIS_VOID, const String *file, bool followLink)
FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}
/***********************************************************************************************************************************
Info for all files/paths in a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storageRemoteInfoList(THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData)
storageRemoteInfoList(
THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData, StorageInterfaceInfoListParam param)
{
THIS(StorageRemote);
@ -171,6 +167,7 @@ storageRemoteInfoList(THIS_VOID, const String *path, StorageInfoListCallback cal
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(FUNCTIONP, callback);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -210,18 +207,16 @@ storageRemoteInfoList(THIS_VOID, const String *path, StorageInfoListCallback cal
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Get a list of files from a directory
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StringList *
storageRemoteList(THIS_VOID, const String *path, const String *expression)
storageRemoteList(THIS_VOID, const String *path, StorageInterfaceListParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(STRING, expression);
FUNCTION_LOG_PARAM(STRING, param.expression);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -233,7 +228,7 @@ storageRemoteList(THIS_VOID, const String *path, const String *expression)
{
ProtocolCommand *command = protocolCommandNew(PROTOCOL_COMMAND_STORAGE_LIST_STR);
protocolCommandParamAdd(command, VARSTR(path));
protocolCommandParamAdd(command, VARSTR(expression));
protocolCommandParamAdd(command, VARSTR(param.expression));
result = strLstMove(strLstNewVarLst(varVarLst(protocolClientExecute(this->client, command, true))), MEM_CONTEXT_OLD());
}
@ -242,11 +237,9 @@ storageRemoteList(THIS_VOID, const String *path, const String *expression)
FUNCTION_LOG_RETURN(STRING_LIST, result);
}
/***********************************************************************************************************************************
New file read object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageRead *
storageRemoteNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool compressible)
storageRemoteNewRead(THIS_VOID, const String *file, bool ignoreMissing, StorageInterfaceNewReadParam param)
{
THIS(StorageRemote);
@ -254,7 +247,7 @@ storageRemoteNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool com
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, ignoreMissing);
FUNCTION_LOG_PARAM(BOOL, compressible);
FUNCTION_LOG_PARAM(BOOL, param.compressible);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -263,32 +256,29 @@ storageRemoteNewRead(THIS_VOID, const String *file, bool ignoreMissing, bool com
FUNCTION_LOG_RETURN(
STORAGE_READ,
storageReadRemoteNew(
this, this->client, file, ignoreMissing, this->compressLevel > 0 ? compressible : false, this->compressLevel));
this, this->client, file, ignoreMissing, this->compressLevel > 0 ? param.compressible : false, this->compressLevel));
}
/***********************************************************************************************************************************
New file write object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageWrite *
storageRemoteNewWrite(
THIS_VOID, const String *file, mode_t modeFile, mode_t modePath, const String *user, const String *group, time_t timeModified,
bool createPath, bool syncFile, bool syncPath, bool atomic, bool compressible)
THIS_VOID, const String *file, StorageInterfaceNewWriteParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(MODE, modeFile);
FUNCTION_LOG_PARAM(MODE, modePath);
FUNCTION_LOG_PARAM(STRING, user);
FUNCTION_LOG_PARAM(STRING, group);
FUNCTION_LOG_PARAM(TIME, timeModified);
FUNCTION_LOG_PARAM(BOOL, createPath);
FUNCTION_LOG_PARAM(BOOL, syncFile);
FUNCTION_LOG_PARAM(BOOL, syncPath);
FUNCTION_LOG_PARAM(BOOL, atomic);
FUNCTION_LOG_PARAM(BOOL, compressible);
FUNCTION_LOG_PARAM(MODE, param.modeFile);
FUNCTION_LOG_PARAM(MODE, param.modePath);
FUNCTION_LOG_PARAM(STRING, param.user);
FUNCTION_LOG_PARAM(STRING, param.group);
FUNCTION_LOG_PARAM(TIME, param.timeModified);
FUNCTION_LOG_PARAM(BOOL, param.createPath);
FUNCTION_LOG_PARAM(BOOL, param.syncFile);
FUNCTION_LOG_PARAM(BOOL, param.syncPath);
FUNCTION_LOG_PARAM(BOOL, param.atomic);
FUNCTION_LOG_PARAM(BOOL, param.compressible);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -297,15 +287,15 @@ storageRemoteNewWrite(
FUNCTION_LOG_RETURN(
STORAGE_WRITE,
storageWriteRemoteNew(
this, this->client, file, modeFile, modePath, user, group, timeModified, createPath, syncFile, syncPath, atomic,
this->compressLevel > 0 ? compressible : false, this->compressLevel));
this, this->client, file, param.modeFile, param.modePath, param.user, param.group, param.timeModified, param.createPath,
param.syncFile, param.syncPath, param.atomic, this->compressLevel > 0 ? param.compressible : false,
this->compressLevel));
}
/***********************************************************************************************************************************
Create a path. There are no physical paths on S3 so just return success.
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storageRemotePathCreate(THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode)
storageRemotePathCreate(
THIS_VOID, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode, StorageInterfacePathCreateParam param)
{
THIS(StorageRemote);
@ -315,6 +305,7 @@ storageRemotePathCreate(THIS_VOID, const String *path, bool errorOnExists, bool
FUNCTION_LOG_PARAM(BOOL, errorOnExists);
FUNCTION_LOG_PARAM(BOOL, noParentCreate);
FUNCTION_LOG_PARAM(MODE, mode);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -335,17 +326,16 @@ storageRemotePathCreate(THIS_VOID, const String *path, bool errorOnExists, bool
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Does a path exist?
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storageRemotePathExists(THIS_VOID, const String *path)
storageRemotePathExists(THIS_VOID, const String *path, StorageInterfacePathExistsParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, path);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -365,11 +355,9 @@ storageRemotePathExists(THIS_VOID, const String *path)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storageRemotePathRemove(THIS_VOID, const String *path, bool recurse)
storageRemotePathRemove(THIS_VOID, const String *path, bool recurse, StorageInterfacePathRemoveParam param)
{
THIS(StorageRemote);
@ -377,6 +365,7 @@ storageRemotePathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(BOOL, recurse);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -397,17 +386,16 @@ storageRemotePathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
Sync a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storageRemotePathSync(THIS_VOID, const String *path)
storageRemotePathSync(THIS_VOID, const String *path, StorageInterfacePathSyncParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, path);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -425,18 +413,16 @@ storageRemotePathSync(THIS_VOID, const String *path)
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Remove a file
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storageRemoteRemove(THIS_VOID, const String *file, bool errorOnMissing)
storageRemoteRemove(THIS_VOID, const String *file, StorageInterfaceRemoveParam param)
{
THIS(StorageRemote);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, errorOnMissing);
FUNCTION_LOG_PARAM(BOOL, param.errorOnMissing);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -446,7 +432,7 @@ storageRemoteRemove(THIS_VOID, const String *file, bool errorOnMissing)
{
ProtocolCommand *command = protocolCommandNew(PROTOCOL_COMMAND_STORAGE_REMOVE_STR);
protocolCommandParamAdd(command, VARSTR(file));
protocolCommandParamAdd(command, VARBOOL(errorOnMissing));
protocolCommandParamAdd(command, VARBOOL(param.errorOnMissing));
protocolClientExecute(this->client, command, false);
}

View File

@ -519,17 +519,16 @@ storageS3ListInternal(
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Does a file exist? This function is only for files, not paths.
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static bool
storageS3Exists(THIS_VOID, const String *file)
storageS3Exists(THIS_VOID, const String *file, StorageInterfaceExistsParam param)
{
THIS(StorageS3);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, file);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -546,22 +545,20 @@ storageS3Exists(THIS_VOID, const String *file)
FUNCTION_LOG_RETURN(BOOL, result);
}
/***********************************************************************************************************************************
File info
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageInfo
storageS3Info(THIS_VOID, const String *file, bool followLink)
storageS3Info(THIS_VOID, const String *file, StorageInterfaceInfoParam param)
{
THIS(StorageS3);
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, file);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(file != NULL);
(void)followLink;
StorageInfo result = {0};
@ -579,9 +576,7 @@ storageS3Info(THIS_VOID, const String *file, bool followLink)
FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}
/***********************************************************************************************************************************
Info for all files/paths in a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
typedef struct StorageS3InfoListData
{
StorageInfoListCallback callback; // User-supplied callback function
@ -619,7 +614,8 @@ storageS3InfoListCallback(StorageS3 *this, void *callbackData, const String *nam
}
static bool
storageS3InfoList(THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData)
storageS3InfoList(
THIS_VOID, const String *path, StorageInfoListCallback callback, void *callbackData, StorageInterfaceInfoListParam param)
{
THIS(StorageS3);
@ -628,6 +624,7 @@ storageS3InfoList(THIS_VOID, const String *path, StorageInfoListCallback callbac
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(FUNCTIONP, callback);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -644,9 +641,7 @@ storageS3InfoList(THIS_VOID, const String *path, StorageInfoListCallback callbac
FUNCTION_LOG_RETURN(BOOL, true);
}
/***********************************************************************************************************************************
Get a list of files from a directory
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storageS3ListCallback(StorageS3 *this, void *callbackData, const String *name, StorageType type, const XmlNode *xml)
{
@ -670,14 +665,14 @@ storageS3ListCallback(StorageS3 *this, void *callbackData, const String *name, S
}
static StringList *
storageS3List(THIS_VOID, const String *path, const String *expression)
storageS3List(THIS_VOID, const String *path, StorageInterfaceListParam param)
{
THIS(StorageS3);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(STRING, expression);
FUNCTION_LOG_PARAM(STRING, param.expression);
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -689,7 +684,7 @@ storageS3List(THIS_VOID, const String *path, const String *expression)
{
result = strLstNew();
storageS3ListInternal(this, path, expression, false, storageS3ListCallback, result);
storageS3ListInternal(this, path, param.expression, false, storageS3ListCallback, result);
strLstMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
@ -697,11 +692,9 @@ storageS3List(THIS_VOID, const String *path, const String *expression)
FUNCTION_LOG_RETURN(STRING_LIST, result);
}
/***********************************************************************************************************************************
New file read object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageRead *
storageS3NewRead(THIS_VOID, const String *file, bool ignoreMissing, bool compressible)
storageS3NewRead(THIS_VOID, const String *file, bool ignoreMissing, StorageInterfaceNewReadParam param)
{
THIS(StorageS3);
@ -709,7 +702,7 @@ storageS3NewRead(THIS_VOID, const String *file, bool ignoreMissing, bool compres
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, ignoreMissing);
(void)compressible;
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -718,44 +711,29 @@ storageS3NewRead(THIS_VOID, const String *file, bool ignoreMissing, bool compres
FUNCTION_LOG_RETURN(STORAGE_READ, storageReadS3New(this, file, ignoreMissing));
}
/***********************************************************************************************************************************
New file write object
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static StorageWrite *
storageS3NewWrite(
THIS_VOID, const String *file, mode_t modeFile, mode_t modePath, const String *user, const String *group, time_t timeModified,
bool createPath, bool syncFile, bool syncPath, bool atomic, bool compressible)
storageS3NewWrite(THIS_VOID, const String *file, StorageInterfaceNewWriteParam param)
{
THIS(StorageS3);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(MODE, modeFile);
FUNCTION_LOG_PARAM(MODE, modePath);
FUNCTION_LOG_PARAM(STRING, user);
FUNCTION_LOG_PARAM(STRING, group);
FUNCTION_LOG_PARAM(TIME, timeModified);
FUNCTION_LOG_PARAM(BOOL, createPath);
FUNCTION_LOG_PARAM(BOOL, syncFile);
FUNCTION_LOG_PARAM(BOOL, syncPath);
FUNCTION_LOG_PARAM(BOOL, atomic);
(void)compressible;
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(file != NULL);
ASSERT(createPath);
ASSERT(user == NULL);
ASSERT(group == NULL);
ASSERT(timeModified == 0);
ASSERT(param.createPath);
ASSERT(param.user == NULL);
ASSERT(param.group == NULL);
ASSERT(param.timeModified == 0);
FUNCTION_LOG_RETURN(STORAGE_WRITE, storageWriteS3New(this, file, this->partSize));
}
/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
typedef struct StorageS3PathRemoveData
{
MemContext *memContext; // Mem context to create xml document in
@ -851,7 +829,7 @@ storageS3PathRemoveCallback(StorageS3 *this, void *callbackData, const String *n
}
static bool
storageS3PathRemove(THIS_VOID, const String *path, bool recurse)
storageS3PathRemove(THIS_VOID, const String *path, bool recurse, StorageInterfacePathRemoveParam param)
{
THIS(StorageS3);
@ -859,6 +837,7 @@ storageS3PathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(BOOL, recurse);
(void)param; // No parameters are used
FUNCTION_LOG_END();
ASSERT(this != NULL);
@ -877,23 +856,21 @@ storageS3PathRemove(THIS_VOID, const String *path, bool recurse)
FUNCTION_LOG_RETURN(BOOL, true);
}
/***********************************************************************************************************************************
Remove a file
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
static void
storageS3Remove(THIS_VOID, const String *file, bool errorOnMissing)
storageS3Remove(THIS_VOID, const String *file, StorageInterfaceRemoveParam param)
{
THIS(StorageS3);
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_S3, this);
FUNCTION_LOG_PARAM(STRING, file);
FUNCTION_LOG_PARAM(BOOL, errorOnMissing);
FUNCTION_LOG_PARAM(BOOL, param.errorOnMissing);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(file != NULL);
ASSERT(!errorOnMissing);
ASSERT(!param.errorOnMissing);
storageS3Request(this, HTTP_VERB_DELETE_STR, file, NULL, NULL, true, false);

View File

@ -31,7 +31,7 @@ struct Storage
mode_t modePath;
bool write;
bool pathEnforce;
StoragePathExpressionCallback pathExpressionFunction;
StoragePathExpressionCallback *pathExpressionFunction;
};
OBJECT_DEFINE_FREE(STORAGE);
@ -158,7 +158,7 @@ storageExists(const Storage *this, const String *pathExp, StorageExistsParam par
do
{
// Call driver function
result = this->interface.exists(this->driver, path);
result = this->interface.exists(this->driver, path, (StorageInterfaceExistsParam){false});
}
while (!result && wait != NULL && waitMore(wait));
}
@ -253,7 +253,7 @@ storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param)
String *file = storagePathNP(this, fileExp);
// Call driver function
result = this->interface.info(this->driver, file, param.followLink);
result = this->interface.info(this->driver, file, (StorageInterfaceInfoParam){.followLink = param.followLink});
// Error if the file missing and not ignoring
if (!result.exists && !param.ignoreMissing)
@ -329,7 +329,7 @@ storageInfoListSort(
// If no sorting then use the callback directly
if (sortOrder == sortOrderNone)
{
result = this->interface.infoList(this->driver, path, callback, callbackData);
result = this->interface.infoList(this->driver, path, callback, callbackData, (StorageInterfaceInfoListParam){false});
}
// Else sort the info before sending it to the callback
else
@ -341,7 +341,8 @@ storageInfoListSort(
.infoList = lstNewP(sizeof(StorageInfo), .comparator = lstComparatorStr),
};
result = this->interface.infoList(this->driver, path, storageInfoListSortCallback, &data);
result = this->interface.infoList(
this->driver, path, storageInfoListSortCallback, &data, (StorageInterfaceInfoListParam){false});
lstSort(data.infoList, sortOrder);
MEM_CONTEXT_TEMP_RESET_BEGIN()
@ -507,7 +508,7 @@ storageList(const Storage *this, const String *pathExp, StorageListParam param)
String *path = storagePathNP(this, pathExp);
// Get the list
result = this->interface.list(this->driver, path, param.expression);
result = this->interface.list(this->driver, path, (StorageInterfaceListParam){.expression = param.expression});
// If the path does not exist
if (result == NULL)
@ -552,19 +553,19 @@ storageMove(const Storage *this, StorageRead *source, StorageWrite *destination)
MEM_CONTEXT_TEMP_BEGIN()
{
// If the file can't be moved it will need to be copied
if (!this->interface.move(this->driver, source, destination))
if (!this->interface.move(this->driver, source, destination, (StorageInterfaceMoveParam){false}))
{
// Perform the copy
storageCopyNP(source, destination);
// Remove the source file
this->interface.remove(this->driver, storageReadName(source), false);
this->interface.remove(this->driver, storageReadName(source), (StorageInterfaceRemoveParam){.errorOnMissing = false});
// Sync source path if the destination path was synced. We know the source and destination paths are different because
// the move did not succeed. This will need updating when drivers other than Posix/CIFS are implemented because there's
// no way to get coverage on it now.
if (storageWriteSyncPath(destination))
this->interface.pathSync(this->driver, strPath(storageReadName(source)));
this->interface.pathSync(this->driver, strPath(storageReadName(source)), (StorageInterfacePathSyncParam){false});
}
}
MEM_CONTEXT_TEMP_END();
@ -592,7 +593,9 @@ storageNewRead(const Storage *this, const String *fileExp, StorageNewReadParam p
MEM_CONTEXT_TEMP_BEGIN()
{
result = storageReadMove(
this->interface.newRead(this->driver, storagePathNP(this, fileExp), param.ignoreMissing, param.compressible),
this->interface.newRead(
this->driver, storagePathNP(this, fileExp), param.ignoreMissing,
(StorageInterfaceNewReadParam){.compressible = param.compressible}),
MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
@ -630,9 +633,12 @@ storageNewWrite(const Storage *this, const String *fileExp, StorageNewWriteParam
{
result = storageWriteMove(
this->interface.newWrite(
this->driver, storagePathNP(this, fileExp), param.modeFile != 0 ? param.modeFile : this->modeFile,
param.modePath != 0 ? param.modePath : this->modePath, param.user, param.group, param.timeModified,
!param.noCreatePath, !param.noSyncFile, !param.noSyncPath, !param.noAtomic, param.compressible),
this->driver, storagePathNP(this, fileExp),
(StorageInterfaceNewWriteParam){
.modeFile = param.modeFile != 0 ? param.modeFile : this->modeFile,
.modePath = param.modePath != 0 ? param.modePath : this->modePath, .user = param.user, .group = param.group,
.timeModified = param.timeModified, .createPath = !param.noCreatePath, .syncFile = !param.noSyncFile,
.syncPath = !param.noSyncPath, .atomic = !param.noAtomic, .compressible = param.compressible}),
MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
@ -767,7 +773,8 @@ storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateP
// Call driver function
this->interface.pathCreate(
this->driver, path, param.errorOnExists, param.noParentCreate, param.mode != 0 ? param.mode : this->modePath);
this->driver, path, param.errorOnExists, param.noParentCreate, param.mode != 0 ? param.mode : this->modePath,
(StorageInterfacePathCreateParam){false});
}
MEM_CONTEXT_TEMP_END();
@ -792,7 +799,7 @@ storagePathExists(const Storage *this, const String *pathExp)
MEM_CONTEXT_TEMP_BEGIN()
{
result = this->interface.pathExists(this->driver, storagePathNP(this, pathExp));
result = this->interface.pathExists(this->driver, storagePathNP(this, pathExp), (StorageInterfacePathExistsParam){false});
}
MEM_CONTEXT_TEMP_END();
@ -823,8 +830,11 @@ storagePathRemove(const Storage *this, const String *pathExp, StoragePathRemoveP
String *path = storagePathNP(this, pathExp);
// Call driver function
if (!this->interface.pathRemove(this->driver, path, param.recurse) && param.errorOnMissing)
if (!this->interface.pathRemove(this->driver, path, param.recurse, (StorageInterfacePathRemoveParam){false}) &&
param.errorOnMissing)
{
THROW_FMT(PathRemoveError, STORAGE_ERROR_PATH_REMOVE_MISSING, strPtr(path));
}
}
MEM_CONTEXT_TEMP_END();
@ -849,7 +859,7 @@ void storagePathSync(const Storage *this, const String *pathExp)
{
MEM_CONTEXT_TEMP_BEGIN()
{
this->interface.pathSync(this->driver, storagePathNP(this, pathExp));
this->interface.pathSync(this->driver, storagePathNP(this, pathExp), (StorageInterfacePathSyncParam){false});
}
MEM_CONTEXT_TEMP_END();
}
@ -898,7 +908,7 @@ storageRemove(const Storage *this, const String *fileExp, StorageRemoveParam par
String *file = storagePathNP(this, fileExp);
// Call driver function
this->interface.remove(this->driver, file, param.errorOnMissing);
this->interface.remove(this->driver, file, (StorageInterfaceRemoveParam){.errorOnMissing = param.errorOnMissing});
}
MEM_CONTEXT_TEMP_END();

View File

@ -47,7 +47,154 @@ Error messages
/***********************************************************************************************************************************
Path expression callback function type - used to modify paths based on expressions enclosed in <>
***********************************************************************************************************************************/
typedef String *(*StoragePathExpressionCallback)(const String *expression, const String *path);
typedef String *StoragePathExpressionCallback(const String *expression, const String *path);
/***********************************************************************************************************************************
Required interface functions
***********************************************************************************************************************************/
// Does a file exist? This function is only for files, not paths.
typedef struct StorageInterfaceExistsParam
{
bool dummy; // No optional parameters
} StorageInterfaceExistsParam;
typedef bool StorageInterfaceExists(void *thisVoid, const String *file, StorageInterfaceExistsParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Get information about a file
typedef struct StorageInterfaceInfoParam
{
// Should symlinks be followed? Only required on storage that supports symlinks.
bool followLink;
} StorageInterfaceInfoParam;
typedef StorageInfo StorageInterfaceInfo(void *thisVoid, const String *file, StorageInterfaceInfoParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Get a list of files
typedef struct StorageInterfaceListParam
{
// Regular expression used to filter the results
const String *expression;
} StorageInterfaceListParam;
typedef StringList *StorageInterfaceList(void *thisVoid, const String *path, StorageInterfaceListParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Create a file read object. The file should not be opened immediately -- open() will be called on the IoRead interface when the
// file needs to be opened.
typedef struct StorageInterfaceNewReadParam
{
// Is the file compressible? This is useful when the file must be moved across a network and some temporary compression is
// helpful.
bool compressible;
} StorageInterfaceNewReadParam;
typedef StorageRead *StorageInterfaceNewRead(
void *thisVoid, const String *file, bool ignoreMissing, StorageInterfaceNewReadParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Create a file write object. The file should not be opened immediately -- open() will be called on the IoWrite interface when the
// file needs to be opened.
typedef struct StorageInterfaceNewWriteParam
{
// File/path mode for storage that supports Posix-style permissions. modePath is only used in conjunction with createPath.
mode_t modeFile;
mode_t modePath;
// User/group name
const String *user;
const String *group;
// Modified time
time_t timeModified;
// Will paths be created as needed?
bool createPath;
// Sync file/path when required by the storage
bool syncFile;
bool syncPath;
// Ensure the file written atomically. If this is false it's OK to write atomically if that's all the storage supperts
// (e.g. S3). Non-atomic writes are used in some places where there is a performance advantage and atomicity is not needed.
bool atomic;
// Is the file compressible? This is useful when the file must be moved across a network and some temporary compression is
// helpful.
bool compressible;
} StorageInterfaceNewWriteParam;
typedef StorageWrite *StorageInterfaceNewWrite(void *thisVoid, const String *file, StorageInterfaceNewWriteParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Get info for a path and all paths/files in the path (does not recurse)
typedef struct StorageInterfaceInfoListParam
{
bool dummy; // No optional parameters
} StorageInterfaceInfoListParam;
typedef bool StorageInterfaceInfoList(
void *thisVoid, const String *file, StorageInfoListCallback callback, void *callbackData, StorageInterfaceInfoListParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Remove a path (and optionally recurse)
typedef struct StorageInterfacePathRemoveParam
{
bool dummy; // No optional parameters
} StorageInterfacePathRemoveParam;
typedef bool StorageInterfacePathRemove(void *thisVoid, const String *path, bool recurse, StorageInterfacePathRemoveParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Remove a file
typedef struct StorageInterfaceRemoveParam
{
// Error when the file to delete is missing
bool errorOnMissing;
} StorageInterfaceRemoveParam;
typedef void StorageInterfaceRemove(void *thisVoid, const String *file, StorageInterfaceRemoveParam param);
/***********************************************************************************************************************************
Optional interface functions
***********************************************************************************************************************************/
// Move a file atomically
typedef struct StorageInterfaceMoveParam
{
bool dummy; // No optional parameters
} StorageInterfaceMoveParam;
typedef bool StorageInterfaceMove(void *thisVoid, StorageRead *source, StorageWrite *destination, StorageInterfaceMoveParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Create a path
typedef struct StorageInterfacePathCreateParam
{
bool dummy; // No optional parameters
} StorageInterfacePathCreateParam;
typedef void StorageInterfacePathCreate(
void *thisVoid, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode,
StorageInterfacePathCreateParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Does a path exist?
typedef struct StorageInterfacePathExistsParam
{
bool dummy; // No optional parameters
} StorageInterfacePathExistsParam;
typedef bool StorageInterfacePathExists(void *thisVoid, const String *path, StorageInterfacePathExistsParam param);
// ---------------------------------------------------------------------------------------------------------------------------------
// Sync a path
typedef struct StorageInterfacePathSyncParam
{
bool dummy; // No optional parameters
} StorageInterfacePathSyncParam;
typedef void StorageInterfacePathSync(void *thisVoid, const String *path, StorageInterfacePathSyncParam param);
/***********************************************************************************************************************************
Constructor
@ -57,21 +204,21 @@ typedef struct StorageInterface
// Features implemented by the storage driver
uint64_t feature;
bool (*copy)(StorageRead *source, StorageWrite *destination);
bool (*exists)(void *driver, const String *file);
StorageInfo (*info)(void *driver, const String *path, bool followLink);
bool (*infoList)(void *driver, const String *file, StorageInfoListCallback callback, void *callbackData);
StringList *(*list)(void *driver, const String *path, const String *expression);
bool (*move)(void *driver, StorageRead *source, StorageWrite *destination);
StorageRead *(*newRead)(void *driver, const String *file, bool ignoreMissing, bool compressible);
StorageWrite *(*newWrite)(
void *driver, const String *file, mode_t modeFile, mode_t modePath, const String *user, const String *group,
time_t timeModified, bool createPath, bool syncFile, bool syncPath, bool atomic, bool compressible);
void (*pathCreate)(void *driver, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode);
bool (*pathExists)(void *driver, const String *path);
bool (*pathRemove)(void *driver, const String *path, bool recurse);
void (*pathSync)(void *driver, const String *path);
void (*remove)(void *driver, const String *file, bool errorOnMissing);
// Required functions
StorageInterfaceExists *exists;
StorageInterfaceInfo *info;
StorageInterfaceInfoList *infoList;
StorageInterfaceList *list;
StorageInterfaceNewRead *newRead;
StorageInterfaceNewWrite *newWrite;
StorageInterfacePathRemove *pathRemove;
StorageInterfaceRemove *remove;
// Optional functions
StorageInterfaceMove *move;
StorageInterfacePathCreate *pathCreate;
StorageInterfacePathExists *pathExists;
StorageInterfacePathSync *pathSync;
} StorageInterface;
#define storageNewP(type, path, modeFile, modePath, write, pathExpressionFunction, driver, ...) \