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