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