- Create the cache directly from the schema (installed) file.
[platform/upstream/libzypp.git] / zypp / PathInfo.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PathInfo.cc
10  *
11 */
12
13 #include <sys/types.h> // for ::minor, ::major macros
14 #include <sys/statvfs.h>
15
16 #include <iostream>
17 #include <fstream>
18 #include <iomanip>
19
20 #include <boost/filesystem/operations.hpp>
21 #include <boost/filesystem/exception.hpp>
22
23 #include "zypp/base/Logger.h"
24 #include "zypp/base/String.h"
25 #include "zypp/base/IOStream.h"
26
27 #include "zypp/ExternalProgram.h"
28 #include "zypp/PathInfo.h"
29 #include "zypp/Digest.h"
30
31
32 using std::string;
33
34 ///////////////////////////////////////////////////////////////////
35 namespace zypp
36 { /////////////////////////////////////////////////////////////////
37   ///////////////////////////////////////////////////////////////////
38   namespace filesystem
39   { /////////////////////////////////////////////////////////////////
40
41     /******************************************************************
42      **
43      ** FUNCTION NAME : operator<<
44      ** FUNCTION TYPE : std::ostream &
45     */
46     std::ostream & operator<<( std::ostream & str, FileType obj )
47     {
48       switch ( obj ) {
49 #define EMUMOUT(T) case T: return str << #T; break
50         EMUMOUT( FT_NOT_AVAIL );
51         EMUMOUT( FT_NOT_EXIST );
52         EMUMOUT( FT_FILE );
53         EMUMOUT( FT_DIR );
54         EMUMOUT( FT_CHARDEV );
55         EMUMOUT( FT_BLOCKDEV );
56         EMUMOUT( FT_FIFO );
57         EMUMOUT( FT_LINK );
58         EMUMOUT( FT_SOCKET );
59 #undef EMUMOUT
60       }
61       return str;
62     }
63
64     ///////////////////////////////////////////////////////////////////
65     //
66     //  METHOD NAME : StatMode::fileType
67     //  METHOD TYPE : FileType
68     //
69     FileType StatMode::fileType() const
70     {
71       if ( isFile() )
72         return FT_FILE;
73       if ( isDir() )
74         return FT_DIR;
75       if ( isLink() )
76         return FT_LINK;
77       if ( isChr() )
78         return FT_CHARDEV;
79       if ( isBlk() )
80         return FT_BLOCKDEV;
81       if ( isFifo() )
82         return FT_FIFO;
83       if ( isSock() )
84         return FT_SOCKET ;
85
86       return FT_NOT_AVAIL;
87     }
88
89     /******************************************************************
90      **
91      ** FUNCTION NAME : operator<<
92      ** FUNCTION TYPE : std::ostream &
93     */
94     std::ostream & operator<<( std::ostream & str, const StatMode & obj )
95     {
96       iostr::IosFmtFlagsSaver autoResoreState( str );
97
98       char t = '?';
99       if ( obj.isFile() )
100         t = '-';
101       else if ( obj.isDir() )
102         t = 'd';
103       else if ( obj.isLink() )
104         t = 'l';
105       else if ( obj.isChr() )
106         t = 'c';
107       else if ( obj.isBlk() )
108         t = 'b';
109       else if ( obj.isFifo() )
110         t = 'p';
111       else if ( obj.isSock() )
112         t = 's';
113
114       str << t << " " << std::setfill( '0' ) << std::setw( 4 ) << std::oct << obj.perm();
115       return str;
116     }
117
118     ///////////////////////////////////////////////////////////////////
119     //
120     //  Class : PathInfo
121     //
122     ///////////////////////////////////////////////////////////////////
123
124     ///////////////////////////////////////////////////////////////////
125     //
126     //  METHOD NAME : PathInfo::PathInfo
127     //  METHOD TYPE : Constructor
128     //
129     PathInfo::PathInfo()
130     : mode_e( STAT )
131     , error_i( -1 )
132     {}
133
134     ///////////////////////////////////////////////////////////////////
135     //
136     //  METHOD NAME : PathInfo::PathInfo
137     //  METHOD TYPE : Constructor
138     //
139     PathInfo::PathInfo( const Pathname & path, Mode initial )
140     : path_t( path )
141     , mode_e( initial )
142     , error_i( -1 )
143     {
144       operator()();
145     }
146
147     ///////////////////////////////////////////////////////////////////
148     //
149     //  METHOD NAME : PathInfo::PathInfo
150     //  METHOD TYPE : Constructor
151     //
152     PathInfo::PathInfo( const std::string & path, Mode initial )
153     : path_t( path )
154     , mode_e( initial )
155     , error_i( -1 )
156     {
157       operator()();
158     }
159
160     ///////////////////////////////////////////////////////////////////
161     //
162     //  METHOD NAME : PathInfo::PathInfo
163     //  METHOD TYPE : Constructor
164     //
165     PathInfo::PathInfo( const char * path, Mode initial )
166     : path_t( path )
167     , mode_e( initial )
168     , error_i( -1 )
169     {
170       operator()();
171     }
172
173     ///////////////////////////////////////////////////////////////////
174     //
175     //  METHOD NAME : PathInfo::~PathInfo
176     //  METHOD TYPE : Destructor
177     //
178     PathInfo::~PathInfo()
179     {
180     }
181
182     ///////////////////////////////////////////////////////////////////
183     //
184     //  METHOD NAME : PathInfo::operator()
185     //  METHOD TYPE : bool
186     //
187     bool PathInfo::operator()()
188     {
189       if ( path_t.empty() ) {
190         error_i = -1;
191       } else {
192         switch ( mode_e ) {
193         case STAT:
194           error_i = ::stat( path_t.asString().c_str(), &statbuf_C );
195           break;
196         case LSTAT:
197           error_i = ::lstat( path_t.asString().c_str(), &statbuf_C );
198           break;
199         }
200         if ( error_i == -1 )
201           error_i = errno;
202       }
203       return !error_i;
204     }
205
206     ///////////////////////////////////////////////////////////////////
207     //
208     //  METHOD NAME : PathInfo::fileType
209     //  METHOD TYPE : File_type
210     //
211     FileType PathInfo::fileType() const
212     {
213       if ( isExist() )
214         return asStatMode().fileType();
215       return FT_NOT_EXIST;
216     }
217
218     ///////////////////////////////////////////////////////////////////
219     //
220     //  METHOD NAME : PathInfo::userMay
221     //  METHOD TYPE : mode_t
222     //
223     mode_t PathInfo::userMay() const
224     {
225       if ( !isExist() )
226         return 0;
227       if ( owner() == getuid() ) {
228         return( uperm()/0100 );
229       } else if ( group() == getgid() ) {
230         return( gperm()/010 );
231       }
232       return operm();
233     }
234
235     /******************************************************************
236      **
237      ** FUNCTION NAME : PathInfo::major
238      ** FUNCTION TYPE : unsigned int
239      */
240     unsigned int PathInfo::major() const
241     {
242       return isBlk() || isChr() ? ::major(statbuf_C.st_rdev) : 0;
243     }
244
245     /******************************************************************
246      **
247      ** FUNCTION NAME : PathInfo::minor
248      ** FUNCTION TYPE : unsigned int
249      */
250     unsigned int PathInfo::minor() const
251     {
252       return isBlk() || isChr() ? ::minor(statbuf_C.st_rdev) : 0;
253     }
254
255     /******************************************************************
256      **
257      ** FUNCTION NAME : operator<<
258      ** FUNCTION TYPE :  std::ostream &
259     */
260     std::ostream & operator<<( std::ostream & str, const PathInfo & obj )
261     {
262       iostr::IosFmtFlagsSaver autoResoreState( str );
263
264       str << obj.asString() << "{";
265       if ( !obj.isExist() ) {
266         str << "does not exist}";
267       } else {
268         str << obj.asStatMode() << " " << std::dec << obj.owner() << "/" << obj.group();
269
270         if ( obj.isFile() )
271           str << " size " << obj.size();
272
273         str << "}";
274       }
275
276       return str;
277     }
278
279     ///////////////////////////////////////////////////////////////////
280     //
281     //  filesystem utilities
282     //
283     ///////////////////////////////////////////////////////////////////
284
285     /******************************************************************
286      **
287      ** FUNCTION NAME : _Log_Result
288      ** FUNCTION TYPE : int
289      **
290      ** DESCRIPTION : Helper function to log return values.
291     */
292     inline int _Log_Result( const int res, const char * rclass = "errno" )
293     {
294       if ( res )
295         DBG << " FAILED: " << rclass << " " << res;
296       DBG << std::endl;
297       return res;
298     }
299
300     ///////////////////////////////////////////////////////////////////
301     //
302     //  METHOD NAME : PathInfo::mkdir
303     //  METHOD TYPE : int
304     //
305     int mkdir( const Pathname & path, unsigned mode )
306     {
307       DBG << "mkdir " << path << ' ' << str::octstring( mode );
308       if ( ::mkdir( path.asString().c_str(), mode ) == -1 ) {
309         return _Log_Result( errno );
310       }
311       return _Log_Result( 0 );
312     }
313
314     ///////////////////////////////////////////////////////////////////
315     //
316     //  METHOD NAME : assert_dir()
317     //  METHOD TYPE : int
318     //
319     int assert_dir( const Pathname & path, unsigned mode )
320     {
321       string::size_type pos, lastpos = 0;
322       string spath = path.asString()+"/";
323       int ret = 0;
324
325       if(path.empty())
326         return ENOENT;
327
328       // skip ./
329       if(path.relative())
330         lastpos=2;
331       // skip /
332       else
333         lastpos=1;
334
335       //    DBG << "about to create " << spath << endl;
336       while((pos = spath.find('/',lastpos)) != string::npos )
337         {
338           string dir = spath.substr(0,pos);
339           ret = ::mkdir(dir.c_str(), mode);
340           if(ret == -1)
341             {
342               // ignore errors about already existing directorys
343               if(errno == EEXIST)
344                 ret=0;
345               else
346                 ret=errno;
347             }
348           //    DBG << "creating directory " << dir << (ret?" failed":" succeeded") << endl;
349           lastpos = pos+1;
350         }
351       return ret;
352     }
353
354     ///////////////////////////////////////////////////////////////////
355     //
356     //  METHOD NAME : rmdir
357     //  METHOD TYPE : int
358     //
359     int rmdir( const Pathname & path )
360     {
361       DBG << "rmdir " << path;
362       if ( ::rmdir( path.asString().c_str() ) == -1 ) {
363         return _Log_Result( errno );
364       }
365       return _Log_Result( 0 );
366     }
367
368     ///////////////////////////////////////////////////////////////////
369     //
370     //  METHOD NAME : recursive_rmdir
371     //  METHOD TYPE : int
372     //
373     int recursive_rmdir( const Pathname & path )
374     {
375       DBG << "recursive_rmdir " << path << ' ';
376       PathInfo p( path );
377
378       if ( !p.isExist() ) {
379         return _Log_Result( 0 );
380       }
381
382       if ( !p.isDir() ) {
383         return _Log_Result( ENOTDIR );
384       }
385
386       try
387         {
388           boost::filesystem::path bp( path.asString(), boost::filesystem::native );
389           boost::filesystem::remove_all( bp );
390         }
391       catch ( boost::filesystem::filesystem_error & excpt )
392         {
393           DBG << " FAILED: " << excpt.what() << std::endl;
394           return -1;
395         }
396
397       return _Log_Result( 0 );
398     }
399
400     ///////////////////////////////////////////////////////////////////
401     //
402     //  METHOD NAME : clean_dir
403     //  METHOD TYPE : int
404     //
405     int clean_dir( const Pathname & path )
406     {
407       DBG << "clean_dir " << path << ' ';
408       PathInfo p( path );
409
410       if ( !p.isExist() ) {
411         return _Log_Result( 0 );
412       }
413
414       if ( !p.isDir() ) {
415         return _Log_Result( ENOTDIR );
416       }
417
418       string cmd( str::form( "cd '%s' && rm -rf --preserve-root -- *", path.asString().c_str() ) );
419       ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
420       for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
421         DBG << "  " << output;
422       }
423       int ret = prog.close();
424       return _Log_Result( ret, "returned" );
425     }
426
427     ///////////////////////////////////////////////////////////////////
428     //
429     //  METHOD NAME : copy_dir
430     //  METHOD TYPE : int
431     //
432     int copy_dir( const Pathname & srcpath, const Pathname & destpath )
433     {
434       DBG << "copy_dir " << srcpath << " -> " << destpath << ' ';
435
436       PathInfo sp( srcpath );
437       if ( !sp.isDir() ) {
438         return _Log_Result( ENOTDIR );
439       }
440
441       PathInfo dp( destpath );
442       if ( !dp.isDir() ) {
443         return _Log_Result( ENOTDIR );
444       }
445
446       PathInfo tp( destpath + srcpath.basename() );
447       if ( tp.isExist() ) {
448         return _Log_Result( EEXIST );
449       }
450
451
452       const char *const argv[] = {
453         "/bin/cp",
454         "-dR",
455         "--",
456         srcpath.asString().c_str(),
457         destpath.asString().c_str(),
458         NULL
459       };
460       ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
461       for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
462         DBG << "  " << output;
463       }
464       int ret = prog.close();
465       return _Log_Result( ret, "returned" );
466     }
467
468     ///////////////////////////////////////////////////////////////////
469     //
470     //  METHOD NAME : copy_dir_content
471     //  METHOD TYPE : int
472     //
473     int copy_dir_content(const Pathname & srcpath, const Pathname & destpath)
474     {
475       DBG << "copy_dir " << srcpath << " -> " << destpath << ' ';
476
477       PathInfo sp( srcpath );
478       if ( !sp.isDir() ) {
479         return _Log_Result( ENOTDIR );
480       }
481
482       PathInfo dp( destpath );
483       if ( !dp.isDir() ) {
484         return _Log_Result( ENOTDIR );
485       }
486
487       if ( srcpath == destpath ) {
488         return _Log_Result( EEXIST );
489       }
490
491       std::string src( srcpath.asString());
492       src += "/.";
493       const char *const argv[] = {
494         "/bin/cp",
495         "-dR",
496         "--",
497         src.c_str(),
498         destpath.asString().c_str(),
499         NULL
500       };
501       ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
502       for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
503         DBG << "  " << output;
504       }
505       int ret = prog.close();
506       return _Log_Result( ret, "returned" );
507     }
508
509     ///////////////////////////////////////////////////////////////////
510     //
511     //  METHOD NAME : readdir
512     //  METHOD TYPE : int
513     //
514     int readdir( std::list<std::string> & retlist,
515                  const Pathname & path, bool dots )
516     {
517       retlist.clear();
518
519       DBG << "readdir " << path << ' ';
520
521       DIR * dir = ::opendir( path.asString().c_str() );
522       if ( ! dir ) {
523         return _Log_Result( errno );
524       }
525
526       struct dirent *entry;
527       while ( (entry = ::readdir( dir )) != 0 ) {
528
529         if ( entry->d_name[0] == '.' ) {
530           if ( !dots )
531             continue;
532           if ( entry->d_name[1] == '\0'
533                || (    entry->d_name[1] == '.'
534                     && entry->d_name[2] == '\0' ) )
535             continue;
536         }
537         retlist.push_back( entry->d_name );
538       }
539
540       ::closedir( dir );
541
542       return _Log_Result( 0 );
543     }
544
545
546     ///////////////////////////////////////////////////////////////////
547     //
548     //  METHOD NAME : readdir
549     //  METHOD TYPE : int
550     //
551     int readdir( std::list<Pathname> & retlist,
552                  const Pathname & path, bool dots )
553     {
554       retlist.clear();
555
556       std::list<string> content;
557       int res = readdir( content, path, dots );
558
559       if ( !res ) {
560         for ( std::list<string>::const_iterator it = content.begin(); it != content.end(); ++it ) {
561           retlist.push_back( path + *it );
562         }
563       }
564
565       return res;
566     }
567
568     ///////////////////////////////////////////////////////////////////
569     //
570     //  METHOD NAME : readdir
571     //  METHOD TYPE : int
572     //
573     int readdir( DirContent & retlist, const Pathname & path,
574                  bool dots, PathInfo::Mode statmode )
575     {
576       retlist.clear();
577
578       std::list<string> content;
579       int res = readdir( content, path, dots );
580
581       if ( !res ) {
582         for ( std::list<string>::const_iterator it = content.begin(); it != content.end(); ++it ) {
583           PathInfo p( path + *it, statmode );
584           retlist.push_back( DirEntry( *it, p.fileType() ) );
585         }
586       }
587
588       return res;
589     }
590
591     ///////////////////////////////////////////////////////////////////
592     //
593     //  METHOD NAME : is_empty_dir
594     //  METHOD TYPE : int
595     //
596     int is_empty_dir(const Pathname & path)
597     {
598       DIR * dir = ::opendir( path.asString().c_str() );
599       if ( ! dir ) {
600         return _Log_Result( errno );
601       }
602
603       struct dirent *entry;
604       while ( (entry = ::readdir( dir )) != NULL )
605       {
606         std::string name(entry->d_name);
607
608         if ( name == "." || name == "..")
609           continue;
610
611         break;
612       }
613       ::closedir( dir );
614
615       return entry != NULL ? -1 : 0;
616     }
617
618     ///////////////////////////////////////////////////////////////////
619     //
620     //  METHOD NAME : unlink
621     //  METHOD TYPE : int
622     //
623     int unlink( const Pathname & path )
624     {
625       DBG << "unlink " << path;
626       if ( ::unlink( path.asString().c_str() ) == -1 ) {
627         return _Log_Result( errno );
628       }
629       return _Log_Result( 0 );
630     }
631
632     ///////////////////////////////////////////////////////////////////
633     //
634     //  METHOD NAME : rename
635     //  METHOD TYPE : int
636     //
637     int rename( const Pathname & oldpath, const Pathname & newpath )
638     {
639       DBG << "rename " << oldpath << " -> " << newpath;
640       if ( ::rename( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
641         return _Log_Result( errno );
642       }
643       return _Log_Result( 0 );
644     }
645
646     ///////////////////////////////////////////////////////////////////
647     //
648     //  METHOD NAME : copy
649     //  METHOD TYPE : int
650     //
651     int copy( const Pathname & file, const Pathname & dest )
652     {
653       DBG << "copy " << file << " -> " << dest << ' ';
654
655       PathInfo sp( file );
656       if ( !sp.isFile() ) {
657         return _Log_Result( EINVAL );
658       }
659
660       PathInfo dp( dest );
661       if ( dp.isDir() ) {
662         return _Log_Result( EISDIR );
663       }
664
665       const char *const argv[] = {
666         "/bin/cp",
667         "--",
668         file.asString().c_str(),
669         dest.asString().c_str(),
670         NULL
671       };
672       ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
673       for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
674         DBG << "  " << output;
675       }
676       int ret = prog.close();
677       return _Log_Result( ret, "returned" );
678     }
679
680     ///////////////////////////////////////////////////////////////////
681     //
682     //  METHOD NAME : symlink
683     //  METHOD TYPE : int
684     //
685     int symlink( const Pathname & oldpath, const Pathname & newpath )
686     {
687       DBG << "symlink " << newpath << " -> " << oldpath;
688       if ( ::symlink( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
689         return _Log_Result( errno );
690       }
691       return _Log_Result( 0 );
692     }
693
694     ///////////////////////////////////////////////////////////////////
695     //
696     //  METHOD NAME : hardlink
697     //  METHOD TYPE : int
698     //
699     int hardlink( const Pathname & oldpath, const Pathname & newpath )
700     {
701       DBG << "hardlink " << newpath << " -> " << oldpath;
702       if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
703         return _Log_Result( errno );
704       }
705       return _Log_Result( 0 );
706     }
707
708     ///////////////////////////////////////////////////////////////////
709     //
710     //  METHOD NAME : copy_file2dir
711     //  METHOD TYPE : int
712     //
713     int copy_file2dir( const Pathname & file, const Pathname & dest )
714     {
715       DBG << "copy_file2dir " << file << " -> " << dest << ' ';
716
717       PathInfo sp( file );
718       if ( !sp.isFile() ) {
719         return _Log_Result( EINVAL );
720       }
721
722       PathInfo dp( dest );
723       if ( !dp.isDir() ) {
724         return _Log_Result( ENOTDIR );
725       }
726
727       const char *const argv[] = {
728         "/bin/cp",
729         "--",
730         file.asString().c_str(),
731         dest.asString().c_str(),
732         NULL
733       };
734       ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
735       for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
736         DBG << "  " << output;
737       }
738       int ret = prog.close();
739       return _Log_Result( ret, "returned" );
740     }
741
742     ///////////////////////////////////////////////////////////////////
743     //
744     //  METHOD NAME : md5sum
745     //  METHOD TYPE : std::string
746     //
747     std::string md5sum( const Pathname & file )
748     {
749       if ( ! PathInfo( file ).isFile() ) {
750         return string();
751       }
752       std::ifstream istr( file.asString().c_str() );
753       if ( ! istr ) {
754         return string();
755       }
756       return Digest::digest( "MD5", istr );
757     }
758
759     ///////////////////////////////////////////////////////////////////
760     //
761     //  METHOD NAME : sha1sum
762     //  METHOD TYPE : std::string
763     //
764     std::string sha1sum( const Pathname & file )
765     {
766       return checksum(file, "SHA1");
767     }
768
769     ///////////////////////////////////////////////////////////////////
770     //
771     //  METHOD NAME : checksum
772     //  METHOD TYPE : std::string
773     //
774     std::string checksum( const Pathname & file, const std::string &algorithm )
775     {
776       if ( ! PathInfo( file ).isFile() ) {
777         return string();
778       }
779       std::ifstream istr( file.asString().c_str() );
780       if ( ! istr ) {
781         return string();
782       }
783       return Digest::digest( algorithm, istr );
784     }
785
786     bool is_checksum( const Pathname & file, const CheckSum &checksum )
787     {
788       return ( filesystem::checksum(file,  checksum.type()) == checksum.checksum() );
789     }
790
791     ///////////////////////////////////////////////////////////////////
792     //
793     //  METHOD NAME : erase
794     //  METHOD TYPE : int
795     //
796     int erase( const Pathname & path )
797     {
798       int res = 0;
799       PathInfo p( path, PathInfo::LSTAT );
800       if ( p.isExist() )
801         {
802           if ( p.isDir() )
803             res = recursive_rmdir( path );
804           else
805             res = unlink( path );
806         }
807       return res;
808     }
809
810     ///////////////////////////////////////////////////////////////////
811     //
812     //  METHOD NAME : chmod
813     //  METHOD TYPE : int
814     //
815     int chmod( const Pathname & path, mode_t mode )
816     {
817       DBG << "chmod " << path << ' ' << str::octstring( mode );
818       if ( ::chmod( path.asString().c_str(), mode ) == -1 ) {
819         return _Log_Result( errno );
820       }
821       return _Log_Result( 0 );
822     }
823
824     ///////////////////////////////////////////////////////////////////
825     //
826     //  METHOD NAME : zipType
827     //  METHOD TYPE : ZIP_TYPE
828     //
829     ZIP_TYPE zipType( const Pathname & file )
830     {
831       ZIP_TYPE ret = ZT_NONE;
832
833       int fd = open( file.asString().c_str(), O_RDONLY );
834
835       if ( fd != -1 ) {
836         const int magicSize = 3;
837         unsigned char magic[magicSize];
838         memset( magic, 0, magicSize );
839         if ( read( fd, magic, magicSize ) == magicSize ) {
840           if ( magic[0] == 0037 && magic[1] == 0213 ) {
841             ret = ZT_GZ;
842           } else if ( magic[0] == 'B' && magic[1] == 'Z' && magic[2] == 'h' ) {
843             ret = ZT_BZ2;
844           }
845         }
846         close( fd );
847       }
848
849       return ret;
850     }
851
852     ///////////////////////////////////////////////////////////////////
853     //
854     //  METHOD NAME : df
855     //  METHOD TYPE : ByteCount
856     //
857     ByteCount df( const Pathname & path_r )
858     {
859       ByteCount ret( -1 );
860       struct statvfs sb;
861       if ( statvfs( path_r.c_str(), &sb ) == 0 )
862         {
863           ret = sb.f_bfree * sb.f_bsize;
864         }
865       return ret;
866     }
867
868     /////////////////////////////////////////////////////////////////
869   } // namespace filesystem
870   ///////////////////////////////////////////////////////////////////
871   /////////////////////////////////////////////////////////////////
872 } // namespace zypp
873 ///////////////////////////////////////////////////////////////////