Split directory.cpp into unix/win32 parts (#491)

directory.cpp was essentially two implementations in one, separated with ifdefs. It's cleaner to just have two separate files, seeing how CMakeLists.txt for libmediation needs to check the platform it's running on and add the appropriate file implementation anyway.

This commit splits this file into two and extracts common code parts to directory_priv.h.
master
Daniel Kamil Kozar 2021-11-12 18:16:15 +01:00 committed by GitHub
parent c2de3db345
commit c483756b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 305 additions and 275 deletions

View File

@ -6,3 +6,4 @@ BreakBeforeBraces: Allman
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
ColumnLimit: 120
IncludeBlocks: Preserve

View File

@ -2,17 +2,16 @@ cmake_minimum_required (VERSION 3.1)
project(mediation)
add_library(mediation STATIC
fs/directory.cpp
types/types.cpp
system/terminatablethread.cpp
)
IF(WIN32)
target_compile_definitions(mediation PRIVATE "-DUNICODE")
target_sources(mediation PRIVATE fs/osdep/file_win32.cpp)
target_sources(mediation PRIVATE fs/osdep/file_win32.cpp fs/osdep/directory_win32.cpp)
ELSE()
target_compile_definitions(mediation PRIVATE "-D_FILE_OFFSET_BITS=64")
target_sources(mediation PRIVATE fs/osdep/file_unix.cpp)
target_sources(mediation PRIVATE fs/osdep/file_unix.cpp fs/osdep/directory_unix.cpp)
ENDIF()
set(CMAKE_INCLUDE_CURRENT_DIR ON)

View File

@ -1,272 +0,0 @@
#include "directory.h"
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sstream>
#include "file.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <dirent.h>
#include <memory.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#endif
using namespace std;
char getDirSeparator()
{
#ifdef _WIN32
return '\\';
#else
return '/';
#endif
}
string extractFileDir(const string& fileName)
{
size_t index = fileName.find_last_of('/');
if (index != string::npos)
return fileName.substr(0, index + 1);
#ifdef _WIN32
index = fileName.find_last_of('\\');
if (index != string::npos)
return fileName.substr(0, index + 1);
#endif
return "";
}
bool fileExists(const string& fileName)
{
#ifdef _WIN32
File f;
return f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting);
#else
struct stat buf;
return stat(fileName.c_str(), &buf) == 0;
#endif
}
uint64_t getFileSize(const std::string& fileName)
{
#ifdef _WIN32
File f;
if (f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting))
{
uint64_t rv;
return f.size(&rv) ? rv : 0;
}
else
{
return 0;
}
#else
struct stat fileStat;
auto res = stat(fileName.c_str(), &fileStat) == 0;
return res ? static_cast<uint64_t>(fileStat.st_size) : 0;
#endif
}
bool createDir(const std::string& dirName, bool createParentDirs)
{
if (dirName.empty())
return false;
if (createParentDirs)
{
for (string::size_type separatorPos = dirName.find_first_not_of(getDirSeparator()), dirEnd = string::npos;
separatorPos != string::npos;
dirEnd = separatorPos, separatorPos = dirName.find_first_not_of(getDirSeparator(), separatorPos))
{
separatorPos = dirName.find(getDirSeparator(), separatorPos);
if (dirEnd != string::npos)
{
string parentDir = dirName.substr(0, dirEnd);
#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__))
if (mkdir(parentDir.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == -1)
{
if (errno != EEXIST)
return false;
}
#elif defined(_WIN32)
if (parentDir.size() == 0 || parentDir[parentDir.size() - 1] == ':' || parentDir == string("\\\\.") ||
parentDir == string("\\\\.\\") || // UNC patch prefix
(strStartWith(parentDir, "\\\\.\\") && parentDir[parentDir.size() - 1] == '}')) // UNC patch prefix
continue;
if (CreateDirectory(toWide(parentDir).data(), 0) == 0)
{
if (GetLastError() != ERROR_ALREADY_EXISTS)
return false;
}
#endif
}
}
}
#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__))
return mkdir(dirName.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0;
#elif defined(_WIN32)
return CreateDirectory(toWide(dirName).data(), 0) != 0;
#endif
}
bool deleteFile(const string& fileName)
{
#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__))
return unlink(fileName.c_str()) == 0;
#else
if (DeleteFile(toWide(fileName).data()))
{
return true;
}
else
{
DWORD err = GetLastError();
return false;
}
return DeleteFile(toWide(fileName).data()) != 0;
#endif
}
//-----------------------------------------------------------------------------
#if defined(_WIN32)
/** windows implementation */
//-----------------------------------------------------------------------------
#include <windows.h>
bool findFiles(const string& path, const string& fileMask, vector<string>* fileList, bool savePaths)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
HANDLE hSearch; // Search handle returned by FindFirstFile
auto searchStr = toWide(path + '/' + fileMask);
hSearch = FindFirstFile(searchStr.data(), &fileData);
if (hSearch == INVALID_HANDLE_VALUE)
return false;
do
{
if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
auto fileName = toUtf8(fileData.cFileName);
fileList->push_back(savePaths ? (path + '/' + fileName) : fileName);
}
} while (FindNextFile(hSearch, &fileData));
FindClose(hSearch);
return true;
}
bool findDirs(const string& path, vector<string>* dirsList)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
HANDLE hSearch; // Search handle returned by FindFirstFile
auto searchStr = toWide(path + "*");
hSearch = FindFirstFile(searchStr.data(), &fileData);
if (hSearch == INVALID_HANDLE_VALUE)
return false;
do
{
if (!(fileData.dwFileAttributes ^ FILE_ATTRIBUTE_DIRECTORY))
{
auto dirName = toUtf8(fileData.cFileName);
if ("." != dirName && ".." != dirName)
dirsList->push_back(path + dirName + "/");
}
} while (FindNextFile(hSearch, &fileData));
FindClose(hSearch);
return true;
}
#elif __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__))
#include <fnmatch.h>
bool findFiles(const string& path, const string& fileMask, vector<string>* fileList, bool savePaths)
{
dirent** namelist;
int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort);
if (n < 0)
{
return false;
}
else
{
while (n--)
{
if (namelist[n]->d_type == DT_REG)
{
string fileName(namelist[n]->d_name);
if (0 == fnmatch(fileMask.c_str(), fileName.c_str(), 0))
fileList->push_back(savePaths ? path + fileName : fileName);
}
free(namelist[n]);
}
free(namelist);
}
return true;
}
bool findDirs(const string& path, vector<string>* dirsList)
{
dirent** namelist;
int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort);
if (n < 0)
{
return false;
}
else
{
while (n--)
{
if (namelist[n]->d_type == DT_DIR)
{
string dirName(namelist[n]->d_name);
// we save only normal ones
if ("." != dirName && ".." != dirName)
dirsList->push_back(path + dirName + "/");
}
free(namelist[n]);
}
free(namelist);
}
return true;
}
#endif
//-----------------------------------------------------------------------------
bool findFilesRecursive(const string& path, const string& mask, vector<string>* const fileList)
{
// finding files
findFiles(path, mask, fileList, true);
vector<string> dirList;
findDirs(path, &dirList);
for (unsigned int d_idx = 0; d_idx != dirList.size(); d_idx++) findFilesRecursive(dirList[d_idx], mask, fileList);
return true;
}

