Skip to content
Permalink
Browse files

Add pathExists() to Storage object.

The S3 driver did not get an implementation since S3 has a weak notion of paths, and it is not currently required.
  • Loading branch information...
dwsteele committed May 9, 2019
1 parent cb00030 commit c99c7c458b0a04d1f1a637be70bb4f8e8011feb0
@@ -51,6 +51,10 @@
<p>Allow <code>StorageFileWrite</code> to set user, group, and modification time.</p>
</release-item>

<release-item>
<p>Add <code>pathExists()</code> to <code>Storage</code> object.</p>
</release-item>

<release-item>
<p>Don't append <code>strerror()</code> to error message when <code>errno</code> is 0.</p>
</release-item>
@@ -479,6 +479,40 @@ 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)
{
THIS(StoragePosix);

FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_END();

ASSERT(this != NULL);
ASSERT(path != NULL);

bool result = false;

// Attempt to stat the file to determine if it exists
struct stat statPath;

// Any error other than entry not found should be reported
if (stat(strPtr(path), &statPath) == -1)
{
if (errno != ENOENT)
THROW_SYS_ERROR_FMT(PathOpenError, "unable to stat '%s'", strPtr(path));
}
// Else found
else
result = S_ISDIR(statPath.st_mode);

FUNCTION_LOG_RETURN(BOOL, result);
}

/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
@@ -638,7 +672,8 @@ storagePosixNewInternal(
type, path, modeFile, modePath, write, pathExpressionFunction, driver, .exists = storagePosixExists,
.info = storagePosixInfo, .infoList = storagePosixInfoList, .list = storagePosixList, .move = storagePosixMove,
.newRead = storagePosixNewRead, .newWrite = storagePosixNewWrite, .pathCreate = storagePosixPathCreate,
.pathRemove = storagePosixPathRemove, .pathSync = storagePosixPathSync, .remove = storagePosixRemove);
.pathExists = storagePosixPathExists, .pathRemove = storagePosixPathRemove, .pathSync = storagePosixPathSync,
.remove = storagePosixRemove);
}
MEM_CONTEXT_NEW_END();

@@ -19,6 +19,7 @@ STRING_EXTERN(PROTOCOL_COMMAND_STORAGE_EXISTS_STR, PROTOCOL_COM
STRING_EXTERN(PROTOCOL_COMMAND_STORAGE_LIST_STR, PROTOCOL_COMMAND_STORAGE_LIST);
STRING_EXTERN(PROTOCOL_COMMAND_STORAGE_OPEN_READ_STR, PROTOCOL_COMMAND_STORAGE_OPEN_READ);
STRING_EXTERN(PROTOCOL_COMMAND_STORAGE_OPEN_WRITE_STR, PROTOCOL_COMMAND_STORAGE_OPEN_WRITE);
STRING_EXTERN(PROTOCOL_COMMAND_STORAGE_PATH_EXISTS_STR, PROTOCOL_COMMAND_STORAGE_PATH_EXISTS);

/***********************************************************************************************************************************
Regular expressions
@@ -164,6 +165,14 @@ storageRemoteProtocol(const String *command, const VariantList *paramList, Proto

protocolServerResponse(server, NULL);
}
else if (strEq(command, PROTOCOL_COMMAND_STORAGE_PATH_EXISTS_STR))
{
// Not all drivers implement pathExists()
CHECK(interface.pathExists != NULL);

protocolServerResponse(server, VARBOOL( // The unusual line break is to make coverage happy -- not sure why
interface.pathExists(driver, storagePathNP(storage, varStr(varLstGet(paramList, 0))))));
}
else
found = false;
}
@@ -21,6 +21,8 @@ Constants
STRING_DECLARE(PROTOCOL_COMMAND_STORAGE_OPEN_READ_STR);
#define PROTOCOL_COMMAND_STORAGE_OPEN_WRITE "storageOpenWrite"
STRING_DECLARE(PROTOCOL_COMMAND_STORAGE_OPEN_WRITE_STR);
#define PROTOCOL_COMMAND_STORAGE_PATH_EXISTS "storagePathExists"
STRING_DECLARE(PROTOCOL_COMMAND_STORAGE_PATH_EXISTS_STR);

/***********************************************************************************************************************************
Functions
@@ -189,6 +189,35 @@ 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)
{
THIS(StorageRemote);

FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE_REMOTE, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_END();

ASSERT(this != NULL);

bool result = false;

MEM_CONTEXT_TEMP_BEGIN()
{
ProtocolCommand *command = protocolCommandNew(PROTOCOL_COMMAND_STORAGE_PATH_EXISTS_STR);
protocolCommandParamAdd(command, VARSTR(path));

result = varBool(protocolClientExecute(this->client, command, true));
}
MEM_CONTEXT_TEMP_END();

FUNCTION_LOG_RETURN(BOOL, result);
}

/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
@@ -286,8 +315,8 @@ storageRemoteNew(
this = storageNewP(
STORAGE_REMOTE_TYPE_STR, NULL, modeFile, modePath, write, pathExpressionFunction, driver,
.exists = storageRemoteExists, .info = storageRemoteInfo, .list = storageRemoteList, .newRead = storageRemoteNewRead,
.newWrite = storageRemoteNewWrite, .pathCreate = storageRemotePathCreate, .pathRemove = storageRemotePathRemove,
.pathSync = storageRemotePathSync, .remove = storageRemoteRemove);
.newWrite = storageRemoteNewWrite, .pathCreate = storageRemotePathCreate, .pathExists = storageRemotePathExists,
.pathRemove = storageRemotePathRemove, .pathSync = storageRemotePathSync, .remove = storageRemoteRemove);
}
MEM_CONTEXT_NEW_END();

@@ -583,6 +583,31 @@ storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateP
FUNCTION_LOG_RETURN_VOID();
}

/***********************************************************************************************************************************
Does a path exist?
***********************************************************************************************************************************/
bool
storagePathExists(const Storage *this, const String *pathExp)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, this);
FUNCTION_LOG_PARAM(STRING, pathExp);
FUNCTION_LOG_END();

