00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <sys/types.h>
00014 #include <utime.h>
00015 #include <sys/statvfs.h>
00016
00017 #include <iostream>
00018 #include <fstream>
00019 #include <iomanip>
00020
00021 #include "zypp/base/Logger.h"
00022 #include "zypp/base/String.h"
00023 #include "zypp/base/IOStream.h"
00024
00025 #include "zypp/ExternalProgram.h"
00026 #include "zypp/PathInfo.h"
00027 #include "zypp/Digest.h"
00028 #include "zypp/TmpPath.h"
00029
00030 using std::endl;
00031 using std::string;
00032
00034 namespace zypp
00035 {
00036
00037 namespace filesystem
00038 {
00039
00040
00041
00042
00043
00044
00045 std::ostream & operator<<( std::ostream & str, FileType obj )
00046 {
00047 switch ( obj ) {
00048 #define EMUMOUT(T) case T: return str << #T; break
00049 EMUMOUT( FT_NOT_AVAIL );
00050 EMUMOUT( FT_NOT_EXIST );
00051 EMUMOUT( FT_FILE );
00052 EMUMOUT( FT_DIR );
00053 EMUMOUT( FT_CHARDEV );
00054 EMUMOUT( FT_BLOCKDEV );
00055 EMUMOUT( FT_FIFO );
00056 EMUMOUT( FT_LINK );
00057 EMUMOUT( FT_SOCKET );
00058 #undef EMUMOUT
00059 }
00060 return str;
00061 }
00062
00064
00065
00066
00067
00068 FileType StatMode::fileType() const
00069 {
00070 if ( isFile() )
00071 return FT_FILE;
00072 if ( isDir() )
00073 return FT_DIR;
00074 if ( isLink() )
00075 return FT_LINK;
00076 if ( isChr() )
00077 return FT_CHARDEV;
00078 if ( isBlk() )
00079 return FT_BLOCKDEV;
00080 if ( isFifo() )
00081 return FT_FIFO;
00082 if ( isSock() )
00083 return FT_SOCKET ;
00084
00085 return FT_NOT_AVAIL;
00086 }
00087
00088
00089
00090
00091
00092
00093 std::ostream & operator<<( std::ostream & str, const StatMode & obj )
00094 {
00095 iostr::IosFmtFlagsSaver autoResoreState( str );
00096
00097 char t = '?';
00098 if ( obj.isFile() )
00099 t = '-';
00100 else if ( obj.isDir() )
00101 t = 'd';
00102 else if ( obj.isLink() )
00103 t = 'l';
00104 else if ( obj.isChr() )
00105 t = 'c';
00106 else if ( obj.isBlk() )
00107 t = 'b';
00108 else if ( obj.isFifo() )
00109 t = 'p';
00110 else if ( obj.isSock() )
00111 t = 's';
00112
00113 str << t << " " << std::setfill( '0' ) << std::setw( 4 ) << std::oct << obj.perm();
00114 return str;
00115 }
00116
00118
00119
00120
00122
00124
00125
00126
00127
00128 PathInfo::PathInfo()
00129 : mode_e( STAT )
00130 , error_i( -1 )
00131 {}
00132
00134
00135
00136
00137
00138 PathInfo::PathInfo( const Pathname & path, Mode initial )
00139 : path_t( path )
00140 , mode_e( initial )
00141 , error_i( -1 )
00142 {
00143 operator()();
00144 }
00145
00147
00148
00149
00150
00151 PathInfo::PathInfo( const std::string & path, Mode initial )
00152 : path_t( path )
00153 , mode_e( initial )
00154 , error_i( -1 )
00155 {
00156 operator()();
00157 }
00158
00160
00161
00162
00163
00164 PathInfo::PathInfo( const char * path, Mode initial )
00165 : path_t( path )
00166 , mode_e( initial )
00167 , error_i( -1 )
00168 {
00169 operator()();
00170 }
00171
00173
00174
00175
00176
00177 PathInfo::~PathInfo()
00178 {
00179 }
00180
00182
00183
00184
00185
00186 bool PathInfo::operator()()
00187 {
00188 if ( path_t.empty() ) {
00189 error_i = -1;
00190 } else {
00191 switch ( mode_e ) {
00192 case STAT:
00193 error_i = ::stat( path_t.asString().c_str(), &statbuf_C );
00194 break;
00195 case LSTAT:
00196 error_i = ::lstat( path_t.asString().c_str(), &statbuf_C );
00197 break;
00198 }
00199 if ( error_i == -1 )
00200 error_i = errno;
00201 }
00202 return !error_i;
00203 }
00204
00206
00207
00208
00209
00210 FileType PathInfo::fileType() const
00211 {
00212 if ( isExist() )
00213 return asStatMode().fileType();
00214 return FT_NOT_EXIST;
00215 }
00216
00218
00219
00220
00221
00222 mode_t PathInfo::userMay() const
00223 {
00224 if ( !isExist() )
00225 return 0;
00226 if ( owner() == getuid() ) {
00227 return( uperm()/0100 );
00228 } else if ( group() == getgid() ) {
00229 return( gperm()/010 );
00230 }
00231 return operm();
00232 }
00233
00234
00235
00236
00237
00238
00239 unsigned int PathInfo::major() const
00240 {
00241 return isBlk() || isChr() ? ::major(statbuf_C.st_rdev) : 0;
00242 }
00243
00244
00245
00246
00247
00248
00249 unsigned int PathInfo::minor() const
00250 {
00251 return isBlk() || isChr() ? ::minor(statbuf_C.st_rdev) : 0;
00252 }
00253
00254
00255
00256
00257
00258
00259 std::ostream & operator<<( std::ostream & str, const PathInfo & obj )
00260 {
00261 iostr::IosFmtFlagsSaver autoResoreState( str );
00262
00263 str << obj.asString() << "{";
00264 if ( !obj.isExist() ) {
00265 str << "does not exist}";
00266 } else {
00267 str << obj.asStatMode() << " " << std::dec << obj.owner() << "/" << obj.group();
00268
00269 if ( obj.isFile() )
00270 str << " size " << obj.size();
00271
00272 str << "}";
00273 }
00274
00275 return str;
00276 }
00277
00279
00280
00281
00283
00284
00285
00286
00287
00288
00289
00290
00291 #define _Log_Result MIL << endl, __Log_Result
00292 inline int __Log_Result( const int res, const char * rclass = 0 )
00293 {
00294 if ( res )
00295 {
00296 if ( rclass )
00297 WAR << " FAILED: " << rclass << " " << res << endl;
00298 else
00299 WAR << " FAILED: " << str::strerror( res ) << endl;
00300 }
00301 return res;
00302 }
00303
00305
00306
00307
00308
00309 int mkdir( const Pathname & path, unsigned mode )
00310 {
00311 MIL << "mkdir " << path << ' ' << str::octstring( mode );
00312 if ( ::mkdir( path.asString().c_str(), mode ) == -1 ) {
00313 return _Log_Result( errno );
00314 }
00315 return _Log_Result( 0 );
00316 }
00317
00319
00320
00321
00322
00323 int assert_dir( const Pathname & path, unsigned mode )
00324 {
00325 if ( path.empty() )
00326 return ENOENT;
00327
00328 {
00329 PathInfo pi( path );
00330 if ( pi.isDir() )
00331 return 0;
00332 if ( pi.isExist() )
00333 return EEXIST;
00334 }
00335
00336 string spath = path.asString()+"/";
00337 string::size_type lastpos = ( path.relative() ? 2 : 1 );
00338 string::size_type pos = string::npos;
00339 int ret = 0;
00340
00341 while ( (pos = spath.find('/',lastpos)) != string::npos )
00342 {
00343 string dir( spath.substr(0,pos) );
00344 ret = ::mkdir( dir.c_str(), mode );
00345 if ( ret == -1 )
00346 {
00347 if ( errno == EEXIST )
00348 ret = 0;
00349 else
00350 {
00351 ret = errno;
00352 WAR << " FAILED: mkdir " << dir << ' ' << str::octstring( mode ) << " errno " << ret << endl;
00353 }
00354 }
00355 else
00356 {
00357 MIL << "mkdir " << dir << ' ' << str::octstring( mode ) << endl;
00358 }
00359 lastpos = pos+1;
00360 }
00361
00362 return ret;
00363 }
00364
00366
00367
00368
00369
00370 int rmdir( const Pathname & path )
00371 {
00372 MIL << "rmdir " << path;
00373 if ( ::rmdir( path.asString().c_str() ) == -1 ) {
00374 return _Log_Result( errno );
00375 }
00376 return _Log_Result( 0 );
00377 }
00378
00380
00381
00382
00383
00384 static int recursive_rmdir_1( const Pathname & dir )
00385 {
00386 DIR * dp;
00387 struct dirent * d;
00388
00389 if ( ! (dp = opendir( dir.c_str() )) )
00390 return _Log_Result( errno );
00391
00392 while ( (d = readdir(dp)) )
00393 {
00394 std::string direntry = d->d_name;
00395 if ( direntry == "." || direntry == ".." )
00396 continue;
00397 Pathname new_path( dir / d->d_name );
00398
00399 struct stat st;
00400 if ( ! lstat( new_path.c_str(), &st ) )
00401 {
00402 if ( S_ISDIR( st.st_mode ) )
00403 recursive_rmdir_1( new_path );
00404 else
00405 ::unlink( new_path.c_str() );
00406 }
00407 }
00408 closedir( dp );
00409
00410 if ( ::rmdir( dir.c_str() ) < 0 )
00411 return errno;
00412
00413 return 0;
00414 }
00416 int recursive_rmdir( const Pathname & path )
00417 {
00418 MIL << "recursive_rmdir " << path << ' ';
00419 PathInfo p( path );
00420
00421 if ( !p.isExist() ) {
00422 return _Log_Result( 0 );
00423 }
00424
00425 if ( !p.isDir() ) {
00426 return _Log_Result( ENOTDIR );
00427 }
00428
00429 return _Log_Result( recursive_rmdir_1( path ) );
00430 }
00431
00433
00434
00435
00436
00437 int clean_dir( const Pathname & path )
00438 {
00439 MIL << "clean_dir " << path << ' ';
00440 PathInfo p( path );
00441
00442 if ( !p.isExist() ) {
00443 return _Log_Result( 0 );
00444 }
00445
00446 if ( !p.isDir() ) {
00447 return _Log_Result( ENOTDIR );
00448 }
00449
00450 string cmd( str::form( "cd '%s' && rm -rf --preserve-root -- *", path.asString().c_str() ) );
00451 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
00452 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
00453 MIL << " " << output;
00454 }
00455 int ret = prog.close();
00456 return _Log_Result( ret, "returned" );
00457 }
00458
00460
00461
00462
00463
00464 int copy_dir( const Pathname & srcpath, const Pathname & destpath )
00465 {
00466 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
00467
00468 PathInfo sp( srcpath );
00469 if ( !sp.isDir() ) {
00470 return _Log_Result( ENOTDIR );
00471 }
00472
00473 PathInfo dp( destpath );
00474 if ( !dp.isDir() ) {
00475 return _Log_Result( ENOTDIR );
00476 }
00477
00478 PathInfo tp( destpath + srcpath.basename() );
00479 if ( tp.isExist() ) {
00480 return _Log_Result( EEXIST );
00481 }
00482
00483
00484 const char *const argv[] = {
00485 "/bin/cp",
00486 "-dR",
00487 "--",
00488 srcpath.asString().c_str(),
00489 destpath.asString().c_str(),
00490 NULL
00491 };
00492 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
00493 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
00494 MIL << " " << output;
00495 }
00496 int ret = prog.close();
00497 return _Log_Result( ret, "returned" );
00498 }
00499
00501
00502
00503
00504
00505 int copy_dir_content(const Pathname & srcpath, const Pathname & destpath)
00506 {
00507 MIL << "copy_dir " << srcpath << " -> " << destpath << ' ';
00508
00509 PathInfo sp( srcpath );
00510 if ( !sp.isDir() ) {
00511 return _Log_Result( ENOTDIR );
00512 }
00513
00514 PathInfo dp( destpath );
00515 if ( !dp.isDir() ) {
00516 return _Log_Result( ENOTDIR );
00517 }
00518
00519 if ( srcpath == destpath ) {
00520 return _Log_Result( EEXIST );
00521 }
00522
00523 std::string src( srcpath.asString());
00524 src += "/.";
00525 const char *const argv[] = {
00526 "/bin/cp",
00527 "-dR",
00528 "--",
00529 src.c_str(),
00530 destpath.asString().c_str(),
00531 NULL
00532 };
00533 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
00534 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
00535 MIL << " " << output;
00536 }
00537 int ret = prog.close();
00538 return _Log_Result( ret, "returned" );
00539 }
00540
00542
00543
00544
00545
00546 int readdir( std::list<std::string> & retlist,
00547 const Pathname & path, bool dots )
00548 {
00549 retlist.clear();
00550
00551 MIL << "readdir " << path << ' ';
00552
00553 DIR * dir = ::opendir( path.asString().c_str() );
00554 if ( ! dir ) {
00555 return _Log_Result( errno );
00556 }
00557
00558 struct dirent *entry;
00559 while ( (entry = ::readdir( dir )) != 0 ) {
00560
00561 if ( entry->d_name[0] == '.' ) {
00562 if ( !dots )
00563 continue;
00564 if ( entry->d_name[1] == '\0'
00565 || ( entry->d_name[1] == '.'
00566 && entry->d_name[2] == '\0' ) )
00567 continue;
00568 }
00569 retlist.push_back( entry->d_name );
00570 }
00571
00572 ::closedir( dir );
00573
00574 return _Log_Result( 0 );
00575 }
00576
00577
00579
00580
00581
00582
00583 int readdir( std::list<Pathname> & retlist,
00584 const Pathname & path, bool dots )
00585 {
00586 retlist.clear();
00587
00588 std::list<string> content;
00589 int res = readdir( content, path, dots );
00590
00591 if ( !res ) {
00592 for ( std::list<string>::const_iterator it = content.begin(); it != content.end(); ++it ) {
00593 retlist.push_back( path + *it );
00594 }
00595 }
00596
00597 return res;
00598 }
00599
00601
00602
00603
00604
00605
00606 bool DirEntry::operator==( const DirEntry &rhs ) const
00607 {
00608
00609 if ( type == FT_NOT_AVAIL || rhs.type == FT_NOT_AVAIL )
00610 return ( name == rhs.name );
00611 return ((name == rhs.name ) && (type == rhs.type));
00612 }
00613
00614 int readdir( DirContent & retlist, const Pathname & path,
00615 bool dots, PathInfo::Mode statmode )
00616 {
00617 retlist.clear();
00618
00619 std::list<string> content;
00620 int res = readdir( content, path, dots );
00621
00622 if ( !res ) {
00623 for ( std::list<string>::const_iterator it = content.begin(); it != content.end(); ++it ) {
00624 PathInfo p( path + *it, statmode );
00625 retlist.push_back( DirEntry( *it, p.fileType() ) );
00626 }
00627 }
00628
00629 return res;
00630 }
00631
00633
00634
00635
00636
00637 int is_empty_dir(const Pathname & path)
00638 {
00639 DIR * dir = ::opendir( path.asString().c_str() );
00640 if ( ! dir ) {
00641 return _Log_Result( errno );
00642 }
00643
00644 struct dirent *entry;
00645 while ( (entry = ::readdir( dir )) != NULL )
00646 {
00647 std::string name(entry->d_name);
00648
00649 if ( name == "." || name == "..")
00650 continue;
00651
00652 break;
00653 }
00654 ::closedir( dir );
00655
00656 return entry != NULL ? -1 : 0;
00657 }
00658
00660
00661
00662
00663
00664 int unlink( const Pathname & path )
00665 {
00666 MIL << "unlink " << path;
00667 if ( ::unlink( path.asString().c_str() ) == -1 ) {
00668 return _Log_Result( errno );
00669 }
00670 return _Log_Result( 0 );
00671 }
00672
00674
00675
00676
00677
00678 int rename( const Pathname & oldpath, const Pathname & newpath )
00679 {
00680 MIL << "rename " << oldpath << " -> " << newpath;
00681 if ( ::rename( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
00682 return _Log_Result( errno );
00683 }
00684 return _Log_Result( 0 );
00685 }
00686
00688
00689
00690
00691
00692 int exchange( const Pathname & lpath, const Pathname & rpath )
00693 {
00694 MIL << "exchange " << lpath << " <-> " << rpath;
00695 if ( lpath.empty() || rpath.empty() )
00696 return _Log_Result( EINVAL );
00697
00698 PathInfo linfo( lpath );
00699 PathInfo rinfo( rpath );
00700
00701 if ( ! linfo.isExist() )
00702 {
00703 if ( ! rinfo.isExist() )
00704 return _Log_Result( 0 );
00705
00706
00707 int ret = assert_dir( lpath.dirname() );
00708 if ( ret != 0 )
00709 return _Log_Result( ret );
00710 if ( ::rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
00711 return _Log_Result( errno );
00712 }
00713 return _Log_Result( 0 );
00714 }
00715
00716
00717 if ( ! rinfo.isExist() )
00718 {
00719
00720 int ret = assert_dir( rpath.dirname() );
00721 if ( ret != 0 )
00722 return _Log_Result( ret );
00723 if ( ::rename( lpath.c_str(), rpath.c_str() ) == -1 ) {
00724 return _Log_Result( errno );
00725 }
00726 return _Log_Result( 0 );
00727 }
00728
00729
00730 TmpFile tmpfile( TmpFile::makeSibling( rpath ) );
00731 if ( ! tmpfile )
00732 return _Log_Result( errno );
00733 Pathname tmp( tmpfile.path() );
00734 ::unlink( tmp.c_str() );
00735
00736 if ( ::rename( lpath.c_str(), tmp.c_str() ) == -1 ) {
00737 return _Log_Result( errno );
00738 }
00739 if ( ::rename( rpath.c_str(), lpath.c_str() ) == -1 ) {
00740 ::rename( tmp.c_str(), lpath.c_str() );
00741 return _Log_Result( errno );
00742 }
00743 if ( ::rename( tmp.c_str(), rpath.c_str() ) == -1 ) {
00744 ::rename( lpath.c_str(), rpath.c_str() );
00745 ::rename( tmp.c_str(), lpath.c_str() );
00746 return _Log_Result( errno );
00747 }
00748 return _Log_Result( 0 );
00749 }
00750
00752
00753
00754
00755
00756 int copy( const Pathname & file, const Pathname & dest )
00757 {
00758 MIL << "copy " << file << " -> " << dest << ' ';
00759
00760 PathInfo sp( file );
00761 if ( !sp.isFile() ) {
00762 return _Log_Result( EINVAL );
00763 }
00764
00765 PathInfo dp( dest );
00766 if ( dp.isDir() ) {
00767 return _Log_Result( EISDIR );
00768 }
00769
00770 const char *const argv[] = {
00771 "/bin/cp",
00772 "--remove-destination",
00773 "--",
00774 file.asString().c_str(),
00775 dest.asString().c_str(),
00776 NULL
00777 };
00778 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
00779 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
00780 MIL << " " << output;
00781 }
00782 int ret = prog.close();
00783 return _Log_Result( ret, "returned" );
00784 }
00785
00787
00788
00789
00790
00791 int symlink( const Pathname & oldpath, const Pathname & newpath )
00792 {
00793 MIL << "symlink " << newpath << " -> " << oldpath;
00794 if ( ::symlink( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
00795 return _Log_Result( errno );
00796 }
00797 return _Log_Result( 0 );
00798 }
00799
00801
00802
00803
00804
00805 int hardlink( const Pathname & oldpath, const Pathname & newpath )
00806 {
00807 MIL << "hardlink " << newpath << " -> " << oldpath;
00808 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
00809 return _Log_Result( errno );
00810 }
00811 return _Log_Result( 0 );
00812 }
00813
00815
00816
00817
00818
00819 int hardlinkCopy( const Pathname & oldpath, const Pathname & newpath )
00820 {
00821 MIL << "hardlinkCopy " << oldpath << " -> " << newpath;
00822
00823 PathInfo oldpi( oldpath, PathInfo::LSTAT );
00824 if ( oldpi.isLink() )
00825 {
00826
00827 return copy( oldpath, newpath );
00828 }
00829
00830
00831 if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 )
00832 {
00833 switch ( errno )
00834 {
00835 case EEXIST:
00836 if ( unlink( newpath ) == 0 && ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) != -1 )
00837 return _Log_Result( 0 );
00838 break;
00839 case EXDEV:
00840 return copy( oldpath, newpath );
00841 break;
00842 }
00843 return _Log_Result( errno );
00844 }
00845 return _Log_Result( 0 );
00846 }
00847
00849
00850
00851
00852
00853 int readlink( const Pathname & symlink_r, Pathname & target_r )
00854 {
00855 static const ssize_t bufsiz = 2047;
00856 static char buf[bufsiz+1];
00857 ssize_t ret = ::readlink( symlink_r.c_str(), buf, bufsiz );
00858 if ( ret == -1 )
00859 {
00860 target_r = Pathname();
00861 MIL << "readlink " << symlink_r;
00862 return _Log_Result( errno );
00863 }
00864 buf[ret] = '\0';
00865 target_r = buf;
00866 return 0;
00867 }
00868
00870
00871
00872
00873
00874 Pathname expandlink( const Pathname & path_r )
00875 {
00876 static const unsigned int level_limit = 256;
00877 static unsigned int count;
00878 Pathname path(path_r);
00879 PathInfo info(path_r, PathInfo::LSTAT);
00880
00881 for (count = level_limit; info.isLink() && count; count--)
00882 {
00883 DBG << "following symlink " << path;
00884 path = path.dirname() / readlink(path);
00885 DBG << "->" << path << std::endl;
00886 info = PathInfo(path, PathInfo::LSTAT);
00887 }
00888
00889
00890 if (count == 0)
00891 {
00892 ERR << "Expand level limit reached. Probably a cyclic symbolic link." << endl;
00893 return Pathname();
00894 }
00895
00896 else if (count < level_limit)
00897 {
00898
00899 if (PathInfo(path).isExist())
00900 return path;
00901
00902 else
00903 {
00904 ERR << path << " is broken (expanded from " << path_r << ")" << endl;
00905 return Pathname();
00906 }
00907 }
00908
00909
00910 DBG << "not a symlink" << endl;
00911 return path;
00912 }
00913
00915
00916
00917
00918
00919 int copy_file2dir( const Pathname & file, const Pathname & dest )
00920 {
00921 MIL << "copy_file2dir " << file << " -> " << dest << ' ';
00922
00923 PathInfo sp( file );
00924 if ( !sp.isFile() ) {
00925 return _Log_Result( EINVAL );
00926 }
00927
00928 PathInfo dp( dest );
00929 if ( !dp.isDir() ) {
00930 return _Log_Result( ENOTDIR );
00931 }
00932
00933 const char *const argv[] = {
00934 "/bin/cp",
00935 "--",
00936 file.asString().c_str(),
00937 dest.asString().c_str(),
00938 NULL
00939 };
00940 ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
00941 for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
00942 MIL << " " << output;
00943 }
00944 int ret = prog.close();
00945 return _Log_Result( ret, "returned" );
00946 }
00947
00949
00950
00951
00952
00953 std::string md5sum( const Pathname & file )
00954 {
00955 if ( ! PathInfo( file ).isFile() ) {
00956 return string();
00957 }
00958 std::ifstream istr( file.asString().c_str() );
00959 if ( ! istr ) {
00960 return string();
00961 }
00962 return Digest::digest( "MD5", istr );
00963 }
00964
00966
00967
00968
00969
00970 std::string sha1sum( const Pathname & file )
00971 {
00972 return checksum(file, "SHA1");
00973 }
00974
00976
00977
00978
00979
00980 std::string checksum( const Pathname & file, const std::string &algorithm )
00981 {
00982 if ( ! PathInfo( file ).isFile() ) {
00983 return string();
00984 }
00985 std::ifstream istr( file.asString().c_str() );
00986 if ( ! istr ) {
00987 return string();
00988 }
00989 return Digest::digest( algorithm, istr );
00990 }
00991
00992 bool is_checksum( const Pathname & file, const CheckSum &checksum )
00993 {
00994 return ( filesystem::checksum(file, checksum.type()) == checksum.checksum() );
00995 }
00996
00998
00999
01000
01001
01002 int erase( const Pathname & path )
01003 {
01004 int res = 0;
01005 PathInfo p( path, PathInfo::LSTAT );
01006 if ( p.isExist() )
01007 {
01008 if ( p.isDir() )
01009 res = recursive_rmdir( path );
01010 else
01011 res = unlink( path );
01012 }
01013 return res;
01014 }
01015
01017
01018
01019
01020
01021 int chmod( const Pathname & path, mode_t mode )
01022 {
01023 MIL << "chmod " << path << ' ' << str::octstring( mode );
01024 if ( ::chmod( path.asString().c_str(), mode ) == -1 ) {
01025 return _Log_Result( errno );
01026 }
01027 return _Log_Result( 0 );
01028 }
01029
01030 int addmod( const Pathname & path, mode_t mode )
01031 {
01032 mode_t omode( PathInfo( path ).st_mode() );
01033 mode_t tmode( omode | mode );
01034 if ( omode != mode )
01035 return chmod( path, tmode );
01036 return 0;
01037 }
01038
01039 int delmod( const Pathname & path, mode_t mode )
01040 {
01041 mode_t omode( PathInfo( path ).st_mode() );
01042 mode_t tmode( omode & ~mode );
01043 if ( omode != mode )
01044 return chmod( path, tmode );
01045 return 0;
01046 }
01047
01049
01050
01051
01052
01053 ZIP_TYPE zipType( const Pathname & file )
01054 {
01055 ZIP_TYPE ret = ZT_NONE;
01056
01057 int fd = open( file.asString().c_str(), O_RDONLY );
01058
01059 if ( fd != -1 ) {
01060 const int magicSize = 3;
01061 unsigned char magic[magicSize];
01062 memset( magic, 0, magicSize );
01063 if ( read( fd, magic, magicSize ) == magicSize ) {
01064 if ( magic[0] == 0037 && magic[1] == 0213 ) {
01065 ret = ZT_GZ;
01066 } else if ( magic[0] == 'B' && magic[1] == 'Z' && magic[2] == 'h' ) {
01067 ret = ZT_BZ2;
01068 }
01069 }
01070 close( fd );
01071 }
01072
01073 return ret;
01074 }
01075
01077
01078
01079
01080
01081 ByteCount df( const Pathname & path_r )
01082 {
01083 ByteCount ret( -1 );
01084 struct statvfs sb;
01085 if ( statvfs( path_r.c_str(), &sb ) == 0 )
01086 {
01087 ret = sb.f_bfree * sb.f_bsize;
01088 }
01089 return ret;
01090 }
01091
01093
01094
01095
01096
01097 mode_t getUmask()
01098 {
01099 mode_t mask = ::umask( 0022 );
01100 ::umask( mask );
01101 return mask;
01102 }
01103
01105
01106
01107
01108
01109 int assert_file( const Pathname & path, unsigned mode )
01110 {
01111 int ret = assert_dir( path.dirname() );
01112 MIL << "assert_file " << str::octstring( mode ) << " " << path;
01113 if ( ret != 0 )
01114 return _Log_Result( ret );
01115
01116 PathInfo pi( path );
01117 if ( pi.isExist() )
01118 return _Log_Result( pi.isFile() ? 0 : EEXIST );
01119
01120 int fd = ::creat( path.c_str(), mode );
01121 if ( fd == -1 )
01122 return _Log_Result( errno );
01123
01124 ::close( fd );
01125 return _Log_Result( 0 );
01126 }
01127
01129
01130
01131
01132
01133 int touch (const Pathname & path)
01134 {
01135 MIL << "touch " << path;
01136 struct ::utimbuf times;
01137 times.actime = ::time( 0 );
01138 times.modtime = ::time( 0 );
01139 if ( ::utime( path.asString().c_str(), × ) == -1 ) {
01140 return _Log_Result( errno );
01141 }
01142 return _Log_Result( 0 );
01143 }
01144
01146 }
01149 }