From: Duncan Mac-Vicar P Date: Thu, 9 Aug 2007 12:24:34 +0000 (+0000) Subject: Squashed commit of the following: X-Git-Tag: BASE-SuSE-Linux-10_3-Branch~335 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=748e59c1f183f2e3f1bd4488b02a83c841884fc1;p=platform%2Fupstream%2Flibzypp.git Squashed commit of the following: commit fb2dba632df53d074600eecb7bd1d19767acda21 Author: Duncan Mac-Vicar P Date: Thu Aug 9 12:39:10 2007 +0200 - check for vendors in candidates - check that the resolvables are not empty before calling vendor() commit 173588f356356c129dab39fb32b8cf802dfaae78 Author: Duncan Mac-Vicar P Date: Wed Aug 8 14:02:06 2007 +0200 - typo - trustedVendors file location commit cc8b757dc0dd8ef1616c5e0404e7894a7802d39c Author: Duncan Mac-Vicar P Date: Wed Aug 8 13:53:59 2007 +0200 Implementation of a saner locking solution: - no automatic inter-vendor upgrades - no automatic untrusted vendor protection - user defined locks from /etc/zypp/locks --- diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt index 7077c73..ef789d9 100644 --- a/zypp/CMakeLists.txt +++ b/zypp/CMakeLists.txt @@ -87,6 +87,7 @@ SET( zypp_SRCS RepoStatus.cc RepoManager.cc MediaProducts.cc + Locks.cc ) SET( zypp_HEADERS @@ -184,6 +185,7 @@ SET( zypp_HEADERS RepoStatus.h RepoManager.h MediaProducts.h + Locks.h ) INSTALL( FILES ${zypp_HEADERS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include/zypp" ) diff --git a/zypp/Locks.cc b/zypp/Locks.cc new file mode 100644 index 0000000..9651319 --- /dev/null +++ b/zypp/Locks.cc @@ -0,0 +1,254 @@ + + + + + + +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "zypp/base/Logger.h" +#include "zypp/base/IOStream.h" +#include "zypp/PoolItem.h" +#include "zypp/CapFactory.h" +#include "zypp/CapMatchHelper.h" +#include "zypp/capability/Capabilities.h" + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "locks" + +#include "zypp/Locks.h" +#include "zypp/PathInfo.h" + +using namespace std; +using namespace zypp; +using namespace boost; +using boost::regex; + +namespace zypp +{ +namespace locks +{ + +// +// collect matching names +// +// called by regexp matching, see 'Match' below +// + +struct NameMatchCollectorFunc +{ + set matches; + + bool operator()( const PoolItem &item ) + { + matches.insert( item.resolvable()->name() ); + return true; + } +}; + + +// taken from zypper +struct Match +{ + const regex * _regex; + + Match(const regex & regex ) : + _regex(®ex) + {} + + bool operator()(const zypp::PoolItem & pi) const + { + return + // match resolvable name + regex_match(pi.resolvable()->name(), *_regex); + } +}; + + +string +wildcards2regex(const string & str) +{ + string regexed; + + regex all("\\*"); // regex to search for '*' + regex one("\\?"); // regex to search for '?' + string r_all(".*"); // regex equivalent of '*' + string r_one("."); // regex equivalent of '?' + + // replace all "*" in input with ".*" + regexed = regex_replace(str, all, r_all); + MIL << "wildcards2regex: " << str << " -> " << regexed; + + // replace all "?" in input with "." + regexed = regex_replace(regexed, one, r_one); + MIL << " -> " << regexed << endl; + + return regexed; +} + + +// +// assign Lock to installed pool item +// + +struct ItemLockerFunc +{ + ItemLockerFunc( const string lock_str ) + : _lock_str(lock_str) + {} + + bool operator()( const CapAndItem &cai_r ) + { + PoolItem_Ref item(cai_r.item); + MIL << "Locking " << cai_r.item << "(matched by " << _lock_str << ")" << endl; + item.status().setLock( true, ResStatus::USER); + return true; + } + + string _lock_str; +}; + +struct AddLockToPool +{ + AddLockToPool( const ResPool &pool ) + : _pool(pool) + , _count(0) + { + + } + + bool operator()( const std::string & str_r ) + { + CapFactory cap_factory; + + std::string line( str::trim( str_r ) ); + + if ( line.empty() || line[0] != '#') + return true; + + // zypp does not provide wildcard or regex support in the Capability matching helpers + // but it still parses the index if it contains wildcards. + // so we decompose the capability, and keep the op and edition, while, the name + // is converted to a regexp and matched against all possible names in the _pool + // Then these names are combined with the original edition and relation and we + // got a new capability for matching wildcard to use with the capability match + // helpers + + Rel rel; + Edition edition; + string name; + + try + { + Capability capability = cap_factory.parse( ResTraits::kind, line ); + + capability::NamedCap::constPtr named = capability::asKind(capability); + if ( named ) + { + rel = named->op(); + edition = named->edition(); + name = named->index(); + } + else + { + ERR << "Not a named capability in: '" << line << "' skipping" << std::endl; + return true; + } + } + catch ( const Exception &e ) + { + ERR << "Can't parse capability in: '" << line << "' (" << e.msg() << ") skipping" << std::endl; + return true; + } + + // Operator NONE is not allowed in Capability + if (rel == Rel::NONE) rel = Rel::ANY; + + NameMatchCollectorFunc nameMatchFunc; + + // regex flags + unsigned int flags = regex::normal; + flags |= regex_constants::icase; + regex reg; + + // create regex object + string regstr( wildcards2regex( name ) ); + MIL << "regstr '" << regstr << "'" << endl; + try + { + reg.assign( regstr, flags ); + } + catch (regex_error & e) + { + ERR << "locks: " << regstr << " is not a valid regular expression: \"" << e.what() << "\"" << endl; + ERR << "This is a bug, please file a bug report against libzypp-zmd-backend" << endl; + // ignore this lock and continue + return true;; + } + + invokeOnEach( _pool.begin(), _pool.end(), Match(reg), functor::functorRef(nameMatchFunc) ); + + MIL << "Found " << nameMatchFunc.matches.size() << " matches." << endl; + + // now we have all the names matching + + // for each name matching try to match a capability + + ItemLockerFunc lockItemFunc( line ); + + for ( set::const_iterator it = nameMatchFunc.matches.begin(); it != nameMatchFunc.matches.end(); ++it ) + { + string matched_name = *it; + + try + { + Capability capability = cap_factory.parse( ResTraits::kind, matched_name, rel, edition ); + MIL << "Locking capability " << capability << endl; + forEachMatchIn( _pool, Dep::PROVIDES, capability, functor::functorRef(lockItemFunc) ); + } + catch ( const Exception &e ) + { + ERR << "Invalid lock: " << e.msg() << std::endl; + } + ++_count; + } + return true; + } // end operator()() + + ResPool _pool; + int _count; +}; + +// +// read 'locks' table, evaluate 'glob' column, assign locks to pool +// +int +readLocks(const ResPool & pool, const Pathname &file ) +{ + PathInfo lockrc( file ); + if ( lockrc.isFile() ) + { + MIL << "Reading " << lockrc << endl; + ifstream inp( file.c_str() ); + AddLockToPool addlock(pool); + iostr::forEachLine( inp, addlock); + MIL << addlock._count << " locks." << endl; + return addlock._count; + } + return 0; +} + +} // ns locks +} // ns zypp diff --git a/zypp/Locks.h b/zypp/Locks.h new file mode 100644 index 0000000..f3789d3 --- /dev/null +++ b/zypp/Locks.h @@ -0,0 +1,17 @@ + +#ifndef ZYPP_LOCKS_H +#define ZYPP_LOCKS_H + +#include "zypp/ResPool.h" +#include "zypp/Pathname.h" + +namespace zypp +{ + namespace locks + { + + int readLocks(const ResPool & pool, const Pathname &file ); + } +} + +#endif \ No newline at end of file diff --git a/zypp/VendorAttr.cc b/zypp/VendorAttr.cc index 8c49a2f..a8d7bc2 100644 --- a/zypp/VendorAttr.cc +++ b/zypp/VendorAttr.cc @@ -29,6 +29,8 @@ #include "zypp/VendorAttr.h" #include "zypp/ZYppFactory.h" +#include "zypp/ZConfig.h" + using namespace std; #undef ZYPP_BASE_LOGGER_LOGGROUP @@ -80,9 +82,6 @@ namespace zypp } return res.first->second; } - - bool applyAutoProtection = true; - ///////////////////////////////////////////////////////////////// } // namespace /////////////////////////////////////////////////////////////////// @@ -107,7 +106,7 @@ namespace zypp }; _trustedVendors.insert( vendors, vendors+(sizeof(vendors)/sizeof(const char *)) ); - Pathname vendorrcPath( getZYpp()->homePath() / "db/trustedVendors" ); + Pathname vendorrcPath( "/etc/zypp/trustedVendors" ); try { Target_Ptr trg( getZYpp()->target() ); @@ -131,14 +130,14 @@ namespace zypp void VendorAttr::enableAutoProtect() { - MIL << "Foreign vendor auto protection enabled." << endl; - applyAutoProtection = true; + MIL << "FIXME: Not implemented." << endl; + // FIXME use ZConfig } void VendorAttr::disableAutoProtect() { - MIL << "Foreign vendor auto protection disabled." << endl; - applyAutoProtection = false; + MIL << "FIXME: Not implemented." << endl; + // FIXME use ZConfig } bool VendorAttr::isKnown( const Vendor & vendor_r ) const @@ -146,7 +145,7 @@ namespace zypp bool VendorAttr::autoProtect( const Vendor & vendor_r ) const - { return( applyAutoProtection && ! trusted( vendor_r ) ); } + { return( ZConfig::instance().autolock_untrustedvendor() && ! trusted( vendor_r ) ); } ///////////////////////////////////////////////////////////////// } // namespace zypp diff --git a/zypp/ZConfig.cc b/zypp/ZConfig.cc index a31666d..f83c88f 100644 --- a/zypp/ZConfig.cc +++ b/zypp/ZConfig.cc @@ -37,6 +37,7 @@ namespace zypp public: Impl() : repo_add_probe(false) + , autolock_untrustedvendor(false) { MIL << "ZConfig singleton created." << endl; Pathname confpath("/etc/zypp/zypp.conf"); @@ -86,6 +87,10 @@ namespace zypp repo_add_probe = (value == "1"); } } + else if ( section == "locking" ) + { + autolock_untrustedvendor = ( value == "1" ); + } } } @@ -106,6 +111,9 @@ namespace zypp bool repo_add_probe; + // [locking] + bool autolock_untrustedvendor; + }; /////////////////////////////////////////////////////////////////// @@ -192,6 +200,11 @@ namespace zypp return _pimpl->repo_add_probe; } + bool ZConfig::autolock_untrustedvendor() const + { + return _pimpl->autolock_untrustedvendor; + } + ///////////////////////////////////////////////////////////////// } // namespace zypp /////////////////////////////////////////////////////////////////// diff --git a/zypp/ZConfig.h b/zypp/ZConfig.h index 79ef4c0..533b7de 100644 --- a/zypp/ZConfig.h +++ b/zypp/ZConfig.h @@ -80,6 +80,13 @@ namespace zypp */ bool repo_add_probe() const; + /** + * Whether untrusted vendor should be autolocked + / config option + * repo.add.probe + */ + bool autolock_untrustedvendor() const; + public: class Impl; /** Dtor */ diff --git a/zypp/solver/detail/Helper.cc b/zypp/solver/detail/Helper.cc index 1705b93..9cfd8f8 100644 --- a/zypp/solver/detail/Helper.cc +++ b/zypp/solver/detail/Helper.cc @@ -124,10 +124,30 @@ class LookForUpdate : public resfilter::PoolItemFilterFunctor bool operator()( PoolItem_Ref provider ) { + MIL << "comparing: " << endl << provider << endl << uninstalled << endl; + + // is valid + if ( ! provider.resolvable() ) + { + MIL << "Warning: '" << provider << "' not valid" << endl; + return true; + } + + if ( uninstalled.resolvable() ) + { + if ( uninstalled->vendor() != provider->vendor() ) + { + MIL << "Discarding '" << provider << "' from vendor '" + << provider->vendor() << "' different to uninstalled '" + << uninstalled->vendor() << "' vendor." << endl; + return true; + } + } + if ((!uninstalled // none yet || (uninstalled->edition().compare( provider->edition() ) < 0) // or a better edition - || (uninstalled->arch().compare( provider->arch() ) < 0) ) // or a better architecture - && !provider.status().isLocked()) // is not locked + || (uninstalled->arch().compare( provider->arch() ) < 0) ) // or a better architecture + && !provider.status().isLocked() ) // is not locked { uninstalled = provider; // store } diff --git a/zypp/solver/detail/QueueItemRequire.cc b/zypp/solver/detail/QueueItemRequire.cc index 9f213b8..724dc6c 100644 --- a/zypp/solver/detail/QueueItemRequire.cc +++ b/zypp/solver/detail/QueueItemRequire.cc @@ -220,6 +220,7 @@ struct RequireProcess && ! _context->isParallelInstall( provider ) && _context->itemIsPossible( provider ) && ! provider.status().isLocked() + && ( (!provider || !upgrades) || (provider->vendor() == upgrades->vendor()) ) && ! (provider.status().isKept() &&provider.status().isByUser()) ) { diff --git a/zypp/solver/detail/ResolverUpgrade.cc b/zypp/solver/detail/ResolverUpgrade.cc index b2f1d26..c68b8c4 100644 --- a/zypp/solver/detail/ResolverUpgrade.cc +++ b/zypp/solver/detail/ResolverUpgrade.cc @@ -357,7 +357,8 @@ Resolver::doUpgrade( UpgradeStatistics & opt_stats_r ) if (cand_it == candidatemap.end() // not in map yet || (cand_it->second->arch().compare( candidate->arch() ) < 0) // or the new has better architecture || ((cand_it->second->arch().compare( candidate->arch() ) == 0) // or the new has the same architecture - && (cand_it->second->edition().compare( candidate->edition() ) < 0) ) ) // and a better edition (-> 157501) + && (cand_it->second->edition().compare( candidate->edition() ) < 0) // and a better edition (-> 157501) + && (cand_it->second->vendor() == candidate->vendor() ) ) )// and same vendor { candidatemap[installed] = candidate; // put it in ! }