252 lines
5.7 KiB
C++

#include <efsw/platform/posix/FileSystemImpl.hpp>
#if defined( EFSW_PLATFORM_POSIX )
#include <cstring>
#include <dirent.h>
#include <efsw/FileInfo.hpp>
#include <efsw/FileSystem.hpp>
#include <unistd.h>
#ifndef _DARWIN_FEATURE_64_BIT_INODE
#define _DARWIN_FEATURE_64_BIT_INODE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <climits>
#include <cstdlib>
#include <sys/stat.h>
#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID
#include <sys/vfs.h>
#elif EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_IOS
#include <sys/mount.h>
#include <sys/param.h>
#endif
/** Remote file systems codes */
#define S_MAGIC_AFS 0x5346414F
#define S_MAGIC_AUFS 0x61756673
#define S_MAGIC_CEPH 0x00C36400
#define S_MAGIC_CIFS 0xFF534D42
#define S_MAGIC_CODA 0x73757245
#define S_MAGIC_FHGFS 0x19830326
#define S_MAGIC_FUSEBLK 0x65735546
#define S_MAGIC_FUSECTL 0x65735543
#define S_MAGIC_GFS 0x01161970
#define S_MAGIC_GPFS 0x47504653
#define S_MAGIC_KAFS 0x6B414653
#define S_MAGIC_LUSTRE 0x0BD00BD0
#define S_MAGIC_NCP 0x564C
#define S_MAGIC_NFS 0x6969
#define S_MAGIC_NFSD 0x6E667364
#define S_MAGIC_OCFS2 0x7461636F
#define S_MAGIC_PANFS 0xAAD7AAEA
#define S_MAGIC_PIPEFS 0x50495045
#define S_MAGIC_SMB 0x517B
#define S_MAGIC_SNFS 0xBEEFDEAD
#define S_MAGIC_VMHGFS 0xBACBACBC
#define S_MAGIC_VXFS 0xA501FCF5
#if EFSW_OS == EFSW_OS_LINUX
#include <cstdio>
#include <mntent.h>
#endif
namespace efsw { namespace Platform {
#if EFSW_OS == EFSW_OS_LINUX
std::string findMountPoint( std::string file ) {
std::string cwd = FileSystem::getCurrentWorkingDirectory();
struct stat last_stat;
struct stat file_stat;
stat( file.c_str(), &file_stat );
std::string mp;
if ( efsw::FileSystem::isDirectory( file ) ) {
last_stat = file_stat;
if ( !FileSystem::changeWorkingDirectory( file ) )
return "";
} else {
std::string dir = efsw::FileSystem::pathRemoveFileName( file );
if ( !FileSystem::changeWorkingDirectory( dir ) )
return "";
if ( stat( ".", &last_stat ) < 0 )
return "";
}
while ( true ) {
struct stat st;
if ( stat( "..", &st ) < 0 )
goto done;
if ( st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino )
break;
if ( !FileSystem::changeWorkingDirectory( ".." ) ) {
goto done;
}
last_stat = st;
}
/* Finally reached a mount point, see what it's called. */
mp = FileSystem::getCurrentWorkingDirectory();
done:
FileSystem::changeWorkingDirectory( cwd );
return mp;
}
std::string findDevicePath( const std::string& directory ) {
struct mntent* ent;
FILE* aFile;
aFile = setmntent( "/proc/mounts", "r" );
if ( aFile == NULL )
return "";
while ( NULL != ( ent = getmntent( aFile ) ) ) {
std::string dirName( ent->mnt_dir );
if ( dirName == directory ) {
std::string fsName( ent->mnt_fsname );
endmntent( aFile );
return fsName;
}
}
endmntent( aFile );
return "";
}
bool isLocalFUSEDirectory( std::string directory ) {
efsw::FileSystem::dirRemoveSlashAtEnd( directory );
directory = findMountPoint( directory );
if ( !directory.empty() ) {
std::string devicePath = findDevicePath( directory );
return !devicePath.empty();
}
return false;
}
#endif
bool FileSystem::changeWorkingDirectory( const std::string& path ) {
return -1 != chdir( path.c_str() );
}
std::string FileSystem::getCurrentWorkingDirectory() {
char dir[PATH_MAX + 1];
char* result = getcwd( dir, PATH_MAX + 1 );
return result != NULL ? std::string( result ) : std::string();
}
FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) {
FileInfoMap files;
DIR* dp;
struct dirent* dirp;
if ( ( dp = opendir( path.c_str() ) ) == NULL )
return files;
while ( ( dirp = readdir( dp ) ) != NULL ) {
if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) {
std::string name( dirp->d_name );
std::string fpath( path + name );
files[name] = FileInfo( fpath );
}
}
closedir( dp );
return files;
}
char FileSystem::getOSSlash() {
return '/';
}
bool FileSystem::isDirectory( const std::string& path ) {
struct stat st;
int res = stat( path.c_str(), &st );
if ( 0 == res ) {
return static_cast<bool>( S_ISDIR( st.st_mode ) );
}
return false;
}
bool FileSystem::isRemoteFS( const std::string& directory ) {
#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || \
EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS
struct statfs statfsbuf;
statfs( directory.c_str(), &statfsbuf );
switch ( statfsbuf.f_type | 0UL ) {
case S_MAGIC_FUSEBLK: /* 0x65735546 remote */
{
#if EFSW_OS == EFSW_OS_LINUX
return !isLocalFUSEDirectory( directory );
#endif
}
case S_MAGIC_AFS: /* 0x5346414F remote */
case S_MAGIC_AUFS: /* 0x61756673 remote */
case S_MAGIC_CEPH: /* 0x00C36400 remote */
case S_MAGIC_CIFS: /* 0xFF534D42 remote */
case S_MAGIC_CODA: /* 0x73757245 remote */
case S_MAGIC_FHGFS: /* 0x19830326 remote */
case S_MAGIC_FUSECTL: /* 0x65735543 remote */
case S_MAGIC_GFS: /* 0x01161970 remote */
case S_MAGIC_GPFS: /* 0x47504653 remote */
case S_MAGIC_KAFS: /* 0x6B414653 remote */
case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */
case S_MAGIC_NCP: /* 0x564C remote */
case S_MAGIC_NFS: /* 0x6969 remote */
case S_MAGIC_NFSD: /* 0x6E667364 remote */
case S_MAGIC_OCFS2: /* 0x7461636F remote */
case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */
case S_MAGIC_PIPEFS: /* 0x50495045 remote */
case S_MAGIC_SMB: /* 0x517B remote */
case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */
case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */
case S_MAGIC_VXFS: /* 0xA501FCF5 remote */
{
return true;
}
default: {
return false;
}
}
#endif
return false;
}
}} // namespace efsw::Platform
#endif