1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PathInfo.cc
13 #include <sys/types.h> // for ::minor, ::major macros
14 #include <utime.h> // for ::utime
15 #include <sys/statvfs.h>
21 #include "zypp/base/LogTools.h"
22 #include "zypp/base/String.h"
23 #include "zypp/base/IOStream.h"
24 #include "zypp/base/StrMatcher.h"
25 #include "zypp/base/Errno.h"
27 #include "zypp/AutoDispose.h"
28 #include "zypp/ExternalProgram.h"
29 #include "zypp/PathInfo.h"
30 #include "zypp/Digest.h"
31 #include "zypp/TmpPath.h"
36 ///////////////////////////////////////////////////////////////////
38 { /////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////
41 { /////////////////////////////////////////////////////////////////
43 /******************************************************************
45 ** FUNCTION NAME : operator<<
46 ** FUNCTION TYPE : std::ostream &
48 std::ostream & operator<<( std::ostream & str, FileType obj )
51 #define EMUMOUT(T) case T: return str << #T; break
52 EMUMOUT( FT_NOT_AVAIL );
53 EMUMOUT( FT_NOT_EXIST );
56 EMUMOUT( FT_CHARDEV );
57 EMUMOUT( FT_BLOCKDEV );
66 ///////////////////////////////////////////////////////////////////
68 // METHOD NAME : StatMode::fileType
69 // METHOD TYPE : FileType
71 FileType StatMode::fileType() const
91 /******************************************************************
93 ** FUNCTION NAME : operator<<
94 ** FUNCTION TYPE : std::ostream &
96 std::ostream & operator<<( std::ostream & str, const StatMode & obj )
98 iostr::IosFmtFlagsSaver autoResoreState( str );
103 else if ( obj.isDir() )
105 else if ( obj.isLink() )
107 else if ( obj.isChr() )
109 else if ( obj.isBlk() )
111 else if ( obj.isFifo() )
113 else if ( obj.isSock() )
116 str << t << " " << std::setfill( '0' ) << std::setw( 4 ) << std::oct << obj.perm();
120 ///////////////////////////////////////////////////////////////////
124 ///////////////////////////////////////////////////////////////////
126 ///////////////////////////////////////////////////////////////////
128 // METHOD NAME : PathInfo::PathInfo
129 // METHOD TYPE : Constructor
136 ///////////////////////////////////////////////////////////////////
138 // METHOD NAME : PathInfo::PathInfo
139 // METHOD TYPE : Constructor
141 PathInfo::PathInfo( const Pathname & path, Mode initial )
149 ///////////////////////////////////////////////////////////////////
151 // METHOD NAME : PathInfo::PathInfo
152 // METHOD TYPE : Constructor
154 PathInfo::PathInfo( const std::string & path, Mode initial )
162 ///////////////////////////////////////////////////////////////////
164 // METHOD NAME : PathInfo::PathInfo
165 // METHOD TYPE : Constructor
167 PathInfo::PathInfo( const char * path, Mode initial )
175 ///////////////////////////////////////////////////////////////////
177 // METHOD NAME : PathInfo::~PathInfo
178 // METHOD TYPE : Destructor
180 PathInfo::~PathInfo()
184 ///////////////////////////////////////////////////////////////////
186 // METHOD NAME : PathInfo::operator()
187 // METHOD TYPE : bool
189 bool PathInfo::operator()()
191 if ( path_t.empty() ) {
196 error_i = ::stat( path_t.asString().c_str(), &statbuf_C );
199 error_i = ::lstat( path_t.asString().c_str(), &statbuf_C );
208 ///////////////////////////////////////////////////////////////////
210 // METHOD NAME : PathInfo::fileType
211 // METHOD TYPE : File_type
213 FileType PathInfo::fileType() const
216 return asStatMode().fileType();
220 ///////////////////////////////////////////////////////////////////
222 // METHOD NAME : PathInfo::userMay
223 // METHOD TYPE : mode_t
225 mode_t PathInfo::userMay() const
229 if ( owner() == geteuid() ) {
230 return( uperm()/0100 );
231 } else if ( group() == getegid() ) {
232 return( gperm()/010 );
237 /******************************************************************
239 ** FUNCTION NAME : PathInfo::devMajor
240 ** FUNCTION TYPE : unsigned int
242 unsigned int PathInfo::devMajor() const
244 return isBlk() || isChr() ? ::major(statbuf_C.st_rdev) : 0;
247 /******************************************************************
249 ** FUNCTION NAME : PathInfo::devMinor
250 ** FUNCTION TYPE : unsigned int
252 unsigned int PathInfo::devMinor() const
254 return isBlk() || isChr() ? ::minor(statbuf_C.st_rdev) : 0;
257 unsigned int PathInfo::major() const
258 { INT << "Cleanup the code: This method is deprecated" << endl; return devMajor(); }
259 unsigned int PathInfo::minor() const
260 { INT << "Cleanup the code: This method is deprecated" << endl; return devMinor(); }
262 /******************************************************************
264 ** FUNCTION NAME : operator<<
265 ** FUNCTION TYPE : std::ostream &
267 std::ostream & operator<<( std::ostream & str, const PathInfo & obj )
269 iostr::IosFmtFlagsSaver autoResoreState( str );
271 str << obj.asString() << "{";
272 if ( !obj.isExist() ) {
273 str << Errno( obj.error() );
275 str << obj.asStatMode() << " " << std::dec << obj.owner() << "/" << obj.group();
278 str << " size " << obj.size();
284 ///////////////////////////////////////////////////////////////////
286 // filesystem utilities
288 ///////////////////////////////////////////////////////////////////
290 /******************************************************************
292 ** FUNCTION NAME : _Log_Result
293 ** FUNCTION TYPE : int
295 ** DESCRIPTION : Helper function to log return values.
297 #define _Log_Result MIL << endl, __Log_Result
298 inline int __Log_Result( const int res, const char * rclass = 0 /*errno*/ )
303 WAR << " FAILED: " << rclass << " " << res << endl;
305 WAR << " FAILED: " << str::strerror( res ) << endl;
310 ///////////////////////////////////////////////////////////////////
312 // METHOD NAME : PathInfo::mkdir
315 int mkdir( const Pathname & path, unsigned mode )
317 MIL << "mkdir " << path << ' ' << str::octstring( mode );
318 if ( ::mkdir( path.asString().c_str(), mode ) == -1 ) {
319 return _Log_Result( errno );
321 return _Log_Result( 0 );
324 ///////////////////////////////////////////////////////////////////
326 // METHOD NAME : assert_dir()
329 int assert_dir( const Pathname & path, unsigned mode )
334 { // Handle existing paths in advance.
342 string spath = path.asString()+"/";
343 string::size_type lastpos = ( path.relative() ? 2 : 1 ); // skip leasding './' or '/'
344 string::size_type pos = string::npos;
347 while ( (pos = spath.find('/',lastpos)) != string::npos )
349 string dir( spath.substr(0,pos) );
350 ret = ::mkdir( dir.c_str(), mode );
353 if ( errno == EEXIST ) // ignore errors about already existing paths
358 WAR << " FAILED: mkdir " << dir << ' ' << str::octstring( mode ) << " errno " << ret << endl;
363 MIL << "mkdir " << dir << ' ' << str::octstring( mode ) << endl;
371 ///////////////////////////////////////////////////////////////////
373 // METHOD NAME : rmdir
376 int rmdir( const Pathname & path )
378 MIL << "rmdir " << path;
379 if ( ::rmdir( path.asString().c_str() ) == -1 ) {
380 return _Log_Result( errno );
382 return _Log_Result( 0 );
385 ///////////////////////////////////////////////////////////////////
387 // METHOD NAME : recursive_rmdir
390 static int recursive_rmdir_1( const Pathname & dir )
395 if ( ! (dp = opendir( dir.c_str() )) )
396 return _Log_Result( errno );
398 while ( (d = readdir(dp)) )
400 std::string direntry = d->d_name;
401 if ( direntry == "." || direntry == ".." )
403 Pathname new_path( dir / d->d_name );
406 if ( ! lstat( new_path.c_str(), &st ) )
408 if ( S_ISDIR( st.st_mode ) )
409 recursive_rmdir_1( new_path );
411 ::unlink( new_path.c_str() );
416 if ( ::rmdir( dir.c_str() ) < 0 )
421 ///////////////////////////////////////////////////////////////////
422 int recursive_rmdir( const Pathname & path )
424 MIL << "recursive_rmdir " << path << ' ';
427 if ( !p.isExist() ) {
428 return _Log_Result( 0 );
432 return _Log_Result( ENOTDIR );
435 return _Log_Result( recursive_rmdir_1( path ) );
438 ///////////////////////////////////////////////////////////////////
440 // METHOD NAME : clean_dir
443 int clean_dir( const Pathname & path )
445 MIL << "clean_dir " << path << ' ';
448 if ( !p.isExist() ) {
449 return _Log_Result( 0 );
453 return _Log_Result( ENOTDIR );
456 string cmd( str::form( "cd '%s' && rm -rf --preserve-root -- *", path.asString().c_str() ) );
457 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
458 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
459 MIL << " " << output;
461 int ret = prog.close();
462 return _Log_Result( ret, "returned" );
465 ///////////////////////////////////////////////////////////////////
467 // METHOD NAME : copy_dir
470 int copy_dir( const Pathname & srcpath, const Pathname & destpath )
472 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
474 PathInfo sp( srcpath );
476 return _Log_Result( ENOTDIR );
479 PathInfo dp( destpath );
481 return _Log_Result( ENOTDIR );
484 PathInfo tp( destpath + srcpath.basename() );
485 if ( tp.isExist() ) {
486 return _Log_Result( EEXIST );
490 const char *const argv[] = {
494 srcpath.asString().c_str(),
495 destpath.asString().c_str(),
498 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
499 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
500 MIL << " " << output;
502 int ret = prog.close();
503 return _Log_Result( ret, "returned" );
506 ///////////////////////////////////////////////////////////////////
508 // METHOD NAME : copy_dir_content
511 int copy_dir_content(const Pathname & srcpath, const Pathname & destpath)
513 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
515 PathInfo sp( srcpath );
517 return _Log_Result( ENOTDIR );
520 PathInfo dp( destpath );
522 return _Log_Result( ENOTDIR );
525 if ( srcpath == destpath ) {
526 return _Log_Result( EEXIST );
529 std::string src( srcpath.asString());
531 const char *const argv[] = {
536 destpath.asString().c_str(),
539 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
540 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
541 MIL << " " << output;
543 int ret = prog.close();
544 return _Log_Result( ret, "returned" );
547 ///////////////////////////////////////////////////////////////////////
549 ///////////////////////////////////////////////////////////////////////
551 const StrMatcher & matchNoDots()
553 static StrMatcher noDots( "[^.]*", Match::GLOB );
557 int dirForEach( const Pathname & dir_r, function<bool(const Pathname &, const char *const)> fnc_r )
562 AutoDispose<DIR *> dir( ::opendir( dir_r.c_str() ),
563 []( DIR * dir_r ) { if ( dir_r ) ::closedir( dir_r ); } );
565 MIL << "readdir " << dir_r << ' ';
567 return _Log_Result( errno );
568 MIL << endl; // close line before callbacks are invoked.
571 for ( struct dirent * entry = ::readdir( dir ); entry; entry = ::readdir( dir ) )
573 if ( entry->d_name[0] == '.' && ( entry->d_name[1] == '\0' || ( entry->d_name[1] == '.' && entry->d_name[2] == '\0' ) ) )
574 continue; // omitt . and ..
576 if ( ! fnc_r( dir_r, entry->d_name ) )
585 int dirForEach( const Pathname & dir_r, const StrMatcher & matcher_r, function<bool( const Pathname &, const char *const)> fnc_r )
590 bool nodots = ( &matcher_r == &matchNoDots() );
591 return dirForEach( dir_r,
592 [&]( const Pathname & dir_r, const char *const name_r )->bool
594 if ( ( nodots && name_r[0] == '.' ) || ! matcher_r( name_r ) )
596 return fnc_r( dir_r, name_r );
600 ///////////////////////////////////////////////////////////////////
602 ///////////////////////////////////////////////////////////////////
604 int readdir( std::list<std::string> & retlist_r, const Pathname & path_r, bool dots_r )
607 return dirForEach( path_r,
608 [&]( const Pathname & dir_r, const char *const name_r )->bool
610 if ( dots_r || name_r[0] != '.' )
611 retlist_r.push_back( name_r );
617 int readdir( std::list<Pathname> & retlist_r, const Pathname & path_r, bool dots_r )
620 return dirForEach( path_r,
621 [&]( const Pathname & dir_r, const char *const name_r )->bool
623 if ( dots_r || name_r[0] != '.' )
624 retlist_r.push_back( dir_r/name_r );
629 bool DirEntry::operator==( const DirEntry &rhs ) const
631 // if one of the types is not known, use the name only
632 if ( type == FT_NOT_AVAIL || rhs.type == FT_NOT_AVAIL )
633 return ( name == rhs.name );
634 return ((name == rhs.name ) && (type == rhs.type));
637 int readdir( DirContent & retlist_r, const Pathname & path_r, bool dots_r, PathInfo::Mode statmode_r )
640 return dirForEach( path_r,
641 [&]( const Pathname & dir_r, const char *const name_r )->bool
643 if ( dots_r || name_r[0] != '.' )
644 retlist_r.push_back( DirEntry( name_r, PathInfo( dir_r/name_r, statmode_r ).fileType() ) );
649 std::ostream & operator<<( std::ostream & str, const DirContent & obj )
650 { return dumpRange( str, obj.begin(), obj.end() ); }
652 ///////////////////////////////////////////////////////////////////
654 ///////////////////////////////////////////////////////////////////
656 int is_empty_dir( const Pathname & path_r )
658 return dirForEach( path_r,
659 [&]( const Pathname & dir_r, const char *const name_r )->bool
663 ///////////////////////////////////////////////////////////////////
665 // METHOD NAME : unlink
668 int unlink( const Pathname & path )
670 MIL << "unlink " << path;
671 if ( ::unlink( path.asString().c_str() ) == -1 ) {
672 return _Log_Result( errno );
674 return _Log_Result( 0 );
677 ///////////////////////////////////////////////////////////////////
679 // METHOD NAME : rename
682 int rename( const Pathname & oldpath, const Pathname & newpath )
684 MIL << "rename " << oldpath << " -> " << newpath;
685 if ( ::rename( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
686 return _Log_Result( errno );
688 return _Log_Result( 0 );
691 ///////////////////////////////////////////////////////////////////
693 // METHOD NAME : exchange
696 int exchange( const Pathname & lpath, const Pathname & rpath )
698 MIL << "exchange " << lpath << " <-> " << rpath;
699 if ( lpath.empty() || rpath.empty() )
700 return _Log_Result( EINVAL );
702 PathInfo linfo( lpath );
703 PathInfo rinfo( rpath );
705 if ( ! linfo.isExist() )
707 if ( ! rinfo.isExist() )
708 return _Log_Result( 0 ); // both don't exist.
710 // just rename rpath -> lpath
711 int ret = assert_dir( lpath.dirname() );
713 return _Log_Result( ret );
714 if ( ::rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
715 return _Log_Result( errno );
717 return _Log_Result( 0 );
720 // HERE: lpath exists:
721 if ( ! rinfo.isExist() )
723 // just rename lpath -> rpath
724 int ret = assert_dir( rpath.dirname() );
726 return _Log_Result( ret );
727 if ( ::rename( lpath.c_str(), rpath.c_str() ) == -1 ) {
728 return _Log_Result( errno );
730 return _Log_Result( 0 );
734 TmpFile tmpfile( TmpFile::makeSibling( rpath ) );
736 return _Log_Result( errno );
737 Pathname tmp( tmpfile.path() );
738 ::unlink( tmp.c_str() );
740 if ( ::rename( lpath.c_str(), tmp.c_str() ) == -1 ) {
741 return _Log_Result( errno );
743 if ( ::rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
744 ::rename( tmp.c_str(), lpath.c_str() );
745 return _Log_Result( errno );
747 if ( ::rename( tmp.c_str(), rpath.c_str() ) == -1 ) {
748 ::rename( lpath.c_str(), rpath.c_str() );
749 ::rename( tmp.c_str(), lpath.c_str() );
750 return _Log_Result( errno );
752 return _Log_Result( 0 );
755 ///////////////////////////////////////////////////////////////////
757 // METHOD NAME : copy
760 int copy( const Pathname & file, const Pathname & dest )
762 MIL << "copy " << file << " -> " << dest << ' ';
765 if ( !sp.isFile() ) {
766 return _Log_Result( EINVAL );
771 return _Log_Result( EISDIR );
774 const char *const argv[] = {
776 "--remove-destination",
778 file.asString().c_str(),
779 dest.asString().c_str(),
782 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
783 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
784 MIL << " " << output;
786 int ret = prog.close();
787 return _Log_Result( ret, "returned" );
790 ///////////////////////////////////////////////////////////////////
792 // METHOD NAME : symlink
795 int symlink( const Pathname & oldpath, const Pathname & newpath )
797 MIL << "symlink " << newpath << " -> " << oldpath;
798 if ( ::symlink( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
799 return _Log_Result( errno );
801 return _Log_Result( 0 );
804 ///////////////////////////////////////////////////////////////////
806 // METHOD NAME : hardlink
809 int hardlink( const Pathname & oldpath, const Pathname & newpath )
811 MIL << "hardlink " << newpath << " -> " << oldpath;
812 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
813 return _Log_Result( errno );
815 return _Log_Result( 0 );
818 ///////////////////////////////////////////////////////////////////
820 // METHOD NAME : hardlink
823 int hardlinkCopy( const Pathname & oldpath, const Pathname & newpath )
825 MIL << "hardlinkCopy " << oldpath << " -> " << newpath;
827 PathInfo pi( oldpath, PathInfo::LSTAT );
830 // dont hardlink symlinks!
831 return copy( oldpath, newpath );
837 int res = unlink( newpath );
839 return _Log_Result( res );
842 // Here: no symlink, no newpath
843 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 )
847 case EPERM: // /proc/sys/fs/protected_hardlink in proc(5)
848 case EXDEV: // oldpath and newpath are not on the same mounted file system
849 return copy( oldpath, newpath );
852 return _Log_Result( errno );
854 return _Log_Result( 0 );
857 ///////////////////////////////////////////////////////////////////
859 // METHOD NAME : readlink
862 int readlink( const Pathname & symlink_r, Pathname & target_r )
864 static const ssize_t bufsiz = 2047;
865 static char buf[bufsiz+1];
866 ssize_t ret = ::readlink( symlink_r.c_str(), buf, bufsiz );
869 target_r = Pathname();
870 MIL << "readlink " << symlink_r;
871 return _Log_Result( errno );
878 ///////////////////////////////////////////////////////////////////
880 // METHOD NAME : expandlink
881 // METHOD TYPE : Pathname
883 Pathname expandlink( const Pathname & path_r )
885 static const unsigned int level_limit = 256;
886 static unsigned int count;
887 Pathname path(path_r);
888 PathInfo info(path_r, PathInfo::LSTAT);
890 for (count = level_limit; info.isLink() && count; count--)
892 DBG << "following symlink " << path;
893 path = path.dirname() / readlink(path);
894 DBG << "->" << path << std::endl;
895 info = PathInfo(path, PathInfo::LSTAT);
898 // expand limit reached
901 ERR << "Expand level limit reached. Probably a cyclic symbolic link." << endl;
905 else if (count < level_limit)
907 // check for a broken link
908 if (PathInfo(path).isExist())
910 // broken link, return an empty path
913 ERR << path << " is broken (expanded from " << path_r << ")" << endl;
918 // not a symlink, return the original pathname
919 DBG << "not a symlink" << endl;
923 ///////////////////////////////////////////////////////////////////
925 // METHOD NAME : copy_file2dir
928 int copy_file2dir( const Pathname & file, const Pathname & dest )
930 MIL << "copy_file2dir " << file << " -> " << dest << ' ';
933 if ( !sp.isFile() ) {
934 return _Log_Result( EINVAL );
939 return _Log_Result( ENOTDIR );
942 const char *const argv[] = {
945 file.asString().c_str(),
946 dest.asString().c_str(),
949 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
950 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
951 MIL << " " << output;
953 int ret = prog.close();
954 return _Log_Result( ret, "returned" );
957 ///////////////////////////////////////////////////////////////////
959 // METHOD NAME : md5sum
960 // METHOD TYPE : std::string
962 std::string md5sum( const Pathname & file )
964 if ( ! PathInfo( file ).isFile() ) {
967 std::ifstream istr( file.asString().c_str() );
971 return Digest::digest( "MD5", istr );
974 ///////////////////////////////////////////////////////////////////
976 // METHOD NAME : sha1sum
977 // METHOD TYPE : std::string
979 std::string sha1sum( const Pathname & file )
981 return checksum(file, "SHA1");
984 ///////////////////////////////////////////////////////////////////
986 // METHOD NAME : checksum
987 // METHOD TYPE : std::string
989 std::string checksum( const Pathname & file, const std::string &algorithm )
991 if ( ! PathInfo( file ).isFile() ) {
994 std::ifstream istr( file.asString().c_str() );
998 return Digest::digest( algorithm, istr );
1001 bool is_checksum( const Pathname & file, const CheckSum &checksum )
1003 return ( filesystem::checksum(file, checksum.type()) == checksum.checksum() );
1006 ///////////////////////////////////////////////////////////////////
1008 // METHOD NAME : erase
1009 // METHOD TYPE : int
1011 int erase( const Pathname & path )
1014 PathInfo p( path, PathInfo::LSTAT );
1018 res = recursive_rmdir( path );
1020 res = unlink( path );
1025 ///////////////////////////////////////////////////////////////////
1027 // METHOD NAME : chmod
1028 // METHOD TYPE : int
1030 int chmod( const Pathname & path, mode_t mode )
1032 MIL << "chmod " << path << ' ' << str::octstring( mode );
1033 if ( ::chmod( path.asString().c_str(), mode ) == -1 ) {
1034 return _Log_Result( errno );
1036 return _Log_Result( 0 );
1039 int addmod( const Pathname & path, mode_t mode )
1041 mode_t omode( PathInfo( path ).st_mode() );
1042 mode_t tmode( omode | mode );
1043 if ( omode != mode )
1044 return chmod( path, tmode );
1048 int delmod( const Pathname & path, mode_t mode )
1050 mode_t omode( PathInfo( path ).st_mode() );
1051 mode_t tmode( omode & ~mode );
1052 if ( omode != mode )
1053 return chmod( path, tmode );
1057 //////////////////////////////////////////////////////////////////
1059 // METHOD NAME : zipType
1060 // METHOD TYPE : ZIP_TYPE
1062 ZIP_TYPE zipType( const Pathname & file )
1064 ZIP_TYPE ret = ZT_NONE;
1066 int fd = open( file.asString().c_str(), O_RDONLY|O_CLOEXEC );
1069 const int magicSize = 3;
1070 unsigned char magic[magicSize];
1071 memset( magic, 0, magicSize );
1072 if ( read( fd, magic, magicSize ) == magicSize ) {
1073 if ( magic[0] == 0037 && magic[1] == 0213 ) {
1075 } else if ( magic[0] == 'B' && magic[1] == 'Z' && magic[2] == 'h' ) {
1085 ///////////////////////////////////////////////////////////////////
1088 // METHOD TYPE : ByteCount
1090 ByteCount df( const Pathname & path_r )
1092 ByteCount ret( -1 );
1094 if ( statvfs( path_r.c_str(), &sb ) == 0 )
1096 ret = sb.f_bfree * sb.f_bsize;
1101 ///////////////////////////////////////////////////////////////////
1103 // METHOD NAME : getUmask
1104 // METHOD TYPE : mode_t
1108 mode_t mask = ::umask( 0022 );
1113 ///////////////////////////////////////////////////////////////////
1115 // METHOD NAME : getUmask
1116 // METHOD TYPE : mode_t
1118 int assert_file( const Pathname & path, unsigned mode )
1120 int ret = assert_dir( path.dirname() );
1121 MIL << "assert_file " << str::octstring( mode ) << " " << path;
1123 return _Log_Result( ret );
1125 PathInfo pi( path );
1127 return _Log_Result( pi.isFile() ? 0 : EEXIST );
1129 int fd = ::creat( path.c_str(), mode );
1131 return _Log_Result( errno );
1134 return _Log_Result( 0 );
1137 ///////////////////////////////////////////////////////////////////
1139 // METHOD NAME : touch
1140 // METHOD TYPE : int
1142 int touch (const Pathname & path)
1144 MIL << "touch " << path;
1145 struct ::utimbuf times;
1146 times.actime = ::time( 0 );
1147 times.modtime = ::time( 0 );
1148 if ( ::utime( path.asString().c_str(), × ) == -1 ) {
1149 return _Log_Result( errno );
1151 return _Log_Result( 0 );
1154 /////////////////////////////////////////////////////////////////
1155 } // namespace filesystem
1156 ///////////////////////////////////////////////////////////////////
1157 /////////////////////////////////////////////////////////////////
1159 ///////////////////////////////////////////////////////////////////