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 ===============================================================*/
|
||||
|
||||
// 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
|
||||
{
|
||||
Filesystem( ) = delete;
|
||||
|
@ -208,6 +217,29 @@ class Filesystem final
|
|||
// Return the absolute path to the current working directory
|
||||
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>
|
||||
using namespace ebcl;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# define M_PATHSEP_ '\\'
|
||||
#else
|
||||
# define M_PATHSEP_ '/'
|
||||
#ifndef _WIN32
|
||||
# include <sys/stat.h>
|
||||
# include <dirent.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
using namespace ebcl;
|
||||
|
||||
|
||||
|
||||
/*= 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 ===============================================================*/
|
||||
|
||||
T_FSPath Filesystem::Cwd( ) noexcept
|
||||
|
@ -414,3 +507,159 @@ T_FSPath Filesystem::Cwd( ) noexcept
|
|||
assert( path.isValid( ) );
|
||||
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