00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Regex.h"
00016 #include "zypp/base/Exception.h"
00017 #include "zypp/capability/CapabilityImpl.h"
00018 #include "zypp/capability/Capabilities.h"
00019
00020 using namespace std;
00021
00023 namespace zypp
00024 {
00025
00026 namespace capability
00027 {
00028 IMPL_PTR_TYPE(CapabilityImpl)
00029
00030
00031
00032
00033
00034
00035 CapabilityImpl::CapabilityImpl( const Resolvable::Kind & refers_r )
00036 : _refers( refers_r )
00037 {}
00038
00040
00041
00042
00043
00044 bool CapabilityImpl::capImplOrderLess( const constPtr & rhs ) const
00045 {
00046 return encode() < rhs->encode();
00047 }
00048
00050
00051
00052
00053
00054 std::ostream & CapabilityImpl::dumpOn( std::ostream & str ) const
00055 {
00056 return str << '[' << refers() << "] "
00057 << '(' << kind() << ") "
00058 << asString();
00059 }
00060
00062 static void assertResKind( const Resolvable::Kind & refers_r )
00063 {
00064 if ( refers_r == Resolvable::Kind() )
00065 ZYPP_THROW( Exception("Missing or empty Resolvable::Kind in Capability") );
00066 }
00067
00068 bool isEditionSpec( Rel op_r, const Edition & edition_r )
00069 {
00070 switch ( op_r.inSwitch() )
00071 {
00072 case Rel::ANY_e:
00073 if ( edition_r != Edition::noedition )
00074 WAR << "Operator " << op_r << " causes Edition "
00075 << edition_r << " to be ignored." << endl;
00076 return false;
00077 break;
00078
00079 case Rel::NONE_e:
00080 ZYPP_THROW( Exception("Operator NONE is not allowed in Capability") );
00081 break;
00082
00083 case Rel::EQ_e:
00084 case Rel::NE_e:
00085 case Rel::LT_e:
00086 case Rel::LE_e:
00087 case Rel::GT_e:
00088 case Rel::GE_e:
00089 return true;
00090 break;
00091 }
00092
00093 ZYPP_THROW( Exception("Unknown Operator NONE is not allowed in Capability") );
00094 return false;
00095 }
00096
00097 bool isFileSpec( const std::string & name_r )
00098 {
00099 return *name_r.c_str() == '/';
00100 }
00101
00102 bool isInterestingFileSpec( const std::string & name_r )
00103 {
00104 static str::smatch what;
00105 static const str::regex filenameRegex(
00106 "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
00107 str::regex::optimize|str::regex::nosubs );
00108
00109 return str::regex_match( name_r, what, filenameRegex );
00110 }
00111
00112 bool isSplitSpec( const std::string & name_r )
00113 {
00114 return name_r.find( ":/" ) != std::string::npos;
00115 }
00116
00117 bool isHalSpec( const std::string & name_r )
00118 {
00119 return name_r.substr(0,4) == "hal(";
00120 }
00121
00122 bool isModaliasSpec( const std::string & name_r )
00123 {
00124 return name_r.substr(0,9) == "modalias(";
00125 }
00126
00127 bool isFilesystemSpec( const std::string & name_r )
00128 {
00129 return name_r.substr(0,11) == "filesystem(";
00130 }
00131
00132 CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r,
00133 const std::string & name_r )
00134 {
00135
00136 if ( name_r.empty() )
00137 {
00138
00139 return capability::NullCap::instance();
00140 }
00141
00142 assertResKind( refers_r );
00143
00144 return new capability::FileCap( refers_r, name_r );
00145 }
00146
00147 CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
00148 const std::string & name_r )
00149 {
00150
00151 if ( name_r.empty() )
00152 {
00153
00154 return capability::NullCap::instance();
00155 }
00156
00157 assertResKind( refers_r );
00158
00159
00160 if ( isFileSpec( name_r ) )
00161 {
00162 return new capability::FileCap( refers_r, name_r );
00163 }
00164 if ( isFilesystemSpec( name_r ) )
00165 {
00166 return buildFilesystem( refers_r, name_r );
00167 }
00168
00169
00170 static const str::regex rx( "([^/]*):(/.*)" );
00171 str::smatch what;
00172 if( str::regex_match( name_r, what, rx ) )
00173 {
00174 return new capability::SplitCap( refers_r, what[1], what[2] );
00175 }
00176
00177
00178 return new capability::NamedCap( refers_r, name_r );
00179 }
00180
00181 CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
00182 const std::string & name_r,
00183 Rel op_r,
00184 const Edition & edition_r )
00185 {
00186 if ( isEditionSpec( op_r, edition_r ) )
00187 {
00188 assertResKind( refers_r );
00189
00190
00191 return new capability::VersionedCap( refers_r, name_r, op_r, edition_r );
00192 }
00193
00194
00195
00196 return buildNamed( refers_r, name_r );
00197 }
00198
00199 CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r,
00200 const std::string & name_r,
00201 Rel op_r,
00202 const std::string & value_r )
00203 {
00204 if ( op_r != Rel::ANY )
00205 {
00206 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + op_r.asString() + "'") );
00207 }
00208
00209
00210 static const str::regex rx( "hal\\(([^)]*)\\)" );
00211 str::smatch what;
00212 if( str::regex_match( name_r, what, rx ) )
00213 {
00214
00215 return new capability::HalCap( ResTraits<SystemResObject>::kind,
00216 what[1] );
00217 }
00218
00219 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + name_r + "'") );
00220 return NULL;
00221 }
00222
00223 CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r,
00224 const std::string & name_r,
00225 Rel op_r,
00226 const std::string & value_r )
00227 {
00228 if ( op_r != Rel::ANY )
00229 {
00230 ZYPP_THROW( Exception("Unsupported kind of Modalias Capability '" + op_r.asString() + "'") );
00231 }
00232
00233
00234 static const str::regex rx( "modalias\\(([^)]*)\\)" );
00235 str::smatch what;
00236 if( str::regex_match( name_r, what, rx ) )
00237 {
00238
00239 return new capability::ModaliasCap( ResTraits<SystemResObject>::kind,
00240 what[1] );
00241 }
00242
00243 ZYPP_THROW( Exception("Unsupported kind of Modalias Capability'" + name_r + "'") );
00244 return NULL;
00245 }
00246
00247
00248
00249
00250
00251
00252 CapabilityImpl::Ptr buildFilesystem( const Resolvable::Kind & refers_r,
00253 const std::string & name_r )
00254 {
00255
00256 static const str::regex rx( "filesystem\\(([^)]*)\\)" );
00257 str::smatch what;
00258 if( str::regex_match( name_r, what, rx ) )
00259 {
00260
00261 return new capability::FilesystemCap( ResTraits<SystemResObject>::kind,
00262 what[1] );
00263 }
00264
00265 ZYPP_THROW( Exception("Unsupported kind of Filesystem Capability'" + name_r + "'") );
00266 return NULL;
00267 }
00268
00269
00270 CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00271 const std::string & strval_r )
00272 try
00273 {
00274 if ( isHalSpec( strval_r ) )
00275 {
00276 return buildHal( refers_r, strval_r );
00277 }
00278 if ( isModaliasSpec( strval_r ) )
00279 {
00280 return buildModalias( refers_r, strval_r );
00281 }
00282 if ( isFilesystemSpec( strval_r ) )
00283 {
00284 return buildFilesystem( refers_r, strval_r );
00285 }
00286 if ( isFileSpec( strval_r ) )
00287 {
00288 return buildFile( refers_r, strval_r );
00289 }
00290
00291
00292
00293 static const str::regex rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
00294 str::smatch what;
00295 if( str::regex_match( strval_r,what, rx ) )
00296 {
00297 Rel op;
00298 Edition edition;
00299 try
00300 {
00301 op = Rel(what[3]);
00302 edition = Edition(what[5]);
00303 }
00304 catch ( Exception & excpt )
00305 {
00306
00307 ZYPP_CAUGHT( excpt );
00308 DBG << "Trying named cap for: " << strval_r << endl;
00309
00310 return buildNamed( refers_r, strval_r );
00311 }
00312
00313
00314 return buildVersioned( refers_r,
00315 what[1], op, edition );
00316 }
00317
00318
00319 return buildNamed( refers_r, strval_r );
00320 }
00321 catch ( Exception & excpt )
00322 {
00323 ZYPP_RETHROW( excpt );
00324 return NULL;
00325 }
00326
00327
00328 CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00329 const std::string & name_r,
00330 const std::string & op_r,
00331 const std::string & edition_r )
00332 try
00333 {
00334 if ( isHalSpec( name_r ) )
00335 {
00336 return buildHal( refers_r, name_r, Rel(op_r), edition_r );
00337 }
00338 if ( isModaliasSpec( name_r ) )
00339 {
00340 return buildModalias( refers_r, name_r, Rel(op_r), edition_r );
00341 }
00342
00343 return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
00344 }
00345 catch ( Exception & excpt )
00346 {
00347 ZYPP_RETHROW( excpt );
00348 return NULL;
00349 }
00350
00352
00353
00354
00355
00356 CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00357 const std::string & name_r,
00358 Rel op_r,
00359 const Edition & edition_r )
00360 try
00361 {
00362 if ( isHalSpec( name_r ) )
00363 {
00364 return buildHal( refers_r, name_r, op_r, edition_r.asString() );
00365 }
00366 if ( isModaliasSpec( name_r ) )
00367 {
00368 return buildModalias( refers_r, name_r, op_r, edition_r.asString() );
00369 }
00370 return buildVersioned( refers_r, name_r, op_r, edition_r );
00371 }
00372 catch ( Exception & excpt )
00373 {
00374 ZYPP_RETHROW( excpt );
00375 return NULL;
00376 }
00377
00379
00381 }
00384 }