#include #include #include #ifndef _DARWIN_FEATURE_64_BIT_INODE #define _DARWIN_FEATURE_64_BIT_INODE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include #ifdef EFSW_COMPILER_MSVC #ifndef S_ISDIR #define S_ISDIR( f ) ( (f)&_S_IFDIR ) #endif #ifndef S_ISREG #define S_ISREG( f ) ( (f)&_S_IFREG ) #endif #ifndef S_ISRDBL #define S_ISRDBL( f ) ( (f)&_S_IREAD ) #endif #else #include #ifndef S_ISRDBL #define S_ISRDBL( f ) ( (f)&S_IRUSR ) #endif #endif #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 #include #endif namespace efsw { bool FileInfo::exists( const std::string& filePath ) { FileInfo fi( filePath ); return fi.exists(); } bool FileInfo::isLink( const std::string& filePath ) { FileInfo fi( filePath, true ); return fi.isLink(); } bool FileInfo::inodeSupported() { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 return true; #else return false; #endif } FileInfo::FileInfo() : ModificationTime( 0 ), OwnerId( 0 ), GroupId( 0 ), Permissions( 0 ), Inode( 0 ) {} FileInfo::FileInfo( const std::string& filepath ) : Filepath( filepath ), ModificationTime( 0 ), OwnerId( 0 ), GroupId( 0 ), Permissions( 0 ), Inode( 0 ) { getInfo(); } FileInfo::FileInfo( const std::string& filepath, bool linkInfo ) : Filepath( filepath ), ModificationTime( 0 ), OwnerId( 0 ), GroupId( 0 ), Permissions( 0 ), Inode( 0 ) { if ( linkInfo ) { getRealInfo(); } else { getInfo(); } } void FileInfo::getInfo() { #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 if ( Filepath.size() == 3 && Filepath[1] == ':' && Filepath[2] == FileSystem::getOSSlash() ) { Filepath += FileSystem::getOSSlash(); } #endif /// Why i'm doing this? stat in mingw32 doesn't work for directories if the dir path ends with a /// path slash bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); if ( slashAtEnd ) { FileSystem::dirRemoveSlashAtEnd( Filepath ); } #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 struct stat st; int res = stat( Filepath.c_str(), &st ); #else struct _stat st; int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); #endif if ( 0 == res ) { ModificationTime = st.st_mtime; Size = st.st_size; OwnerId = st.st_uid; GroupId = st.st_gid; Permissions = st.st_mode; Inode = st.st_ino; } if ( slashAtEnd ) { FileSystem::dirAddSlashAtEnd( Filepath ); } } void FileInfo::getRealInfo() { bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); if ( slashAtEnd ) { FileSystem::dirRemoveSlashAtEnd( Filepath ); } #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 struct stat st; int res = lstat( Filepath.c_str(), &st ); #else struct _stat st; int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); #endif if ( 0 == res ) { ModificationTime = st.st_mtime; Size = st.st_size; OwnerId = st.st_uid; GroupId = st.st_gid; Permissions = st.st_mode; Inode = st.st_ino; } if ( slashAtEnd ) { FileSystem::dirAddSlashAtEnd( Filepath ); } } bool FileInfo::operator==( const FileInfo& Other ) const { return ( ModificationTime == Other.ModificationTime && Size == Other.Size && OwnerId == Other.OwnerId && GroupId == Other.GroupId && Permissions == Other.Permissions && Inode == Other.Inode ); } bool FileInfo::isDirectory() const { return 0 != S_ISDIR( Permissions ); } bool FileInfo::isRegularFile() const { return 0 != S_ISREG( Permissions ); } bool FileInfo::isReadable() const { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 static bool isRoot = getuid() == 0; return isRoot || 0 != S_ISRDBL( Permissions ); #else return 0 != S_ISRDBL( Permissions ); #endif } bool FileInfo::isLink() const { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 return S_ISLNK( Permissions ); #else return false; #endif } std::string FileInfo::linksTo() { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 if ( isLink() ) { std::error_code ec; auto ch = std::filesystem::canonical( Filepath, ec ); if ( !ec ) { return ch.string(); } } #endif return std::string( "" ); } bool FileInfo::exists() { bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); if ( slashAtEnd ) { FileSystem::dirRemoveSlashAtEnd( Filepath ); } #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 struct stat st; int res = stat( Filepath.c_str(), &st ); #else struct _stat st; int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); #endif if ( slashAtEnd ) { FileSystem::dirAddSlashAtEnd( Filepath ); } return 0 == res; } FileInfo& FileInfo::operator=( const FileInfo& Other ) { this->Filepath = Other.Filepath; this->Size = Other.Size; this->ModificationTime = Other.ModificationTime; this->GroupId = Other.GroupId; this->OwnerId = Other.OwnerId; this->Permissions = Other.Permissions; this->Inode = Other.Inode; return *this; } bool FileInfo::sameInode( const FileInfo& Other ) const { return inodeSupported() && Inode == Other.Inode; } bool FileInfo::operator!=( const FileInfo& Other ) const { return !( *this == Other ); } } // namespace efsw