libept
0.5.25
|
00001 // -*- C++ -*- 00002 00003 #include <string> 00004 #include <wibble/test.h> 00005 00006 #include <ept/token.h> 00007 #include <ept/core/source.h> 00008 00009 #include <iostream> 00010 #include <wibble/exception.h> 00011 00012 #include <apt-pkg/pkgcache.h> 00013 #include <apt-pkg/sourcelist.h> 00014 #include <apt-pkg/error.h> 00015 #include <apt-pkg/policy.h> 00016 #include <apt-pkg/cachefile.h> 00017 #include <apt-pkg/progress.h> 00018 #include <apt-pkg/pkgcachegen.h> 00019 #include <apt-pkg/init.h> 00020 00021 #ifndef EPT_APT_H 00022 #define EPT_APT_H 00023 00024 namespace ept { 00025 namespace core { 00026 00027 struct AptException : wibble::exception::Generic { 00028 std::string desc() const throw () { 00029 return "APT Error"; 00030 } 00031 00032 AptException( const std::string &ctx ) : Generic( ctx ) { 00033 while ( !_error->empty() ) { 00034 std::string err; 00035 _error->PopMessage( err ); 00036 std::cerr << err << std::endl; 00037 addContext( err ); 00038 } 00039 } 00040 }; 00041 00042 struct PackageState { 00043 enum Query { 00044 Install = 1 << 0, 00045 Upgrade = 1 << 1, 00046 Keep = 1 << 2, 00047 Remove = 1 << 3, 00048 Installed = 1 << 4, 00049 Upgradable = 1 << 5, 00050 NowBroken = 1 << 6, 00051 WillBreak = 1 << 7, 00052 ReInstall = 1 << 8, 00053 Purge = 1 << 9, 00054 Hold = 1 << 10, 00055 Valid = 1 << 11 00056 }; 00057 00058 typedef unsigned state; 00059 00060 operator unsigned() { return m_state; }; 00061 00062 PackageState &operator=( unsigned i ) { 00063 m_state = i; 00064 return *this; 00065 } 00066 00067 PackageState &operator|=( const PackageState &s ) { 00068 m_state |= s.m_state; 00069 return *this; 00070 } 00071 00072 PackageState( unsigned a ) { 00073 m_state = a; 00074 } 00075 00076 PackageState() : m_state( 0 ) {} 00077 00078 // FIXME this probably needs to be used consistently in core and out of core 00079 bool isValid() const { return m_state & Valid; } 00080 // FIXME compatibility API for non-core apt 00081 bool isInstalled() const { return installed(); } 00082 00083 bool install() const { return m_state & Install; } 00084 // reinstall() implies install() 00085 bool reinstall() const { return m_state & ReInstall; } 00086 bool remove() const { return m_state & Remove; } 00087 // purge() implies remove() 00088 bool purge() const { return m_state & Purge; } 00089 bool keep() const { return m_state & Keep; } 00090 bool willBreak() const { return m_state & WillBreak; } 00091 // upgrade() implies install() 00092 bool upgrade() const { return hasNewVersion() && install(); } 00093 // newInsstal() implies install() 00094 bool newInstall() const { return !installed() && install(); } 00095 bool hold() const { return m_state & Hold; } 00096 00097 bool installed() const { return m_state & Installed; } 00098 bool hasNewVersion() const { return m_state & Upgradable; } 00099 bool upgradable() const { return hasNewVersion() && !hold(); } 00100 bool held() const { return hasNewVersion() && hold(); } 00101 bool nowBroken() const { return m_state & NowBroken; } 00102 00103 bool modify() const { return install() || remove(); } 00104 00105 protected: 00106 unsigned m_state; 00107 }; 00108 00109 time_t aptTimestamp(); 00110 00111 // wrap the apt's database 00112 struct AptDatabase { 00113 pkgCache &cache() { 00114 if ( !m_cache ) 00115 openCache(); 00116 return *m_cache; 00117 } 00118 00119 pkgDepCache &state() { 00120 if ( !m_state ) 00121 openState(); 00122 return *m_state; 00123 } 00124 00125 pkgPolicy &policy() { 00126 if ( !m_policy ) 00127 openCache(); 00128 return *m_policy; 00129 } 00130 00131 OpProgress *m_progress; 00132 bool m_tryWriteable; 00133 bool m_writeable; 00134 00135 time_t timestamp() { 00136 return aptTimestamp(); 00137 } 00138 00139 AptDatabase() { 00140 m_cache = 0; 00141 m_state = 0; 00142 m_policy = 0; 00143 m_progress = new OpProgress(); 00144 m_tryWriteable = true; 00145 m_writeable = false; 00146 } 00147 00148 void setProgress( OpProgress *p ) { 00149 m_progress = p; 00150 } 00151 00152 bool writeable() { 00153 if ( !m_cache ) 00154 openCache(); 00155 return m_writeable; 00156 } 00157 00158 void openState() { 00159 m_state = new pkgDepCache( &cache(), m_policy ); 00160 m_state->Init( m_progress ); 00161 m_progress->Done(); 00162 } 00163 00164 void openCache() { 00165 if ( !_config->FindB("Initialized") ) { 00166 pkgInitConfig(*_config); 00167 _config->Set("Initialized", 1); 00168 pkgInitSystem(*_config, _system); 00169 } 00170 00171 m_writeable = m_tryWriteable; 00172 00173 if ( m_tryWriteable ) { 00174 try { 00175 _system->Lock(); 00176 } catch ( std::exception e ) { 00177 m_tryWriteable = false; 00178 openCache(); 00179 m_tryWriteable = true; 00180 throw; 00181 } 00182 } 00183 00184 pkgSourceList list; 00185 if ( list.ReadMainList() == false ) { 00186 _error->DumpErrors(); 00187 throw wibble::exception::System( 00188 "The list of sources could not be read." ); 00189 } 00190 00191 MMap *m = 0; 00192 bool Res = pkgMakeStatusCache( list, *m_progress, &m, !m_writeable ); 00193 00194 if ( !Res ) { 00195 std::cerr << "The package lists or status file " 00196 "could not be parsed or opened." << std::endl; 00197 throw AptException( 00198 "The package lists or status file " 00199 "could not be parsed or opened." ); 00200 } 00201 00202 m_cache = new pkgCache( m, true ); 00203 m_policy = new pkgPolicy( m_cache ); 00204 if ( ReadPinFile( *m_policy ) == false ) 00205 throw wibble::exception::System( "error reading pin file" ); 00206 m_progress->Done(); 00207 } 00208 00209 void invalidate() { 00210 if ( _config->FindB("Initialized") ) { 00211 _system->UnLock(); 00212 } 00213 00214 delete m_state; 00215 m_state = 0; 00216 delete m_policy; 00217 m_policy = 0; 00218 delete m_cache; 00219 m_cache = 0; 00220 } 00221 00222 pkgCache::VerIterator anyVersion( pkgCache::PkgIterator pi ) { 00223 if ( pi.end() ) return pkgCache::VerIterator(); 00224 return pi.VersionList(); 00225 } 00226 00227 Token candidateVersion( Token p ) { 00228 pkgCache::PkgIterator pi = cache().FindPkg( p.package() ); 00229 if ( pi.end() ) return Token(); 00230 pkgCache::VerIterator vi = policy().GetCandidateVer( pi ); 00231 if ( vi.end() ) return Token(); 00232 00233 Token t; t._id = p.package() + "_" + vi.VerStr(); 00234 return t; 00235 } 00236 00237 pkgCache::VerIterator candidateVersion( pkgCache::PkgIterator pi ) { 00238 if ( pi.end() ) return pkgCache::VerIterator(); 00239 pkgCache::VerIterator vi = policy().GetCandidateVer( pi ); 00240 if ( vi.end() ) return pkgCache::VerIterator(); 00241 return vi; 00242 } 00243 00244 pkgCache::VerIterator installedVersion( pkgCache::PkgIterator pi ) { 00245 if ( pi.end() ) return pkgCache::VerIterator(); 00246 pkgCache::VerIterator vi = pkgCache::VerIterator( cache(), 00247 cache().VerP + pi->CurrentVer ); 00248 if ( vi.end() ) return pkgCache::VerIterator(); 00249 return vi; 00250 } 00251 00252 pkgCache::PkgIterator lookupPackage( Token t ) { 00253 return cache().FindPkg( t.package() ); 00254 } 00255 00256 pkgCache::VerIterator lookupVersion( Token t ) { 00257 if ( !t.hasVersion() ) 00258 t = candidateVersion( t ); 00259 pkgCache::PkgIterator pi = lookupPackage( t ); 00260 if ( pi.end() ) 00261 return pkgCache::VerIterator(); 00262 for (pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); ++vi) 00263 if ( t.version() == vi.VerStr() ) 00264 return vi; 00265 return pkgCache::VerIterator(); 00266 } 00267 00268 static pkgCache::VerFileIterator lookupVersionFile( 00269 pkgCache::VerIterator vi ) 00270 { 00271 if ( vi.end() ) 00272 return pkgCache::VerFileIterator(); 00273 pkgCache::VerFileIterator vfi = vi.FileList(); 00274 for ( ; !vfi.end(); vfi++ ) 00275 if ( ( vfi.File()->Flags & pkgCache::Flag::NotSource ) == 0) 00276 break; 00277 if ( vfi.end() ) 00278 vfi = vi.FileList(); 00279 return vfi; 00280 } 00281 00282 PackageState invalidState() { 00283 return PackageState( PackageState::NowBroken | PackageState::Keep ); 00284 } 00285 00286 PackageState packageState( pkgCache::PkgIterator P ) 00287 { 00288 PackageState s = 0; 00289 if ( P.end() ) 00290 return invalidState(); 00291 if ( ! ( P->CurrentState == pkgCache::State::ConfigFiles 00292 || P->CurrentState == pkgCache::State::NotInstalled ) ) 00293 s |= PackageState::Installed; 00294 if ( s & PackageState::Installed && 00295 candidateVersion( P ) != installedVersion( P ) ) 00296 s |= PackageState::Upgradable; 00297 pkgDepCache::StateCache S = state()[ P ]; 00298 if ( S.Install() ) 00299 s |= PackageState::Install; 00300 if ( ( S.iFlags & pkgDepCache::ReInstall ) 00301 == pkgDepCache::ReInstall ) 00302 s |= PackageState::ReInstall; 00303 if ( S.Keep() ) 00304 s |= PackageState::Keep; 00305 if ( S.Delete() ) 00306 s |= PackageState::Remove; 00307 if ( ( S.iFlags & pkgDepCache::Purge ) == pkgDepCache::Purge ) 00308 s |= PackageState::Purge; 00309 if ( S.NowBroken() ) 00310 s |= PackageState::NowBroken; 00311 if ( S.InstBroken() ) 00312 s |= PackageState::WillBreak; 00313 if ( P->SelectedState == pkgCache::State::Hold ) 00314 s |= PackageState::Hold; 00315 return s; 00316 } 00317 00318 PackageState packageState( Token t ) { 00319 t = validate( t ); 00320 if ( t.valid() ) 00321 return packageState( lookupPackage( t ) ); 00322 return invalidState(); 00323 } 00324 00325 Token validate( Token t ) { 00326 if ( t.hasVersion() ) 00327 return lookupVersion( t ).end() ? Token() : t; 00328 return lookupPackage( t ).end() ? Token() : t; 00329 } 00330 00331 ~AptDatabase() { 00332 invalidate(); 00333 } 00334 00335 protected: 00336 pkgCache *m_cache; 00337 pkgDepCache *m_state; 00338 pkgPolicy *m_policy; 00339 }; 00340 00341 template< typename Internal > 00342 struct AptInternalList { 00343 Internal m_head; 00344 typedef Internal Type; 00345 AptInternalList tail() const { 00346 AptInternalList t = *this; 00347 t.m_head++; 00348 return t; 00349 } 00350 const Internal &head() const { return m_head; } 00351 Internal &head() { return m_head; } 00352 bool empty() const { return m_head.end(); } 00353 AptInternalList( Internal head ) : m_head( head ) {} 00354 AptInternalList() {} 00355 }; 00356 00357 namespace version { 00358 00359 typedef enum { Package, VersionString, Section, Architecture, 00360 Depends, Recommends, Record } PropertyId; 00361 00362 typedef pkgCache::VerIterator Internal; 00363 template< PropertyId > struct PropertyType {}; 00364 00365 } 00366 00367 namespace package { 00368 00369 typedef enum { Name, Versions, AnyVersion, State, CandidateVersion, 00370 InstalledVersion } PropertyId; 00371 typedef pkgCache::PkgIterator Internal; 00372 template< PropertyId > struct PropertyType {}; 00373 00374 struct VersionList { 00375 version::Internal m_head; 00376 VersionList tail() const; 00377 const version::Internal &head() const { return m_head; } 00378 version::Internal &head() { return m_head; } 00379 }; 00380 00381 typedef AptInternalList< Internal > InternalList; 00382 00383 } 00384 00385 namespace record { 00386 00387 typedef enum { Record, Name, Priority, Section, InstalledSize, Maintainer, 00388 Architecture, SourcePackage, Version, Description, 00389 ShortDescription, LongDescription, PackageSize } PropertyId; 00390 00391 extern const char *fields[]; 00392 00393 typedef pkgCache::VerFileIterator Internal; 00394 00395 template< PropertyId > struct PropertyType { 00396 typedef std::string T; 00397 }; 00398 00399 } 00400 } 00401 } 00402 00403 #include <ept/core/apt/package.h> 00404 #include <ept/core/apt/version.h> 00405 #include <ept/core/apt/record.h> 00406 00407 #endif