ASSERT(this != NULL);
ASSERT(this->interface.pathExists != NULL);

bool result = false;

MEM_CONTEXT_TEMP_BEGIN()
{
result = this->interface.pathExists(this->driver, storagePathNP(this, pathExp));
}
MEM_CONTEXT_TEMP_END();

FUNCTION_LOG_RETURN(BOOL, result);
}

/***********************************************************************************************************************************
Remove a path
***********************************************************************************************************************************/
@@ -183,6 +183,14 @@ typedef struct StoragePathCreateParam

void storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateParam param);

/***********************************************************************************************************************************
storagePathExists
***********************************************************************************************************************************/
#define storagePathExistsNP(this, pathExp) \
storagePathExists(this, pathExp)

bool storagePathExists(const Storage *this, const String *pathExp);

/***********************************************************************************************************************************
storagePathRemove
***********************************************************************************************************************************/
@@ -34,6 +34,7 @@ typedef struct StorageInterface
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);
void (*pathCreate)(void *driver, const String *path, bool errorOnExists, bool noParentCreate, mode_t mode);
bool (*pathExists)(void *driver, const String *path);
void (*pathRemove)(void *driver, const String *path, bool errorOnMissing, bool recurse);
void (*pathSync)(void *driver, const String *path, bool ignoreMissing);
void (*remove)(void *driver, const String *file, bool errorOnMissing);
@@ -525,7 +525,7 @@ unit:

# ----------------------------------------------------------------------------------------------------------------------------
- name: remote
total: 5
total: 6
perlReq: true

coverage:
@@ -149,24 +149,32 @@ testRun(void)
}

// *****************************************************************************************************************************
if (testBegin("storageExists()"))
if (testBegin("storageExists() and storagePathExists()"))
{
TEST_CREATE_NOPERM();

// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(storageExistsNP(storageTest, strNew("missing")), false, "file does not exist");
TEST_RESULT_BOOL(storageExistsP(storageTest, strNew("missing"), .timeout = 100), false, "file does not exist");

// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(storagePathExistsNP(storageTest, strNew("missing")), false, "path does not exist");
TEST_RESULT_BOOL(storagePathExistsNP(storageTest, NULL), true, "test path exists");

// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR_FMT(
storageExistsNP(storageTest, fileNoPerm), FileOpenError,
"unable to stat '%s': [13] Permission denied", strPtr(fileNoPerm));
TEST_ERROR_FMT(
storagePathExistsNP(storageTest, fileNoPerm), PathOpenError,
"unable to stat '%s': [13] Permission denied", strPtr(fileNoPerm));

// -------------------------------------------------------------------------------------------------------------------------
String *fileExists = strNewFmt("%s/exists", testPath());
TEST_RESULT_INT(system(strPtr(strNewFmt("touch %s", strPtr(fileExists)))), 0, "create exists file");

TEST_RESULT_BOOL(storageExistsNP(storageTest, fileExists), true, "file exists");
TEST_RESULT_BOOL(storagePathExistsNP(storageTest, fileExists), false, "not a path");
TEST_RESULT_INT(system(strPtr(strNewFmt("sudo rm %s", strPtr(fileExists)))), 0, "remove exists file");

// -------------------------------------------------------------------------------------------------------------------------
@@ -302,6 +302,28 @@ testRun(void)
"check file");
}

// *****************************************************************************************************************************
if (testBegin("storagePathExists()"))
{
Storage *storageRemote = NULL;
TEST_ASSIGN(storageRemote, storageRepoGet(strNew(STORAGE_TYPE_POSIX), false), "get remote repo storage");
storagePathCreateNP(storageTest, strNew("repo"));

TEST_RESULT_BOOL(storagePathExistsNP(storageRemote, strNew("missing")), false, "path does not exist");
TEST_RESULT_BOOL(storagePathExistsNP(storageRemote, NULL), true, "path exists");

// Check protocol function directly
// -------------------------------------------------------------------------------------------------------------------------
VariantList *paramList = varLstNew();
varLstAdd(paramList, varNewStr(strNew("test")));

TEST_RESULT_BOOL(
storageRemoteProtocol(PROTOCOL_COMMAND_STORAGE_PATH_EXISTS_STR, paramList, server), true, "protocol path exists");
TEST_RESULT_STR(strPtr(strNewBuf(serverWrite)), "{\"out\":false}\n", "check result");

bufUsedSet(serverWrite, 0);
}

// *****************************************************************************************************************************
if (testBegin("UNIMPLEMENTED"))
{

0 comments on commit c99c7c4

Please sign in to comment.
You can’t perform that action at this time.