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