• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

apt.h

Go to the documentation of this file.
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

Generated on Fri Oct 14 2011 17:41:02 for libept by  doxygen 1.7.1