View File

@ -0,0 +1,55 @@
#ifndef libmediation_directory_priv_h
#define libmediation_directory_priv_h
#include <string>
#include <vector>
template <typename F, typename D>
void recurseDirectorySearch(F&& findFilesFn, D&& findDirsFn, const std::string& path, const std::string& mask,
std::vector<std::string>* const fileList)
{
// finding files
findFilesFn(path, mask, fileList, true);
std::vector<std::string> dirList;
findDirsFn(path, &dirList);
for (auto&& dir : dirList)
{
recurseDirectorySearch(findFilesFn, findDirsFn, dir, mask, fileList);
}
}
template <typename SkipParentDirFn, typename CreateParentDirFn>
bool preCreateDir(SkipParentDirFn&& skipParentFn, CreateParentDirFn&& createParentFn, char dirSeparator,
const std::string& dirName, bool createParentDirs)
{
if (dirName.empty())
return false;
if (createParentDirs)
{
for (auto separatorPos = dirName.find_first_not_of(dirSeparator), dirEnd = std::string::npos;
separatorPos != std::string::npos;
dirEnd = separatorPos, separatorPos = dirName.find_first_not_of(dirSeparator, separatorPos))
{
separatorPos = dirName.find(dirSeparator, separatorPos);
if (dirEnd != std::string::npos)
{
auto parentDir = dirName.substr(0, dirEnd);
if (skipParentFn(parentDir))
{
continue;
}
if (!createParentFn(parentDir))
{
return false;
}
}
}
}
return true;
}
#endif

View File

