Filesystem - Actual filesystem operations
* Entry type, directory listing * Directory creation and deletion * File deletion * Move
This commit is contained in:
parent
3ef6dcd55e
commit
68716e9193
2 changed files with 288 additions and 7 deletions
|
@ -201,6 +201,15 @@ M_LSHIFT_OP( T_StringBuilder , T_FSPath const& );
|
||||||
|
|
||||||
/*= FILESYSTEM ===============================================================*/
|
/*= FILESYSTEM ===============================================================*/
|
||||||
|
|
||||||
|
// Type of entries
|
||||||
|
enum class E_FSEntryType {
|
||||||
|
NONE , // Filesystem entry does not exist
|
||||||
|
FILE , // Filesystem entry refers to a file
|
||||||
|
DIRECTORY , // Filesystem entry refers to a directory
|
||||||
|
OTHER // Filesystem entry exists but refers to something else
|
||||||
|
// entirely (e.g. symlinks) and is therefore off-limits
|
||||||
|
};
|
||||||
|
|
||||||
class Filesystem final
|
class Filesystem final
|
||||||
{
|
{
|
||||||
Filesystem( ) = delete;
|
Filesystem( ) = delete;
|
||||||
|
@ -208,6 +217,29 @@ class Filesystem final
|
||||||
// Return the absolute path to the current working directory
|
// Return the absolute path to the current working directory
|
||||||
static T_FSPath Cwd( ) noexcept;
|
static T_FSPath Cwd( ) noexcept;
|
||||||
|
|
||||||
|
// Get the type of an entry
|
||||||
|
static E_FSEntryType TypeOf( T_FSPath const& path ) noexcept;
|
||||||
|
|
||||||
|
// List a directory's contents
|
||||||
|
static bool List( T_FSPath const& path ,
|
||||||
|
T_Array< T_String >& output ) noexcept;
|
||||||
|
|
||||||
|
// Create a new directory
|
||||||
|
static bool MkDir( T_FSPath const& path ) noexcept;
|
||||||
|
|
||||||
|
// Create a new directory, including parent directories if
|
||||||
|
// they do not exist
|
||||||
|
static bool MkDirFull( T_FSPath const& path ) noexcept;
|
||||||
|
|
||||||
|
// Delete a directory
|
||||||
|
static bool RmDir( T_FSPath const& path ) noexcept;
|
||||||
|
|
||||||
|
// Delete a file
|
||||||
|
static bool Rm( T_FSPath const& path ) noexcept;
|
||||||
|
|
||||||
|
// Move or rename a file
|
||||||
|
static bool Move( T_FSPath const& from ,
|
||||||
|
T_FSPath const& to ) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,13 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
#include <ebcl/Filesystem.hh>
|
#include <ebcl/Filesystem.hh>
|
||||||
using namespace ebcl;
|
#ifndef _WIN32
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <dirent.h>
|
||||||
#ifdef _WIN32
|
|
||||||
# define M_PATHSEP_ '\\'
|
|
||||||
#else
|
|
||||||
# define M_PATHSEP_ '/'
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
using namespace ebcl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*= T_FSPathStyle ============================================================*/
|
/*= T_FSPathStyle ============================================================*/
|
||||||
|
@ -390,6 +388,101 @@ T_FSPath T_FSPath::canonical( ) const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_DirLister_ =============================================================*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class T_DirLister_
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
T_Buffer< char > path_;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle_;
|
||||||
|
WIN32_FIND_DATAW output_;
|
||||||
|
#else
|
||||||
|
DIR* dir_;
|
||||||
|
struct dirent* output_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit T_DirLister_( T_Buffer< char > path ) noexcept;
|
||||||
|
~T_DirLister_( );
|
||||||
|
|
||||||
|
bool start( ) noexcept;
|
||||||
|
void next( ) noexcept;
|
||||||
|
bool hasValue( ) const noexcept;
|
||||||
|
T_String getName( ) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
inline T_DirLister_::T_DirLister_( T_Buffer< char > path ) noexcept
|
||||||
|
: path_( std::move( path ) )
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
dir_ = nullptr;
|
||||||
|
output_ = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
T_DirLister_::~T_DirLister_( )
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
if ( dir_ != nullptr ) {
|
||||||
|
closedir( dir_ );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool T_DirLister_::start( ) noexcept
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
dir_ = opendir( &path_[ 0 ] );
|
||||||
|
if ( dir_ == nullptr ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output_ = readdir( dir_ );
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void T_DirLister_::next( ) noexcept
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
output_ = readdir( dir_ );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool T_DirLister_::hasValue( ) const noexcept
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
return output_ != nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T_String T_DirLister_::getName( ) const noexcept
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
# error "Not implemented"
|
||||||
|
#else
|
||||||
|
return T_String( output_->d_name );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= Filesystem ===============================================================*/
|
/*= Filesystem ===============================================================*/
|
||||||
|
|
||||||
T_FSPath Filesystem::Cwd( ) noexcept
|
T_FSPath Filesystem::Cwd( ) noexcept
|
||||||
|
@ -414,3 +507,159 @@ T_FSPath Filesystem::Cwd( ) noexcept
|
||||||
assert( path.isValid( ) );
|
assert( path.isValid( ) );
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
E_FSEntryType Filesystem::TypeOf(
|
||||||
|
T_FSPath const& path ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return E_FSEntryType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto chars{ path.toString( ).toOSString( ) };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
uint32_t fa( GetFileAttributesW( (wchar_t const*) & chars[ 0 ] ) );
|
||||||
|
if ( fa == INVALID_FILE_ATTRIBUTES ) {
|
||||||
|
return E_FSEntryType::NONE;
|
||||||
|
} else if ( ( fa & FILE_ATTRIBUTE_DIRECTORY ) != 0 ) {
|
||||||
|
return E_FSEntryType::DIRECTORY;
|
||||||
|
} else if ( ( fa & FILE_ATTRIBUTE_NORMAL ) != 0 ) {
|
||||||
|
return E_FSEntryType::FILE;
|
||||||
|
} else {
|
||||||
|
return E_FSEntryType::OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct stat fa;
|
||||||
|
if ( stat( ( char const* ) &chars[ 0 ] , &fa ) ) {
|
||||||
|
return E_FSEntryType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto masked( fa.st_mode & S_IFMT );
|
||||||
|
switch ( masked ) {
|
||||||
|
case S_IFREG:
|
||||||
|
return E_FSEntryType::FILE;
|
||||||
|
|
||||||
|
case S_IFDIR:
|
||||||
|
return E_FSEntryType::DIRECTORY;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return E_FSEntryType::OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::List(
|
||||||
|
T_FSPath const& path ,
|
||||||
|
T_Array< T_String >& output ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_DirLister_ dl{ path.toString( ).toOSString( ) };
|
||||||
|
if ( !dl.start( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while ( dl.hasValue( ) ) {
|
||||||
|
output.add( dl.getName( ) );
|
||||||
|
dl.next( );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::MkDir(
|
||||||
|
T_FSPath const& path ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto chars{ path.toString( ).toOSString( ) };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
return CreateDirectoryW( ( wchar_t const* ) &chars[ 0 ] , nullptr );
|
||||||
|
#else
|
||||||
|
return mkdir( ( char const* ) &chars[ 0 ] , 0755 ) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::MkDirFull(
|
||||||
|
T_FSPath const& path ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T_FSPath full{ path.canonical( ) };
|
||||||
|
T_FSPath current{ full.root( ) };
|
||||||
|
for ( auto const& cmp : full.components( ) ) {
|
||||||
|
current = current.child( cmp );
|
||||||
|
const auto t{ TypeOf( current ) };
|
||||||
|
if ( t == E_FSEntryType::NONE ) {
|
||||||
|
if ( !MkDir( current ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if ( t != E_FSEntryType::DIRECTORY ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::RmDir(
|
||||||
|
T_FSPath const& path ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto chars{ path.toString( ).toOSString( ) };
|
||||||
|
#ifdef _WIN32
|
||||||
|
return RemoveDirectoryW( ( wchar_t const* ) &chars[ 0 ] );
|
||||||
|
#else
|
||||||
|
return rmdir( ( char const* ) &chars[ 0 ] ) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::Rm(
|
||||||
|
T_FSPath const& path ) noexcept
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
if ( !path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto chars{ path.toString( ).toOSString( ) };
|
||||||
|
#ifdef _WIN32
|
||||||
|
return DeleteFileW( ( wchar_t const* ) &chars[ 0 ] );
|
||||||
|
#else
|
||||||
|
return unlink( ( char const* ) &chars[ 0 ] ) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filesystem::Move(
|
||||||
|
T_FSPath const& from ,
|
||||||
|
T_FSPath const& to ) noexcept
|
||||||
|
{
|
||||||
|
assert( from.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
assert( to.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
|
||||||
|
const auto charsFrom{ from.toString( ).toOSString( ) };
|
||||||
|
const auto charsTo{ to.toString( ).toOSString( ) };
|
||||||
|
#ifdef _WIN32
|
||||||
|
return MoveFileW( ( wchar_t const* ) &charsFrom[ 0 ] ,
|
||||||
|
( wchar_t const* ) &charsTo[ 0 ] );
|
||||||
|
#else
|
||||||
|
return rename( ( char const* ) &charsFrom[ 0 ] ,
|
||||||
|
( char const* ) &charsTo[ 0 ] ) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue