1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PathInfo.h
12 #ifndef ZYPP_PATHINFO_H
13 #define ZYPP_PATHINFO_H
17 #include <sys/types.h>
30 #include "zypp/Pathname.h"
31 #include "zypp/CheckSum.h"
33 ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
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.
46 { /////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////
49 /** File type information.
50 * \todo Think about an \ref g_EnumerationClass
54 FT_NOT_AVAIL = 0x00, // no typeinfo available
55 FT_NOT_EXIST = 0x01, // file does not exist
64 ///////////////////////////////////////////////////////////////////
66 /** \relates FileType Stram output. */
67 extern std::ostream & operator<<( std::ostream & str, FileType obj );
69 ///////////////////////////////////////////////////////////////////
71 ///////////////////////////////////////////////////////////////////
73 // CLASS NAME : StatMode
75 * @short Wrapper class for mode_t values as derived from ::stat
79 friend std::ostream & operator<<( std::ostream & str, const StatMode & obj );
82 /** Ctor taking mode_t value from ::stat. */
83 StatMode( const mode_t & mode_r = 0 )
89 /** \name Query FileType. */
91 FileType fileType() const;
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 ); }
102 /** \name Query user permissions. */
104 bool isRUsr() const { return (_mode & S_IRUSR); }
105 bool isWUsr() const { return (_mode & S_IWUSR); }
106 bool isXUsr() const { return (_mode & S_IXUSR); }
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(); }
116 /** \name Query group permissions. */
118 bool isRGrp() const { return (_mode & S_IRGRP); }
119 bool isWGrp() const { return (_mode & S_IWGRP); }
120 bool isXGrp() const { return (_mode & S_IXGRP); }
123 /** \name Query others permissions. */
125 bool isROth() const { return (_mode & S_IROTH); }
126 bool isWOth() const { return (_mode & S_IWOTH); }
127 bool isXOth() const { return (_mode & S_IXOTH); }
130 /** \name Query special permissions. */
133 bool isUid() const { return (_mode & S_ISUID); }
135 bool isGid() const { return (_mode & S_ISGID); }
137 bool isVtx() const { return (_mode & S_ISVTX); }
140 /** \name Query permission */
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())); }
148 /** \name Extract permission bits only. */
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)); }
156 /** Return the mode_t value. */
157 mode_t st_mode() const { return _mode; }
162 ///////////////////////////////////////////////////////////////////
164 /** \relates StatMode Stream output. */
165 extern std::ostream & operator<<( std::ostream & str, const StatMode & obj );
167 ///////////////////////////////////////////////////////////////////
169 ///////////////////////////////////////////////////////////////////
171 // CLASS NAME : DevInoCache
172 /** Simple cache remembering device/inode to detect hardlinks.
175 * for ( all files ) {
176 * if ( trace.insert( file.device, file.inode ) ) {
177 * // 1st occurance of file
179 * // else: hardlink; already counted this device/inode
191 void clear() { _devino.clear(); }
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).
198 bool insert( const dev_t & dev_r, const ino_t & ino_r ) {
199 return _devino[dev_r].insert( ino_r ).second;
203 std::map<dev_t,std::set<ino_t> > _devino;
205 ///////////////////////////////////////////////////////////////////
207 ///////////////////////////////////////////////////////////////////
209 // CLASS NAME : PathInfo
210 /** Wrapper class for ::stat/::lstat.
212 * \note All attribute quieries test for isExist(), and return \c false or
213 * \c 0, if stat was not successful.
215 * \note For convenience PathInfo is available as zypp::PathInfo too.
219 friend std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
222 /** stat() or lstat() */
223 enum Mode { STAT, LSTAT };
226 /** \name Construct from Pathname.
227 * Default mode is \c STAT.
232 PathInfo( const Pathname & path, Mode initial = STAT );
234 PathInfo( const std::string & path, Mode initial = STAT );
236 PathInfo( const char * path, Mode initial = STAT );
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; }
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; }
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()(); }
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. */
272 /** Return whether valid stat info exists.
273 * That's usg. whether the file exist and you had permission to
276 bool isExist() const { return !error_i; }
278 /** \name Query StatMode attibutes.
279 * Combines \ref zypp::PathInfo::isExist and \ref zypp::filesystem::StatMode query.
282 FileType fileType() const;
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 ); }
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); }
297 bool isR() const { return isRUsr(); }
298 bool isW() const { return isWUsr(); }
299 bool isX() const { return isXUsr(); }
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); }
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); }
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); }
313 bool isPerm ( mode_t m ) const { return isExist() && (m == perm()); }
314 bool hasPerm( mode_t m ) const { return isExist() && (m == (m & perm())); }
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; }
321 mode_t st_mode() const { return isExist() ? statbuf_C.st_mode : 0; }
324 /** Return st_mode() as filesystem::StatMode. */
325 StatMode asStatMode() const { return st_mode(); }
327 nlink_t nlink() const { return isExist() ? statbuf_C.st_nlink : 0; }
329 /** \name Owner and group */
331 uid_t owner() const { return isExist() ? statbuf_C.st_uid : 0; }
332 gid_t group() const { return isExist() ? statbuf_C.st_gid : 0; }
335 /** \name Permission according to current uid/gid. */
337 /** Returns current users permission (<tt>[0-7]</tt>)*/
338 mode_t userMay() const;
340 bool userMayR() const { return( userMay() & 04 ); }
341 bool userMayW() const { return( userMay() & 02 ); }
342 bool userMayX() const { return( userMay() & 01 ); }
344 bool userMayRW() const { return( (userMay() & 06) == 06 ); }
345 bool userMayRX() const { return( (userMay() & 05) == 05 ); }
346 bool userMayWX() const { return( (userMay() & 03) == 03 ); }
348 bool userMayRWX() const { return( userMay() == 07 ); }
351 /** \name Device and inode info. */
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; }
357 unsigned int major() const;
358 unsigned int minor() const;
361 /** \name Size info. */
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; }
368 /** \name Time stamps. */
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; }
377 struct stat statbuf_C;
381 ///////////////////////////////////////////////////////////////////
383 /** \relates PathInfo Stream output. */
384 extern std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
386 ///////////////////////////////////////////////////////////////////
388 ///////////////////////////////////////////////////////////////////
389 /** \name Directory related functions. */
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.
396 * @return 0 on success, errno on failure
398 int mkdir( const Pathname & path, unsigned mode = 0755 );
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.
405 * @return 0 on success, errno on failure
407 int assert_dir( const Pathname & path, unsigned mode = 0755 );
410 * Like '::rmdir'. Delete a directory, which must be empty.
412 * @return 0 on success, errno on failure
414 int rmdir( const Pathname & path );
417 * Like 'rm -r DIR'. Delete a directory, recursively removing its contents.
419 * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
420 * commands return value.
422 int recursive_rmdir( const Pathname & path );
425 * Like 'rm -r DIR/ *'. Delete directory contents, but keep the directory itself.
427 * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
428 * commands return value.
430 int clean_dir( const Pathname & path );
433 * Like 'cp -a srcpath destpath'. Copy directory tree. srcpath/destpath must be
434 * directories. 'basename srcpath' must not exist in destpath.
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.
439 int copy_dir( const Pathname & srcpath, const Pathname & destpath );
442 * Like 'cp -a srcpath/. destpath'. Copy the content of srcpath recursively
443 * into destpath. Both \p srcpath and \p destpath has to exists.
445 * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory,
446 * EEXIST if srcpath and destpath are equal, otherwise the commands
449 int copy_dir_content( const Pathname & srcpath, const Pathname & destpath);
452 * Return content of directory via retlist. If dots is false
453 * entries starting with '.' are not reported. "." and ".."
454 * are never reported.
456 * Returns just the directory entries as string.
458 * @return 0 on success, errno on failure.
460 * \todo provide some readdirIterator.
463 int readdir( std::list<std::string> & retlist,
464 const Pathname & path, bool dots = true );
467 * Return content of directory via retlist. If dots is false
468 * entries starting with '.' are not reported. "." and ".."
469 * are never reported.
471 * Returns the directory entries prefixed with \a path.
473 * @return 0 on success, errno on failure.
475 * \todo provide some readdirIterator.
478 int readdir( std::list<Pathname> & retlist,
479 const Pathname & path, bool dots = true );
481 /** Listentry returned by readdir. */
485 DirEntry( const std::string & name_r = std::string(), FileType type_r = FT_NOT_AVAIL )
491 /** Returned by readdir. */
492 typedef std::list<DirEntry> DirContent;
495 * Return content of directory via retlist. If dots is false
496 * entries starting with '.' are not reported. "." and ".."
497 * are never reported.
499 * The type of individual directory entries is determined accoding to
500 * statmode (i.e. via stat or lstat).
502 * @return 0 on success, errno on failure.
504 int readdir( DirContent & retlist, const Pathname & path,
505 bool dots = true, PathInfo::Mode statmode = PathInfo::STAT );
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.
513 int is_empty_dir(const Pathname & path);
517 ///////////////////////////////////////////////////////////////////
518 /** \name File related functions. */
521 * Like '::unlink'. Delete a file (symbolic link, socket, fifo or device).
523 * @return 0 on success, errno on failure
525 int unlink( const Pathname & path );
528 * Like '::rename'. Renames a file, moving it between directories if required.
530 * @return 0 on success, errno on failure
532 int rename( const Pathname & oldpath, const Pathname & newpath );
535 * Like 'cp file dest'. Copy file to destination file.
537 * @return 0 on success, EINVAL if file is not a file, EISDIR if
538 * destiantion is a directory, otherwise the commands return value.
540 int copy( const Pathname & file, const Pathname & dest );
543 * Like '::symlink'. Creates a symbolic link named newpath which contains
544 * the string oldpath. If newpath exists it will not be overwritten.
546 * @return 0 on success, errno on failure.
548 int symlink( const Pathname & oldpath, const Pathname & newpath );
551 * Like '::link'. Creates a hard link named newpath to an existing file
552 * oldpath. If newpath exists it will not be overwritten.
554 * @return 0 on success, errno on failure.
556 int hardlink( const Pathname & oldpath, const Pathname & newpath );
559 * Like 'cp file dest'. Copy file to dest dir.
561 * @return 0 on success, EINVAL if file is not a file, ENOTDIR if dest
562 * is no directory, otherwise the commands return value.
564 int copy_file2dir( const Pathname & file, const Pathname & dest );
567 ///////////////////////////////////////////////////////////////////
568 /** \name Digest computaion.
569 * \todo check cooperation with zypp::Digest
573 * Compute a files md5sum.
575 * @return the files md5sum on success, otherwise an empty string..
577 std::string md5sum( const Pathname & file );
580 * Compute a files sha1sum.
582 * @return the files sha1sum on success, otherwise an empty string..
584 std::string sha1sum( const Pathname & file );
588 * Compute a files checksum
590 * @return the files checksum on success, otherwise an empty string..
592 std::string checksum( const Pathname & file, const std::string &algorithm );
595 * check files checksum
597 * @return true if the checksum matchs
599 bool is_checksum( const Pathname & file, const CheckSum &checksum );
601 ///////////////////////////////////////////////////////////////////
602 /** \name Changing permissions. */
605 * Like '::chmod'. The mode of the file given by path is changed.
607 * @return 0 on success, errno on failure
609 int chmod( const Pathname & path, mode_t mode );
612 ///////////////////////////////////////////////////////////////////
616 * Test whether a file is compressed (gzip/bzip2).
618 * @return ZT_GZ, ZT_BZ2 if file is compressed, otherwise ZT_NONE.
620 enum ZIP_TYPE { ZT_NONE, ZT_GZ, ZT_BZ2 };
622 ZIP_TYPE zipType( const Pathname & file );
625 * Erase whatever happens to be located at path (file or directory).
627 * @return 0 on success.
629 * \todo check cooperation with zypp::TmpFile and zypp::TmpDir
631 int erase( const Pathname & path );
634 /////////////////////////////////////////////////////////////////
635 } // namespace filesystem
636 ///////////////////////////////////////////////////////////////////
638 /** Dragged into namespace zypp. */
639 using filesystem::PathInfo;
641 /////////////////////////////////////////////////////////////////
643 ///////////////////////////////////////////////////////////////////
644 #endif // ZYPP_PATHINFO_H