libept
core/apt.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 #include <string>
4 #include <wibble/test.h>
5 
6 #include <ept/token.h>
7 #include <ept/core/source.h>
8 
9 #include <iostream>
10 #include <wibble/exception.h>
11 
12 #include <apt-pkg/pkgcache.h>
13 #include <apt-pkg/sourcelist.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/policy.h>
16 #include <apt-pkg/cachefile.h>
17 #include <apt-pkg/progress.h>
18 #include <apt-pkg/pkgcachegen.h>
19 #include <apt-pkg/init.h>
20 
21 #ifndef EPT_APT_H
22 #define EPT_APT_H
23 
24 namespace ept {
25 namespace core {
26 
27 struct AptException : wibble::exception::Generic {
28  std::string desc() const throw () {
29  return "APT Error";
30  }
31 
32  AptException( const std::string &ctx ) : Generic( ctx ) {
33  while ( !_error->empty() ) {
34  std::string err;
35  _error->PopMessage( err );
36  std::cerr << err << std::endl;
37  addContext( err );
38  }
39  }
40 };
41 
42 struct PackageState {
43  enum Query {
44  Install = 1 << 0,
45  Upgrade = 1 << 1,
46  Keep = 1 << 2,
47  Remove = 1 << 3,
48  Installed = 1 << 4,
49  Upgradable = 1 << 5,
50  NowBroken = 1 << 6,
51  WillBreak = 1 << 7,
52  ReInstall = 1 << 8,
53  Purge = 1 << 9,
54  Hold = 1 << 10,
55  Valid = 1 << 11
56  };
57 
58  typedef unsigned state;
59 
60  operator unsigned() { return m_state; };
61 
62  PackageState &operator=( unsigned i ) {
63  m_state = i;
64  return *this;
65  }
66 
68  m_state |= s.m_state;
69  return *this;
70  }
71 
72  PackageState( unsigned a ) {
73  m_state = a;
74  }
75 
76  PackageState() : m_state( 0 ) {}
77 
78  // FIXME this probably needs to be used consistently in core and out of core
79  bool isValid() const { return m_state & Valid; }
80  // FIXME compatibility API for non-core apt
81  bool isInstalled() const { return installed(); }
82 
83  bool install() const { return m_state & Install; }
84  // reinstall() implies install()
85  bool reinstall() const { return m_state & ReInstall; }
86  bool remove() const { return m_state & Remove; }
87  // purge() implies remove()
88  bool purge() const { return m_state & Purge; }
89  bool keep() const { return m_state & Keep; }
90  bool willBreak() const { return m_state & WillBreak; }
91  // upgrade() implies install()
92  bool upgrade() const { return hasNewVersion() && install(); }
93  // newInsstal() implies install()
94  bool newInstall() const { return !installed() && install(); }
95  bool hold() const { return m_state & Hold; }
96 
97  bool installed() const { return m_state & Installed; }
98  bool hasNewVersion() const { return m_state & Upgradable; }
99  bool upgradable() const { return hasNewVersion() && !hold(); }
100  bool held() const { return hasNewVersion() && hold(); }
101  bool nowBroken() const { return m_state & NowBroken; }
102 
103  bool modify() const { return install() || remove(); }
104 
105 protected:
106  unsigned m_state;
107 };
108 
109 time_t aptTimestamp();
110 
111 // wrap the apt's database
112 struct AptDatabase {
113  pkgCache &cache() {
114  if ( !m_cache )
115  openCache();
116  return *m_cache;
117  }
118 
119  pkgDepCache &state() {
120  if ( !m_state )
121  openState();
122  return *m_state;
123  }
124 
125  pkgPolicy &policy() {
126  if ( !m_policy )
127  openCache();
128  return *m_policy;
129  }
130 
131  OpProgress *m_progress;
134 
135  time_t timestamp() {
136  return aptTimestamp();
137  }
138 
140  m_cache = 0;
141  m_state = 0;
142  m_policy = 0;
143  m_progress = new OpProgress();
144  m_tryWriteable = true;
145  m_writeable = false;
146  }
147 
148  void setProgress( OpProgress *p ) {
149  m_progress = p;
150  }
151 
152  bool writeable() {
153  if ( !m_cache )
154  openCache();
155  return m_writeable;
156  }
157 
158  void openState() {
159  m_state = new pkgDepCache( &cache(), m_policy );
160  m_state->Init( m_progress );
161  m_progress->Done();
162  }
163 
164  void openCache() {
165  if ( !_config->FindB("Initialized") ) {
166  pkgInitConfig(*_config);
167  _config->Set("Initialized", 1);
168  pkgInitSystem(*_config, _system);
169  }
170 
172 
173  if ( m_tryWriteable ) {
174  try {
175  _system->Lock();
176  } catch ( std::exception e ) {
177  m_tryWriteable = false;
178  openCache();
179  m_tryWriteable = true;
180  throw;
181  }
182  }
183 
184  pkgSourceList list;
185  if ( list.ReadMainList() == false ) {
186  _error->DumpErrors();
187  throw wibble::exception::System(
188  "The list of sources could not be read." );
189  }
190 
191  MMap *m = 0;
192  bool Res = pkgMakeStatusCache( list, *m_progress, &m, !m_writeable );
193 
194  if ( !Res ) {
195  std::cerr << "The package lists or status file "
196  "could not be parsed or opened." << std::endl;
197  throw AptException(
198  "The package lists or status file "
199  "could not be parsed or opened." );
200  }
201 
202  m_cache = new pkgCache( m, true );
203  m_policy = new pkgPolicy( m_cache );
204  if ( ReadPinFile( *m_policy ) == false )
205  throw wibble::exception::System( "error reading pin file" );
206  m_progress->Done();
207  }
208 
209  void invalidate() {
210  if ( _config->FindB("Initialized") ) {
211  _system->UnLock();
212  }
213 
214  delete m_state;
215  m_state = 0;
216  delete m_policy;
217  m_policy = 0;
218  delete m_cache;
219  m_cache = 0;
220  }
221 
222  pkgCache::VerIterator anyVersion( pkgCache::PkgIterator pi ) {
223  if ( pi.end() ) return pkgCache::VerIterator();
224  return pi.VersionList();
225  }
226 
228  pkgCache::PkgIterator pi = cache().FindPkg( p.package() );
229  if ( pi.end() ) return Token();
230  pkgCache::VerIterator vi = policy().GetCandidateVer( pi );
231  if ( vi.end() ) return Token();
232 
233  Token t; t._id = p.package() + "_" + vi.VerStr();
234  return t;
235  }
236 
237  pkgCache::VerIterator candidateVersion( pkgCache::PkgIterator pi ) {
238  if ( pi.end() ) return pkgCache::VerIterator();
239  pkgCache::VerIterator vi = policy().GetCandidateVer( pi );
240  if ( vi.end() ) return pkgCache::VerIterator();
241  return vi;
242  }
243 
244  pkgCache::VerIterator installedVersion( pkgCache::PkgIterator pi ) {
245  if ( pi.end() ) return pkgCache::VerIterator();
246  pkgCache::VerIterator vi = pkgCache::VerIterator( cache(),
247  cache().VerP + pi->CurrentVer );
248  if ( vi.end() ) return pkgCache::VerIterator();
249  return vi;
250  }
251 
252  pkgCache::PkgIterator lookupPackage( Token t ) {
253  return cache().FindPkg( t.package() );
254  }
255 
256  pkgCache::VerIterator lookupVersion( Token t ) {
257  if ( !t.hasVersion() )
258  t = candidateVersion( t );
259  pkgCache::PkgIterator pi = lookupPackage( t );
260  if ( pi.end() )
261  return pkgCache::VerIterator();
262  for (pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); ++vi)
263  if ( t.version() == vi.VerStr() )
264  return vi;
265  return pkgCache::VerIterator();
266  }
267 
268  static pkgCache::VerFileIterator lookupVersionFile(
269  pkgCache::VerIterator vi )
270  {
271  if ( vi.end() )
272  return pkgCache::VerFileIterator();
273  pkgCache::VerFileIterator vfi = vi.FileList();
274  for ( ; !vfi.end(); vfi++ )
275  if ( ( vfi.File()->Flags & pkgCache::Flag::NotSource ) == 0)
276  break;
277  if ( vfi.end() )
278  vfi = vi.FileList();
279  return vfi;
280  }
281 
284  }
285 
286  PackageState packageState( pkgCache::PkgIterator P )
287  {
288  PackageState s = 0;
289  if ( P.end() )
290  return invalidState();
291  if ( ! ( P->CurrentState == pkgCache::State::ConfigFiles
292  || P->CurrentState == pkgCache::State::NotInstalled ) )
294  if ( s & PackageState::Installed &&
295  candidateVersion( P ) != installedVersion( P ) )
297  pkgDepCache::StateCache S = state()[ P ];
298  if ( S.Install() )
300  if ( ( S.iFlags & pkgDepCache::ReInstall )
301  == pkgDepCache::ReInstall )
303  if ( S.Keep() )
304  s |= PackageState::Keep;
305  if ( S.Delete() )
307  if ( ( S.iFlags & pkgDepCache::Purge ) == pkgDepCache::Purge )
308  s |= PackageState::Purge;
309  if ( S.NowBroken() )
311  if ( S.InstBroken() )
313  if ( P->SelectedState == pkgCache::State::Hold )
314  s |= PackageState::Hold;
315  return s;
316  }
317 
319  t = validate( t );
320  if ( t.valid() )
321  return packageState( lookupPackage( t ) );
322  return invalidState();
323  }
324 
326  if ( t.hasVersion() )
327  return lookupVersion( t ).end() ? Token() : t;
328  return lookupPackage( t ).end() ? Token() : t;
329  }
330 
332  invalidate();
333  }
334 
335 protected:
336  pkgCache *m_cache;
337  pkgDepCache *m_state;
338  pkgPolicy *m_policy;
339 };
340 
341 template< typename Internal >
344  typedef Internal Type;
346  AptInternalList t = *this;
347  t.m_head++;
348  return t;
349  }
350  const Internal &head() const { return m_head; }
351  Internal &head() { return m_head; }
352  bool empty() const { return m_head.end(); }
355 };
356 
357 namespace version {
358 
361 
362 typedef pkgCache::VerIterator Internal;
363 template< PropertyId > struct PropertyType {};
364 
365 }
366 
367 namespace package {
368 
371 typedef pkgCache::PkgIterator Internal;
372 template< PropertyId > struct PropertyType {};
373 
374 struct VersionList {
376  VersionList tail() const;
377  const version::Internal &head() const { return m_head; }
379 };
380 
382 
383 }
384 
385 namespace record {
386 
390 
391 extern const char *fields[];
392 
393 typedef pkgCache::VerFileIterator Internal;
394 
395 template< PropertyId > struct PropertyType {
396  typedef std::string T;
397 };
398 
399 }
400 }
401 }
402 
403 #include <ept/core/apt/package.h>
404 #include <ept/core/apt/version.h>
405 #include <ept/core/apt/record.h>
406 
407 #endif