Skip to content

Commit

Permalink
Merge branch 'develop' into KDESKTOP-813-Enhance-CI-logging-visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
ClementKunz authored May 2, 2024
2 parents dfd4be2 + 8410114 commit 3b01b1e
Show file tree
Hide file tree
Showing 17 changed files with 678 additions and 287 deletions.
12 changes: 9 additions & 3 deletions src/libcommon/utility/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ typedef std::string NodeId;
typedef std::filesystem::path SyncPath;
typedef std::filesystem::path::string_type SyncName;
typedef std::filesystem::path::value_type SyncChar;
typedef std::filesystem::directory_entry DirectoryEntry;
typedef std::filesystem::directory_options DirectoryOptions;

typedef std::variant<bool, int, int64_t, uint64_t, double, std::string, std::wstring> SigValueType;

Expand Down Expand Up @@ -344,6 +346,7 @@ typedef enum {
IoErrorIsADirectory,
IoErrorNoSuchFileOrDirectory,
IoErrorResultOutOfRange,
IoErrorInvalidDirectoryIterator,
IoErrorUnknown
} IoError;

Expand All @@ -360,8 +363,11 @@ struct ItemType {
};

enum class AppStateKey {
// Adding a new key here requires to add it in insertDefaultAppState in parmsdbappstate.cpp and ideally testparmsdb.cpp
Unknown, // Used for initialization, will throw error if used
Test // To be removed after the implementation of the first key
// Adding a new key here requires to add it in insertDefaultAppState in parmsdbappstate.cpp
LastServerSelfRestart,
LastClientSelfRestart,

Unknown, //!\ keep in last position (For tests) /!\\ Used for initialization, will throw error if used.
};

} // namespace KDC
113 changes: 113 additions & 0 deletions src/libcommonserver/io/iohelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ std::string IoHelper::ioError2StdString(IoError ioError) noexcept {
return "Result out of range";
case IoErrorSuccess:
return "Success";
case IoErrorInvalidDirectoryIterator:
return "Invalid directory iterator";
default:
return "Unknown error";
}
Expand Down Expand Up @@ -478,6 +480,34 @@ bool IoHelper::createDirectory(const SyncPath &path, IoError &ioError) noexcept
return creationSuccess;
}

bool IoHelper::deleteDirectory(const SyncPath &path, IoError &ioError) noexcept {
std::error_code ec;
std::filesystem::remove_all(path, ec);
ioError = stdError2ioError(ec);
return ioError == IoErrorSuccess;
}

bool IoHelper::copyFileOrDirectory(const SyncPath &sourcePath, const SyncPath &destinationPath, IoError &ioError) noexcept {
std::error_code ec;
std::filesystem::copy(sourcePath, destinationPath, std::filesystem::copy_options::recursive, ec);
ioError = IoHelper::stdError2ioError(ec);

return ioError == IoErrorSuccess;
}

bool IoHelper::getDirectoryIterator(const SyncPath &path, bool recursive, IoError &ioError,
DirectoryIterator &iterator) noexcept {
iterator = DirectoryIterator(path, recursive, ioError);
return ioError == IoErrorSuccess;
}

bool IoHelper::getDirectoryEntry(const SyncPath &path, IoError &ioError, DirectoryEntry &entry) noexcept {
std::error_code ec;
entry = std::filesystem::directory_entry(path, ec);
ioError = stdError2ioError(ec);
return ioError == IoErrorSuccess;
}

