Go to the documentation of this file.00001
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
00079 bool isValid() const { return m_state & Valid; }
00080
00081 bool isInstalled() const { return installed(); }
00082
00083 bool install() const { return m_state & Install; }
00084
00085 bool reinstall() const { return m_state & ReInstall; }
00086 bool remove() const { return m_state & Remove; }
00087
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
00092 bool upgrade() const { return hasNewVersion() && install(); }
00093
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
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