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