[DEV] filesystem start to have a good API
This commit is contained in:
parent
ae40e4a10d
commit
e6bb8fb633
@ -28,6 +28,10 @@ enum {
|
||||
right_user_read = 1 << 8,
|
||||
};
|
||||
|
||||
|
||||
etk::fs::Permissions etk::fs::Permissions::genericFolder{right_user_execute|right_user_write|right_user_read|right_group_read|right_group_execute};
|
||||
etk::fs::Permissions etk::fs::Permissions::genericFile{right_user_write|right_user_read|right_group_read};
|
||||
|
||||
etk::fs::Permissions::Permissions(uint16_t _newRight) :
|
||||
m_rights(_newRight&0x01FF) {
|
||||
|
||||
|
@ -16,6 +16,9 @@ namespace etk {
|
||||
* @brief File System Right management
|
||||
*/
|
||||
class Permissions {
|
||||
public:
|
||||
static Permissions genericFile;
|
||||
static Permissions genericFolder;
|
||||
private:
|
||||
uint16_t m_rights; //!< right manage in a bit field
|
||||
public:
|
||||
|
@ -9,6 +9,9 @@
|
||||
#ifdef __TARGET_OS__Windows
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#elif defined(__TARGET_OS__MacOs) || defined(__TARGET_OS__IOs)
|
||||
#include <cstring>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
@ -16,6 +19,7 @@ extern "C" {
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
}
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -23,54 +27,6 @@ extern "C" {
|
||||
#include <etk/io/File.hpp>
|
||||
#include <etk/io/SeekMode.hpp>
|
||||
|
||||
namespace etk {
|
||||
static int32_t mkdir(const char* _path, mode_t _mode) {
|
||||
struct stat st;
|
||||
int32_t status = 0;
|
||||
if (stat(_path, &st) != 0) {
|
||||
/* Directory does not exist. EEXIST for race condition */
|
||||
#ifdef __TARGET_OS__Windows
|
||||
if(0!=::mkdir(_path)
|
||||
#else
|
||||
if(0!=::mkdir(_path, _mode)
|
||||
#endif
|
||||
&& errno != EEXIST) {
|
||||
status = -1;
|
||||
}
|
||||
} else if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
status = -1;
|
||||
}
|
||||
|
||||
return(status);
|
||||
}
|
||||
static int32_t mkPath(const char* _path, mode_t _mode) {
|
||||
char *pp;
|
||||
char *sp;
|
||||
int status;
|
||||
char *copypath = strdup(_path);
|
||||
if (copypath == null) {
|
||||
return -1;
|
||||
}
|
||||
status = 0;
|
||||
pp = copypath;
|
||||
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
|
||||
if (sp != pp) {
|
||||
/* Neither root nor double slash in path */
|
||||
*sp = '\0';
|
||||
status = etk::mkdir(copypath, _mode);
|
||||
*sp = '/';
|
||||
}
|
||||
pp = sp + 1;
|
||||
}
|
||||
if (status == 0) {
|
||||
status = etk::mkdir(_path, _mode);
|
||||
}
|
||||
free(copypath);
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
|
||||
bool etk::fs::copy(const etk::Path& _path1, const etk::Path& _path2) {
|
||||
return false;
|
||||
}
|
||||
@ -91,7 +47,7 @@ bool etk::fs::move(const etk::Path& _path1, const etk::Path& _path2) {
|
||||
TK_DEBUG("Move : \"" << _path1 << "\" ==> \"" << _path2 << "\"");
|
||||
// create path to be sure it exist ...
|
||||
TK_VERBOSE("create path: '" << _path2.getParent() << "'");
|
||||
etk::mkPath(_path2.getParent().getString().c_str() , 0755);
|
||||
etk::fs::makeDirectories(_path2.getParent());
|
||||
int32_t res = ::rename(_path1.getString().c_str(), _path2.getString().c_str());
|
||||
if (res!=0) {
|
||||
TK_ERROR("Can not move the file: '" << _path1 << "' ==> '" << _path2 << "'");
|
||||
@ -101,11 +57,11 @@ bool etk::fs::move(const etk::Path& _path1, const etk::Path& _path2) {
|
||||
}
|
||||
|
||||
bool etk::fs::moveDirectory(const etk::Path& _path1, const etk::Path& _path2) {
|
||||
return false;
|
||||
return etk::fs::move(_path1, _path2);
|
||||
}
|
||||
|
||||
bool etk::fs::moveFile(const etk::Path& _path1, const etk::Path& _path2) {
|
||||
return false;
|
||||
return etk::fs::move(_path1, _path2);
|
||||
}
|
||||
|
||||
|
||||
@ -116,8 +72,14 @@ bool etk::fs::remove(const etk::Path& _path) {
|
||||
return etk::fs::removeFile(_path);
|
||||
}
|
||||
|
||||
bool etk::fs::removeDirectory(const etk::Path& _path) {
|
||||
if( 0 != ::rmdir(_path.getString().c_str()) ) {
|
||||
bool etk::fs::removeDirectory(const etk::Path& _path, bool _force) {
|
||||
if (_force == true) {
|
||||
if (0 != remove(_path.getString().c_str()) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if ( 0 != ::rmdir(_path.getString().c_str()) ) {
|
||||
if (ENOTEMPTY == errno) {
|
||||
TK_ERROR("The Directory is not empty...");
|
||||
}
|
||||
@ -133,6 +95,39 @@ bool etk::fs::removeFile(const etk::Path& _path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool etk::fs::makeDirectory(const etk::Path& _path, etk::fs::Permissions _permission) {
|
||||
if (etk::fs::exist(_path) == true) {
|
||||
return true;
|
||||
}
|
||||
#ifdef __TARGET_OS__Windows
|
||||
if (0!=mkdir(_path.getString().c_str())) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
mode_t mode = _permission.getRightValue();
|
||||
if (0!=mkdir(_path.getString().c_str(), mode)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool etk::fs::makeDirectories(const etk::Path& _path, etk::fs::Permissions _permission) {
|
||||
auto elements = _path.getString().split('/');
|
||||
etk::Path pathToCreate;
|
||||
if (elements[0].size() == 0) {
|
||||
elements.popFront();
|
||||
pathToCreate = etk::Path("/");
|
||||
}
|
||||
for (auto& it: elements) {
|
||||
pathToCreate /= it;
|
||||
if (etk::fs::makeDirectory(pathToCreate, _permission) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool etk::fs::touch(const etk::Path& _path) {
|
||||
TK_DEBUG("Touch FILE : " << _path);
|
||||
//just open in write an close ==> this will update the time
|
||||
@ -223,19 +218,51 @@ etk::String etk::fs::getAbsoluteString(const etk::Path& _path) {
|
||||
return _path.getAbsolute();
|
||||
}
|
||||
|
||||
etk::String etk::fs::getSystemString(const etk::Path& _path) {
|
||||
etk::String etk::fs::getNativeString(const etk::Path& _path) {
|
||||
return _path.getNative();
|
||||
}
|
||||
|
||||
/*
|
||||
etk::String etk::fs::getMimeType(const etk::Path& _path) {
|
||||
return "*";
|
||||
}
|
||||
*/
|
||||
|
||||
etk::Path etk::fs::getTemporaryPath() {
|
||||
return etk::Path{"/tmp/"};
|
||||
static char const *folder = null;
|
||||
if (folder == null) {
|
||||
#ifdef __TARGET_OS__Windows
|
||||
folder = GetTempPath();
|
||||
#else
|
||||
folder = getenv("TMPDIR");
|
||||
if (folder == 0) {
|
||||
folder = getenv("TMP");
|
||||
}
|
||||
if (folder == 0) {
|
||||
folder = getenv("TEMP");
|
||||
}
|
||||
if (folder == 0) {
|
||||
folder = getenv("TEMPDIR");
|
||||
}
|
||||
#ifdef __TARGET_OS__Android
|
||||
if (folder == 0) {
|
||||
folder = "/data/local/tmp";
|
||||
}
|
||||
#else
|
||||
if (folder == 0) {
|
||||
folder = "/tmp";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return etk::Path{folder};
|
||||
}
|
||||
|
||||
etk::String etk::fs::getHomePathString() {
|
||||
etk::Path etk::fs::getTemporaryRandomPath() {
|
||||
return etk::fs::getTemporaryPath() / "DFGDSF__TODO__SDFSDF";
|
||||
}
|
||||
|
||||
static etk::String getHomePathString() {
|
||||
static bool isInit = false;
|
||||
static etk::String data = "";
|
||||
if (isInit == false) {
|
||||
@ -258,7 +285,7 @@ etk::String etk::fs::getHomePathString() {
|
||||
}
|
||||
|
||||
etk::Path etk::fs::getHomePath() {
|
||||
return etk::Path(etk::fs::getHomePathString());
|
||||
return etk::Path(getHomePathString());
|
||||
}
|
||||
|
||||
etk::Path etk::fs::getExecutionPath() {
|
||||
@ -280,33 +307,101 @@ etk::Path etk::fs::getExecutionPath() {
|
||||
return g_path;
|
||||
}
|
||||
|
||||
etk::Path etk::fs::getBinaryPath() {
|
||||
|
||||
etk::Path etk::fs::realPath(const etk::Path& _path) {
|
||||
#if ! defined(__TARGET_OS__Windows)
|
||||
char buf[8192];
|
||||
memset(buf, 0, 8192);
|
||||
char *res = realpath(_path.getString().c_str(), buf);
|
||||
if (res) {
|
||||
return etk::Path{buf};
|
||||
}
|
||||
#endif
|
||||
return _path;
|
||||
}
|
||||
|
||||
etk::Path etk::fs::getBinaryPath() {
|
||||
static etk::Path out;
|
||||
if ( out.getString() == "" ) {
|
||||
#if defined(__TARGET_OS__Windows) || defined(__TARGET_OS__MacOs) || defined(__TARGET_OS__IOs)
|
||||
etk::String tmpValue;
|
||||
tmpValue.resize(4096);
|
||||
do {
|
||||
uint_t size = tmpValue.size();
|
||||
#if defined(__TARGET_OS__Windows)
|
||||
uint_t len = GetModuleFileName(NULL, &tmpValue[0], size);
|
||||
if (len < tmpValue.size()) {
|
||||
tmpValue.resize(len);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
uint_t size = tmpValue.size();
|
||||
if (_NSGetExecutablePath(&tmpValue[0], &size) == 0) {
|
||||
tmpValue.resize(strlen(&tmpValue[0]));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
tmpValue.resize(tmpValue.size() * 2);
|
||||
} while (tmpValue.size() < 65536);
|
||||
out = tmpValue;
|
||||
#else
|
||||
if (etk::fs::exist("/proc/self/exe") == true) {
|
||||
out = etk::fs::realPath("/proc/self/exe");
|
||||
} else if (etk::fs::exist("/proc/curproc/file") == true) {
|
||||
out = etk::fs::realPath("/proc/curproc/file");
|
||||
} else if (etk::fs::exist("/proc/curproc/exe") == true) {
|
||||
out = etk::fs::realPath("/proc/curproc/exe");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
etk::Path etk::fs::getBinaryName() {
|
||||
return getBinaryPath().getFileName();
|
||||
}
|
||||
#if 0
|
||||
etk::Path etk::fs::getDataPath() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
uint64_t etk::fs::getCreateTime(const etk::Path& _path) {
|
||||
|
||||
struct stat statProperty;
|
||||
if (-1 == stat(_path.getString().c_str(), &statProperty)) {
|
||||
return 0;
|
||||
}
|
||||
return statProperty.st_ctime;
|
||||
}
|
||||
|
||||
uint64_t etk::fs::getModifyTime(const etk::Path& _path) {
|
||||
|
||||
struct stat statProperty;
|
||||
if (-1 == stat(_path.getString().c_str(), &statProperty)) {
|
||||
return 0;
|
||||
}
|
||||
return statProperty.st_mtime;
|
||||
}
|
||||
|
||||
uint64_t etk::fs::getAccessTime(const etk::Path& _path) {
|
||||
|
||||
struct stat statProperty;
|
||||
if (-1 == stat(_path.getString().c_str(), &statProperty)) {
|
||||
return 0;
|
||||
}
|
||||
return statProperty.st_atime;
|
||||
}
|
||||
|
||||
uint32_t etk::fs::getIdOwner(const etk::Path& _path) {
|
||||
|
||||
struct stat statProperty;
|
||||
if (-1 == stat(_path.getString().c_str(), &statProperty)) {
|
||||
return 0;
|
||||
}
|
||||
return statProperty.st_uid;
|
||||
}
|
||||
|
||||
uint32_t etk::fs::getIdGroup(const etk::Path& _path) {
|
||||
|
||||
struct stat statProperty;
|
||||
if (-1 == stat(_path.getString().c_str(), &statProperty)) {
|
||||
return 0;
|
||||
}
|
||||
return statProperty.st_gid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,7 +61,6 @@ namespace etk {
|
||||
* @return false Operation Failed.
|
||||
*/
|
||||
bool moveFile(const etk::Path& _path1, const etk::Path& _path2);
|
||||
|
||||
/**
|
||||
* @brief Remove a path (if possible...)
|
||||
* @param[in] _path Path to remove.
|
||||
@ -72,10 +71,11 @@ namespace etk {
|
||||
/**
|
||||
* @brief Remove a FOLDER path (if possible...)
|
||||
* @param[in] _path Path to remove.
|
||||
* @param[in] _force Remove all data inside.
|
||||
* @return true Operation succeed.
|
||||
* @return false Operation Failed.
|
||||
*/
|
||||
bool removeDirectory(const etk::Path& _path);
|
||||
bool removeDirectory(const etk::Path& _path, bool _force=false);
|
||||
/**
|
||||
* @brief Remove a FILE path (if possible...)
|
||||
* @param[in] _path Path to remove.
|
||||
@ -83,6 +83,22 @@ namespace etk {
|
||||
* @return false Operation Failed.
|
||||
*/
|
||||
bool removeFile(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Make a directory (last one only)
|
||||
* @param[in] _path Path to create.
|
||||
* @param[in] _permission Permission of creating directory.
|
||||
* @return true Operation succeed.
|
||||
* @return false Operation Failed.
|
||||
*/
|
||||
bool makeDirectory(const etk::Path& _path, etk::fs::Permissions _permission = etk::fs::Permissions::genericFolder);
|
||||
/**
|
||||
* @brief Make a directory (With all parents if needed)
|
||||
* @param[in] _path Path to create.
|
||||
* @param[in] _permission Permission of creating directories.
|
||||
* @return true Operation succeed.
|
||||
* @return false Operation Failed.
|
||||
*/
|
||||
bool makeDirectories(const etk::Path& _path, etk::fs::Permissions _permission = etk::fs::Permissions::genericFolder);
|
||||
/**
|
||||
* @brief update the Time of the file with the current time
|
||||
* @param[in] _path Path to touch.
|
||||
@ -101,32 +117,132 @@ namespace etk {
|
||||
* @return the requested size
|
||||
*/
|
||||
uint64_t fileSize(const etk::Path& _path);
|
||||
|
||||
/**
|
||||
* @brief Check if the path is a directory.
|
||||
* @param[in] _path Path of the requested information/
|
||||
* @return true This is a directory.
|
||||
* @return false This is something else...
|
||||
*/
|
||||
bool isDirectory(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Check if the path is a file (regular).
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return true This is a file.
|
||||
* @return false This is something else...
|
||||
*/
|
||||
bool isFile(const etk::Path& _path);
|
||||
/**
|
||||
* @brief check if the path is a symbolink link.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return true This is a synbolic link.
|
||||
* @return false This is something else...
|
||||
*/
|
||||
bool isSymLink(const etk::Path& _path);
|
||||
|
||||
etk::fs::Permissions getPermission(const etk::Path& _path);
|
||||
|
||||
/**
|
||||
* @brief Get the relative string of the path.
|
||||
* @param[in] _path Path to transform.
|
||||
* @return Well formated string of the path.
|
||||
*/
|
||||
etk::String getRelativeString(const etk::Path& _path);
|
||||
etk::String getDecoratedString(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the absolute string of the path.
|
||||
* @param[in] _path Path to transform.
|
||||
* @return Well formated string of the path.
|
||||
*/
|
||||
etk::String getAbsoluteString(const etk::Path& _path);
|
||||
etk::String getSystemString(const etk::Path& _path);
|
||||
|
||||
etk::String getMimeType(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the native string of the path. (c:\xxx\xxx for windows and /YYY/vvv for unix)
|
||||
* @param[in] _path Path to transform.
|
||||
* @return Well formated string of the path.
|
||||
*/
|
||||
etk::String getNativeString(const etk::Path& _path);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Get the mime type of the file
|
||||
* @param[in] _path Path of the requested information
|
||||
* @return Mime file type "XXX_GROUP_XXX/YYY_ELEMENT_YYY"
|
||||
*/
|
||||
etk::String getMimeType(const etk::Path& _path);
|
||||
#endif
|
||||
/**
|
||||
* @brief Get the realPath of a defined path.
|
||||
* @param[in] Path that we want to have real value.
|
||||
* @return the real path of the _path.
|
||||
*/
|
||||
etk::Path realPath(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get a temporary path that can be write as you want.
|
||||
* @return A system path.
|
||||
*/
|
||||
etk::Path getTemporaryPath();
|
||||
etk::String getHomePathString();
|
||||
/**
|
||||
* @brief Get a temporary path that can be write as you want witha a random subfolder.
|
||||
* @return A system path with gegerated string.
|
||||
*/
|
||||
etk::Path getTemporaryRandomPath();
|
||||
/**
|
||||
* @brief Get user home directory.
|
||||
*/
|
||||
etk::Path getHomePath();
|
||||
/**
|
||||
* @brief Get the Currect execution path.
|
||||
* @return Path where the program is lunch.
|
||||
*/
|
||||
etk::Path getExecutionPath();
|
||||
/**
|
||||
* @brief Current binary name.
|
||||
* @return executable name.
|
||||
*/
|
||||
etk::Path getBinaryName();
|
||||
/**
|
||||
* @brief Full banary name (with root path).
|
||||
* @return the binary absolute path.
|
||||
*/
|
||||
etk::Path getBinaryPath();
|
||||
etk::Path getDataPath();
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Get the data path of the application.
|
||||
* @return the root path of the data for this application.
|
||||
*/
|
||||
etk::Path getDataPath();
|
||||
#endif
|
||||
/**
|
||||
* @brief Get the creation time of the path.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return time since epoch.
|
||||
*/
|
||||
uint64_t getCreateTime(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the tast modification time of the path.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return time since epoch.
|
||||
*/
|
||||
uint64_t getModifyTime(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the last access time of the path.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return time since epoch.
|
||||
*/
|
||||
uint64_t getAccessTime(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the Id of the file owner.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return system user ID.
|
||||
*/
|
||||
uint32_t getIdOwner(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the Id of the file group.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return system group ID.
|
||||
*/
|
||||
uint32_t getIdGroup(const etk::Path& _path);
|
||||
/**
|
||||
* @brief Get the permission of a specific Path.
|
||||
* @param[in] _path Path of the requested information.
|
||||
* @return Generic permission class.
|
||||
*/
|
||||
etk::fs::Permissions getPermission(const etk::Path& _path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,3 +15,28 @@ TEST(TestFileSystem, checkHomePath) {
|
||||
EXPECT_EQ(etk::fs::getHomePath(), basicPath);
|
||||
}
|
||||
|
||||
TEST(TestFileSystem, checkTmpPath) {
|
||||
EXPECT_EQ(etk::fs::getTemporaryPath(), "/tmp");
|
||||
}
|
||||
|
||||
TEST(TestFileSystem, getBinaryName) {
|
||||
EXPECT_EQ(etk::fs::getBinaryName(), "etk-test");
|
||||
}
|
||||
|
||||
TEST(TestFileSystem, getBinaryPath) {
|
||||
EXPECT_EQ(etk::fs::getBinaryPath().getString().split('/').size() > 2, true);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestFileSystem, createDirectory) {
|
||||
etk::Path pathRandom = etk::fs::getTemporaryRandomPath();
|
||||
etk::Path path = pathRandom / "eee" / "kjlk" / "kjhkjh";
|
||||
TEST_WARNING("path tmp: " << path);
|
||||
EXPECT_EQ(etk::fs::exist(path), false);
|
||||
EXPECT_EQ(etk::fs::makeDirectories(path), true);
|
||||
EXPECT_EQ(etk::fs::exist(path), true);
|
||||
EXPECT_EQ(etk::fs::removeDirectory(pathRandom, true), true);
|
||||
EXPECT_EQ(etk::fs::exist(pathRandom), false);
|
||||
EXPECT_EQ(etk::fs::exist(path), false);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user