From 3f5ed121ec2b5c44d13ecd31e6f037d1f8be406e Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Wed, 5 Sep 2018 23:13:29 +0200 Subject: [PATCH] [DEV] finish filesystem interface --- etk/fs/fileSystem.cpp | 84 +++++++++++++++++++++-------------------- etk/io/File.cpp | 14 ++++--- etk/io/ZipFile.cpp | 1 + test/testFileSystem.cpp | 16 +++++--- 4 files changed, 64 insertions(+), 51 deletions(-) diff --git a/etk/fs/fileSystem.cpp b/etk/fs/fileSystem.cpp index 6e6e911..f596b52 100644 --- a/etk/fs/fileSystem.cpp +++ b/etk/fs/fileSystem.cpp @@ -20,10 +20,12 @@ extern "C" { #include #include #include + #include /* Definition of AT_* constants */ } #include #include +#include #include #include @@ -41,16 +43,15 @@ bool etk::fs::copyFile(const etk::Path& _path1, const etk::Path& _path2) { bool etk::fs::move(const etk::Path& _path1, const etk::Path& _path2) { + TK_VERBOSE("Move : \"" << _path1 << "\" ==> \"" << _path2 << "\""); if (etk::fs::exist(_path2) == true) { - remove(_path2); + removes(_path2); } - TK_DEBUG("Move : \"" << _path1 << "\" ==> \"" << _path2 << "\""); // create path to be sure it exist ... - TK_VERBOSE("create path: '" << _path2.getParent() << "'"); 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 << "'"); + int32_t res = ::rename(_path1.getNative().c_str(), _path2.getNative().c_str()); + if (res != 0) { + TK_ERROR("Can not move the file: '" << _path1 << "' ==> '" << _path2 << "' errno" << errno << " (" << strerror(errno) << ")"); return false; } return true; @@ -81,7 +82,7 @@ namespace detail { detail::removes(it, _recursive); } } - if ( 0 != ::rmdir(_path.getString().c_str()) ) { + if ( 0 != ::rmdir(_path.getNative().c_str()) ) { if (ENOTEMPTY == errno) { TK_ERROR("The Directory is not empty..."); } @@ -109,7 +110,7 @@ bool etk::fs::removeDirectories(const etk::Path& _path) { bool etk::fs::removeFile(const etk::Path& _path) { TK_VERBOSE("remove File: " << _path); - if (0 != unlink(_path.getString().c_str()) ) { + if (0 != unlink(_path.getNative().c_str()) ) { return false; } return true; @@ -121,13 +122,13 @@ bool etk::fs::makeDirectory(const etk::Path& _path, etk::fs::Permissions _permis return true; } #ifdef __TARGET_OS__Windows - if (::mkdir(_path.getString().c_str()) != 0 + if (::mkdir(_path.getNative().c_str()) != 0 && errno != EEXIST) { return false; } #else mode_t mode = _permission.getRightValue(); - if ( ::mkdir(_path.getString().c_str(), mode) != 0 + if ( ::mkdir(_path.getNative().c_str(), mode) != 0 && errno != EEXIST ) { return false; } @@ -140,7 +141,7 @@ bool etk::fs::makeDirectories(const etk::Path& _path, etk::fs::Permissions _perm if (etk::fs::exist(_path) == true) { return true; } - auto elements = _path.getString().split('/'); + auto elements = _path.getNative().split('/'); etk::Path pathToCreate; if (elements[0].size() == 0) { elements.popFront(); @@ -156,14 +157,16 @@ bool etk::fs::makeDirectories(const etk::Path& _path, etk::fs::Permissions _perm } bool etk::fs::touch(const etk::Path& _path) { - TK_DEBUG("Touch FILE : " << _path); + TK_VERBOSE("Touch FILE : " << _path); if (etk::fs::exist(_path) == true ) { - //just open in write an close ==> this will update the time - etk::io::File file{_path}; - if (file.open(etk::io::OpenMode::Append) == false) { + int rc = utimensat(0, + _path.getAbsoluteNative().c_str(), + NULL, + AT_SYMLINK_NOFOLLOW); + if (rc) { return false; } - return file.close(); + return true; } // Write the file with nothing inside... etk::io::File file{_path}; @@ -174,19 +177,17 @@ bool etk::fs::touch(const etk::Path& _path) { } bool etk::fs::exist(const etk::Path& _path) { - struct stat st; - int32_t status = 0; - if (stat(_path.getString().c_str(), &st) != 0) { - return false; + if (::access( _path.getNative().c_str(), F_OK ) != -1 ) { + return true; } - return true; + return false; } uint64_t etk::fs::fileSize(const etk::Path& _path) { // Note : this is a proper methode to get the file size for Big files ... otherwithe the size is limited at 2^31 bytes // tmpStat Buffer : struct stat statProperty; - if (stat(_path.getString().c_str(), &statProperty) == -1) { + if (stat(_path.getNative().c_str(), &statProperty) == -1) { //Normal case when the file does not exist ... ==> the it was in unknow mode ... return 0; } @@ -201,7 +202,7 @@ uint64_t etk::fs::fileSize(const etk::Path& _path) { bool etk::fs::isDirectory(const etk::Path& _path) { struct stat st; int32_t status = 0; - if (stat(_path.getString().c_str(), &st) != 0) { + if (stat(_path.getNative().c_str(), &st) != 0) { return false; } else if (!S_ISDIR(st.st_mode)) { return false; @@ -212,7 +213,7 @@ bool etk::fs::isDirectory(const etk::Path& _path) { bool etk::fs::isFile(const etk::Path& _path) { struct stat st; int32_t status = 0; - if (stat(_path.getString().c_str(), &st) != 0) { + if (stat(_path.getNative().c_str(), &st) != 0) { return false; } else if (!S_ISREG(st.st_mode)) { return false; @@ -223,7 +224,7 @@ bool etk::fs::isFile(const etk::Path& _path) { bool etk::fs::isSymLink(const etk::Path& _path) { struct stat st; int32_t status = 0; - if (stat(_path.getString().c_str(), &st) != 0) { + if (stat(_path.getNative().c_str(), &st) != 0) { return false; } else if (!S_ISLNK(st.st_mode)) { return false; @@ -236,7 +237,7 @@ etk::fs::Permissions etk::fs::getPermission(const etk::Path& _path) { etk::fs::Permissions permissions; // tmpStat Buffer : struct stat statProperty; - if (-1 == stat(_path.getString().c_str(), &statProperty)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { //Normal case when the file does not exist ... ==> the it was in unknow mode ... return permissions; } @@ -295,20 +296,21 @@ etk::Path etk::fs::getTemporaryPath() { namespace detail { etk::Path getTemporaryProcessPath(const etk::String& _patern) { - char tmpName[1024]; - strcpy(tmpName, _patern.c_str()); - mktemp(tmpName); - return etk::fs::getTemporaryPath() / tmpName; + etk::Path val; + do { + val = etk::fs::getTemporaryPath() / _patern + etk::random::generateString(16); + } while (etk::fs::exist(val) == true); + return val; } } etk::Path etk::fs::getTemporaryProcessPath() { - static etk::Path out = detail::getTemporaryProcessPath("etk.process.XXXXXX"); + static etk::Path out = detail::getTemporaryProcessPath("etk.process."); return out; } etk::Path etk::fs::getTemporaryRandomPath() { - return detail::getTemporaryProcessPath("etk.random.XXXXXX"); + return detail::getTemporaryProcessPath("etk.random."); } static etk::String getHomePathString() { @@ -339,7 +341,7 @@ etk::Path etk::fs::getHomePath() { etk::Path etk::fs::getExecutionPath() { static etk::Path g_path; - if (g_path.getString() != "") { + if (g_path.getNative() != "") { return g_path; } char cCurrentPath[FILENAME_MAX]; @@ -360,7 +362,7 @@ 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); + char *res = realpath(_path.getNative().c_str(), buf); if (res) { return etk::Path{buf}; } @@ -370,7 +372,7 @@ etk::Path etk::fs::realPath(const etk::Path& _path) { etk::Path etk::fs::getBinaryPath() { static etk::Path out; - if ( out.getString() == "" ) { + if ( out.getNative() == "" ) { #if defined(__TARGET_OS__Windows) || defined(__TARGET_OS__MacOs) || defined(__TARGET_OS__IOs) etk::String tmpValue; tmpValue.resize(4096); @@ -415,7 +417,7 @@ 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)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { return 0; } return statProperty.st_ctime; @@ -423,7 +425,7 @@ uint64_t etk::fs::getCreateTime(const etk::Path& _path) { uint64_t etk::fs::getModifyTime(const etk::Path& _path) { struct stat statProperty; - if (-1 == stat(_path.getString().c_str(), &statProperty)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { return 0; } return statProperty.st_mtime; @@ -431,7 +433,7 @@ uint64_t etk::fs::getModifyTime(const etk::Path& _path) { uint64_t etk::fs::getAccessTime(const etk::Path& _path) { struct stat statProperty; - if (-1 == stat(_path.getString().c_str(), &statProperty)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { return 0; } return statProperty.st_atime; @@ -439,7 +441,7 @@ uint64_t etk::fs::getAccessTime(const etk::Path& _path) { uint32_t etk::fs::getIdOwner(const etk::Path& _path) { struct stat statProperty; - if (-1 == stat(_path.getString().c_str(), &statProperty)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { return 0; } return statProperty.st_uid; @@ -447,7 +449,7 @@ uint32_t etk::fs::getIdOwner(const etk::Path& _path) { uint32_t etk::fs::getIdGroup(const etk::Path& _path) { struct stat statProperty; - if (-1 == stat(_path.getString().c_str(), &statProperty)) { + if (-1 == stat(_path.getNative().c_str(), &statProperty)) { return 0; } return statProperty.st_gid; @@ -460,7 +462,7 @@ etk::Vector etk::fs::list(const etk::Path& _path) { } DIR *dir = null; struct dirent *ent = null; - dir = opendir(_path.getString().c_str()); + dir = opendir(_path.getNative().c_str()); if (dir != null) { // for each element in the drectory... while ((ent = readdir(dir)) != null) { diff --git a/etk/io/File.cpp b/etk/io/File.cpp index ca08e77..b0e0015 100644 --- a/etk/io/File.cpp +++ b/etk/io/File.cpp @@ -7,7 +7,10 @@ #include #include #include - +#include +extern "C" { + #include +} etk::io::File::File() { // nothing to do. @@ -33,17 +36,17 @@ bool etk::io::File::open(etk::io::OpenMode _mode) { TK_VERBOSE(" Read file : " << m_path); switch (_mode) { case etk::io::OpenMode::Read: - m_pointer = fopen(m_path.getNative().c_str(),"rb"); + m_pointer = fopen(m_path.getNative().c_str(), "rb"); break; case etk::io::OpenMode::Write: - m_pointer = fopen(m_path.getNative().c_str(),"wb"); + m_pointer = fopen(m_path.getNative().c_str(), "wb"); break; case etk::io::OpenMode::Append: - m_pointer = fopen(m_path.getNative().c_str(),"ab"); + m_pointer = fopen(m_path.getNative().c_str(), "ab"); break; } if(m_pointer == null) { - TK_ERROR("Can not open the file " << m_path ); + TK_WARNING("Can not open the file " << m_path.getNative() << " mode: " << _mode << " errno" << errno << " (" << strerror(errno) << ")"); return false; } return true; @@ -115,3 +118,4 @@ int64_t etk::io::File::write(const void* _data, int64_t _blockSize, int64_t _nbB } return fwrite(_data, _blockSize, _nbBlock, m_pointer); } + diff --git a/etk/io/ZipFile.cpp b/etk/io/ZipFile.cpp index aabd070..ebfdfca 100644 --- a/etk/io/ZipFile.cpp +++ b/etk/io/ZipFile.cpp @@ -128,3 +128,4 @@ int64_t etk::io::ZipFile::write(const void* _data, int64_t _blockSize, int64_t _ TK_CRITICAL("Can not write on data inside APK : " << m_path); return 0; } + diff --git a/test/testFileSystem.cpp b/test/testFileSystem.cpp index cf07bb8..a2d0d18 100644 --- a/test/testFileSystem.cpp +++ b/test/testFileSystem.cpp @@ -76,7 +76,7 @@ TEST(TestFileSystem, create_and_remove_directories_error) { EXPECT_EQ(etk::fs::makeDirectories(path), false); EXPECT_EQ(etk::fs::exist(path), false); } - +/* TEST(TestFileSystem, move_directory) { etk::Path pathRandom = etk::fs::getTemporaryRandomPath(); etk::Path path1 = pathRandom / "eee1"; @@ -99,43 +99,49 @@ TEST(TestFileSystem, move_directory) { EXPECT_EQ(etk::fs::removeDirectories(pathRandom), true); EXPECT_EQ(etk::fs::exist(pathRandom), false); } +*/ +#include TEST(TestFileSystem, touch) { etk::Path pathRandom = etk::fs::getTemporaryRandomPath(); etk::Path path = pathRandom / "eee" / "kjlk" / "kjhkjh.txt"; TEST_DEBUG("path tmp: " << path); EXPECT_EQ(etk::fs::exist(path), false); + // Touch a file in a unexisting path EXPECT_EQ(etk::fs::touch(path), false); EXPECT_EQ(etk::fs::makeDirectories(path.getParent()), true); EXPECT_EQ(etk::fs::exist(path), false); + // Touch a file in an existing path EXPECT_EQ(etk::fs::touch(path), true); EXPECT_EQ(etk::fs::exist(path), true); uint64_t touch1 = etk::fs::getModifyTime(path); + + usleep(1000000); + // Tich a file already existing EXPECT_EQ(etk::fs::touch(path), true); EXPECT_EQ(etk::fs::exist(path), true); uint64_t touch2 = etk::fs::getModifyTime(path); EXPECT_NE(touch1, touch2); - /* EXPECT_EQ(etk::fs::removeDirectories(pathRandom), true); EXPECT_EQ(etk::fs::exist(pathRandom), false); EXPECT_EQ(etk::fs::exist(path), false); - */ } -/* TEST(TestFileSystem, move_file) { etk::Path pathRandom = etk::fs::getTemporaryRandomPath(); etk::Path path1 = pathRandom / "eee1.txt"; etk::Path path2 = pathRandom / "eee2.mov"; EXPECT_EQ(etk::fs::exist(path1), false); EXPECT_EQ(etk::fs::exist(path2), false); + EXPECT_EQ(etk::fs::makeDirectories(pathRandom), true); EXPECT_EQ(etk::fs::touch(path1), true); EXPECT_EQ(etk::fs::exist(path1), true); EXPECT_EQ(etk::fs::exist(path2), false); EXPECT_EQ(etk::fs::move(path1, path2), true); EXPECT_EQ(etk::fs::exist(path1), false); EXPECT_EQ(etk::fs::exist(path2), true); + /* EXPECT_EQ(etk::fs::removeDirectories(pathRandom), true); EXPECT_EQ(etk::fs::exist(pathRandom), false); + */ } -*/ \ No newline at end of file