Skip to content
Permalink
Browse files

Add storageInfoList() to get detailed info about all entries in a path.

The function provides all the file/path/link information required to build a backup manifest.

Also update storageInfo() to provide the same information for a single file.
  • Loading branch information...
dwsteele committed Apr 23, 2019
1 parent f492f05 commit 52b0b81976df5583ebe12189d8697dd66d23e84b
@@ -25,6 +25,10 @@
<p>Only process next filter in <code>IoFilterGroup</code> when input buffer is full or flushing.</p>
</release-item>

<release-item>
<p>Add <code>storageInfoList()</code> to get detailed info about all entries in a path.</p>
</release-item>

<release-item>
<p>Add <code>ioWriteStr()</code> and <code>ioWriteStrLine()</code>.</p>
</release-item>
@@ -188,11 +188,10 @@ cmdArchiveGet(void)
if (strLstSize(queue) > 0)
{
// Get size of the WAL segment
size_t walSegmentSize = storageInfoNP(storageLocal(), walDestination).size;
uint64_t walSegmentSize = storageInfoNP(storageLocal(), walDestination).size;

// Use WAL segment size to estimate queue size and determine if the async process should be launched
queueFull =
strLstSize(queue) * walSegmentSize > cfgOptionUInt64(cfgOptArchiveGetQueueMax) / 2;
queueFull = strLstSize(queue) * walSegmentSize > cfgOptionUInt64(cfgOptArchiveGetQueueMax) / 2;
}
}

@@ -4,6 +4,8 @@ Posix Storage Driver
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@@ -16,6 +18,13 @@ Posix Storage Driver
#include "storage/driver/posix/storage.h"
#include "storage/driver/posix/common.h"

/***********************************************************************************************************************************
Define PATH_MAX if it is not defined
***********************************************************************************************************************************/
#ifndef PATH_MAX
#define PATH_MAX (4 * 1024)
#endif

