1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PathInfo.cc
13 #include <utime.h> // for ::utime
14 #include <sys/statvfs.h>
15 #include <sys/sysmacros.h> // for ::minor, ::major macros
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 /******************************************************************
259 ** FUNCTION NAME : operator<<
260 ** FUNCTION TYPE : std::ostream &
262 std::ostream & operator<<( std::ostream & str, const PathInfo & obj )
264 iostr::IosFmtFlagsSaver autoResoreState( str );
266 str << obj.asString() << "{";
267 if ( !obj.isExist() ) {
268 str << Errno( obj.error() );
270 str << obj.asStatMode() << " " << std::dec << obj.owner() << "/" << obj.group();
273 str << " size " << obj.size();
279 ///////////////////////////////////////////////////////////////////
281 // filesystem utilities
283 ///////////////////////////////////////////////////////////////////
285 #define logResult MIL << endl, doLogResult
287 /** Helper function to log return values. */
288 inline int doLogResult( const int res, const char * rclass = 0 /*errno*/ )
293 WAR << " FAILED: " << rclass << " " << res << endl;
295 WAR << " FAILED: " << str::strerror( res ) << endl;
301 ///////////////////////////////////////////////////////////////////
303 // METHOD NAME : PathInfo::mkdir
306 int mkdir( const Pathname & path, unsigned mode )
308 MIL << "mkdir " << path << ' ' << str::octstring( mode );
309 if ( ::mkdir( path.asString().c_str(), mode ) == -1 ) {
310 return logResult( errno );
312 return logResult( 0 );
315 ///////////////////////////////////////////////////////////////////
317 // METHOD NAME : assert_dir()
320 int assert_dir( const Pathname & path, unsigned mode )
325 { // Handle existing paths in advance.
333 string spath = path.asString()+"/";
334 std::string::size_type lastpos = ( path.relative() ? 2 : 1 ); // skip leasding './' or '/'
335 std::string::size_type pos = std::string::npos;
338 while ( (pos = spath.find('/',lastpos)) != std::string::npos )
340 string dir( spath.substr(0,pos) );
341 ret = ::mkdir( dir.c_str(), mode );
344 if ( errno == EEXIST ) // ignore errors about already existing paths
349 WAR << " FAILED: mkdir " << dir << ' ' << str::octstring( mode ) << " errno " << ret << endl;
354 MIL << "mkdir " << dir << ' ' << str::octstring( mode ) << endl;
362 ///////////////////////////////////////////////////////////////////
364 // METHOD NAME : rmdir
367 int rmdir( const Pathname & path )
369 MIL << "rmdir " << path;
370 if ( ::rmdir( path.asString().c_str() ) == -1 ) {
371 return logResult( errno );
373 return logResult( 0 );
376 ///////////////////////////////////////////////////////////////////
378 // METHOD NAME : recursive_rmdir
381 static int recursive_rmdir_1( const Pathname & dir, bool removeDir = true )
386 if ( ! (dp = opendir( dir.c_str() )) )
387 return logResult( errno );
389 while ( (d = readdir(dp)) )
391 std::string direntry = d->d_name;
392 if ( direntry == "." || direntry == ".." )
394 Pathname new_path( dir / d->d_name );
397 if ( ! lstat( new_path.c_str(), &st ) )
399 if ( S_ISDIR( st.st_mode ) )
400 recursive_rmdir_1( new_path );
402 ::unlink( new_path.c_str() );
407 if ( removeDir && ::rmdir( dir.c_str() ) < 0 )
412 ///////////////////////////////////////////////////////////////////
413 int recursive_rmdir( const Pathname & path )
415 MIL << "recursive_rmdir " << path << ' ';
418 if ( !p.isExist() ) {
419 return logResult( 0 );
423 return logResult( ENOTDIR );
426 p.lstat(); // get dir symlinks
428 MIL << "unlink symlink ";
429 if ( ::unlink( path.asString().c_str() ) == -1 ) {
430 return logResult( errno );
432 return logResult( 0 );
435 return logResult( 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 logResult( 0 );
453 return logResult( ENOTDIR );
456 return logResult( recursive_rmdir_1( path, false/* don't remove path itself */ ) );
459 ///////////////////////////////////////////////////////////////////
461 // METHOD NAME : copy_dir
464 int copy_dir( const Pathname & srcpath, const Pathname & destpath )
466 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
468 PathInfo sp( srcpath );
470 return logResult( ENOTDIR );
473 PathInfo dp( destpath );
475 return logResult( ENOTDIR );
478 PathInfo tp( destpath + srcpath.basename() );
479 if ( tp.isExist() ) {
480 return logResult( EEXIST );
484 const char *const argv[] = {
488 srcpath.asString().c_str(),
489 destpath.asString().c_str(),
492 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
493 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
494 MIL << " " << output;
496 int ret = prog.close();
497 return logResult( ret, "returned" );
500 ///////////////////////////////////////////////////////////////////
502 // METHOD NAME : copy_dir_content
505 int copy_dir_content(const Pathname & srcpath, const Pathname & destpath)
507 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
509 PathInfo sp( srcpath );
511 return logResult( ENOTDIR );
514 PathInfo dp( destpath );
516 return logResult( ENOTDIR );
519 if ( srcpath == destpath ) {
520 return logResult( EEXIST );
523 std::string src( srcpath.asString());
525 const char *const argv[] = {
530 destpath.asString().c_str(),
533 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
534 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
535 MIL << " " << output;
537 int ret = prog.close();
538 return logResult( ret, "returned" );
541 ///////////////////////////////////////////////////////////////////////
543 ///////////////////////////////////////////////////////////////////////
545 const StrMatcher & matchNoDots()
547 static StrMatcher noDots( "[^.]*", Match::GLOB );
551 int dirForEach( const Pathname & dir_r, function<bool(const Pathname &, const char *const)> fnc_r )
556 AutoDispose<DIR *> dir( ::opendir( dir_r.c_str() ),
557 []( DIR * dir_r ) { if ( dir_r ) ::closedir( dir_r ); } );
559 MIL << "readdir " << dir_r << ' ';
561 return logResult( errno );
562 MIL << endl; // close line before callbacks are invoked.
565 for ( struct dirent * entry = ::readdir( dir ); entry; entry = ::readdir( dir ) )
567 if ( entry->d_name[0] == '.' && ( entry->d_name[1] == '\0' || ( entry->d_name[1] == '.' && entry->d_name[2] == '\0' ) ) )
568 continue; // omitt . and ..
570 if ( ! fnc_r( dir_r, entry->d_name ) )
579 int dirForEach( const Pathname & dir_r, const StrMatcher & matcher_r, function<bool( const Pathname &, const char *const)> fnc_r )
584 bool nodots = ( &matcher_r == &matchNoDots() );
585 return dirForEach( dir_r,
586 [&]( const Pathname & dir_r, const char *const name_r )->bool
588 if ( ( nodots && name_r[0] == '.' ) || ! matcher_r( name_r ) )
590 return fnc_r( dir_r, name_r );
594 ///////////////////////////////////////////////////////////////////
596 ///////////////////////////////////////////////////////////////////
598 int readdir( std::list<std::string> & retlist_r, const Pathname & path_r, bool dots_r )
601 return dirForEach( path_r,
602 [&]( const Pathname & dir_r, const char *const name_r )->bool
604 if ( dots_r || name_r[0] != '.' )
605 retlist_r.push_back( name_r );
611 int readdir( std::list<Pathname> & retlist_r, const Pathname & path_r, bool dots_r )
614 return dirForEach( path_r,
615 [&]( const Pathname & dir_r, const char *const name_r )->bool
617 if ( dots_r || name_r[0] != '.' )
618 retlist_r.push_back( dir_r/name_r );
623 bool DirEntry::operator==( const DirEntry &rhs ) const
625 // if one of the types is not known, use the name only
626 if ( type == FT_NOT_AVAIL || rhs.type == FT_NOT_AVAIL )
627 return ( name == rhs.name );
628 return ((name == rhs.name ) && (type == rhs.type));
631 int readdir( DirContent & retlist_r, const Pathname & path_r, bool dots_r, PathInfo::Mode statmode_r )
634 return dirForEach( path_r,
635 [&]( const Pathname & dir_r, const char *const name_r )->bool
637 if ( dots_r || name_r[0] != '.' )
638 retlist_r.push_back( DirEntry( name_r, PathInfo( dir_r/name_r, statmode_r ).fileType() ) );
643 std::ostream & operator<<( std::ostream & str, const DirContent & obj )
644 { return dumpRange( str, obj.begin(), obj.end() ); }
646 ///////////////////////////////////////////////////////////////////
648 ///////////////////////////////////////////////////////////////////
650 int is_empty_dir( const Pathname & path_r )
652 return dirForEach( path_r,
653 [&]( const Pathname & dir_r, const char *const name_r )->bool
657 ///////////////////////////////////////////////////////////////////
659 // METHOD NAME : unlink
662 int unlink( const Pathname & path )
664 MIL << "unlink " << path;
665 if ( ::unlink( path.asString().c_str() ) == -1 ) {
666 return logResult( errno );
668 return logResult( 0 );
671 ///////////////////////////////////////////////////////////////////
674 int safe_rename( const Pathname & oldpath, const Pathname & newpath )
676 int ret = ::rename( oldpath.asString().c_str(), newpath.asString().c_str() );
678 // rename(2) can fail on OverlayFS. Fallback to using mv(1), which is
679 // explicitly mentioned in the kernel docs to deal correctly with OverlayFS.
680 if ( ret == -1 && errno == EXDEV ) {
681 const char *const argv[] = {
683 oldpath.asString().c_str(),
684 newpath.asString().c_str(),
687 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
688 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
689 MIL << " " << output;
697 ///////////////////////////////////////////////////////////////////
699 ///////////////////////////////////////////////////////////////////
701 // METHOD NAME : rename
704 int rename( const Pathname & oldpath, const Pathname & newpath )
706 MIL << "rename " << oldpath << " -> " << newpath;
707 if ( safe_rename( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
708 return logResult( errno );
710 return logResult( 0 );
713 ///////////////////////////////////////////////////////////////////
715 // METHOD NAME : exchange
718 int exchange( const Pathname & lpath, const Pathname & rpath )
720 MIL << "exchange " << lpath << " <-> " << rpath;
721 if ( lpath.empty() || rpath.empty() )
722 return logResult( EINVAL );
724 PathInfo linfo( lpath );
725 PathInfo rinfo( rpath );
727 if ( ! linfo.isExist() )
729 if ( ! rinfo.isExist() )
730 return logResult( 0 ); // both don't exist.
732 // just rename rpath -> lpath
733 int ret = assert_dir( lpath.dirname() );
735 return logResult( ret );
736 if ( safe_rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
737 return logResult( errno );
739 return logResult( 0 );
742 // HERE: lpath exists:
743 if ( ! rinfo.isExist() )
745 // just rename lpath -> rpath
746 int ret = assert_dir( rpath.dirname() );
748 return logResult( ret );
749 if ( safe_rename( lpath.c_str(), rpath.c_str() ) == -1 ) {
750 return logResult( errno );
752 return logResult( 0 );
756 TmpFile tmpfile( TmpFile::makeSibling( rpath ) );
758 return logResult( errno );
759 Pathname tmp( tmpfile.path() );
760 ::unlink( tmp.c_str() );
762 if ( safe_rename( lpath.c_str(), tmp.c_str() ) == -1 ) {
763 return logResult( errno );
765 if ( safe_rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
766 safe_rename( tmp.c_str(), lpath.c_str() );
767 return logResult( errno );
769 if ( safe_rename( tmp.c_str(), rpath.c_str() ) == -1 ) {
770 safe_rename( lpath.c_str(), rpath.c_str() );
771 safe_rename( tmp.c_str(), lpath.c_str() );
772 return logResult( errno );
774 return logResult( 0 );
777 ///////////////////////////////////////////////////////////////////
779 // METHOD NAME : copy
782 int copy( const Pathname & file, const Pathname & dest )
784 MIL << "copy " << file << " -> " << dest << ' ';
787 if ( !sp.isFile() ) {
788 return logResult( EINVAL );
793 return logResult( EISDIR );
796 const char *const argv[] = {
798 "--remove-destination",
800 file.asString().c_str(),
801 dest.asString().c_str(),
804 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
805 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
806 MIL << " " << output;
808 int ret = prog.close();
809 return logResult( ret, "returned" );
812 ///////////////////////////////////////////////////////////////////
814 // METHOD NAME : symlink
817 int symlink( const Pathname & oldpath, const Pathname & newpath )
819 MIL << "symlink " << newpath << " -> " << oldpath;
820 if ( ::symlink( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
821 return logResult( errno );
823 return logResult( 0 );
826 ///////////////////////////////////////////////////////////////////
828 // METHOD NAME : hardlink
831 int hardlink( const Pathname & oldpath, const Pathname & newpath )
833 MIL << "hardlink " << newpath << " -> " << oldpath;
834 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
835 return logResult( errno );
837 return logResult( 0 );
840 ///////////////////////////////////////////////////////////////////
842 // METHOD NAME : hardlink
845 int hardlinkCopy( const Pathname & oldpath, const Pathname & newpath )
847 MIL << "hardlinkCopy " << oldpath << " -> " << newpath;
849 PathInfo pi( oldpath, PathInfo::LSTAT );
852 // dont hardlink symlinks!
853 MIL << " => copy" << endl;
854 return copy( oldpath, newpath );
860 int res = unlink( newpath );
862 return logResult( res );
865 // Here: no symlink, no newpath
866 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 )
870 case EPERM: // /proc/sys/fs/protected_hardlink in proc(5)
871 case EXDEV: // oldpath and newpath are not on the same mounted file system
872 MIL << " => copy" << endl;
873 return copy( oldpath, newpath );
876 return logResult( errno );
878 return logResult( 0 );
881 ///////////////////////////////////////////////////////////////////
883 // METHOD NAME : readlink
886 int readlink( const Pathname & symlink_r, Pathname & target_r )
888 static const ssize_t bufsiz = 2047;
889 static char buf[bufsiz+1];
890 ssize_t ret = ::readlink( symlink_r.c_str(), buf, bufsiz );
893 target_r = Pathname();
894 MIL << "readlink " << symlink_r;
895 return logResult( errno );
902 ///////////////////////////////////////////////////////////////////
904 // METHOD NAME : expandlink
905 // METHOD TYPE : Pathname
907 Pathname expandlink( const Pathname & path_r )
909 static const unsigned int level_limit = 256;
910 static unsigned int count;
911 Pathname path(path_r);
912 PathInfo info(path_r, PathInfo::LSTAT);
914 for (count = level_limit; info.isLink() && count; count--)
916 DBG << "following symlink " << path;
917 path = path.dirname() / readlink(path);
918 DBG << "->" << path << std::endl;
919 info = PathInfo(path, PathInfo::LSTAT);
922 // expand limit reached
925 ERR << "Expand level limit reached. Probably a cyclic symbolic link." << endl;
929 else if (count < level_limit)
931 // check for a broken link
932 if (PathInfo(path).isExist())
934 // broken link, return an empty path
937 ERR << path << " is broken (expanded from " << path_r << ")" << endl;
942 // not a symlink, return the original pathname
943 DBG << "not a symlink" << endl;
947 ///////////////////////////////////////////////////////////////////
949 // METHOD NAME : copy_file2dir
952 int copy_file2dir( const Pathname & file, const Pathname & dest )
954 MIL << "copy_file2dir " << file << " -> " << dest << ' ';
957 if ( !sp.isFile() ) {
958 return logResult( EINVAL );
963 return logResult( ENOTDIR );
966 const char *const argv[] = {
969 file.asString().c_str(),
970 dest.asString().c_str(),
973 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
974 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
975 MIL << " " << output;
977 int ret = prog.close();
978 return logResult( ret, "returned" );
981 ///////////////////////////////////////////////////////////////////
983 // METHOD NAME : md5sum
984 // METHOD TYPE : std::string
986 std::string md5sum( const Pathname & file )
988 if ( ! PathInfo( file ).isFile() ) {
991 std::ifstream istr( file.asString().c_str() );
995 return Digest::digest( "MD5", istr );
998 ///////////////////////////////////////////////////////////////////
1000 // METHOD NAME : sha1sum
1001 // METHOD TYPE : std::string
1003 std::string sha1sum( const Pathname & file )
1005 return checksum(file, "SHA1");
1008 ///////////////////////////////////////////////////////////////////
1010 // METHOD NAME : checksum
1011 // METHOD TYPE : std::string
1013 std::string checksum( const Pathname & file, const std::string &algorithm )
1015 if ( ! PathInfo( file ).isFile() ) {
1018 std::ifstream istr( file.asString().c_str() );
1022 return Digest::digest( algorithm, istr );
1025 bool is_checksum( const Pathname & file, const CheckSum &checksum )
1027 return ( filesystem::checksum(file, checksum.type()) == checksum.checksum() );
1030 ///////////////////////////////////////////////////////////////////
1032 // METHOD NAME : erase
1033 // METHOD TYPE : int
1035 int erase( const Pathname & path )
1038 PathInfo p( path, PathInfo::LSTAT );
1042 res = recursive_rmdir( path );
1044 res = unlink( path );
1049 ///////////////////////////////////////////////////////////////////
1051 // METHOD NAME : chmod
1052 // METHOD TYPE : int
1054 int chmod( const Pathname & path, mode_t mode )
1056 MIL << "chmod " << path << ' ' << str::octstring( mode );
1057 if ( ::chmod( path.asString().c_str(), mode ) == -1 ) {
1058 return logResult( errno );
1060 return logResult( 0 );
1063 int addmod( const Pathname & path, mode_t mode )
1065 mode_t omode( PathInfo( path ).st_mode() );
1066 mode_t tmode( omode | mode );
1067 if ( omode != mode )
1068 return chmod( path, tmode );
1072 int delmod( const Pathname & path, mode_t mode )
1074 mode_t omode( PathInfo( path ).st_mode() );
1075 mode_t tmode( omode & ~mode );
1076 if ( omode != mode )
1077 return chmod( path, tmode );
1081 //////////////////////////////////////////////////////////////////
1083 // METHOD NAME : zipType
1084 // METHOD TYPE : ZIP_TYPE
1086 ZIP_TYPE zipType( const Pathname & file )
1088 ZIP_TYPE ret = ZT_NONE;
1090 int fd = open( file.asString().c_str(), O_RDONLY|O_CLOEXEC );
1093 const int magicSize = 5;
1094 unsigned char magic[magicSize];
1095 memset( magic, 0, magicSize );
1096 if ( read( fd, magic, magicSize ) == magicSize ) {
1097 if ( magic[0] == 0037 && magic[1] == 0213 ) {
1099 } else if ( magic[0] == 'B' && magic[1] == 'Z' && magic[2] == 'h' ) {
1101 } else if ( magic[0] == '\0' && magic[1] == 'Z' && magic[2] == 'C' && magic[3] == 'K' && magic[4] == '1') {
1112 ///////////////////////////////////////////////////////////////////
1115 // METHOD TYPE : ByteCount
1117 ByteCount df( const Pathname & path_r )
1119 ByteCount ret( -1 );
1121 if ( statvfs( path_r.c_str(), &sb ) == 0 )
1123 ret = sb.f_bfree * sb.f_bsize;
1128 ///////////////////////////////////////////////////////////////////
1130 // METHOD NAME : getUmask
1131 // METHOD TYPE : mode_t
1135 mode_t mask = ::umask( 0022 );
1140 ///////////////////////////////////////////////////////////////////
1142 // METHOD NAME : getUmask
1143 // METHOD TYPE : mode_t
1145 int assert_file( const Pathname & path, unsigned mode )
1147 int ret = assert_dir( path.dirname() );
1148 MIL << "assert_file " << str::octstring( mode ) << " " << path;
1150 return logResult( ret );
1152 PathInfo pi( path );
1154 return logResult( pi.isFile() ? 0 : EEXIST );
1156 int fd = ::creat( path.c_str(), mode );
1158 return logResult( errno );
1161 return logResult( 0 );
1164 int assert_file_mode( const Pathname & path, unsigned mode )
1166 int ret = assert_dir( path.dirname() );
1167 MIL << "assert_file_mode " << str::octstring( mode ) << " " << path;
1169 return logResult( ret );
1171 PathInfo pi( path );
1174 if ( ! pi.isFile() )
1175 return logResult( EEXIST );
1177 mode = applyUmaskTo( mode );
1178 if ( pi.st_mode() != mode )
1179 return chmod( path, mode );
1181 return logResult( 0 );
1184 int fd = ::creat( path.c_str(), mode );
1186 return logResult( errno );
1188 return logResult( 0 );
1191 ///////////////////////////////////////////////////////////////////
1193 // METHOD NAME : touch
1194 // METHOD TYPE : int
1196 int touch (const Pathname & path)
1198 MIL << "touch " << path;
1199 struct ::utimbuf times;
1200 times.actime = ::time( 0 );
1201 times.modtime = ::time( 0 );
1202 if ( ::utime( path.asString().c_str(), × ) == -1 ) {
1203 return logResult( errno );
1205 return logResult( 0 );
1208 /////////////////////////////////////////////////////////////////
1209 } // namespace filesystem
1210 ///////////////////////////////////////////////////////////////////
1211 /////////////////////////////////////////////////////////////////
1213 ///////////////////////////////////////////////////////////////////