@ -0,0 +1,116 @@
#include "../directory.h"
#include "../directory_priv.h"
#include <dirent.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
char getDirSeparator() { return '/'; }
string extractFileDir(const string& fileName)
{
size_t index = fileName.find_last_of('/');
if (index != string::npos)
return fileName.substr(0, index + 1);
return "";
}
bool fileExists(const string& fileName)
{
struct stat buf;
return stat(fileName.c_str(), &buf) == 0;
}
uint64_t getFileSize(const std::string& fileName)
{
struct stat fileStat;
auto res = stat(fileName.c_str(), &fileStat) == 0;
return res ? static_cast<uint64_t>(fileStat.st_size) : 0;
}
bool createDir(const std::string& dirName, bool createParentDirs)
{
auto ok = preCreateDir([](auto) { return false; },
[](auto&& parentDir) {
if (mkdir(parentDir.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == -1)
{
if (errno != EEXIST)
return false;
}
return true;
},
getDirSeparator(), dirName, createParentDirs);
return ok ? mkdir(dirName.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0 : false;
}
bool deleteFile(const string& fileName) { return unlink(fileName.c_str()) == 0; }
bool findFiles(const string& path, const string& fileMask, vector<string>* fileList, bool savePaths)
{
dirent** namelist;
int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort);
if (n < 0)
{
return false;
}
else
{
while (n--)
{
if (namelist[n]->d_type == DT_REG)
{
string fileName(namelist[n]->d_name);
if (0 == fnmatch(fileMask.c_str(), fileName.c_str(), 0))
fileList->push_back(savePaths ? path + fileName : fileName);
}
free(namelist[n]);
}
free(namelist);
}
return true;
}
bool findDirs(const string& path, vector<string>* dirsList)
{
dirent** namelist;
int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort);
if (n < 0)
{
return false;
}
else
{
while (n--)
{
if (namelist[n]->d_type == DT_DIR)
{
string dirName(namelist[n]->d_name);
// we save only normal ones
if ("." != dirName && ".." != dirName)
dirsList->push_back(path + dirName + "/");
}
free(namelist[n]);
}
free(namelist);
}
return true;
}
bool findFilesRecursive(const string& path, const string& mask, vector<string>* const fileList)
{
recurseDirectorySearch(findFiles, findDirs, path, mask, fileList);
return true;
}

View File

@ -0,0 +1,131 @@
#include <windows.h>
#include "../directory.h"
#include "../directory_priv.h"
#include "../file.h"
using namespace std;
char getDirSeparator() { return '\\'; }
string extractFileDir(const string& fileName)
{
size_t index = fileName.find_last_of('\\');
if (index != string::npos)
return fileName.substr(0, index + 1);
return "";
}
bool fileExists(const string& fileName)
{
File f;
return f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting);
}
uint64_t getFileSize(const std::string& fileName)
{
File f;
if (f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting))
{
uint64_t rv;
return f.size(&rv) ? rv : 0;
}
else
{
return 0;
}
}
bool createDir(const std::string& dirName, bool createParentDirs)
{
bool ok = preCreateDir(
[](auto&& parentDir) {
return parentDir.empty() || parentDir[parentDir.size() - 1] == ':' || parentDir == "\\\\." ||
parentDir == "\\\\.\\" || // UNC patch prefix
(strStartWith(parentDir, "\\\\.\\") && parentDir[parentDir.size() - 1] == '}'); // UNC patch prefix
},
[](auto&& parentDir) {
if (CreateDirectory(toWide(parentDir).data(), 0) == 0)
{
if (GetLastError() != ERROR_ALREADY_EXISTS)
return false;
}
return true;
},
getDirSeparator(), dirName, createParentDirs);
return ok ? CreateDirectory(toWide(dirName).data(), 0) != 0 : false;
}
bool deleteFile(const string& fileName)
{
if (DeleteFile(toWide(fileName).data()))
{
return true;
}
else
{
DWORD err = GetLastError();
return false;
}
return DeleteFile(toWide(fileName).data()) != 0;
}
bool findFiles(const string& path, const string& fileMask, vector<string>* fileList, bool savePaths)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
HANDLE hSearch; // Search handle returned by FindFirstFile
auto searchStr = toWide(path + '/' + fileMask);
hSearch = FindFirstFile(searchStr.data(), &fileData);
if (hSearch == INVALID_HANDLE_VALUE)
return false;
do
{
if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
auto fileName = toUtf8(fileData.cFileName);
fileList->push_back(savePaths ? (path + '/' + fileName) : fileName);
}
} while (FindNextFile(hSearch, &fileData));
FindClose(hSearch);
return true;
}
bool findDirs(const string& path, vector<string>* dirsList)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
HANDLE hSearch; // Search handle returned by FindFirstFile
auto searchStr = toWide(path + "*");
hSearch = FindFirstFile(searchStr.data(), &fileData);
if (hSearch == INVALID_HANDLE_VALUE)
return false;
do
{
if (!(fileData.dwFileAttributes ^ FILE_ATTRIBUTE_DIRECTORY))
{
auto dirName = toUtf8(fileData.cFileName);
if ("." != dirName && ".." != dirName)
dirsList->push_back(path + dirName + "/");
}
} while (FindNextFile(hSearch, &fileData));
FindClose(hSearch);
return true;
}
bool findFilesRecursive(const string& path, const string& mask, vector<string>* const fileList)
{
recurseDirectorySearch(findFiles, findDirs, path, mask, fileList);
return true;
}