/***********************************************************************************************************************************
Driver type constant string
***********************************************************************************************************************************/
@@ -60,8 +69,8 @@ storageDriverPosixNew(
this->interface = storageNewP(
STORAGE_DRIVER_POSIX_TYPE_STR, path, modeFile, modePath, write, pathExpressionFunction, this,
.exists = (StorageInterfaceExists)storageDriverPosixExists, .info = (StorageInterfaceInfo)storageDriverPosixInfo,
.list = (StorageInterfaceList)storageDriverPosixList, .move = (StorageInterfaceMove)storageDriverPosixMove,
.newRead = (StorageInterfaceNewRead)storageDriverPosixNewRead,
.infoList = (StorageInterfaceInfoList)storageDriverPosixInfoList, .list = (StorageInterfaceList)storageDriverPosixList,
.move = (StorageInterfaceMove)storageDriverPosixMove, .newRead = (StorageInterfaceNewRead)storageDriverPosixNewRead,
.newWrite = (StorageInterfaceNewWrite)storageDriverPosixNewWrite,
.pathCreate = (StorageInterfacePathCreate)storageDriverPosixPathCreate,
.pathRemove = (StorageInterfacePathRemove)storageDriverPosixPathRemove,
@@ -134,16 +143,40 @@ storageDriverPosixInfo(StorageDriverPosix *this, const String *file, bool ignore
else
{
result.exists = true;
result.timeModified = statFile.st_mtime;

// Get user name if it exists
struct passwd *userData = getpwuid(statFile.st_uid);

if (userData != NULL)
result.user = strNew(userData->pw_name);

// Get group name if it exists
struct group *groupData = getgrgid(statFile.st_gid);

if (groupData != NULL)
result.group = strNew(groupData->gr_name);

if (S_ISREG(statFile.st_mode))
{
result.type = storageTypeFile;
result.size = (size_t)statFile.st_size;
result.size = (uint64_t)statFile.st_size;
}
else if (S_ISDIR(statFile.st_mode))
result.type = storageTypePath;
else if (S_ISLNK(statFile.st_mode))
{
result.type = storageTypeLink;

char linkDestination[PATH_MAX];
ssize_t linkDestinationSize = 0;

THROW_ON_SYS_ERROR_FMT(
(linkDestinationSize = readlink(strPtr(file), linkDestination, sizeof(linkDestination) - 1)) == -1,
FileReadError, "unable to get destination for link '%s'", strPtr(file));

result.linkDestination = strNewN(linkDestination, (size_t)linkDestinationSize);
}
else
THROW_FMT(FileInfoError, "invalid type for '%s'", strPtr(file));

@@ -153,6 +186,106 @@ storageDriverPosixInfo(StorageDriverPosix *this, const String *file, bool ignore
FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}

/***********************************************************************************************************************************
Info for all files/paths in a path
***********************************************************************************************************************************/
static void
storageDriverPosixInfoListEntry(
StorageDriverPosix *this, const String *path, const String *name, StorageInfoListCallback callback, void *callbackData)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STORAGE_DRIVER_POSIX, this);
FUNCTION_TEST_PARAM(STRING, path);
FUNCTION_TEST_PARAM(STRING, name);
FUNCTION_TEST_PARAM(FUNCTIONP, callback);
FUNCTION_TEST_PARAM_P(VOID, callbackData);
FUNCTION_TEST_END();

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

if (!strEqZ(name, ".."))
{
String *pathInfo = strEqZ(name, ".") ? strDup(path) : strNewFmt("%s/%s", strPtr(path), strPtr(name));

StorageInfo storageInfo = storageDriverPosixInfo(this, pathInfo, true);

if (storageInfo.exists)
{
storageInfo.name = name;
callback(callbackData, &storageInfo);
}

strFree(pathInfo);
}

FUNCTION_TEST_RETURN_VOID();
}

bool
storageDriverPosixInfoList(
StorageDriverPosix *this, const String *path, bool errorOnMissing, StorageInfoListCallback callback, void *callbackData)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STORAGE_DRIVER_POSIX, this);
FUNCTION_LOG_PARAM(STRING, path);
FUNCTION_LOG_PARAM(BOOL, errorOnMissing);
FUNCTION_LOG_PARAM(FUNCTIONP, callback);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
FUNCTION_LOG_END();

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

DIR *dir = NULL;
bool result = false;

TRY_BEGIN()
{
// Open the directory for read
dir = opendir(strPtr(path));

// If the directory could not be opened process errors but ignore missing directories when specified
if (!dir)
{
if (errorOnMissing || errno != ENOENT)
THROW_SYS_ERROR_FMT(PathOpenError, "unable to open path '%s' for read", strPtr(path));
}
else
{
// Directory was found
result = true;

MEM_CONTEXT_TEMP_BEGIN()
{
// Read the directory entries
struct dirent *dirEntry = readdir(dir);

while (dirEntry != NULL)
{
// Get info and perform callback
storageDriverPosixInfoListEntry(this, path, STR(dirEntry->d_name), callback, callbackData);

// Get next entry
dirEntry = readdir(dir);
}
}
MEM_CONTEXT_TEMP_END();
}
}
FINALLY()
{
if (dir != NULL)
closedir(dir);
}
TRY_END();

FUNCTION_LOG_RETURN(BOOL, result);
}

/***********************************************************************************************************************************
Get a list of files from a directory
***********************************************************************************************************************************/
@@ -35,6 +35,8 @@ Functions
***********************************************************************************************************************************/
bool storageDriverPosixExists(StorageDriverPosix *this, const String *path);
StorageInfo storageDriverPosixInfo(StorageDriverPosix *this, const String *file, bool ignoreMissing);
bool storageDriverPosixInfoList(
StorageDriverPosix *this, const String *path, bool errorOnMissing, StorageInfoListCallback callback, void *callbackData);
StringList *storageDriverPosixList(StorageDriverPosix *this, const String *path, bool errorOnMissing, const String *expression);
bool storageDriverPosixMove(StorageDriverPosix *this, StorageDriverPosixFileRead *source, StorageDriverPosixFileWrite *destination);
StorageFileRead *storageDriverPosixNewRead(StorageDriverPosix *this, const String *file, bool ignoreMissing);
@@ -21,10 +21,15 @@ Object type
***********************************************************************************************************************************/
typedef struct StorageInfo
{
bool exists; // Does the path/file/link exist?
const String *name; // Name of path/file/link
const String *linkDestination; // Destination if this is a link
StorageType type; // Type file/path/link)
size_t size; // Size (path/link is 0)
bool exists; // Does the path/file/link exist?
const String *user; // User that owns the file
const String *group; // Group that owns the file
mode_t mode; // Mode of path/file/link
time_t timeModified; // Time file was last modified
uint64_t size; // Size (path/link is 0)
} StorageInfo;

