13 #include <sys/types.h>
15 #include <sys/statvfs.h>
50 #define EMUMOUT(T) case T: return str << #T; break
102 else if ( obj.
isDir() )
106 else if ( obj.
isChr() )
108 else if ( obj.
isBlk() )
115 str << t <<
" " << std::setfill(
'0' ) << std::setw( 4 ) << std::oct << obj.
perm();
228 if (
owner() == getuid() ) {
229 return(
uperm()/0100 );
230 }
else if (
group() == getgid() ) {
231 return(
gperm()/010 );
267 str <<
"does not exist}";
272 str <<
" size " << obj.
size();
293 #define _Log_Result MIL << endl, __Log_Result
299 WAR <<
" FAILED: " << rclass <<
" " << res << endl;
343 while ( (pos = spath.find(
'/',lastpos)) != string::npos )
345 string dir( spath.substr(0,pos) );
346 ret =
::mkdir( dir.c_str(), mode );
349 if ( errno == EEXIST )
354 WAR <<
" FAILED: mkdir " << dir <<
' ' <<
str::octstring( mode ) <<
" errno " << ret << endl;
374 MIL <<
"rmdir " << path;
375 if ( ::
rmdir( path.asString().c_str() ) == -1 ) {
391 if ( ! (dp = opendir( dir.
c_str() )) )
396 std::string direntry = d->d_name;
397 if ( direntry ==
"." || direntry ==
".." )
399 Pathname new_path( dir / d->d_name );
402 if ( ! lstat( new_path.
c_str(), &st ) )
404 if ( S_ISDIR( st.st_mode ) )
420 MIL <<
"recursive_rmdir " << path <<
' ';
441 MIL <<
"clean_dir " << path <<
' ';
452 string cmd(
str::form(
"cd '%s' && rm -rf --preserve-root -- *", path.asString().c_str() ) );
455 MIL <<
" " << output;
457 int ret = prog.
close();
468 MIL <<
"copy_dir " << srcpath <<
" -> " << destpath <<
' ';
481 if ( tp.isExist() ) {
486 const char *
const argv[] = {
491 destpath.asString().c_str(),
496 MIL <<
" " << output;
498 int ret = prog.
close();
509 MIL <<
"copy_dir " << srcpath <<
" -> " << destpath <<
' ';
521 if ( srcpath == destpath ) {
525 std::string src( srcpath.
asString());
527 const char *
const argv[] = {
532 destpath.asString().c_str(),
537 MIL <<
" " << output;
539 int ret = prog.
close();
559 []( DIR * dir_r ) {
if ( dir_r ) ::closedir( dir_r ); } );
561 MIL <<
"readdir " << dir_r <<
' ';
567 for (
struct dirent * entry = ::
readdir( dir ); entry; entry =
::readdir( dir ) )
569 if ( entry->d_name[0] ==
'.' && ( entry->d_name[1] ==
'\0' || ( entry->d_name[1] ==
'.' && entry->d_name[2] ==
'\0' ) ) )
572 if ( ! fnc_r( dir_r, entry->d_name ) )
588 [&](
const Pathname & dir_r,
const char *
const name_r )->
bool
590 if ( ( nodots && name_r[0] ==
'.' ) || ! matcher_r( name_r ) )
592 return fnc_r( dir_r, name_r );
600 int readdir( std::list<std::string> & retlist_r,
const Pathname & path_r,
bool dots_r )
604 [&](
const Pathname & dir_r,
const char *
const name_r )->
bool
606 if ( dots_r || name_r[0] !=
'.' )
607 retlist_r.push_back( name_r );
617 [&](
const Pathname & dir_r,
const char *
const name_r )->
bool
619 if ( dots_r || name_r[0] !=
'.' )
620 retlist_r.push_back( dir_r/name_r );
637 [&](
const Pathname & dir_r,
const char *
const name_r )->
bool
639 if ( dots_r || name_r[0] !=
'.' )
640 retlist_r.push_back(
DirEntry( name_r,
PathInfo( dir_r/name_r, statmode_r ).fileType() ) );
652 [&](
const Pathname & dir_r,
const char *
const name_r )->
bool
663 MIL <<
"unlink " << path;
664 if ( ::
unlink( path.asString().c_str() ) == -1 ) {
677 MIL <<
"rename " << oldpath <<
" -> " << newpath;
678 if ( ::
rename( oldpath.
asString().c_str(), newpath.asString().c_str() ) == -1 ) {
691 MIL <<
"exchange " << lpath <<
" <-> " << rpath;
692 if ( lpath.
empty() || rpath.empty() )
707 if ( ::
rename( rpath.c_str(), lpath.
c_str() ) == -1 ) {
720 if ( ::
rename( lpath.
c_str(), rpath.c_str() ) == -1 ) {
733 if ( ::
rename( lpath.
c_str(), tmp.c_str() ) == -1 ) {
736 if ( ::
rename( rpath.c_str(), lpath.
c_str() ) == -1 ) {
740 if ( ::
rename( tmp.c_str(), rpath.c_str() ) == -1 ) {
755 MIL <<
"copy " << file <<
" -> " << dest <<
' ';
767 const char *
const argv[] = {
769 "--remove-destination",
772 dest.asString().c_str(),
777 MIL <<
" " << output;
779 int ret = prog.
close();
790 MIL <<
"symlink " << newpath <<
" -> " << oldpath;
791 if ( ::
symlink( oldpath.asString().c_str(), newpath.
asString().c_str() ) == -1 ) {
804 MIL <<
"hardlink " << newpath <<
" -> " << oldpath;
805 if ( ::link( oldpath.asString().c_str(), newpath.
asString().c_str() ) == -1 ) {
818 MIL <<
"hardlinkCopy " << oldpath <<
" -> " << newpath;
824 return copy( oldpath, newpath );
830 int res =
unlink( newpath );
836 if ( ::link( oldpath.
asString().c_str(), newpath.asString().c_str() ) == -1 )
841 return copy( oldpath, newpath );
856 static const ssize_t bufsiz = 2047;
857 static char buf[bufsiz+1];
862 MIL <<
"readlink " << symlink_r;
877 static const unsigned int level_limit = 256;
878 static unsigned int count;
882 for (count = level_limit; info.
isLink() && count; count--)
884 DBG <<
"following symlink " << path;
886 DBG <<
"->" << path << std::endl;
893 ERR <<
"Expand level limit reached. Probably a cyclic symbolic link." << endl;
897 else if (count < level_limit)
905 ERR << path <<
" is broken (expanded from " << path_r <<
")" << endl;
911 DBG <<
"not a symlink" << endl;
922 MIL <<
"copy_file2dir " << file <<
" -> " << dest <<
' ';
934 const char *
const argv[] = {
938 dest.asString().c_str(),
943 MIL <<
" " << output;
945 int ret = prog.
close();
956 if ( !
PathInfo( file ).isFile() ) {
959 std::ifstream istr( file.
asString().c_str() );
983 if ( !
PathInfo( file ).isFile() ) {
986 std::ifstream istr( file.
asString().c_str() );
1033 mode_t omode(
PathInfo( path ).st_mode() );
1034 mode_t tmode( omode | mode );
1035 if ( omode != mode )
1036 return chmod( path, tmode );
1042 mode_t omode(
PathInfo( path ).st_mode() );
1043 mode_t tmode( omode & ~mode );
1044 if ( omode != mode )
1045 return chmod( path, tmode );
1058 int fd = open( file.
asString().c_str(), O_RDONLY|O_CLOEXEC );
1061 const int magicSize = 3;
1062 unsigned char magic[magicSize];
1063 memset( magic, 0, magicSize );
1064 if (
read( fd, magic, magicSize ) == magicSize ) {
1065 if ( magic[0] == 0037 && magic[1] == 0213 ) {
1067 }
else if ( magic[0] ==
'B' && magic[1] ==
'Z' && magic[2] ==
'h' ) {
1086 if ( statvfs( path_r.
c_str(), &sb ) == 0 )
1088 ret = sb.f_bfree * sb.f_bsize;
1100 mode_t mask = ::umask( 0022 );
1121 int fd = ::creat( path.c_str(), mode );
1136 MIL <<
"touch " << path;
1137 struct ::utimbuf times;
1138 times.actime = ::time( 0 );
1139 times.modtime = ::time( 0 );
1140 if ( ::utime( path.asString().c_str(), × ) == -1 ) {