// Copyright (c) 2012-2014 Konstantin Isakov and ZBackup contributors, see CONTRIBUTORS // Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE #include #include #include #include #include #include #include "dir.hh" DIR * dir; namespace Dir { bool exists( string const & name ) { struct stat buf; return stat( name.c_str(), &buf ) == 0 && S_ISDIR( buf.st_mode ); } void create( string const & name ) { if ( mkdir( name.c_str(), 0777 ) != 0 ) throw exCantCreate( name ); } void remove( string const & name ) { if ( rmdir( name.c_str() ) != 0 ) throw exCantRemove( name ); } string addPath( string const & first, string const & second ) { if ( first.empty() ) return second; if ( second.empty() ) return first; if ( first[ first.size() - 1 ] == separator() ) return first + second; else return first + separator() + second; } string getRealPath( string const & path ) { if ( char * r = realpath( path.c_str(), NULL ) ) { string result( r ); free( r ); return result; } else throw exCantGetRealPath( path ); } string getDirName( string const & path ) { char const * c = path.c_str(); std::vector< char > copy( c, c + path.size() + 1 ); return dirname( copy.data() ); } bool isDirEmpty( string const & path ) { Listing lst(path); Entry tmp; return !lst.getNext(tmp); } Listing::Listing( string const & dirName ): dirName( dirName ) { dir = opendir( dirName.c_str() ); if ( !dir ) throw exCantList( dirName ); } Listing::~Listing() { closedir( dir ); } bool Listing::getNext( Entry & result ) { dirent entry; dirent * entryPtr; struct stat entryStats; for ( ; ; ) { if ( readdir_r( dir, &entry, &entryPtr ) != 0 ) throw exCantList( dirName ); if ( !entryPtr ) return false; #ifndef __APPLE__ if ( fstatat( dirfd( dir ), entry.d_name, &entryStats, AT_SYMLINK_NOFOLLOW ) != 0 ) #else if ( lstat( addPath( dirName, entry.d_name ).c_str(), &entryStats ) != 0) #endif throw exCantList( dirName ); bool isDir = S_ISDIR( entryStats.st_mode ); bool isSymLink = S_ISLNK( entryStats.st_mode ); if ( isDir && ( entry.d_name[ 0 ] == '.' && ( !entry.d_name[ 1 ] || entry.d_name[ 1 ] == '.' ) ) ) { // Skip the . or .. entries continue; } result = Entry( entry.d_name, isDir, isSymLink ); return true; } } }