/***********************************************************************************************************************************
@@ -247,12 +247,53 @@ storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param)

// Call driver function
result = this->interface.info(this->driver, file, param.ignoreMissing);

// Dup the strings into the calling context
memContextSwitch(MEM_CONTEXT_OLD());
result.linkDestination = strDup(result.linkDestination);
result.user = strDup(result.user);
result.group = strDup(result.group);
memContextSwitch(MEM_CONTEXT_TEMP());
}
MEM_CONTEXT_TEMP_END();

FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}

/***********************************************************************************************************************************
Info for all files/paths in a path
***********************************************************************************************************************************/
bool
storageInfoList(
const Storage *this, const String *pathExp, StorageInfoListCallback callback, void *callbackData, StorageInfoListParam param)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, this);
FUNCTION_LOG_PARAM(STRING, pathExp);
FUNCTION_LOG_PARAM(FUNCTIONP, callback);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
FUNCTION_LOG_PARAM(BOOL, param.errorOnMissing);
FUNCTION_LOG_END();

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

bool result = false;

MEM_CONTEXT_TEMP_BEGIN()
{
// Build the path
String *path = storagePathNP(this, pathExp);

// Call driver function
result = this->interface.infoList(this->driver, path, param.errorOnMissing, callback, callbackData);
}
MEM_CONTEXT_TEMP_END();

FUNCTION_LOG_RETURN(BOOL, result);
}

/***********************************************************************************************************************************
Get a list of files from a directory
***********************************************************************************************************************************/
@@ -72,6 +72,24 @@ typedef struct StorageInfoParam

StorageInfo storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param);

/***********************************************************************************************************************************
storageInfoList
***********************************************************************************************************************************/
typedef void (*StorageInfoListCallback)(void *callbackData, const StorageInfo *info);

typedef struct StorageInfoListParam
{
bool errorOnMissing;
} StorageInfoListParam;

#define storageInfoListP(this, fileExp, callback, callbackData, ...) \
storageInfoList(this, fileExp, callback, callbackData, (StorageInfoListParam){__VA_ARGS__})
#define storageInfoListNP(this, fileExp, callback, callbackData) \
storageInfoList(this, fileExp, callback, callbackData, (StorageInfoListParam){0})

bool storageInfoList(
const Storage *this, const String *pathExp, StorageInfoListCallback callback, void *callbackData, StorageInfoListParam param);

/***********************************************************************************************************************************
storageList
***********************************************************************************************************************************/
@@ -21,7 +21,9 @@ typedef String *(*StoragePathExpressionCallback)(const String *expression, const
Constructor
***********************************************************************************************************************************/
typedef bool (*StorageInterfaceExists)(void *driver, const String *path);
typedef StorageInfo (*StorageInterfaceInfo)(void *driver, const String *file, bool ignoreMissing);
typedef StorageInfo (*StorageInterfaceInfo)(void *driver, const String *path, bool ignoreMissing);
typedef bool (*StorageInterfaceInfoList)(
void *driver, const String *file, bool ignoreMissing, StorageInfoListCallback callback, void *callbackData);
typedef StringList *(*StorageInterfaceList)(void *driver, const String *path, bool errorOnMissing, const String *expression);
typedef bool (*StorageInterfaceMove)(void *driver, void *source, void *destination);
typedef StorageFileRead *(*StorageInterfaceNewRead)(void *driver, const String *file, bool ignoreMissing);
@@ -37,6 +39,7 @@ typedef struct StorageInterface
{
StorageInterfaceExists exists;
StorageInterfaceInfo info;
StorageInterfaceInfoList infoList;
StorageInterfaceList list;
StorageInterfaceMove move;
StorageInterfaceNewRead newRead;
@@ -503,7 +503,7 @@ unit:

# ----------------------------------------------------------------------------------------------------------------------------
- name: posix
total: 20
total: 21

coverage:
storage/driver/posix/common: full
Oops, something went wrong.

0 comments on commit 52b0b81

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