Filesystem - Actual filesystem operations

* Entry type, directory listing
 * Directory creation and deletion
 * File deletion
 * Move
This commit is contained in:
Emmanuel BENOîT 2018-12-23 22:29:56 +01:00
parent 3ef6dcd55e
commit 68716e9193
2 changed files with 288 additions and 7 deletions

View file

@ -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;
};

View file

@ -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
}