SET(LIBZYPP_MAJOR "14")
SET(LIBZYPP_COMPATMINOR "29")
SET(LIBZYPP_MINOR "29")
-SET(LIBZYPP_PATCH "0")
+SET(LIBZYPP_PATCH "1")
#
-# LAST RELEASED: 14.29.0 (29)
+# LAST RELEASED: 14.29.1 (29)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
BuildRequires: pkg-config
%endif
-BuildRequires: libsolv-devel >= 0.4.2
+BuildRequires: libsolv-devel >= 0.6.5
%if 0%{?suse_version} >= 1100
%requires_eq libsolv-tools
%else
-------------------------------------------------------------------
+Wed Sep 17 13:18:23 CEST 2014 - ma@suse.de
+
+- adjust BuildRequires
+- version 14.29.1 (29)
+
+-------------------------------------------------------------------
Tue Sep 16 10:45:39 CEST 2014 - ma@suse.de
+- DiskUsageCounter: Set growonly on detetcted snapshotting btrfs
+ partitions (bnc#896176)
+- DiskUsageCounter: Allow MountPoint to store fstype
- DiskUsageCounter: Support setting 'growonly' partition hint
(bnc#896176)
- version 14.29.0 (29)
#include "zypp/base/String.h"
#include "zypp/DiskUsageCounter.h"
+#include "zypp/ExternalProgram.h"
#include "zypp/sat/Pool.h"
#include "zypp/sat/detail/PoolImpl.h"
if ( !(procmounts.fail() || procmounts.bad()) ) {
// data to consume
- // rootfs / rootfs rw 0 0
+ // rootfs / rootfs rw 0 0
// /dev/root / reiserfs rw 0 0
- // proc /proc proc rw 0 0
- // devpts /dev/pts devpts rw 0 0
+ // proc /proc proc rw 0 0
+ // devpts /dev/pts devpts rw 0 0
// /dev/hda5 /boot ext2 rw 0 0
- // shmfs /dev/shm shm rw 0 0
+ // shmfs /dev/shm shm rw 0 0
// usbdevfs /proc/bus/usb usbdevfs rw 0 0
std::vector<std::string> words;
// Check whether mounted readonly
//
MountPoint::HintFlags hints;
+
std::vector<std::string> flags;
str::split( words[3], std::back_inserter(flags), "," );
}
//
+ // check for snapshotting btrfs
+ //
+ if ( words[2] == "btrfs" )
+ {
+ if ( geteuid() != 0 )
+ {
+ DBG << "Assume snapshots on " << words[1] << ": non-root user can't check" << std::endl;
+ hints |= MountPoint::Hint_growonly;
+ }
+ else
+ {
+ // For now just check whether there is
+ // at least one snapshot on the volume:
+ ExternalProgram prog({"btrfs","subvolume","list","-s",words[1]});
+ std::string line( prog.receiveLine() );
+ if ( ! line.empty() )
+ {
+ DBG << "Found a snapshot on " << words[1] << ": " << line; // has trailing std::endl
+ hints |= MountPoint::Hint_growonly;
+ }
+ prog.kill();
+ }
+ }
+
+ //
// statvfs (full path!) and get the data
//
struct statvfs sb;
if ( statvfs( words[1].c_str(), &sb ) != 0 ) {
WAR << "Unable to statvfs(" << words[1] << "); errno " << errno << std::endl;
- ret.insert( DiskUsageCounter::MountPoint( mp ) );
+ ret.insert( DiskUsageCounter::MountPoint( mp, words[2], 0LL, 0LL, 0LL, 0LL, hints ) );
}
else
{
DBG << "Filter zero-sized mount point : " << l << std::endl;
continue;
}
- ret.insert( DiskUsageCounter::MountPoint( mp, sb.f_bsize,
+ ret.insert( DiskUsageCounter::MountPoint( mp, words[2], sb.f_bsize,
((long long)sb.f_blocks)*sb.f_bsize/1024,
((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, hints ) );
}
<< " ts: " << obj.totalSize()
<< " us: " << obj.usedSize()
<< " (+-: " << obj.commitDiff()
- << ")" << (obj.readonly?"r":"") << (obj.growonly?"g":"") << " ]";
+ << ")" << (obj.readonly?"r":"") << (obj.growonly?"g":"") << " " << obj.fstype << "]";
return str;
}
{
friend std::ostream & operator<<( std::ostream & str, const MountPoint & obj );
std::string dir; ///< Directory name
+ std::string fstype; ///< Filesystem type (provided by \ref detectMountPoints)
long long block_size; ///< Block size of the filesystem in B (0 if you don't care)
long long total_size; ///< Total size of the filesystem in KiB (0 if you don't care)
long long used_size; ///< Used size of the filesystem in KiB (0 if you don't care)
};
ZYPP_DECLARE_FLAGS(HintFlags,Hint);
-
- /** Ctor initialize directory and sizes */
+ /** Ctor initialize directory, fstype and sizes */
MountPoint( const std::string & d = "/",
+ const std::string & f = std::string(),
long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
HintFlags hints = NoHint )
- : dir(d)
+ : dir(d), fstype(f)
, block_size(bs), total_size(total), used_size(used), pkg_size(pkg)
, readonly(hints.testFlag(Hint_readonly))
, growonly(hints.testFlag(Hint_growonly))
* MountPointSet( { "/", "/usr", "/var" } )
* \endcode
*/
- MountPoint( const char * d, long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, HintFlags hints = NoHint )
+ MountPoint( const char * d,
+ const std::string & f = std::string(),
+ long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : MountPoint( std::string(d?d:""), f, bs, total, used, pkg, hints )
+ {}
+
+
+ /** Ctor initialize directory and sizes */
+ MountPoint( const std::string & d,
+ long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : MountPoint( d, std::string(), bs, total, used, pkg, hints )
+ {}
+ /** \overload <tt>const char *</tt> */
+ MountPoint( const char * d,
+ long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
: MountPoint( std::string(d?d:""), bs, total, used, pkg, hints )
{}
- /** \overload just name and hints, all sizes 0 */
+
+ /** Ctor just name and hints, all sizes 0 */
MountPoint( const std::string & d, HintFlags hints )
- : MountPoint( d, 0LL, 0LL, 0LL, 0LL, hints )
+ : MountPoint( d, std::string(), 0LL, 0LL, 0LL, 0LL, hints )
{}
- /** \overload just name and hints, all sizes 0 */
+ /** \overload <tt>const char *</tt> */
MountPoint( const char * d, HintFlags hints )
: MountPoint( std::string(d?d:""), hints )
{}
- /** \overload just name and hints, all sizes 0 */
- MountPoint( const std::string & d, Hint hint ) // !explicitly overload to prevent propagation enum value -> long long
+ /** \overload to prevent propagation Hint -> long long */
+ MountPoint( const std::string & d, Hint hint )
: MountPoint( d, HintFlags(hint) )
{}
- /** \overload just name and hints, all sizes 0 */
- MountPoint( const char * d, Hint hint ) // !explicitly overload to prevent propagation enum value -> long long
+ /** \overload to prevent propagation Hint -> long long */
+ MountPoint( const char * d, Hint hint )
: MountPoint( std::string(d?d:""), HintFlags(hint) )
{}
const MountPointSet & getMountPoints() const
{ return _mps; }
-
- /** Get mountpoints of system below \a rootdir */
+ /** Get mountpoints of system below \a rootdir
+ * If we happen to detect snapshotting btrfs partitions, the MountPoint::growonly
+ * hint is set. Disk usage computation will assume that deleted packages will not
+ * free any space (kept in a snapshot).
+ */
static MountPointSet detectMountPoints( const std::string & rootdir = "/" );
/** Only one entry for "/" to collect total sizes */
/////////////////////////////////////////////////////////////////////////
namespace zypp
{ ///////////////////////////////////////////////////////////////////////
+
+ /////////////////////////////////////////////////////////////////////////
+ namespace env
+ {
+ inline bool HACKENV( const char * var_r, bool default_r )
+ {
+ bool ret = default_r;
+ const char * val = ::getenv( var_r );
+ if ( val )
+ {
+ ret = str::strToBool( val, default_r );
+ if ( ret != default_r )
+ INT << "HACKENV " << var_r << " = " << ret << endl;
+ }
+ return ret;
+ }
+ } // namespace env
+ /////////////////////////////////////////////////////////////////////////
+
///////////////////////////////////////////////////////////////////////
namespace solver
{ /////////////////////////////////////////////////////////////////////
{
os << "<resolver>" << endl;
if (_solv) {
- // os << " fixsystem = " << _solv->fixsystem << endl;
- // os << " updatesystem = " << _solv->updatesystem << endl;
- os << " allowdowngrade = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE) << endl;
- os << " allowarchchange = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE) << endl;
- os << " allowvendorchange = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE) << endl;
- os << " allowuninstall = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL) << endl;
- os << " noupdateprovide = " << solver_get_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE) << endl;
- os << " dosplitprovides = " << solver_get_flag(_solv, SOLVER_FLAG_SPLITPROVIDES) << endl;
- os << " onlyRequires = " << solver_get_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED) << endl;
- os << " ignorealreadyrecommended = " << !solver_get_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED) << endl;
- os << " distupgrade = " << _distupgrade << endl;
- os << " distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl;
- os << " solveSrcPackages = " << _solveSrcPackages << endl;
- os << " cleandepsOnRemove = " << _cleandepsOnRemove << endl;
+#define OUTS(X) os << " " << #X << "\t= " << solver_get_flag(_solv, SOLVER_FLAG_##X) << endl
+ OUTS( ALLOW_DOWNGRADE );
+ OUTS( ALLOW_ARCHCHANGE );
+ OUTS( ALLOW_VENDORCHANGE );
+ OUTS( ALLOW_UNINSTALL );
+ OUTS( NO_UPDATEPROVIDE );
+ OUTS( SPLITPROVIDES );
+ OUTS( IGNORE_RECOMMENDED );
+ OUTS( ADD_ALREADY_RECOMMENDED );
+ OUTS( NO_INFARCHCHECK );
+ OUTS( ALLOW_NAMECHANGE );
+ OUTS( KEEP_EXPLICIT_OBSOLETES );
+ OUTS( BEST_OBEY_POLICY );
+ OUTS( NO_AUTOTARGET );
+ OUTS( DUP_ALLOW_DOWNGRADE );
+ OUTS( DUP_ALLOW_ARCHCHANGE );
+ OUTS( DUP_ALLOW_VENDORCHANGE );
+ OUTS( DUP_ALLOW_NAMECHANGE );
+ OUTS( KEEP_ORPHANS );
+ OUTS( BREAK_ORPHANS );
+ OUTS( FOCUS_INSTALLED );
+ OUTS( YUM_OBSOLETES );
+#undef OUTS
+ os << " distupgrade = " << _distupgrade << endl;
+ os << " distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl;
+ os << " solveSrcPackages = " << _solveSrcPackages << endl;
+ os << " cleandepsOnRemove = " << _cleandepsOnRemove << endl;
} else {
os << "<NULL>";
}
solver_set_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide);
solver_set_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires);
+#define HACKENV(X,D) solver_set_flag(_solv, X, env::HACKENV( #X, D ) );
+ HACKENV( SOLVER_FLAG_DUP_ALLOW_DOWNGRADE, true );
+ HACKENV( SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE, true );
+ HACKENV( SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE,true );
+ HACKENV( SOLVER_FLAG_DUP_ALLOW_NAMECHANGE, true );
+#undef HACKENV
+
sat::Pool::instance().prepareForSolving();
// Solve !