merge make-it-cool
[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
33 ///////////////////////////////////////////////////////////////////
34 namespace zypp
35 { /////////////////////////////////////////////////////////////////
36
37   ///////////////////////////////////////////////////////////////////
38   /** Types and functions for filesystem operations.
39    * \todo move zypp::filesystem stuff into separate header
40    * \todo Add tmpfile and tmpdir handling.
41    * \todo think about using Exceptions in zypp::filesystem
42    * \todo provide a readdir iterator; at least provide an interface
43    * using an insert_iterator to be independent from std::container.
44   */
45   namespace filesystem
46   { /////////////////////////////////////////////////////////////////
47
48     ///////////////////////////////////////////////////////////////////
49     /** File type information.
50      * \todo Think about an \ref g_EnumerationClass
51     */
52     enum FileType
53       {
54         FT_NOT_AVAIL = 0x00, // no typeinfo available
55         FT_NOT_EXIST = 0x01, // file does not exist
56         FT_FILE      = 0x02,
57         FT_DIR       = 0x04,
58         FT_CHARDEV   = 0x08,
59         FT_BLOCKDEV  = 0x10,
60         FT_FIFO      = 0x20,
61         FT_LINK      = 0x40,
62         FT_SOCKET    = 0x80
63       };
64     ///////////////////////////////////////////////////////////////////
65
66     /** \relates FileType Stram output. */
67     extern std::ostream & operator<<( std::ostream & str, FileType obj );
68
69     ///////////////////////////////////////////////////////////////////
70
71     ///////////////////////////////////////////////////////////////////
72     //
73     //  CLASS NAME : StatMode
74     /**
75      * @short Wrapper class for mode_t values as derived from ::stat
76      **/
77     class StatMode
78     {
79       friend std::ostream & operator<<( std::ostream & str, const StatMode & obj );
80
81     public:
82       /** Ctor taking  mode_t value from ::stat. */
83       StatMode( const mode_t & mode_r = 0 )
84       : _mode( mode_r )
85       {}
86
87     public:
88
89       /** \name Query FileType. */
90       //@{
91       FileType fileType() const;
92
93       bool   isFile()  const { return S_ISREG( _mode ); }
94       bool   isDir ()  const { return S_ISDIR( _mode ); }
95       bool   isLink()  const { return S_ISLNK( _mode ); }
96       bool   isChr()   const { return S_ISCHR( _mode ); }
97       bool   isBlk()   const { return S_ISBLK( _mode ); }
98       bool   isFifo()  const { return S_ISFIFO( _mode ); }
99       bool   isSock()  const { return S_ISSOCK( _mode ); }
100       //@}
101
102       /** \name Query user permissions. */
103       //@{
104       bool   isRUsr()  const { return (_mode & S_IRUSR); }
105       bool   isWUsr()  const { return (_mode & S_IWUSR); }
106       bool   isXUsr()  const { return (_mode & S_IXUSR); }
107
108       /** Short for isRUsr().*/
109       bool   isR()     const { return isRUsr(); }
110       /** Short for isWUsr().*/
111       bool   isW()     const { return isWUsr(); }
112       /** Short for isXUsr().*/
113       bool   isX()     const { return isXUsr(); }
114       //@}
115
116       /** \name Query group permissions. */
117       //@{
118       bool   isRGrp()  const { return (_mode & S_IRGRP); }
119       bool   isWGrp()  const { return (_mode & S_IWGRP); }
120       bool   isXGrp()  const { return (_mode & S_IXGRP); }
121       //@}
122
123       /** \name Query others permissions. */
124       //@{
125       bool   isROth()  const { return (_mode & S_IROTH); }
126       bool   isWOth()  const { return (_mode & S_IWOTH); }
127       bool   isXOth()  const { return (_mode & S_IXOTH); }
128       //@}
129
130       /** \name Query special permissions. */
131       //@{
132       /** Set UID bit. */
133       bool   isUid()   const { return (_mode & S_ISUID); }
134       /** Set GID bit. */
135       bool   isGid()   const { return (_mode & S_ISGID); }
136       /** Sticky bit. */
137       bool   isVtx()   const { return (_mode & S_ISVTX); }
138       //@}
139
140       /** \name Query permission */
141       //@{
142       /** Test for equal permission bits. */
143       bool   isPerm ( mode_t m ) const { return (m == perm()); }
144       /** Test for set permission bits. */
145       bool   hasPerm( mode_t m ) const { return (m == (m & perm())); }
146       //@}
147
148       /** \name Extract permission bits only. */
149       //@{
150       mode_t uperm()   const { return (_mode & S_IRWXU); }
151       mode_t gperm()   const { return (_mode & S_IRWXG); }
152       mode_t operm()   const { return (_mode & S_IRWXO); }
153       mode_t perm()    const { return (_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)); }
154       //@}
155
156       /** Return the mode_t value. */
157       mode_t st_mode() const { return _mode; }
158
159     private:
160       mode_t _mode;
161     };
162     ///////////////////////////////////////////////////////////////////
163
164     /** \relates StatMode Stream output. */
165     extern std::ostream & operator<<( std::ostream & str, const StatMode & obj );
166
167     ///////////////////////////////////////////////////////////////////
168
169     ///////////////////////////////////////////////////////////////////
170     //
171     //  CLASS NAME : DevInoCache
172     /** Simple cache remembering device/inode to detect hardlinks.
173      * \code
174      *     DevInoCache trace;
175      *     for ( all files ) {
176      *       if ( trace.insert( file.device, file.inode ) ) {
177      *         // 1st occurance of file
178      *       }
179      *         // else: hardlink; already counted this device/inode
180      *       }
181      *     }
182      * \endcode
183      **/
184     class DevInoCache
185     {
186     public:
187       /** Ctor */
188       DevInoCache() {}
189
190       /** Clear cache. */
191       void clear() { _devino.clear(); }
192
193       /** Remember dev/ino.
194        * \Return <code>true</code> if it's inserted the first
195        * time, <code>false</code> if alredy present in cache
196        * (a hardlink to a previously remembered file).
197        **/
198       bool insert( const dev_t & dev_r, const ino_t & ino_r ) {
199         return _devino[dev_r].insert( ino_r ).second;
200       }
201
202     private:
203       std::map<dev_t,std::set<ino_t> > _devino;
204     };
205     ///////////////////////////////////////////////////////////////////
206
207     ///////////////////////////////////////////////////////////////////
208     //
209     //  CLASS NAME : PathInfo
210     /** Wrapper class for ::stat/::lstat.
211      *
212      * \note All attribute quieries test for isExist(), and return \c false or
213      * \c 0, if stat was not successful.
214      *
215      * \note For convenience PathInfo is available as zypp::PathInfo too.
216      **/
217     class PathInfo
218     {
219       friend std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
220
221     public:
222       /** stat() or lstat() */
223       enum Mode { STAT, LSTAT };
224
225     public:
226       /** \name Construct from Pathname.
227        * Default mode is \c STAT.
228       */
229       //@{
230       PathInfo();
231       explicit
232       PathInfo( const Pathname & path, Mode initial = STAT );
233       explicit
234       PathInfo( const std::string & path, Mode initial = STAT );
235       explicit
236       PathInfo( const char * path, Mode initial = STAT );
237       //@}
238
239       /**Dtor */
240       ~PathInfo();
241
242       /** Return current Pathname. */
243       const Pathname &    path()     const { return path_t; }
244       /** Return current Pathname as String. */
245       const std::string & asString() const { return path_t.asString(); }
246       /** Return current stat Mode. */
247       Mode                mode()     const { return mode_e; }
248       /** Return error returned from last stat/lstat call. */
249       int                 error()    const { return error_i; }
250
251       /** Set a new Pathname. */
252       void setPath( const Pathname & path ) { if ( path != path_t ) error_i = -1; path_t = path; }
253       /** Set a new Mode . */
254       void setMode( Mode mode )             { if ( mode != mode_e ) error_i = -1; mode_e = mode; }
255
256       /** STAT \a path. */
257       bool stat      ( const Pathname & path ) { setPath( path ); setMode( STAT );  return operator()(); }
258       /** LSTAT \a path. */
259       bool lstat     ( const Pathname & path ) { setPath( path ); setMode( LSTAT ); return operator()(); }
260       /** Restat \a path using current mode. */
261       bool operator()( const Pathname & path ) { setPath( path ); return operator()(); }
262
263       /** STAT current path. */
264       bool stat()   { setMode( STAT );  return operator()(); }
265       /** LSTAT current path. */
266       bool lstat()  { setMode( LSTAT ); return operator()(); }
267       /** Restat current path using current mode. */
268       bool operator()();
269
270     public:
271
272       /** Return whether valid stat info exists.
273        * That's usg. whether the file exist and you had permission to
274        * stat it.
275       */
276       bool   isExist() const { return !error_i; }
277
278       /** \name Query StatMode attibutes.
279        * Combines \ref zypp::PathInfo::isExist and \ref zypp::filesystem::StatMode query.
280       */
281       //@{
282       FileType fileType() const;
283
284       bool   isFile()  const { return isExist() && S_ISREG( statbuf_C.st_mode ); }
285       bool   isDir ()  const { return isExist() && S_ISDIR( statbuf_C.st_mode ); }
286       bool   isLink()  const { return isExist() && S_ISLNK( statbuf_C.st_mode ); }
287       bool   isChr()   const { return isExist() && S_ISCHR( statbuf_C.st_mode ); }
288       bool   isBlk()   const { return isExist() && S_ISBLK( statbuf_C.st_mode ); }
289       bool   isFifo()  const { return isExist() && S_ISFIFO( statbuf_C.st_mode ); }
290       bool   isSock()  const { return isExist() && S_ISSOCK( statbuf_C.st_mode ); }
291
292       // permission
293       bool   isRUsr()  const { return isExist() && (statbuf_C.st_mode & S_IRUSR); }
294       bool   isWUsr()  const { return isExist() && (statbuf_C.st_mode & S_IWUSR); }
295       bool   isXUsr()  const { return isExist() && (statbuf_C.st_mode & S_IXUSR); }
296
297       bool   isR()     const { return isRUsr(); }
298       bool   isW()     const { return isWUsr(); }
299       bool   isX()     const { return isXUsr(); }
300
301       bool   isRGrp()  const { return isExist() && (statbuf_C.st_mode & S_IRGRP); }
302       bool   isWGrp()  const { return isExist() && (statbuf_C.st_mode & S_IWGRP); }
303       bool   isXGrp()  const { return isExist() && (statbuf_C.st_mode & S_IXGRP); }
304
305       bool   isROth()  const { return isExist() && (statbuf_C.st_mode & S_IROTH); }
306       bool   isWOth()  const { return isExist() && (statbuf_C.st_mode & S_IWOTH); }
307       bool   isXOth()  const { return isExist() && (statbuf_C.st_mode & S_IXOTH); }
308
309       bool   isUid()   const { return isExist() && (statbuf_C.st_mode & S_ISUID); }
310       bool   isGid()   const { return isExist() && (statbuf_C.st_mode & S_ISGID); }
311       bool   isVtx()   const { return isExist() && (statbuf_C.st_mode & S_ISVTX); }
312
313       bool   isPerm ( mode_t m ) const { return isExist() && (m == perm()); }
314       bool   hasPerm( mode_t m ) const { return isExist() && (m == (m & perm())); }
315
316       mode_t uperm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXU) : 0; }
317       mode_t gperm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXG) : 0; }
318       mode_t operm()   const { return isExist() ? (statbuf_C.st_mode & S_IRWXO) : 0; }
319       mode_t perm()    const { return isExist() ? (statbuf_C.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)) : 0; }
320
321       mode_t st_mode() const { return isExist() ? statbuf_C.st_mode : 0; }
322       //@}
323
324       /** Return st_mode() as filesystem::StatMode. */
325       StatMode asStatMode() const { return st_mode(); }
326
327       nlink_t nlink()  const { return isExist() ? statbuf_C.st_nlink : 0; }
328
329       /** \name Owner and group */
330       //@{
331       uid_t  owner()   const { return isExist() ? statbuf_C.st_uid : 0; }
332       gid_t  group()   const { return isExist() ? statbuf_C.st_gid : 0; }
333       //@}
334
335       /** \name Permission according to current uid/gid. */
336       //@{
337       /** Returns current users permission (<tt>[0-7]</tt>)*/
338       mode_t userMay() const;
339
340       bool   userMayR() const { return( userMay() & 04 ); }
341       bool   userMayW() const { return( userMay() & 02 ); }
342       bool   userMayX() const { return( userMay() & 01 ); }
343
344       bool   userMayRW()  const { return( (userMay() & 06) == 06 ); }
345       bool   userMayRX()  const { return( (userMay() & 05) == 05 ); }
346       bool   userMayWX()  const { return( (userMay() & 03) == 03 ); }
347
348       bool   userMayRWX() const { return( userMay() == 07 ); }
349       //@}
350
351       /** \name Device and inode info. */
352       //@{
353       ino_t  ino()     const { return isExist() ? statbuf_C.st_ino  : 0; }
354       dev_t  dev()     const { return isExist() ? statbuf_C.st_dev  : 0; }
355       dev_t  rdev()    const { return isExist() ? statbuf_C.st_rdev : 0; }
356
357       unsigned int major() const;
358       unsigned int minor() const;
359       //@}
360
361       /** \name Size info. */
362       //@{
363       off_t         size()    const { return isExist() ? statbuf_C.st_size : 0; }
364       unsigned long blksize() const { return isExist() ? statbuf_C.st_blksize : 0; }
365       unsigned long blocks()  const { return isExist() ? statbuf_C.st_blocks  : 0; }
366       //@}
367
368       /** \name Time stamps. */
369       //@{
370       time_t atime()   const { return isExist() ? statbuf_C.st_atime : 0; } /* time of last access */
371       time_t mtime()   const { return isExist() ? statbuf_C.st_mtime : 0; } /* time of last modification */
372       time_t ctime()   const { return isExist() ? statbuf_C.st_ctime : 0; }
373       //@}
374
375     private:
376       Pathname    path_t;
377       struct stat statbuf_C;
378       Mode        mode_e;
379       int         error_i;
380     };
381     ///////////////////////////////////////////////////////////////////
382
383     /** \relates PathInfo Stream output. */
384     extern std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
385
386     ///////////////////////////////////////////////////////////////////
387
388     ///////////////////////////////////////////////////////////////////
389     /** \name Directory related functions. */
390     //@{
391     /**
392      * Like '::mkdir'. Attempt to create a new directory named path. mode
393      * specifies the permissions to use. It is modified by the process's
394      * umask in the usual way.
395      *
396      * @return 0 on success, errno on failure
397      **/
398     int mkdir( const Pathname & path, unsigned mode = 0755 );
399
400     /**
401      * Like 'mkdir -p'. No error if directory exists. Make parent directories
402      * as needed. mode specifies the permissions to use, if directories have to
403      * be created. It is modified by the process's umask in the usual way.
404      *
405      * @return 0 on success, errno on failure
406      **/
407     int assert_dir( const Pathname & path, unsigned mode = 0755 );
408
409     /**
410      * Like '::rmdir'. Delete a directory, which must be empty.
411      *
412      * @return 0 on success, errno on failure
413      **/
414     int rmdir( const Pathname & path );
415
416     /**
417      * Like 'rm -r DIR'. Delete a directory, recursively removing its contents.
418      *
419      * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
420      * commands return value.
421      **/
422     int recursive_rmdir( const Pathname & path );
423
424     /**
425      * Like 'rm -r DIR/ *'. Delete directory contents, but keep the directory itself.
426      *
427      * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
428      * commands return value.
429      **/
430     int clean_dir( const Pathname & path );
431
432     /**
433      * Like 'cp -a srcpath destpath'. Copy directory tree. srcpath/destpath must be
434      * directories. 'basename srcpath' must not exist in destpath.
435      *
436      * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory, EEXIST if
437      * 'basename srcpath' exists in destpath, otherwise the commands return value.
438      **/
439     int copy_dir( const Pathname & srcpath, const Pathname & destpath );
440
441     /**
442      * Like 'cp -a srcpath/. destpath'. Copy the content of srcpath recursively
443      * into destpath. Both \p srcpath and \p destpath has to exists.
444      *
445      * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory,
446      * EEXIST if srcpath and destpath are equal, otherwise the commands
447      * return value.
448      */
449     int copy_dir_content( const Pathname & srcpath, const Pathname & destpath);
450
451     /**
452      * Return content of directory via retlist. If dots is false
453      * entries starting with '.' are not reported. "." and ".."
454      * are never reported.
455      *
456      * Returns just the directory entries as string.
457      *
458      * @return 0 on success, errno on failure.
459      *
460      * \todo provide some readdirIterator.
461      **/
462
463     int readdir( std::list<std::string> & retlist,
464                  const Pathname & path, bool dots = true );
465
466     /**
467      * Return content of directory via retlist. If dots is false
468      * entries starting with '.' are not reported. "." and ".."
469      * are never reported.
470      *
471      * Returns the directory entries prefixed with \a path.
472      *
473      * @return 0 on success, errno on failure.
474      *
475      * \todo provide some readdirIterator.
476      **/
477
478     int readdir( std::list<Pathname> & retlist,
479                  const Pathname & path, bool dots = true );
480
481     /** Listentry returned by readdir. */
482     struct DirEntry {
483       std::string name;
484       FileType    type;
485       DirEntry( const std::string & name_r = std::string(), FileType type_r = FT_NOT_AVAIL )
486       : name( name_r )
487       , type( type_r )
488       {}
489     };
490
491     /** Returned by readdir. */
492     typedef std::list<DirEntry> DirContent;
493
494     /**
495      * Return content of directory via retlist. If dots is false
496      * entries starting with '.' are not reported. "." and ".."
497      * are never reported.
498      *
499      * The type of individual directory entries is determined accoding to
500      * statmode (i.e. via stat or lstat).
501      *
502      * @return 0 on success, errno on failure.
503      **/
504     int readdir( DirContent & retlist, const Pathname & path,
505                  bool dots = true, PathInfo::Mode statmode = PathInfo::STAT );
506
507
508     /**
509      * Check if the specified directory is empty.
510      * \param path The path of the directory to check.
511      * \return 0 if directory is empty, -1 if not, errno > 0 on failure.
512      */
513     int is_empty_dir(const Pathname & path);
514
515     //@}
516
517     ///////////////////////////////////////////////////////////////////
518     /** \name File related functions. */
519     //@{
520     /**
521      * Like '::unlink'. Delete a file (symbolic link, socket, fifo or device).
522      *
523      * @return 0 on success, errno on failure
524      **/
525     int unlink( const Pathname & path );
526
527     /**
528      * Like '::rename'. Renames a file, moving it between directories if required.
529      *
530      * @return 0 on success, errno on failure
531      **/
532     int rename( const Pathname & oldpath, const Pathname & newpath );
533
534     /**
535      * Like 'cp file dest'. Copy file to destination file.
536      *
537      * @return 0 on success, EINVAL if file is not a file, EISDIR if
538      * destiantion is a directory, otherwise the commands return value.
539      **/
540     int copy( const Pathname & file, const Pathname & dest );
541
542     /**
543      * Like '::symlink'. Creates a symbolic link named newpath which contains
544      * the string oldpath. If newpath exists it will not be overwritten.
545      *
546      * @return 0 on success, errno on failure.
547      **/
548     int symlink( const Pathname & oldpath, const Pathname & newpath );
549
550     /**
551      * Like '::link'. Creates a hard link named newpath to an existing file
552      * oldpath. If newpath exists it will not be overwritten.
553      *
554      * @return 0 on success, errno on failure.
555      **/
556     int hardlink( const Pathname & oldpath, const Pathname & newpath );
557
558     /**
559      * Like 'cp file dest'. Copy file to dest dir.
560      *
561      * @return 0 on success, EINVAL if file is not a file, ENOTDIR if dest
562      * is no directory, otherwise the commands return value.
563      **/
564     int copy_file2dir( const Pathname & file, const Pathname & dest );
565     //@}
566
567     ///////////////////////////////////////////////////////////////////
568     /** \name Digest computaion.
569      * \todo check cooperation with zypp::Digest
570     */
571     //@{
572     /**
573      * Compute a files md5sum.
574      *
575      * @return the files md5sum on success, otherwise an empty string..
576      **/
577     std::string md5sum( const Pathname & file );
578
579     /**
580      * Compute a files sha1sum.
581      *
582      * @return the files sha1sum on success, otherwise an empty string..
583      **/
584     std::string sha1sum( const Pathname & file );
585     //@}
586
587     /**
588      * Compute a files checksum
589      *
590      * @return the files checksum on success, otherwise an empty string..
591      **/
592     std::string checksum( const Pathname & file, const std::string &algorithm );
593
594     /**
595      * check files checksum
596      *
597      * @return true if the checksum matchs
598      **/
599     bool is_checksum( const Pathname & file, const CheckSum &checksum );
600
601     ///////////////////////////////////////////////////////////////////
602     /** \name Changing permissions. */
603     //@{
604     /**
605      * Like '::chmod'. The mode of the file given by path is changed.
606      *
607      * @return 0 on success, errno on failure
608      **/
609     int chmod( const Pathname & path, mode_t mode );
610     //@}
611
612     ///////////////////////////////////////////////////////////////////
613     /** \name Misc. */
614     //@{
615     /**
616      * Test whether a file is compressed (gzip/bzip2).
617      *
618      * @return ZT_GZ, ZT_BZ2 if file is compressed, otherwise ZT_NONE.
619      **/
620     enum ZIP_TYPE { ZT_NONE, ZT_GZ, ZT_BZ2 };
621
622     ZIP_TYPE zipType( const Pathname & file );
623
624     /**
625      * Erase whatever happens to be located at path (file or directory).
626      *
627      * @return 0 on success.
628      *
629      * \todo check cooperation with zypp::TmpFile and zypp::TmpDir
630      **/
631     int erase( const Pathname & path );
632     //@}
633
634     /////////////////////////////////////////////////////////////////
635   } // namespace filesystem
636   ///////////////////////////////////////////////////////////////////
637
638   /** Dragged into namespace zypp. */
639   using filesystem::PathInfo;
640
641   /////////////////////////////////////////////////////////////////
642 } // namespace zypp
643 ///////////////////////////////////////////////////////////////////
644 #endif // ZYPP_PATHINFO_H