LTP GCOV extension - code coverage report
Current view: directory - ept/apt - apt.cc
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 323
Code covered: 76.8 % Executed lines: 248

       1                 : /** \file
       2                 :  * High-level front-end to libapt-pkg, as a data provider for the ept framework.
       3                 :  */
       4                 : 
       5                 : /* 
       6                 :  * Copyright (C) 2007,2008  Enrico Zini <enrico@enricozini.org>
       7                 :  *
       8                 :  * This library is free software; you can redistribute it and/or
       9                 :  * modify it under the terms of the GNU Lesser General Public
      10                 :  * License as published by the Free Software Foundation; either
      11                 :  * version 2.1 of the License, or (at your option) any later version.
      12                 :  *
      13                 :  * This library is distributed in the hope that it will be useful,
      14                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :  * Lesser General Public License for more details.
      17                 :  *
      18                 :  * You should have received a copy of the GNU Lesser General Public
      19                 :  * License along with this library; if not, write to the Free Software
      20                 :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
      21                 :  */
      22                 : 
      23                 : #include <ept/apt/apt.h>
      24                 : 
      25                 : #include <apt-pkg/error.h>
      26                 : #include <apt-pkg/init.h>
      27                 : #include <apt-pkg/progress.h>
      28                 : #include <apt-pkg/sourcelist.h>
      29                 : #include <apt-pkg/pkgcachegen.h>
      30                 : #include <apt-pkg/policy.h>
      31                 : #include <apt-pkg/cachefile.h>
      32                 : 
      33                 : #include <wibble/sys/fs.h>
      34                 : #include <sys/stat.h>
      35                 : 
      36                 : #include <vector>
      37                 : #include <algorithm>
      38                 : 
      39                 : #include <iostream>
      40                 : 
      41                 : using namespace std;
      42                 : 
      43                 : namespace ept {
      44                 : namespace apt {
      45                 : using core::aptTimestamp;
      46                 : 
      47               0 : Exception::Exception(const std::string& context) throw ()
      48               0 :         : Generic(context)
      49                 : {
      50                 :         // Concatenate all errors and warnings found
      51               0 :         string err;
      52               0 :         while (!_error->empty())
      53                 :         {
      54               0 :                 bool type = _error->PopMessage(err);
      55               0 :                 if (type)
      56               0 :                         m_message += "E: " + err + "\n";
      57                 :                 else
      58               0 :                         m_message += "W: " + err + "\n";
      59               0 :    }
      60               0 : }
      61                 : 
      62              29 : static void aptInit ()
      63                 : {
      64              29 :     if (_config->FindB("Initialized"))
      65              29 :         return;
      66                 : 
      67               0 :     if (!pkgInitConfig (*_config))
      68               0 :                 throw Exception("initialising apt configuration");
      69                 : 
      70               0 :     _config->Set("Initialized", 1);
      71                 : 
      72                 :         /*
      73                 :     _config->Set("Dir", CACHE_DIR);
      74                 :     _config->Set("Dir::Cache", "cache");
      75                 :     _config->Set("Dir::State", "state");
      76                 :     _config->Set("Dir::Etc", "etc");
      77                 :     _config->Set("Dir::State::status", CACHE_DIR "dpkg-status");
      78                 :         */
      79               0 :     if (!pkgInitSystem (*_config, _system))
      80               0 :                 throw Exception("initialising apt system");
      81                 : }
      82                 : 
      83                 : struct AptImplementation
      84                 : {
      85                 :         pkgSourceList* m_list;
      86                 :         MMap *m;
      87                 :         OpProgress progress;
      88                 :         pkgCache* m_cache;
      89                 :         pkgPolicy* m_policy;
      90                 :         pkgCacheFile* m_depcache;
      91                 :         time_t m_open_timestamp;
      92                 :         
      93              29 :         AptImplementation() : m_list(0), m(0), m_cache(0), m_policy(0), m_depcache(0), m_open_timestamp(0)
      94                 :         {
      95                 :                 // Init the apt library if needed
      96              29 :                 aptInit();
      97                 : 
      98              29 :                 m_open_timestamp = aptTimestamp();
      99                 : 
     100              29 :                 m_list = new pkgSourceList;
     101              58 :                 if (!m_list->ReadMainList())
     102               0 :                         throw Exception("reading list of sources");
     103                 : 
     104              29 :                 bool res = pkgMakeStatusCache(*m_list, progress, &m, true);
     105              29 :                 progress.Done();
     106              29 :                 if (!res)
     107               0 :                         throw Exception("Reading the package lists or status file");
     108                 : 
     109              29 :                 m_cache = new pkgCache(m);
     110              58 :                 m_policy = new pkgPolicy(m_cache);
     111              58 :                 if (!ReadPinFile(*m_policy))
     112               0 :                         throw Exception("Reading the policy pin file");
     113              29 :         }
     114                 : 
     115              29 :         ~AptImplementation()
     116                 :         {
     117              29 :                 if (m_depcache) delete m_depcache;
     118              29 :                 if (m_policy) delete m_policy;
     119              29 :                 if (m_cache) delete m_cache;
     120              29 :                 if (m) delete m;
     121              29 :                 if (m_list) delete m_list;
     122              29 :         }
     123                 : 
     124            3980 :         pkgCache& cache()
     125                 :         {
     126            3980 :                 return *m_cache;
     127                 :         }
     128                 : 
     129           16099 :         pkgPolicy& policy()
     130                 :         {
     131           16099 :                 return *m_policy;
     132                 :         }
     133                 : 
     134               1 :         pkgCacheFile& depcache()
     135                 :         {
     136               1 :                 if (!m_depcache)
     137                 :                 {
     138               1 :                         m_depcache = new pkgCacheFile;
     139               1 :                         if (!m_depcache->Open(progress, false))
     140               0 :                                 throw Exception("Opening the cache file");
     141                 :                 }
     142               1 :                 return *m_depcache;
     143                 :         }
     144                 : };
     145                 : 
     146                 : // Sort a version list by package file locality
     147           39519 : bool localityCompare(const pkgCache::VerFile* a, const pkgCache::VerFile* b)
     148                 : {
     149           39519 :    if (a == 0 && b == 0)
     150               0 :       return false;
     151           39519 :    if (a == 0)
     152               0 :       return true;
     153           39519 :    if (b == 0)
     154               0 :       return false;
     155                 :    
     156           39519 :    if (a->File == b->File)
     157           39060 :       return a->Offset < b->Offset;
     158             459 :    return a->File < b->File;
     159                 : }
     160                 : 
     161                 : // Iterate records using the algorithm used by apt-cache dumpavail
     162                 : struct RecordIteratorImpl
     163                 : {
     164                 :         mutable int _ref;
     165                 :         AptImplementation& apt;
     166                 :         vector<pkgCache::VerFile*> vflist;
     167                 :         pkgCache::PkgFileIterator lastFile;
     168                 :         FileFd file;
     169                 :         size_t lastOffset;
     170                 : 
     171               9 :         RecordIteratorImpl(AptImplementation& apt) : _ref(0), apt(apt), vflist(0)
     172                 :         {
     173                 :                 // We already have an estimate of how many versions we're about to find
     174               9 :                 vflist.reserve(apt.cache().HeaderP->PackageCount + 1);
     175                 : 
     176                 :                 // Populate the vector of versions to print
     177           34002 :                 for (pkgCache::PkgIterator pi = apt.cache().PkgBegin(); !pi.end(); ++pi)
     178                 :                 {    
     179           33993 :                         if (pi->VersionList == 0)
     180           17901 :                                 continue;
     181                 : 
     182                 :                         /* Get the candidate version or fallback on the installed version,
     183                 :                          * as usual */
     184           16092 :                         pkgCache::VerIterator vi = apt.policy().GetCandidateVer(pi);
     185           16092 :                         if (vi.end() == true)
     186                 :                         {
     187            1926 :                                 if (pi->CurrentVer == 0)
     188            1926 :                                         continue;
     189               0 :                                 vi = pi.CurrentVer();
     190                 :                         }
     191                 : 
     192                 :                         // Choose a valid file that contains the record for this version
     193           14166 :                         pkgCache::VerFileIterator vfi = vi.FileList();
     194           24507 :                         for ( ; !vfi.end(); ++vfi)
     195           14166 :                                 if ((vfi.File()->Flags & pkgCache::Flag::NotSource) == 0)
     196            3825 :                                         break;
     197                 : 
     198                 :                         // Handle packages whose candidate version is currently installed
     199                 :                         // from outside the archives (like from a locally built .deb
     200           14166 :                         if (vfi.end() == true)
     201                 :                         {
     202           20682 :                                 for (pkgCache::VerIterator cur = pi.VersionList(); cur.end() != true; cur++)
     203                 :                                 {
     204           20763 :                                         for (vfi = cur.FileList(); vfi.end() == false; vfi++)
     205                 :                                         {        
     206           10422 :                                                 if ((vfi.File()->Flags & pkgCache::Flag::NotSource) == 0)
     207                 :                                                 {
     208              81 :                                                         vfi = vi.FileList();
     209              81 :                                                         break;
     210                 :                                                 }
     211                 :                                         }
     212                 : 
     213           10422 :                                         if (vfi.end() == false)
     214              81 :                                                 break;
     215                 :                                 }
     216                 :                         }
     217           14166 :                         if (!vfi.end())
     218            3906 :                                 vflist.push_back(vfi);
     219                 :                 }
     220                 : 
     221                 :                 //cerr << vflist.size() << " versions found" << endl;
     222                 : 
     223               9 :                 sort(vflist.begin(), vflist.end(), localityCompare);
     224                 : 
     225                 :                 //for (size_t i = 0; i < vflist.size(); ++i)
     226                 :                 //{
     227                 :                 //      pkgCache::PkgFileIterator fi(apt.cache(), vflist[i]->File + apt.cache().PkgFileP);
     228                 :                 //      cerr << i << ": " << fi.FileName() << ":" << vflist[i]->Offset << "-" << vflist[i]->Size << endl;
     229                 :                 //}
     230                 :                 //cerr << "Done indexing." << endl;
     231               9 :         }
     232                 : 
     233               9 :         ~RecordIteratorImpl()
     234                 :         {
     235               9 :                 if (file.IsOpen())
     236               9 :                         file.Close();
     237               9 :         }
     238                 : 
     239              14 :         void ref() { ++_ref; }
     240              14 :         bool unref() { return --_ref == 0; }
     241                 : 
     242            3906 :         size_t size() { return vflist.size(); }
     243                 : 
     244            3906 :         string record(size_t idx)
     245                 :         {
     246                 :                 //cerr << "Access record " << idx << endl;
     247                 :                 //cerr << "lastfile: " << (lastFile.Cache() != 0) << endl;
     248                 :                 // We can't reuse the file that was already open: open the new one
     249            3906 :                 if ((lastFile.Cache() == 0) || vflist[idx]->File + apt.cache().PkgFileP != lastFile)
     250                 :                 {
     251                 :                         //cerr << "Needs open/reopen" << endl;
     252              18 :                         lastFile = pkgCache::PkgFileIterator(apt.cache(), vflist[idx]->File + apt.cache().PkgFileP);
     253              18 :                         if (!lastFile.IsOk())
     254               0 :                                 throw Exception(string("Reading the data record for a package from file ") + lastFile.FileName());
     255                 :                         //cerr << "Ok for " << lastFile.FileName() << endl;
     256              18 :                         if (file.IsOpen())
     257               9 :                                 file.Close();
     258              18 :                         if (!file.Open(lastFile.FileName(), FileFd::ReadOnly))
     259               0 :                                 throw Exception(string("Opening file ") + lastFile.FileName());
     260                 :                         //cerr << "Opened " << lastFile.FileName() << endl;
     261              18 :                         lastOffset = 0;
     262                 :                 }
     263                 : 
     264                 :                 //cerr << "Reading from " << lastFile.FileName() << ":" << vflist[idx]->Offset << "-" << vflist[idx]->Size << " (lastOffset: " << lastOffset << ")" << endl;
     265                 : 
     266                 :                 // If we start near were we ended, avoid a seek and enlarge the read a bit
     267            3906 :                 size_t slack = vflist[idx]->Offset - lastOffset;
     268                 :                 //cerr << "Slack: " << slack << endl;
     269            3906 :                 if (slack > 8)
     270                 :                 {
     271                 :                         //cerr << "Slack too big: seek to " << vflist[idx]->Offset << endl;
     272             171 :                         slack = 0;
     273             171 :                         if (!file.Seek(vflist[idx]->Offset))
     274               0 :                                 throw Exception(string("Cannot seek to package record in file ") + lastFile.FileName());
     275                 :                 }
     276                 : 
     277            3906 :                 char buffer[vflist[idx]->Size + slack + 1];
     278            3906 :                 if (!file.Read(buffer, vflist[idx]->Size + slack))
     279               0 :                         throw Exception(string("Cannot read package record in file ") + lastFile.FileName());
     280            3906 :                 buffer[vflist[idx]->Size + slack] = '\n';
     281                 :                 //cerr << "Data read (slack: " << slack << ")" << endl;
     282                 : 
     283            3906 :                 lastOffset = vflist[idx]->Offset + vflist[idx]->Size;
     284                 : 
     285            3906 :                 return string(buffer+slack);
     286                 :         }
     287                 : };
     288                 : 
     289              20 : Apt::Iterator::Iterator(const Iterator& i)
     290                 : {
     291              20 :         if (i.cur)
     292                 :         {
     293              10 :                 pkgCache::PkgIterator* p = new pkgCache::PkgIterator;
     294              10 :                 *p = *static_cast<pkgCache::PkgIterator*>(i.cur);
     295              10 :                 cur = p;
     296                 :         } else
     297              10 :                 cur = 0;
     298              20 : }
     299                 : 
     300               0 : Apt::Iterator& Apt::Iterator::operator=(const Iterator& i)
     301                 : {
     302               0 :         if (cur != i.cur)
     303                 :         {
     304               0 :                 if (cur) delete static_cast<pkgCache::PkgIterator*>(cur);
     305               0 :                 if (i.cur)
     306                 :                 {
     307               0 :                         pkgCache::PkgIterator* p = new pkgCache::PkgIterator;
     308               0 :                         *p = *static_cast<pkgCache::PkgIterator*>(i.cur);
     309               0 :                         cur = p;
     310                 :                 } else
     311               0 :                         cur = 0;
     312                 :         }
     313               0 :         return *this;
     314                 : }
     315                 : 
     316            3605 : Apt::Iterator::~Iterator()
     317                 : {
     318            3605 :         if (cur) delete static_cast<pkgCache::PkgIterator*>(cur);
     319            3605 : }
     320            5364 : std::string Apt::Iterator::operator*()
     321                 : {
     322            5364 :         return static_cast<pkgCache::PkgIterator*>(cur)->Name();
     323                 : }
     324            7152 : Apt::Iterator& Apt::Iterator::operator++()
     325                 : {
     326            7152 :         pkgCache::PkgIterator* iter = static_cast<pkgCache::PkgIterator*>(cur);
     327            7152 :         ++*iter;
     328           22260 :         while (!iter->end() && (*iter)->VersionList == 0)
     329            7956 :                 ++*iter;
     330            7152 :         if (iter->end())
     331                 :         {
     332               4 :                 delete iter;
     333               4 :                 cur = 0;
     334                 :         }
     335            7152 :         return *this;
     336                 : }
     337               0 : bool Apt::Iterator::operator==(const Iterator& i) const
     338                 : {
     339               0 :         if (cur == 0 && i.cur == 0)
     340               0 :                 return true;
     341               0 :         if (cur == 0 || i.cur == 0)
     342               0 :                 return false;
     343               0 :         pkgCache::PkgIterator* iter1 = static_cast<pkgCache::PkgIterator*>(cur);
     344               0 :         pkgCache::PkgIterator* iter2 = static_cast<pkgCache::PkgIterator*>(i.cur);
     345               0 :         return *iter1 == *iter2;
     346                 : }
     347            7157 : bool Apt::Iterator::operator!=(const Iterator& i) const
     348                 : {
     349            7157 :         if (cur == 0 && i.cur == 0)
     350               4 :                 return false;
     351            7153 :         if (cur == 0 || i.cur == 0)
     352            7153 :                 return true;
     353               0 :         pkgCache::PkgIterator* iter1 = static_cast<pkgCache::PkgIterator*>(cur);
     354               0 :         pkgCache::PkgIterator* iter2 = static_cast<pkgCache::PkgIterator*>(i.cur);
     355               0 :         return *iter1 != *iter2;
     356                 : }
     357                 : 
     358                 : 
     359               9 : Apt::RecordIterator::RecordIterator(RecordIteratorImpl* impl, size_t pos)
     360               9 :         : impl(impl), pos(pos), cur_pos(pos)
     361                 : {
     362               9 :         if (impl)
     363                 :         {
     364               9 :                 impl->ref();
     365               9 :                 cur = impl->record(pos);
     366               9 :                 cur_pos = pos;
     367                 :         }
     368               9 : }
     369              10 : Apt::RecordIterator::RecordIterator(const RecordIterator& r)
     370              10 :         : impl(r.impl), pos(r.pos), cur(r.cur), cur_pos(r.cur_pos)
     371                 : {
     372              10 :         if (impl)
     373               5 :                 impl->ref();
     374              10 : }
     375            3500 : Apt::RecordIterator::~RecordIterator()
     376                 : {
     377            3500 :         if (impl && impl->unref())
     378               1 :                 delete impl;
     379            3500 : }
     380            3906 : std::string Apt::RecordIterator::operator*()
     381                 : {
     382            3906 :         if (cur_pos != pos)
     383                 :         {
     384            3464 :                 cur = impl->record(pos);
     385            3464 :                 cur_pos = pos;
     386                 :         }
     387            3906 :         return cur;
     388                 : }
     389             868 : std::string* Apt::RecordIterator::operator->()
     390                 : {
     391             868 :         if (cur_pos != pos)
     392                 :         {
     393             433 :                 cur = impl->record(pos);
     394             433 :                 cur_pos = pos;
     395                 :         }
     396             868 :         return &cur;
     397                 : }
     398            3906 : Apt::RecordIterator& Apt::RecordIterator::operator++()
     399                 : {
     400            3906 :         ++pos;
     401            3906 :         if (pos >= impl->size())
     402                 :         {
     403                 :                 // If we reach the end, we become an end iterator
     404               9 :                 if (impl && impl->unref())
     405               8 :                         delete impl;
     406               9 :                 impl = 0;
     407               9 :                 pos = 0;
     408                 :         }
     409            3906 :         return *this;
     410                 : }
     411               0 : Apt::RecordIterator& Apt::RecordIterator::operator=(const RecordIterator& r)
     412                 : {
     413                 :         // Increment first, to avoid it reaching zero on assignment to self
     414               0 :         if (r.impl) r.impl->ref();
     415               0 :         if (impl && impl->unref())
     416               0 :                 delete impl;
     417               0 :         impl = r.impl;
     418               0 :         pos = r.pos;
     419               0 :         cur = r.cur;
     420               0 :         cur_pos = r.cur_pos;
     421               0 :         return *this;
     422                 : }
     423               0 : bool Apt::RecordIterator::operator==(const RecordIterator& ri) const
     424                 : {
     425               0 :         return impl == ri.impl && pos == ri.pos;
     426                 : }
     427            3915 : bool Apt::RecordIterator::operator!=(const RecordIterator& ri) const
     428                 : {
     429            3915 :         return impl != ri.impl || pos != ri.pos;
     430                 : }
     431                 : 
     432                 : 
     433              28 : Apt::Apt() : impl(new AptImplementation()) {}
     434              28 : Apt::~Apt() { delete impl; }
     435                 : 
     436               4 : Apt::iterator Apt::begin() const
     437                 : {
     438               4 :         pkgCache::PkgIterator* p = new pkgCache::PkgIterator;
     439               4 :         *p = impl->cache().PkgBegin();
     440               4 :         return Apt::Iterator(p);
     441                 : }
     442                 : 
     443            3581 : Apt::iterator Apt::end() const
     444                 : {
     445            3581 :         return Apt::Iterator();
     446                 : }
     447                 : 
     448               9 : Apt::record_iterator Apt::recordBegin() const
     449                 : {
     450               9 :         return Apt::RecordIterator(new RecordIteratorImpl(*impl));
     451                 : }
     452                 : 
     453            3481 : Apt::record_iterator Apt::recordEnd() const
     454                 : {
     455            3481 :         return Apt::RecordIterator();
     456                 : }
     457                 : 
     458               0 : size_t Apt::size() const
     459                 : {
     460               0 :         return impl->cache().HeaderP->PackageCount;
     461                 : }
     462                 : 
     463              16 : time_t Apt::timestamp()
     464                 : {
     465              16 :         return aptTimestamp();
     466                 : }
     467                 : 
     468               5 : bool Apt::isValid(const std::string& pkg) const
     469                 : {
     470               5 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(pkg);
     471               5 :         return !pi.end();
     472                 : }
     473                 : 
     474               4 : Version Apt::validate(const Version& ver) const
     475                 : {
     476               4 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(ver.name());
     477               5 :         if (pi.end()) return Version();
     478               4 :         for (pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); vi++)
     479                 :         {
     480               3 :                 const char* v = vi.VerStr();
     481               3 :                 if (v == 0) continue;
     482               3 :                 if (ver.version() == v)
     483               2 :                         return ver;
     484                 :         }
     485               1 :         return Version();
     486                 : }
     487                 : 
     488               4 : Version Apt::candidateVersion(const std::string& pkg) const
     489                 : {
     490               4 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(pkg);
     491               4 :         if (pi.end()) return Version();
     492               3 :         pkgCache::VerIterator vi = impl->policy().GetCandidateVer(pi);
     493               3 :         if (vi.end()) return Version();
     494               3 :         return Version(pkg, vi.VerStr());
     495                 : }
     496                 : 
     497               2 : Version Apt::installedVersion(const std::string& pkg) const
     498                 : {
     499               2 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(pkg);
     500               2 :         if (pi.end()) return Version();
     501               1 :         if (pi->CurrentVer == 0) return Version();
     502               1 :         pkgCache::VerIterator vi = pi.CurrentVer();
     503               1 :         if (vi.end()) return Version();
     504               1 :         return Version(pkg, vi.VerStr());
     505                 : }
     506                 : 
     507               4 : Version Apt::anyVersion(const std::string& pkg) const
     508                 : {
     509               4 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(pkg);
     510               4 :         if (pi.end()) return Version();
     511                 : 
     512               3 :         pkgCache::VerIterator vi = impl->policy().GetCandidateVer(pi);
     513               3 :         if (vi.end())
     514                 :         {
     515               0 :                 if (pi->CurrentVer == 0) return Version();
     516               0 :                 vi = pi.CurrentVer();
     517               0 :                 if (vi.end()) return Version();
     518                 :         }
     519               3 :         return Version(pkg, vi.VerStr());
     520                 : }
     521                 : 
     522               2 : PackageState Apt::state(const std::string& pkg) const
     523                 : {
     524               2 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(pkg);
     525               2 :         if (pi.end()) return PackageState();
     526               1 :         pkgDepCache::StateCache sc = impl->depcache()[pi];
     527                 : 
     528               1 :         unsigned int flags = PackageState::Valid;
     529                 : 
     530                 :         // Check if the package is installed
     531               1 :     if (pi->CurrentState != pkgCache::State::ConfigFiles &&
     532                 :                 pi->CurrentState != pkgCache::State::NotInstalled &&
     533                 :                 pi->CurrentVer != 0)
     534                 :         {
     535                 :                 // Try to get a VerIterator to the installed version
     536               1 :                 pkgCache::VerIterator inst = pi.CurrentVer();
     537               1 :                 if (!inst.end())
     538                 :                 {
     539                 :                         // If we made it so far, it is installed
     540               1 :                         flags |= PackageState::Installed;
     541                 : 
     542                 :                         // Now check if it is upgradable
     543               1 :                         pkgCache::VerIterator cand = impl->policy().GetCandidateVer(pi);
     544                 : 
     545                 :                         // If the candidate version is different than the installed one, then
     546                 :                         // it is installable
     547               1 :                         if (!cand.end() && inst != cand)
     548               0 :                                 flags |= PackageState::Upgradable;
     549                 :                 }
     550                 :         }
     551               1 :     if (sc.Install())
     552               0 :         flags |= PackageState::Install;
     553               1 :     if ((sc.iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
     554               0 :         flags |= PackageState::ReInstall;
     555               1 :     if (sc.Keep())
     556               1 :         flags |= PackageState::Keep;
     557               1 :     if (sc.Delete())
     558               0 :         flags |= PackageState::Remove;
     559               1 :     if ((sc.iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
     560               0 :         flags |= PackageState::Purge;
     561               1 :     if (sc.NowBroken())
     562               0 :         flags |= PackageState::NowBroken;
     563               1 :     if (sc.InstBroken())
     564               0 :         flags |= PackageState::WillBreak;
     565                 : 
     566               1 :         return PackageState(flags);
     567                 : }
     568                 : 
     569               1 : std::string Apt::rawRecord(const std::string& ver) const
     570                 : {
     571                 :         // TODO: possibly reimplement using a single lump of apt code, to avoid
     572                 :         // repeating lookups
     573               1 :         return rawRecord(anyVersion(ver));
     574                 : }
     575                 : 
     576               4 : std::string Apt::rawRecord(const Version& ver) const
     577                 : {
     578               4 :         pkgCache::PkgIterator pi = impl->cache().FindPkg(ver.name());
     579               4 :         if (pi.end()) return std::string();
     580               5 :         for (pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); vi++)
     581                 :         {
     582               4 :                 const char* v = vi.VerStr();
     583               4 :                 if (v == 0) continue;
     584               4 :                 if (ver.version() == v)
     585                 :                 {
     586                 :                         // Code taken and adapted from apt-cache's DisplayRecord
     587                 : 
     588                 :                         // Find an appropriate file
     589               3 :                         pkgCache::VerFileIterator vfi = vi.FileList();
     590               3 :                         for (; !vfi.end(); vfi++)
     591               3 :                                 if ((vfi.File()->Flags & pkgCache::Flag::NotSource) == 0)
     592               3 :                                         break;
     593               3 :                         if (vfi.end())
     594               0 :                                 vfi = vi.FileList();
     595                 : 
     596                 :                         // Check and load the package list file
     597               3 :                         pkgCache::PkgFileIterator pfi = vfi.File();
     598               3 :                         if (!pfi.IsOk())
     599               0 :                                 throw Exception(string("Reading the data record for a package version from file ") + pfi.FileName());
     600                 : 
     601               3 :                         FileFd pkgf(pfi.FileName(), FileFd::ReadOnly);
     602               6 :                         if (_error->PendingError() == true)
     603               0 :                                 return std::string();
     604                 : 
     605                 :                         // Read the record and then write it out again.
     606               3 :                         char* buffer = new char[vfi->Size+1];
     607               3 :                         buffer[vfi->Size] = '\n';
     608               3 :                         if (!pkgf.Seek(vfi->Offset) || !pkgf.Read(buffer, vfi->Size))
     609                 :                         {
     610               0 :                                 delete[] buffer;
     611               0 :                                 return std::string();
     612                 :                         }
     613                 : 
     614               3 :                         std::string res(buffer, vfi->Size);
     615               6 :                         delete[] buffer;
     616               3 :                         return res;
     617                 :                 }
     618                 :         }
     619               1 :         return std::string();
     620                 : }
     621                 : 
     622               2 : void Apt::checkCacheUpdates()
     623                 : {
     624               2 :         if (impl->m_open_timestamp < timestamp())
     625                 :         {
     626                 :                 // Crudely reopen everything
     627               1 :                 delete impl;
     628               1 :                 impl = new AptImplementation;
     629                 :         }
     630               2 : }
     631                 : 
     632               1 : void Apt::invalidateTimestamp()
     633                 : {
     634               1 :         impl->m_open_timestamp = 0;
     635               1 : }
     636                 : 
     637                 : }
     638               6 : }
     639                 : 
     640                 : // vim:set ts=4 sw=4:

Generated by: LTP GCOV extension version 1.6