bool IoHelper::createSymlink(const SyncPath &targetPath, const SyncPath &path, IoError &ioError) noexcept {
if (targetPath == path) {
LOGW_DEBUG(Log::instance()->getLogger(), L"Cannot create symlink on itself - path=" << Path2WStr(path).c_str());
Expand Down Expand Up @@ -508,6 +538,89 @@ bool IoHelper::createSymlink(const SyncPath &targetPath, const SyncPath &path, I
return ioError == IoErrorSuccess;
}

// DirectoryIterator

IoHelper::DirectoryIterator::DirectoryIterator(const SyncPath &directoryPath, bool recursive, IoError &ioError)
: _recursive(recursive), _directoryPath(directoryPath) {
std::error_code ec;

_dirIterator = std::filesystem::begin(
std::filesystem::recursive_directory_iterator(directoryPath, DirectoryOptions::skip_permission_denied, ec));
ioError = IoHelper::stdError2ioError(ec);
}


bool IoHelper::DirectoryIterator::next(DirectoryEntry &nextEntry, bool &endOfDirectory, IoError &ioError) {
std::error_code ec;
endOfDirectory = false;

if (_invalid) {
ioError = IoErrorInvalidDirectoryIterator;
return true;
}

if (_directoryPath == "") {
ioError = IoErrorInvalidArgument;
return false;
}

if (_dirIterator == std::filesystem::end(std::filesystem::recursive_directory_iterator(_directoryPath, ec))) {
endOfDirectory = true;
ioError = IoErrorSuccess;
return true;
}

if (!_recursive) {
disableRecursionPending();
}

if (!_firstElement) {
_dirIterator.increment(ec);
ioError = IoHelper::stdError2ioError(ec);

if (ioError != IoErrorSuccess) {
_invalid = true;
return true;
}

} else {
_firstElement = false;
}

if (_dirIterator != std::filesystem::end(std::filesystem::recursive_directory_iterator(_directoryPath, ec))) {
ioError = IoHelper::stdError2ioError(ec);

if (ioError != IoErrorSuccess) {
_invalid = true;
return true;
}

#ifdef _WIN32
// skip_permission_denied doesn't work on Windows
try {
bool dummy = _dirIterator->exists();
(void)dummy;
nextEntry = *_dirIterator;
return true;
} catch (std::filesystem::filesystem_error &) {
_dirIterator.disable_recursion_pending();
return next(nextEntry, endOfDirectory, ioError);
}

#endif
nextEntry = *_dirIterator;
return true;
} else {
ioError = IoErrorSuccess;
endOfDirectory = true;
return true;
}
}

void IoHelper::DirectoryIterator::disableRecursionPending() {
_dirIterator.disable_recursion_pending();
}

#ifndef _WIN32
//See iohelper_win.cpp for the Windows implementation
bool IoHelper::setRights(const SyncPath &path, bool read, bool write, bool exec, IoError &ioError) noexcept {
Expand Down
66 changes: 65 additions & 1 deletion src/libcommonserver/io/iohelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,31 @@ namespace KDC {

struct FileStat;


struct IoHelper {
public:
class DirectoryIterator {
public:
DirectoryIterator(const SyncPath &directoryPath, bool recursive, IoError &ioError);

DirectoryIterator() = default;
//! Get the next directory entry.
/*!
\param nextEntry is set with the next directory entry.
\param ioError holds the error returned when an underlying OS API call fails.
\return true if no error occurred, false otherwise.
*/
bool next(DirectoryEntry &nextEntry, bool &endOfDirectory, IoError &ioError);
void disableRecursionPending();

private:
bool _recursive = false;
bool _firstElement = true;
bool _invalid = false;
SyncPath _directoryPath;
std::filesystem::recursive_directory_iterator _dirIterator;
};

public:
IoHelper(){};

Expand Down Expand Up @@ -209,6 +233,44 @@ struct IoHelper {
*/
static bool createDirectory(const SyncPath &path, IoError &ioError) noexcept;

//! Remove a directory located under the specified path.
/*!
\param path is the file system path of the directory to remove.
\param ioError holds the error returned when an underlying OS API call fails.
\return true if no unexpected error occurred, false otherwise.
*/
static bool deleteDirectory(const SyncPath &path, IoError &ioError) noexcept;

//! Create a directory iterator for the specified path. The iterator can be used to iterate over the items in the directory.
/*!
\param path is the file system path of the directory to iterate over.
\param recursive is a boolean indicating whether the iterator should be recursive or not.
\param ioError holds the error returned when an underlying OS API call fails.
\param iterator is the directory iterator that is set with the directory iterator for the specified path.
\return true if no unexpected error occurred, false otherwise.
*/
static bool getDirectoryIterator(const SyncPath &path, bool recursive, IoError &ioError,
DirectoryIterator &iterator) noexcept;

//! Create a directory entry for the specified path.
/*!
* \param path is the file system path of the directory entry to create.
* \param ioError holds the error returned when an underlying OS API call fails.
* \entry is the directory entry that is set with the directory entry for the specified path.
* \return true if no unexpected error occurred, false otherwise.
*/
static bool getDirectoryEntry(const SyncPath &path, IoError &ioError, DirectoryEntry &entry) noexcept;

//! Copy the item indicated by `sourcePath` to the location indicated by `destinationPath`.
/*!
\param sourcePath is the file system path of the item to copy.
\param destinationPath is the file system path of the location to copy the item to.
\param ioError holds the error associated to a failure of the underlying OS API call, if any.
\return true if no unexpected error occurred, false otherwise.
*/
static bool copyFileOrDirectory(const SyncPath &sourcePath, const SyncPath &destinationPath, IoError &ioError) noexcept;


#ifdef __APPLE__
// From `man xattr`:
// Extended attributes are arbitrary metadata stored with a file, but separate from the
Expand Down Expand Up @@ -268,7 +330,7 @@ struct IoHelper {
\return true if no unexpected error occurred, false otherwise.
*/
static bool getRights(const SyncPath &path, bool &read, bool &write, bool &exec, IoError &ioError) noexcept;

//! Set the rights of the item indicated by `path`.
/*!
\param path is the file system path of the item.
Expand All @@ -281,6 +343,8 @@ struct IoHelper {
static bool setRights(const SyncPath &path, bool read, bool write, bool exec, IoError &ioError) noexcept;

protected:
friend class DirectoryIterator;

// These functions default to the std::filesystem functions.
// They can be modified in tests.
static std::function<bool(const SyncPath &path, std::error_code &ec)> _isDirectory;
Expand Down
3 changes: 2 additions & 1 deletion src/libcommonserver/io/iohelper_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ IoError dWordError2ioError(DWORD error) noexcept {
case ERROR_FILE_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_NAME:
return IoErrorNoSuchFileOrDirectory;
default:
LOG_WARN(Log::instance()->getLogger(), L"Unknown IO error - error=" << error);
return IoErrorUnknown;
}
} // namespace
Expand Down Expand Up @@ -549,7 +551,6 @@ bool IoHelper::getRights(const SyncPath &path, bool &read, bool &write, bool &ex
LOGW_WARN(logger(), L"Failed to get permissions: " << Utility::formatStdError(path, ec).c_str());
return _isExpectedError(ioError);
}

read = ((perms & std::filesystem::perms::owner_read) != std::filesystem::perms::none);
write = ((perms & std::filesystem::perms::owner_write) != std::filesystem::perms::none);
exec = ((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none);
Expand Down
2 changes: 1 addition & 1 deletion src/libparms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set(parms_SRCS
db/error.h db/error.cpp
db/migrationselectivesync.h db/migrationselectivesync.cpp
db/uploadsessiontoken.h db/uploadsessiontoken.cpp
db/parmsdbappstate.h db/parmsdbappstate.cpp
db/parmsdbappstate.cpp
)

if (APPLE)
Expand Down
Loading

0 comments on commit 3b01b1e

Please sign in to comment.