apt  2.2.4
About: Apt (Advanced Package Tool) is a management system for software packages (Debian/Ubuntu). Release series 2.2.
  Fossies Dox: apt-2.2.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cachefile.cc
Go to the documentation of this file.
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 /* ######################################################################
4 
5  CacheFile - Simple wrapper class for opening, generating and whatnot
6 
7  This class implements a simple 2 line mechanism to open various sorts
8  of caches. It can operate as root, as not root, show progress and so on,
9  it transparently handles everything necessary.
10 
11  ##################################################################### */
12  /*}}}*/
13 // Include Files /*{{{*/
14 #include <config.h>
15 
16 #include <apt-pkg/cachefile.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/depcache.h>
19 #include <apt-pkg/error.h>
20 #include <apt-pkg/fileutl.h>
21 #include <apt-pkg/indexfile.h>
22 #include <apt-pkg/mmap.h>
23 #include <apt-pkg/pkgcache.h>
24 #include <apt-pkg/pkgcachegen.h>
25 #include <apt-pkg/pkgsystem.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/progress.h>
28 #include <apt-pkg/sourcelist.h>
29 
30 #include <limits>
31 #include <memory>
32 #include <string>
33 #include <vector>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 
39 #include <apti18n.h>
40  /*}}}*/
41 
43 {
44  bool WithLock = false;
45 };
46 
47 // CacheFile::CacheFile - Constructor /*{{{*/
48 pkgCacheFile::pkgCacheFile() : d(new Private()), ExternOwner(false), Map(NULL), Cache(NULL),
49  DCache(NULL), SrcList(NULL), Policy(NULL)
50 {
51 }
52 pkgCacheFile::pkgCacheFile(pkgDepCache * const Owner) : d(new Private()), ExternOwner(true),
53  Map(&Owner->GetCache().GetMap()), Cache(&Owner->GetCache()),
54  DCache(Owner), SrcList(NULL), Policy(NULL)
55 {
56 }
57  /*}}}*/
58 // CacheFile::~CacheFile - Destructor /*{{{*/
59 // ---------------------------------------------------------------------
60 /* */
62 {
63  if (ExternOwner == false)
64  {
65  delete DCache;
66  delete Cache;
67  delete Map;
68  }
69  delete Policy;
70  delete SrcList;
71  if (d->WithLock == true)
72  _system->UnLock(true);
73 
74  delete d;
75 }
76  /*}}}*/
77 // CacheFile::BuildCaches - Open and build the cache files /*{{{*/
79 public:
80  ScopedErrorMerge() { _error->PushToStack(); }
81  ~ScopedErrorMerge() { _error->MergeWithStack(); }
82 };
83 
84 bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
85 {
86  std::unique_ptr<pkgCache> Cache;
87  std::unique_ptr<MMap> Map;
88 
89  if (this->Cache != NULL)
90  return true;
91 
92  ScopedErrorMerge sem;
93  if (_config->FindB("pkgCacheFile::Generate", true) == false)
94  {
95  FileFd file(_config->FindFile("Dir::Cache::pkgcache"), FileFd::ReadOnly);
96  if (file.IsOpen() == false || file.Failed())
97  return false;
98  Map.reset(new MMap(file, MMap::Public|MMap::ReadOnly));
99  if (unlikely(Map->validData() == false))
100  return false;
101  Cache.reset(new pkgCache(Map.get()));
102  if (_error->PendingError() == true)
103  return false;
104 
105  this->Cache = Cache.release();
106  this->Map = Map.release();
107  return true;
108  }
109 
110  if (WithLock == true)
111  {
112  if (_system->Lock(Progress) == false)
113  return false;
114  d->WithLock = true;
115  }
116 
117  if (_error->PendingError() == true)
118  return false;
119 
120  if (BuildSourceList(Progress) == false)
121  return false;
122 
123  // Read the caches
124  MMap *TmpMap = nullptr;
125  pkgCache *TmpCache = nullptr;
126  bool Res = pkgCacheGenerator::MakeStatusCache(*SrcList,Progress,&TmpMap, &TmpCache, true);
127  Map.reset(TmpMap);
128  Cache.reset(TmpCache);
129  if (Progress != NULL)
130  Progress->Done();
131  if (Res == false)
132  return _error->Error(_("The package lists or status file could not be parsed or opened."));
133 
134  /* This sux, remove it someday */
135  if (_error->PendingError() == true)
136  _error->Warning(_("You may want to run apt-get update to correct these problems"));
137 
138  if (Cache == nullptr)
139  Cache.reset(new pkgCache(Map.get()));
140  if (_error->PendingError() == true)
141  return false;
142  this->Map = Map.release();
143  this->Cache = Cache.release();
144 
145  return true;
146 }
147  /*}}}*/
148 // CacheFile::BuildSourceList - Open and build all relevant sources.list/*{{{*/
149 // ---------------------------------------------------------------------
150 /* */
152 {
153  std::unique_ptr<pkgSourceList> SrcList;
154  if (this->SrcList != NULL)
155  return true;
156 
157  SrcList.reset(new pkgSourceList());
158  if (SrcList->ReadMainList() == false)
159  return _error->Error(_("The list of sources could not be read."));
160  this->SrcList = SrcList.release();
161  return true;
162 }
163  /*}}}*/
164 // CacheFile::BuildPolicy - Open and build all relevant preferences /*{{{*/
165 // ---------------------------------------------------------------------
166 /* */
168 {
169  std::unique_ptr<pkgPolicy> Policy;
170  if (this->Policy != NULL)
171  return true;
172 
173  Policy.reset(new pkgPolicy(Cache));
174  if (_error->PendingError() == true)
175  return false;
176 
178  ReadPinDir(*Policy);
179 
180  this->Policy = Policy.release();
181  return _error->PendingError() == false;
182 }
183  /*}}}*/
184 // CacheFile::BuildDepCache - Open and build the dependency cache /*{{{*/
185 // ---------------------------------------------------------------------
186 /* */
188 {
189  if (BuildCaches(Progress, false) == false)
190  return false;
191 
192  std::unique_ptr<pkgDepCache> DCache;
193  if (this->DCache != NULL)
194  return true;
195 
196  if (BuildPolicy(Progress) == false)
197  return false;
198 
199  DCache.reset(new pkgDepCache(Cache,Policy));
200  if (_error->PendingError() == true)
201  return false;
202  if (DCache->Init(Progress) == false)
203  return false;
204 
205  this->DCache = DCache.release();
206  return true;
207 }
208  /*}}}*/
209 // CacheFile::Open - Open the cache files, creating if necessary /*{{{*/
210 // ---------------------------------------------------------------------
211 /* */
212 bool pkgCacheFile::Open(OpProgress *Progress, bool WithLock)
213 {
214  if (BuildCaches(Progress,WithLock) == false)
215  return false;
216 
217  if (BuildPolicy(Progress) == false)
218  return false;
219 
220  if (BuildDepCache(Progress) == false)
221  return false;
222 
223  if (Progress != NULL)
224  Progress->Done();
225  if (_error->PendingError() == true)
226  return false;
227 
228  return true;
229 }
230  /*}}}*/
231 bool pkgCacheFile::AddIndexFile(pkgIndexFile * const File) /*{{{*/
232 {
233  if (SrcList == NULL)
234  if (BuildSourceList() == false)
235  return false;
236  SrcList->AddVolatileFile(File);
237 
238  if (Cache == nullptr || File->HasPackages() == false || File->Exists() == false)
239  return true;
240 
241  if (File->FindInCache(*Cache).end() == false)
242  return _error->Warning("Duplicate sources.list entry %s",
243  File->Describe().c_str());
244 
245  if (ExternOwner == false)
246  {
247  delete DCache;
248  delete Cache;
249  }
250  delete Policy;
251  DCache = NULL;
252  Policy = NULL;
253  Cache = NULL;
254 
255  if (ExternOwner == false)
256  {
257  // a dynamic mmap means that we have build at least parts of the cache
258  // in memory – which we might or might not have written to disk.
259  // Throwing away would therefore be a very costly operation we want to avoid
260  DynamicMMap * dynmmap = dynamic_cast<DynamicMMap*>(Map);
261  if (dynmmap != nullptr)
262  {
263  {
264  pkgCacheGenerator Gen(dynmmap, nullptr);
265  if (Gen.Start() == false || File->Merge(Gen, nullptr) == false)
266  return false;
267  }
268  Cache = new pkgCache(Map);
269  if (_error->PendingError() == true) {
270  delete Cache;
271  Cache = nullptr;
272  return false;
273  }
274  return true;
275  }
276  else
277  {
278  delete Map;
279  Map = NULL;
280  }
281  }
282  else
283  {
284  ExternOwner = false;
285  Map = NULL;
286  }
287  _system->UnLock(true);
288  return true;
289 }
290  /*}}}*/
291 // CacheFile::RemoveCaches - remove all cache files from disk /*{{{*/
292 // ---------------------------------------------------------------------
293 /* */
294 static void SetCacheStartBeforeRemovingCache(std::string const &cache)
295 {
296  if (cache.empty())
297  return;
298  auto const CacheStart = _config->FindI("APT::Cache-Start", 0);
299  constexpr auto CacheStartDefault = 24 * 1024 * 1024;
300  struct stat Buf;
301  if (stat(cache.c_str(), &Buf) == 0 && (Buf.st_mode & S_IFREG) != 0)
302  {
303  RemoveFile("RemoveCaches", cache);
304  if (CacheStart == 0 && std::numeric_limits<decltype(CacheStart)>::max() >= Buf.st_size && Buf.st_size > CacheStartDefault)
305  _config->Set("APT::Cache-Start", Buf.st_size);
306  }
307 }
309 {
310  std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
312  std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
314 
315  if (pkgcache.empty() == false)
316  {
317  std::string cachedir = flNotFile(pkgcache);
318  std::string cachefile = flNotDir(pkgcache);
319  if (cachedir.empty() != true && cachefile.empty() != true && DirectoryExists(cachedir) == true)
320  {
321  cachefile.append(".");
322  std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
323  for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
324  {
325  std::string nuke = flNotDir(*file);
326  if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
327  continue;
328  RemoveFile("RemoveCaches", *file);
329  }
330  }
331  }
332 
333  if (srcpkgcache.empty() == true)
334  return;
335 
336  std::string cachedir = flNotFile(srcpkgcache);
337  std::string cachefile = flNotDir(srcpkgcache);
338  if (cachedir.empty() == true || cachefile.empty() == true || DirectoryExists(cachedir) == false)
339  return;
340  cachefile.append(".");
341  std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
342  for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
343  {
344  std::string nuke = flNotDir(*file);
345  if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
346  continue;
347  RemoveFile("RemoveCaches", *file);
348  }
349 }
350  /*}}}*/
351 // CacheFile::Close - close the cache files /*{{{*/
352 // ---------------------------------------------------------------------
353 /* */
355 {
356  if (ExternOwner == false)
357  {
358  delete DCache;
359  delete Cache;
360  delete Map;
361  }
362  else
363  ExternOwner = false;
364  delete Policy;
365  delete SrcList;
366  if (d->WithLock == true)
367  {
368  _system->UnLock(true);
369  d->WithLock = false;
370  }
371 
372  Map = NULL;
373  DCache = NULL;
374  Policy = NULL;
375  Cache = NULL;
376  SrcList = NULL;
377 }
378  /*}}}*/
return false
static void SetCacheStartBeforeRemovingCache(std::string const &cache)
Definition: cachefile.cc:294
int FindI(const char *Name, int const &Default=0) const
void Set(const std::string &Name, const std::string &Value)
Definition: configuration.h:92
bool FindB(const char *Name, bool const &Default=false) const
std::string FindFile(const char *Name, const char *Default=0) const
Definition: fileutl.h:39
bool IsOpen()
Definition: fileutl.h:150
@ ReadOnly
Definition: fileutl.h:59
bool Failed()
Definition: fileutl.h:151
Definition: mmap.h:41
bool validData() const
Definition: mmap.h:66
@ Public
Definition: mmap.h:58
@ ReadOnly
Definition: mmap.h:58
virtual void Done()
Definition: progress.h:60
bool ExternOwner
Definition: cachefile.h:37
pkgDepCache * DCache
Definition: cachefile.h:42
pkgCache * Cache
Definition: cachefile.h:41
bool BuildSourceList(OpProgress *Progress=NULL)
Definition: cachefile.cc:151
virtual ~pkgCacheFile()
Definition: cachefile.cc:61
bool BuildPolicy(OpProgress *Progress=NULL)
Definition: cachefile.cc:167
MMap * Map
Definition: cachefile.h:40
pkgSourceList * SrcList
Definition: cachefile.h:43
bool AddIndexFile(pkgIndexFile *const File)
Definition: cachefile.cc:231
void Close()
Definition: cachefile.cc:354
static void RemoveCaches()
Definition: cachefile.cc:308
bool BuildDepCache(OpProgress *Progress=NULL)
Definition: cachefile.cc:187
pkgPolicy * Policy
Definition: cachefile.h:46
bool Open(OpProgress *Progress=NULL, bool WithLock=true)
Definition: cachefile.cc:212
bool BuildCaches(OpProgress *Progress=NULL, bool WithLock=true)
Definition: cachefile.cc:84
Private *const d
dpointer placeholder (for later in case we need it)
Definition: cachefile.h:34
static APT_PUBLIC bool MakeStatusCache(pkgSourceList &List, OpProgress *Progress, MMap **OutMap=0, bool AllowMem=false)
bool Init(OpProgress *const Prog)
Definition: depcache.cc:229
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const
Definition: indexfile.cc:75
virtual bool Merge(pkgCacheGenerator &, OpProgress *const)
Definition: indexfile.h:144
virtual std::string Describe(bool const Short=false) const =0
virtual bool HasPackages() const =0
virtual bool Exists() const =0
bool ReadMainList()
Definition: sourcelist.cc:307
void AddVolatileFile(pkgIndexFile *const File)
add file for parsing, but not to the cache
Definition: sourcelist.cc:535
virtual bool UnLock(bool NoErrors=false)=0
virtual bool Lock(OpProgress *const Progress=nullptr)=0
Configuration * _config
string flNotFile(string File)
Definition: fileutl.cc:676
bool DirectoryExists(string const &Path)
Definition: fileutl.cc:348
string flNotDir(string File)
Definition: fileutl.cc:664
bool RemoveFile(char const *const Function, std::string const &FileName)
Definition: fileutl.cc:198
std::vector< string > GetListOfFilesInDir(string const &Dir, string const &Ext, bool const &SortList, bool const &AllowNoExt)
Definition: fileutl.cc:421
#define APT_HIDDEN
Definition: macros.h:78
pkgCache - Structure definitions for the cache file
pkgSystem * _system
Definition: pkgsystem.cc:24
bool ReadPinDir(pkgPolicy &Plcy, string Dir)
Definition: policy.cc:373
bool ReadPinFile(pkgPolicy &Plcy, string File)
Definition: policy.cc:405
bool Policy(CommandLine &CmdL)