9119e112827b823e24d1fd5b12b85a9d07d524e3
[platform/upstream/libzypp.git] / zypp / PathInfo.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PathInfo.h
10  *
11 */
12 #ifndef ZYPP_PATHINFO_H
13 #define ZYPP_PATHINFO_H
14
15 extern "C"
16 {
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 }
23
24 #include <cerrno>
25 #include <iosfwd>
26 #include <list>
27 #include <set>
28 #include <map>
29
30 #include "zypp/APIConfig.h"
31 #include "zypp/Pathname.h"
32 #include "zypp/CheckSum.h"
33 #include "zypp/ByteCount.h"
34
35 ///////////////////////////////////////////////////////////////////
36 namespace zypp
37 { /////////////////////////////////////////////////////////////////
38
39   class StrMatcher;
40
41   ///////////////////////////////////////////////////////////////////
42   /** Types and functions for filesystem operations.
43    * \todo move zypp::filesystem stuff into separate header
44    * \todo Add tmpfile and tmpdir handling.
45    * \todo think about using Exceptions in zypp::filesystem
46    * \todo provide a readdir iterator; at least provide an interface
47    * using an insert_iterator to be independent from std::container.
48   */
49   namespace filesystem
50   { /////////////////////////////////////////////////////////////////
51
52     ///////////////////////////////////////////////////////////////////
53     /** File type information.
54      * \todo Think about an \ref g_EnumerationClass
55     */
56     enum FileType
57       {
58         FT_NOT_AVAIL = 0x00, // no typeinfo available
59         FT_NOT_EXIST = 0x01, // file does not exist
60         FT_FILE      = 0x02,
61         FT_DIR       = 0x04,
62         FT_CHARDEV   = 0x08,
63         FT_BLOCKDEV  = 0x10,
64         FT_FIFO      = 0x20,
65         FT_LINK      = 0x40,
66         FT_SOCKET    = 0x80
67       };
68     ///////////////////////////////////////////////////////////////////
69
70     /** \relates FileType Stram output. */
71     extern std::ostream & operator<<( std::ostream & str, FileType obj );
72
73     ///////////////////////////////////////////////////////////////////
74
75     ///////////////////////////////////////////////////////////////////
76     //
77     //  CLASS NAME : StatMode
78     /**
79      * @short Wrapper class for mode_t values as derived from ::stat
80      **/
81     class StatMode
82     {
83       friend std::ostream & operator<<( std::ostream & str, const StatMode & obj );
84
85     public:
86       /** Ctor taking  mode_t value from ::stat. */
87       StatMode( const mode_t & mode_r = 0 )
88       : _mode( mode_r )
89       {}
90
91     public:
92
93       /** \name Query FileType. */
94       //@{
95       FileType fileType() const;
96
97       bool   isFile()  const { return S_ISREG( _mode ); }
98       bool   isDir ()  const { return S_ISDIR( _mode ); }
99       bool   isLink()  const { return S_ISLNK( _mode ); }
100       bool   isChr()   const { return S_ISCHR( _mode ); }
101       bool   isBlk()   const { return S_ISBLK( _mode ); }
102       bool   isFifo()  const { return S_ISFIFO( _mode ); }
103       bool   isSock()  const { return S_ISSOCK( _mode ); }
104       //@}
105
106       /** \name Query user permissions. */
107       //@{
108       bool   isRUsr()  const { return (_mode & S_IRUSR); }
109       bool   isWUsr()  const { return (_mode & S_IWUSR); }
110       bool   isXUsr()  const { return (_mode & S_IXUSR); }
111
112       /** Short for isRUsr().*/
113       bool   isR()     const { return isRUsr(); }
114       /** Short for isWUsr().*/
115       bool   isW()     const { return isWUsr(); }
116       /** Short for isXUsr().*/
117       bool   isX()     const { return isXUsr(); }
118       //@}
119
120       /** \name Query group permissions. */
121       //@{
122       bool   isRGrp()  const { return (_mode & S_IRGRP); }
123       bool   isWGrp()  const { return (_mode & S_IWGRP); }
124       bool   isXGrp()  const { return (_mode & S_IXGRP); }
125       //@}
126
127       /** \name Query others permissions. */
128       //@{
129       bool   isROth()  const { return (_mode & S_IROTH); }
130       bool   isWOth()  const { return (_mode & S_IWOTH); }
131       bool   isXOth()  const { return (_mode & S_IXOTH); }
132       //@}
133
134       /** \name Query special permissions. */
135       //@{
136       /** Set UID bit. */
137       bool   isUid()   const { return (_mode & S_ISUID); }
138       /** Set GID bit. */
139       bool   isGid()   const { return (_mode & S_ISGID); }
140       /** Sticky bit. */
141       bool   isVtx()   const { return (_mode & S_ISVTX); }
142       //@}
143
144       /** \name Query permission */
145       //@{
146       /** Test for equal permission bits. */
147       bool   isPerm ( mode_t m ) const { return (m == perm()); }
148       /** Test for set permission bits. */
149       bool   hasPerm( mode_t m ) const { return (m == (m & perm())); }
150       //@}
151
152       /** \name Extract permission bits only. */
153       //@{
154       mode_t uperm()   const { return (_mode & S_IRWXU); }
155       mode_t gperm()   const { return (_mode & S_IRWXG); }
156       mode_t operm()   const { return (_mode & S_IRWXO); }
157       mode_t perm()    const { return (_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)); }
158       //@}
159
160       /** Return the mode_t value. */
161       mode_t st_mode() const { return _mode; }
162
163     private:
164       mode_t _mode;
165     };
166     ///////////////////////////////////////////////////////////////////
167
168     /** \relates StatMode Stream output. */
169     extern std::ostream & operator<<( std::ostream & str, const StatMode & obj );
170
171     ///////////////////////////////////////////////////////////////////
172
173     ///////////////////////////////////////////////////////////////////
174     //
175     //  CLASS NAME : DevInoCache
176     /** Simple cache remembering device/inode to detect hardlinks.
177      * \code
178      *     DevInoCache trace;
179      *     for ( all files ) {
180      *       if ( trace.insert( file.device, file.inode ) ) {
181      *         // 1st occurance of file
182      *       }
183      *         // else: hardlink; already counted this device/inode
184      *       }
185      *     }
186      * \endcode
187      **/
188     class DevInoCache
189     {
190     public:
191       /** Ctor */
192       DevInoCache() {}
193
194       /** Clear cache. */
195       void clear() { _devino.clear(); }
196
197       /** Remember dev/ino.
198        * \Return <code>true</code> if it's inserted the first
199        * time, <code>false</code> if alredy present in cache
200        * (a hardlink to a previously remembered file).
201        **/
202       bool insert( const dev_t & dev_r, const ino_t & ino_r ) {
203         return _devino[dev_r].insert( ino_r ).second;
204       }
205
206     private:
207       std::map<dev_t,std::set<ino_t> > _devino;
208     };
209     ///////////////////////////////////////////////////////////////////
210
211     ///////////////////////////////////////////////////////////////////
212     //
213     //  CLASS NAME : PathInfo
214     /** Wrapper class for ::stat/::lstat.
215      *
216      * \note All attribute quieries test for isExist(), and return \c false or
217      * \c 0, if stat was not successful.
218      *
219      * \note For convenience PathInfo is available as zypp::PathInfo too.
220      **/
221     class PathInfo
222     {
223       friend std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
224
225     public:
226       /** stat() or lstat() */
227       enum Mode { STAT, LSTAT };
228
229     public:
230       /** \name Construct from Pathname.
231        * Default mode is \c STAT.
232       */
233       //@{
234       PathInfo();
235       explicit
236       PathInfo( const Pathname & path, Mode initial = STAT );
237       explicit
238       PathInfo( const std::string & path, Mode initial = STAT );
239       explicit
240       PathInfo( const char * path, Mode initial = STAT );
241       //@}
242
243       /**Dtor */
244       ~PathInfo();
245
246       /** Return current Pathname. */
247       const Pathname &    path()     const { return path_t; }
248       /** Return current Pathname as String. */
249       const std::string & asString() const { return path_t.asString(); }
250       /** Return current Pathname as C-string. */
251       const char * c_str()           const { return path_t.asString().c_str(); }
252       /** Return current stat Mode. */
253       Mode                mode()     const { return mode_e; }
254       /** Return error returned from last stat/lstat call. */
255       int                 error()    const { return error_i; }
256
257       /** Set a new Pathname. */
258       void setPath( const Pathname & path ) { if ( path != path_t ) error_i = -1; path_t = path; }
259       /** Set a new Mode . */
260       void setMode( Mode mode )             { if ( mode != mode_e ) error_i = -1; mode_e = mode; }
261
262       /** STAT \a path. */
263       bool stat      ( const Pathname & path ) { setPath( path ); setMode( STAT );  return operator()(); }
264       /** LSTAT \a path. */
265       bool lstat     ( const Pathname & path ) { setPath( path ); setMode( LSTAT ); return operator()(); }
266       /** Restat \a path using current mode. */
267       bool operator()( const Pathname & path ) { setPath( path ); return operator()(); }
268
269       /** STAT current path. */
270       bool stat()   { setMode( STAT );  return operator()(); }
271       /** LSTAT current path. */
272       bool lstat()  { setMode( LSTAT ); return operator()(); }
273       /** Restat current path using current mode. */
274       bool operator()();
275
276     public:
277
278       /** Return whether valid stat info exists.
279        * That's usg. whether the file exist and you had permission to
280        * stat it.
281       */
282       bool   isExist() const { return !error_i; }
283
284       /** \name Query StatMode attibutes.
285        * Combines \ref zypp::PathInfo::isExist and \ref zypp::filesystem::StatMode query.
286       */
287       //@{
288       FileType fileType() const;
289
290       bool   isFile()  const { return isExist() && S_ISREG( statbuf_C.st_mode ); }
291       bool   isDir ()  const { return isExist() && S_ISDIR( statbuf_C.st_mode ); }
292       bool   isLink()  const { return isExist() && S_ISLNK( statbuf_C.st_mode ); }
293       bool   isChr()   const { return isExist() && S_ISCHR( statbuf_C.st_mode ); }
294       bool   isBlk()   const { return isExist() && S_ISBLK( statbuf_C.st_mode ); }
295       bool   isFifo()  const { return isExist() && S_ISFIFO( statbuf_C.st_mode ); }
296       bool   isSock()  const { return isExist() && S_ISSOCK( statbuf_C.st_mode ); }
297
298       // permission
299       bool   isRUsr()  const { return isExist() && (statbuf_C.st_mode & S_IRUSR); }
300       bool   isWUsr()  const { return isExist() && (statbuf_C.st_mode & S_IWUSR); }
301       bool   isXUsr()  const { return isExist() && (statbuf_C.st_mode & S_IXUSR); }
302
303       bool   isR()     const { return isRUsr(); }
304       bool   isW()     const { return isWUsr(); }
305       bool   isX()     const { return isXUsr(); }
306
307       bool   isRGrp()  const { return isExist() && (statbuf_C.st_mode & S_IRGRP); }
308       bool   isWGrp()  const { return isExist() && (statbuf_C.st_mode & S_IWGRP); }
309       bool   isXGrp()  const { return isExist() && (statbuf_C.st_mode & S_IXGRP); }
310
311       bool   isROth()  const { return isExist() && (statbuf_C.st_mode & S_IROTH); }
312       bool   isWOth()  const { return isExist() && (statbuf_C.st_mode & S_IWOTH); }
313       bool   isXOth()  const { return isExist() && (statbuf_C.st_mode & S_IXOTH); }
314
315       bool   isUid()   const { return isExist() && (statbuf_C.st_mode & S_ISUID); }
316       bool   isGid()   const { return isExist() && (statbuf_C.st_mode & S_ISGID); }
317       bool   isVtx()   const { return isExist() && (statbuf_C.st_mode & S_ISVTX); }
318
319       bool   isPerm ( mode_t m ) const { return isExist() && (m == perm()); }
320       bool   hasPerm( mode_t m ) const { return isExist() && (m == (m & perm())); }
321
322       mode_t uperm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXU) : 0; }
323       mode_t gperm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXG) : 0; }
324       mode_t operm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXO) : 0; }
325       mode_t perm()    const { return isExist() ? (statbuf_C.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)) : 0; }
326
327       mode_t st_mode() const { return isExist() ? statbuf_C.st_mode : 0; }
328       //@}
329
330       /** Return st_mode() as filesystem::StatMode. */
331       StatMode asStatMode() const { return st_mode(); }
332
333       nlink_t nlink()  const { return isExist() ? statbuf_C.st_nlink : 0; }
334
335       /** \name Owner and group */
336       //@{
337       uid_t  owner()   const { return isExist() ? statbuf_C.st_uid : 0; }
338       gid_t  group()   const { return isExist() ? statbuf_C.st_gid : 0; }
339       //@}
340
341       /** \name Permission according to current uid/gid. */
342       //@{
343       /** Returns current users permission (<tt>[0-7]</tt>)*/
344       mode_t userMay() const;
345
346       bool   userMayR() const { return( userMay() & 04 ); }
347       bool   userMayW() const { return( userMay() & 02 ); }
348       bool   userMayX() const { return( userMay() & 01 ); }
349
350       bool   userMayRW()  const { return( (userMay() & 06) == 06 ); }
351       bool   userMayRX()  const { return( (userMay() & 05) == 05 ); }
352       bool   userMayWX()  const { return( (userMay() & 03) == 03 ); }
353
354       bool   userMayRWX() const { return( userMay() == 07 ); }
355       //@}
356
357       /** \name Device and inode info. */
358       //@{
359       ino_t  ino()     const { return isExist() ? statbuf_C.st_ino  : 0; }
360       dev_t  dev()     const { return isExist() ? statbuf_C.st_dev  : 0; }
361       dev_t  rdev()    const { return isExist() ? statbuf_C.st_rdev : 0; }
362
363       unsigned int devMajor() const;
364       unsigned int devMinor() const;
365
366       /** \deprecated Name clashes with GNU libc macro, use \ref devMajor instead. */
367       unsigned int major() const ZYPP_DEPRECATED;
368       /** \deprecated Name clashes with GNU libc macro, use \ref devMinor instead. */
369       unsigned int minor() const ZYPP_DEPRECATED;
370       //@}
371
372       /** \name Size info. */
373       //@{
374       off_t         size()    const { return isExist() ? statbuf_C.st_size : 0; }
375       unsigned long blksize() const { return isExist() ? statbuf_C.st_blksize : 0; }
376       unsigned long blocks()  const { return isExist() ? statbuf_C.st_blocks  : 0; }
377       //@}
378
379       /** \name Time stamps. */
380       //@{
381       time_t atime()   const { return isExist() ? statbuf_C.st_atime : 0; } /* time of last access */
382       time_t mtime()   const { return isExist() ? statbuf_C.st_mtime : 0; } /* time of last modification */
383       time_t ctime()   const { return isExist() ? statbuf_C.st_ctime : 0; }
384       //@}
385
386     private:
387       Pathname    path_t;
388       struct stat statbuf_C;
389       Mode        mode_e;
390       int         error_i;
391     };
392     ///////////////////////////////////////////////////////////////////
393
394     /** \relates PathInfo Stream output. */
395     extern std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
396
397     ///////////////////////////////////////////////////////////////////
398
399     ///////////////////////////////////////////////////////////////////
400     /** \name Directory related functions. */
401     //@{
402     /**
403      * Like '::mkdir'. Attempt to create a new directory named path. mode
404      * specifies the permissions to use. It is modified by the process's
405      * umask in the usual way.
406      *
407      * @return 0 on success, errno on failure
408      **/
409     int mkdir( const Pathname & path, unsigned mode = 0755 );
410
411     /**
412      * Like 'mkdir -p'. No error if directory exists. Make parent directories
413      * as needed. mode specifies the permissions to use, if directories have to
414      * be created. It is modified by the process's umask in the usual way.
415      *
416      * @return 0 on success, errno on failure
417      **/
418     int assert_dir( const Pathname & path, unsigned mode = 0755 );
419
420     /**
421      * Like '::rmdir'. Delete a directory, which must be empty.
422      *
423      * @return 0 on success, errno on failure
424      **/
425     int rmdir( const Pathname & path );
426
427     /**
428      * Like 'rm -r DIR'. Delete a directory, recursively removing its contents.
429      *
430      * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
431      * commands return value.
432      **/
433     int recursive_rmdir( const Pathname & path );
434
435     /**
436      * Like 'rm -r DIR/ *'. Delete directory contents, but keep the directory itself.
437      *
438      * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
439      * commands return value.
440      **/
441     int clean_dir( const Pathname & path );
442
443     /**
444      * Like 'cp -a srcpath destpath'. Copy directory tree. srcpath/destpath must be
445      * directories. 'basename srcpath' must not exist in destpath.
446      *
447      * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory, EEXIST if
448      * 'basename srcpath' exists in destpath, otherwise the commands return value.
449      **/
450     int copy_dir( const Pathname & srcpath, const Pathname & destpath );
451
452     /**
453      * Like 'cp -a srcpath/. destpath'. Copy the content of srcpath recursively
454      * into destpath. Both \p srcpath and \p destpath has to exists.
455      *
456      * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory,
457      * EEXIST if srcpath and destpath are equal, otherwise the commands
458      * return value.
459      */
460     int copy_dir_content( const Pathname & srcpath, const Pathname & destpath);
461
462     /**
463      * Convenience returning <tt>StrMatcher( "[^.]*", Match::GLOB )</tt>
464      * \see \ref dirForEach
465      */
466     const StrMatcher & matchNoDots();
467
468     /**
469      * Invoke callback function \a fnc_r for each entry in directory \a dir_r.
470      *
471      * If \a fnc_r is a \c NULL function \c 0 is returned immediately without even
472      * testing or accessing \a dir_r.
473      *
474      * Otherwise \c ::readdir is used to read the name of every entry in \a dir_r,
475      * omitting  \c '.' and \c '..'. \a dir_r and the current entries name are passed
476      * as arguments to \a fnc_r. If \a fnc_r returns \c false processing is aborted.
477      *
478      * @return 0 on success, -1 if aborted by callback, errno > 0 on ::readdir failure.
479      */
480     int dirForEach( const Pathname & dir_r, function<bool(const Pathname &, const char *const)> fnc_r );
481
482     /**
483      * \overload taking a \ref StrMatcher to filter the entries for which \a fnc_r is invoked.
484      *
485      * For convenience a \ref StrMatcher \ref matchNoDots is provided in this namespace.</tt>
486      *
487      * \code
488      *   bool cbfnc( const Pathname & dir_r, const char *const str_r )
489      *   {
490      *     D BG <*< " - " << dir_r/str_r << endl;
491      *     return true;
492      *   }
493      *   // Print no-dot files in "/tmp" via callback
494      *   filesystem::dirForEach( "/tmp", filesystem::matchNoDots(), cbfnc );
495      *
496      *   // same via lambda
497      *   filesystem::dirForEach( "/tmp", filesystem::matchNoDots(),
498      *                           [](const Pathname & dir_r, const std::string & str_r)->bool
499      *                           {
500      *                             DBG << " - " << dir_r/str_r << endl;
501      *                             return true;
502      *                           });
503      * \endcode
504      */
505     int dirForEach( const Pathname & dir_r, const StrMatcher & matcher_r, function<bool(const Pathname &, const char *const)> fnc_r );
506
507     /**
508      * Return content of directory via retlist. If dots is false
509      * entries starting with '.' are not reported. "." and ".."
510      * are never reported.
511      *
512      * Returns just the directory entries as string.
513      *
514      * @return 0 on success, errno on failure.
515      *
516      * \todo provide some readdirIterator.
517      **/
518
519     int readdir( std::list<std::string> & retlist,
520                  const Pathname & path, bool dots = true );
521
522     /**
523      * Return content of directory via retlist. If dots is false
524      * entries starting with '.' are not reported. "." and ".."
525      * are never reported.
526      *
527      * Returns the directory entries prefixed with \a path.
528      *
529      * @return 0 on success, errno on failure.
530      *
531      * \todo provide some readdirIterator.
532      **/
533
534     int readdir( std::list<Pathname> & retlist,
535                  const Pathname & path, bool dots = true );
536
537     /** Listentry returned by readdir. */
538     struct DirEntry {
539       std::string name;
540       FileType    type;
541       DirEntry( const std::string & name_r = std::string(), FileType type_r = FT_NOT_AVAIL )
542       : name( name_r )
543       , type( type_r )
544       {}
545
546       bool operator==( const DirEntry &rhs ) const;
547     };
548
549     inline std::ostream & operator<<( std::ostream & str, const DirEntry & obj )
550     { return str << '[' << obj.type << "] " << obj.name; }
551
552     /** Returned by readdir. */
553     typedef std::list<DirEntry> DirContent;
554
555     std::ostream & operator<<( std::ostream & str, const DirContent & obj );
556
557     /**
558      * Return content of directory via retlist. If dots is false
559      * entries starting with '.' are not reported. "." and ".."
560      * are never reported.
561      *
562      * The type of individual directory entries is determined accoding to
563      * statmode (i.e. via stat or lstat).
564      *
565      * @return 0 on success, errno on failure.
566      **/
567     int readdir( DirContent & retlist, const Pathname & path,
568                  bool dots = true, PathInfo::Mode statmode = PathInfo::STAT );
569
570     /**
571      * Check if the specified directory is empty.
572      * \param path The path of the directory to check.
573      * \return 0 if directory is empty, -1 if not, errno > 0 on failure.
574      */
575     int is_empty_dir(const Pathname & path);
576
577     //@}
578
579     ///////////////////////////////////////////////////////////////////
580     /** \name File related functions. */
581     //@{
582     /**
583      * Create an empty file if it does not yet exist. Make parent directories
584      * as needed. mode specifies the permissions to use. It is modified by the
585      * process's umask in the usual way.
586      *
587      * @return 0 on success, errno on failure
588      **/
589     int assert_file( const Pathname & path, unsigned mode = 0644 );
590
591     /**
592      * Change file's modification and access times.
593      *
594      * \return 0 on success, errno on failure
595      * \see man utime
596      */
597     int touch (const Pathname & path);
598
599     /**
600      * Like '::unlink'. Delete a file (symbolic link, socket, fifo or device).
601      *
602      * @return 0 on success, errno on failure
603      **/
604     int unlink( const Pathname & path );
605
606     /**
607      * Like '::rename'. Renames a file, moving it between directories if required.
608      *
609      * @return 0 on success, errno on failure
610      **/
611     int rename( const Pathname & oldpath, const Pathname & newpath );
612
613     /** Exchanges two files or directories.
614      *
615      * Most common use is when building a new config file (or dir)
616      * in a tempfile. After the job is done, configfile and tempfile
617      * are exchanged. This includes moving away the configfile in case
618      * the tempfile does not exist. Parent directories are created as
619      * needed.
620      *
621      * \note Paths are exchanged using \c ::rename, so take care both paths
622      * are located on the same filesystem.
623      *
624      * \code
625      * Pathname configfile( "/etc/myconfig" );
626      * TmpFile  newconfig( TmpFile::makeSibling( configfile ) );
627      * // now write the new config:
628      * std::ofstream o( newconfig.path().c_str() );
629      * o << "mew values << endl;
630      * o.close();
631      * // If everything is fine, exchange the files:
632      * exchange( newconfig.path(), configfile );
633      * // Now the old configfile is still available at newconfig.path()
634      * // until newconfig goes out of scope.
635      * \endcode
636      *
637      * @return 0 on success, errno on failure
638      */
639     int exchange( const Pathname & lpath, const Pathname & rpath );
640
641     /**
642      * Like 'cp file dest'. Copy file to destination file.
643      *
644      * @return 0 on success, EINVAL if file is not a file, EISDIR if
645      * destiantion is a directory, otherwise the commands return value.
646      **/
647     int copy( const Pathname & file, const Pathname & dest );
648
649     /**
650      * Like '::symlink'. Creates a symbolic link named newpath which contains
651      * the string oldpath. If newpath exists it will not be overwritten.
652      *
653      * @return 0 on success, errno on failure.
654      **/
655     int symlink( const Pathname & oldpath, const Pathname & newpath );
656
657     /**
658      * Like '::link'. Creates a hard link named newpath to an existing file
659      * oldpath. If newpath exists it will not be overwritten.
660      *
661      * @return 0 on success, errno on failure.
662      **/
663     int hardlink( const Pathname & oldpath, const Pathname & newpath );
664
665     /**
666      * Create \a newpath as hardlink or copy of \a oldpath.
667      *
668      * @return 0 on success, errno on failure.
669      */
670     int hardlinkCopy( const Pathname & oldpath, const Pathname & newpath );
671
672     /**
673      * Like '::readlink'. Return the contents of the symbolic link
674      * \a symlink_r via \a target_r.
675      *
676      * @return 0 on success, errno on failure.
677      */
678     int readlink( const Pathname & symlink_r, Pathname & target_r );
679     /** \overload Return an empty Pathname on error. */
680     inline Pathname readlink( const Pathname & symlink_r )
681     {
682       Pathname target;
683       readlink( symlink_r, target );
684       return target;
685     }
686
687     /**
688      * Recursively follows the symlink pointed to by \a path_r and returns
689      * the Pathname to the real file or directory pointed to by the link.
690      *
691      * There is a recursion limit of 256 iterations to protect against a cyclic
692      * link.
693      *
694      * @return Pathname of the file or directory pointed to by the given link
695      *   if it is a valid link. If \a path_r is not a link, an exact copy of
696      *   it is returned. If \a path_r is a broken or a cyclic link, an empty
697      *   Pathname is returned and the event logged.
698      */
699     Pathname expandlink( const Pathname & path_r );
700
701     /**
702      * Like 'cp file dest'. Copy file to dest dir.
703      *
704      * @return 0 on success, EINVAL if file is not a file, ENOTDIR if dest
705      * is no directory, otherwise the commands return value.
706      **/
707     int copy_file2dir( const Pathname & file, const Pathname & dest );
708     //@}
709
710     ///////////////////////////////////////////////////////////////////
711     /** \name Digest computaion.
712      * \todo check cooperation with zypp::Digest
713     */
714     //@{
715     /**
716      * Compute a files md5sum.
717      *
718      * @return the files md5sum on success, otherwise an empty string..
719      **/
720     std::string md5sum( const Pathname & file );
721
722     /**
723      * Compute a files sha1sum.
724      *
725      * @return the files sha1sum on success, otherwise an empty string..
726      **/
727     std::string sha1sum( const Pathname & file );
728     //@}
729
730     /**
731      * Compute a files checksum
732      *
733      * @return the files checksum on success, otherwise an empty string..
734      **/
735     std::string checksum( const Pathname & file, const std::string &algorithm );
736
737     /**
738      * check files checksum
739      *
740      * @return true if the checksum matches (an empty Checksum always matches!)
741      **/
742     bool is_checksum( const Pathname & file, const CheckSum &checksum );
743
744     ///////////////////////////////////////////////////////////////////
745     /** \name Changing permissions. */
746     //@{
747     /**
748      * Like '::chmod'. The mode of the file given by path is changed.
749      *
750      * @return 0 on success, errno on failure
751      **/
752     int chmod( const Pathname & path, mode_t mode );
753
754     /**
755      * Add the \c mode bits to the file given by path.
756      *
757      * @return 0 on success, errno on failure
758      */
759     int addmod( const Pathname & path, mode_t mode );
760
761     /**
762      * Remove the \c mode bits from the file given by path.
763      *
764      * @return 0 on success, errno on failure
765      */
766     int delmod( const Pathname & path, mode_t mode );
767     //@}
768
769     ///////////////////////////////////////////////////////////////////
770     /** \name Misc. */
771     //@{
772     /**
773      * Test whether a file is compressed (gzip/bzip2).
774      *
775      * @return ZT_GZ, ZT_BZ2 if file is compressed, otherwise ZT_NONE.
776      **/
777     enum ZIP_TYPE { ZT_NONE, ZT_GZ, ZT_BZ2 };
778
779     ZIP_TYPE zipType( const Pathname & file );
780
781     /**
782      * Erase whatever happens to be located at path (file or directory).
783      *
784      * @return 0 on success.
785      *
786      * \todo check cooperation with zypp::TmpFile and zypp::TmpDir
787      **/
788     int erase( const Pathname & path );
789
790     /**
791      * Report free disk space on a mounted file system.
792      *
793      * path is the path name of any file within the mounted filesystem.
794      *
795      * @return Free disk space or -1 on error.
796      **/
797     ByteCount df( const Pathname & path );
798
799     /**
800      * Get the current umask (file mode creation mask)
801      *
802      * @return The current umask
803      **/
804     mode_t getUmask();
805
806      /**
807      * Modify \c mode_r according to the current umask
808      * <tt>( mode_r & ~getUmask() )</tt>.
809      * \see \ref getUmask.
810      * @return The resulting permissions.
811      **/
812     inline mode_t applyUmaskTo( mode_t mode_r )
813     { return mode_r & ~getUmask(); }
814     //@}
815
816     /////////////////////////////////////////////////////////////////
817   } // namespace filesystem
818   ///////////////////////////////////////////////////////////////////
819
820   /** Dragged into namespace zypp. */
821   using filesystem::PathInfo;
822
823   /////////////////////////////////////////////////////////////////
824 } // namespace zypp
825 ///////////////////////////////////////////////////////////////////
826 #endif // ZYPP_PATHINFO_H