- nuke bunch of old ununsed code
[apt.git] / apt-pkg / rpm / rpmsystem.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: rpmsystem.cc,v 1.9 2002/11/25 18:25:28 niemeyer Exp $
4 /* ######################################################################
5
6    System - Abstraction for running on different systems.
7
8    RPM version of the system stuff
9    
10    ##################################################################### 
11  */
12                                                                         /*}}}*/
13 // Include Files                                                        /*{{{*/
14 #ifdef __GNUG__
15 #pragma implementation "apt-pkg/rpmsystem.h"
16 #endif
17
18 #include <config.h>
19
20 #ifdef HAVE_RPM
21
22 #include <apt-pkg/rpmsystem.h>
23 #include <apt-pkg/rpmversion.h>
24 #include <apt-pkg/rpmindexfile.h>
25 #include <apt-pkg/rpmpm.h>
26 #include <apt-pkg/rpmhandler.h>
27 #include <apt-pkg/configuration.h>
28 #include <apt-pkg/error.h>
29 #include <apt-pkg/fileutl.h>
30 #include <apt-pkg/rpmpackagedata.h>
31
32 #include <apti18n.h>
33     
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <rpm/rpmlib.h>
40 #include <assert.h>
41 #include <time.h>
42                                                                         /*}}}*/
43 // for distrover
44 #if RPM_VERSION >= 0x040101
45 #include <rpmdb.h>
46 #endif
47
48 #if RPM_VERSION >= 0x040201
49 extern int _rpmds_nopromote;
50 #endif
51
52 rpmSystem rpmSys;
53
54 // System::rpmSystem - Constructor                                      /*{{{*/
55 // ---------------------------------------------------------------------
56 /* */
57 rpmSystem::rpmSystem()
58 {
59    LockCount = 0;
60    RpmDB = NULL;
61    StatusFile = NULL;
62    Label = "rpm interface";
63    VS = &rpmVS;
64 }
65                                                                         /*}}}*/
66 rpmSystem::~rpmSystem()
67 {
68    delete StatusFile;
69    delete RpmDB;
70 }
71
72 RPMDBHandler *rpmSystem::GetDBHandler()
73 {
74    if (RpmDB == NULL)
75       RpmDB = new RPMDBHandler();
76    return RpmDB;
77 }
78
79 bool rpmSystem::LockRead()
80 {
81    GetDBHandler();
82    if (_error->PendingError() == true)
83       return false;
84    return true;
85 }
86
87 //
88 // System::Lock - Get the lock                                          /*{{{*/
89 // ---------------------------------------------------------------------
90 /* this will open the rpm database through rpmlib, which will lock the db */
91 bool rpmSystem::Lock()
92 {
93    if (RpmDB != NULL && RpmDB->HasWriteLock() == false)
94    {
95       delete RpmDB;
96       RpmDB = NULL;
97    }
98    if (RpmDB == NULL)
99       RpmDB = new RPMDBHandler(true);
100    if (_error->PendingError() == true)
101       return false;
102    LockCount++;
103    return true;
104 }
105                                                                         /*}}}*/
106 // System::UnLock - Drop a lock                                         /*{{{*/
107 // ---------------------------------------------------------------------
108 /* Close the rpmdb, effectively dropping it's lock */
109 bool rpmSystem::UnLock(bool NoErrors)
110 {
111    if (LockCount == 0 && NoErrors == true)
112       return false;
113    if (LockCount < 1)
114       return _error->Error("Not locked");
115    if (--LockCount == 0)
116    {
117       delete RpmDB;
118       RpmDB = NULL;
119    }
120    return true;
121 }
122                                                                         /*}}}*/
123 // System::CreatePM - Create the underlying package manager             /*{{{*/
124 // ---------------------------------------------------------------------
125 /* */
126 pkgPackageManager *rpmSystem::CreatePM(pkgDepCache *Cache) const
127 {
128    if (_config->Find("RPM::PM", "internal") == "internal")
129       return new pkgRPMLibPM(Cache);
130    else
131       return new pkgRPMExtPM(Cache);
132 }
133                                                                         /*}}}*/
134 // System::Initialize - Setup the configuration space..                 /*{{{*/
135 // ---------------------------------------------------------------------
136 /* These are the rpm specific configuration variables.. */
137 bool rpmSystem::Initialize(Configuration &Cnf)
138 {
139    Cnf.CndSet("Dir::Bin::rpm","/bin/rpm");
140    Cnf.CndSet("Dir::Etc::rpmpriorities", "rpmpriorities");
141    Cnf.CndSet("Dir::Etc::translatelist", "translate.list");
142    Cnf.CndSet("Dir::Etc::translateparts", "translate.list.d");
143    Cnf.CndSet("Dir::State::prefetch", "prefetch");
144    Cnf.CndSet("Dir::Locale",LOCALEDIR);
145    Cnf.CndSet("Acquire::DistroID","Conectiva"); // hee hee
146    Cnf.CndSet("Acquire::CDROM::Mount", "/mnt/cdrom");
147    Cnf.CndSet("Acquire::CDROM::Copy-All", "true");
148
149    // Compatibility with obsoleted options
150    if (Cnf.Exists("APT::PostInstall"))
151    {
152       _error->Warning("Rename obsoleted option APT::PostInstall to APT::Post-Install");
153       Cnf.CndSet("APT::Post-Install::Clean",
154                  Cnf.Find("APT::PostInstall::Clean","false"));
155       Cnf.CndSet("APT::Post-Install::AutoClean",
156                  Cnf.Find("APT::PostInstall::AutoClean","false"));
157    }
158    const Configuration::Item *Top;
159    Top = _config->Tree("RPM::HoldPkgs");
160    if (Top != 0)
161    {
162       _error->Warning("Rename obsoleted option RPM::HoldPkgs to RPM::Hold");
163       for (Top = Top->Child; Top != 0; Top = Top->Next)
164          Cnf.Set("RPM::Hold::", Top->Value.c_str());
165    }
166    Top = _config->Tree("RPM::AllowedDupPkgs");
167    if (Top != 0)
168    {
169       _error->Warning("Rename obsoleted option RPM::AllowedDupPkgs to RPM::Allow-Duplicated");
170       for (Top = Top->Child; Top != 0; Top = Top->Next)
171          Cnf.Set("RPM::Allow-Duplicated::", Top->Value.c_str());
172    }
173    Top = _config->Tree("RPM::IgnorePkgs");
174    if (Top != 0)
175    {
176       _error->Warning("Rename obsoleted option RPM::IgnorePkgs to RPM::Ignore");
177       for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next)
178          Cnf.Set("RPM::Ignore::", Top->Value.c_str());
179    }
180    if (Cnf.Exists("RPM::Force"))
181    {
182       _error->Warning("RPM::Force is obsoleted. Add \"--force\" to RPM::Options instead.");
183       if (Cnf.FindB("RPM::Force",false))
184          Cnf.Set("RPM::Options::", "--force");
185    }
186    if (Cnf.Exists("RPM::NoDeps"))
187    {
188       _error->Warning("RPM::NoDeps is obsoleted. Add \"--nodeps\" to RPM::Options and RPM::Erase-Options instead.");
189       if (Cnf.FindB("RPM::NoDeps",false))
190          Cnf.Set("RPM::Options::", "--nodeps");
191    }
192
193 #if RPM_VERSION >= 0x040201
194    const char *RPMOptions[] =
195    {
196       "RPM::Options",
197       "RPM::Install-Options",
198       "RPM::Erase-Options",
199       NULL,
200    };
201    int NoPromote = 1;
202    const char **Opt = RPMOptions;
203    while (*Opt && NoPromote)
204    {
205       Top = _config->Tree(*Opt);
206       if (Top != 0)
207       {
208          for (Top = Top->Child; Top != 0; Top = Top->Next)
209             if (Top->Value == "--promoteepoch") {
210                NoPromote = 0;
211                break;
212             }
213       }
214       Opt++;
215    }
216    _rpmds_nopromote = NoPromote;
217 #endif
218
219    return true;
220 }
221                                                                         /*}}}*/
222 // System::ArchiveSupported - Is a file format supported                /*{{{*/
223 // ---------------------------------------------------------------------
224 /* The standard name for a rpm is 'rpm'.. There are no seperate versions
225    of .rpm to worry about.. */
226 bool rpmSystem::ArchiveSupported(const char *Type)
227 {
228    if (strcmp(Type,"rpm") == 0)
229       return true;
230    return false;
231 }
232                                                                         /*}}}*/
233 // System::Score - Determine how Re**at'ish this sys is..               /*{{{*/
234 // ---------------------------------------------------------------------
235 /* Check some symptoms that this is a Re**at like system */
236 signed rpmSystem::Score(Configuration const &Cnf)
237 {
238    signed Score = 0;
239
240    rpmReadConfigFiles(NULL, NULL);
241    if (FileExists(RPMDBHandler::DataPath(false)))
242       Score += 10;
243    if (FileExists(Cnf.FindFile("Dir::Bin::rpm","/bin/rpm")) == true)
244       Score += 10;
245
246    return Score;
247 }
248
249 string rpmSystem::DistroVer()
250 {
251    string DistroVerPkg = _config->Find("APT::DistroVerPkg", "");
252    if (DistroVerPkg.empty() || LockRead() == false)
253       return "";
254
255    string DistroVersion = "";
256    if (RpmDB->JumpByName(DistroVerPkg) == true) {
257       DistroVersion = RpmDB->Version();
258    } else {
259       _error->Error(_("Unable to determine version for package %s"),
260                       DistroVerPkg.c_str());
261    }
262    UnLock(true);
263
264    return DistroVersion;
265 }
266
267                                                                         /*}}}*/
268 // System::AddStatusFiles - Register the status files                   /*{{{*/
269 // ---------------------------------------------------------------------
270 /* */
271 bool rpmSystem::AddStatusFiles(vector<pkgIndexFile *> &List)
272 {
273    if (StatusFile == NULL)
274       StatusFile = new rpmDatabaseIndex();
275    List.push_back(StatusFile);
276    return true;
277 }
278                                                                         /*}}}*/
279 // System::AddSourceFiles - Register aditional source files             /*{{{*/
280 // ---------------------------------------------------------------------
281 /* */
282 bool rpmSystem::AddSourceFiles(vector<pkgIndexFile *> &List)
283 {
284    const Configuration::Item *Top;
285    Top = _config->Tree("APT::Arguments");
286    if (Top != 0)
287    {
288       for (Top = Top->Child; Top != 0; Top = Top->Next) {
289          const string &S = Top->Value;
290          if (FileExists(S) && flExtension(S) == "rpm")
291          {
292             if (S.length() > 8 && string(S, S.length()-8) == ".src.rpm")
293                List.push_back(new rpmSingleSrcIndex(S));
294             else
295                List.push_back(new rpmSinglePkgIndex(S));
296          }
297       }
298    }
299    return true;
300 }
301                                                                         /*}}}*/
302 // System::FindIndex - Get an index file for status files               /*{{{*/
303 // ---------------------------------------------------------------------
304 /* */
305 bool rpmSystem::FindIndex(pkgCache::PkgFileIterator File,
306                           pkgIndexFile *&Found) const
307 {
308    if (StatusFile == 0)
309       return false;
310    if (StatusFile->FindInCache(*File.Cache()) == File)
311    {
312       Found = StatusFile;
313       return true;
314    }
315    
316    return false;
317 }
318                                                                         /*}}}*/
319
320 // System::ProcessCache - Do specific changes in the cache              /*{{{*/
321 // ---------------------------------------------------------------------
322 /* */
323 bool rpmSystem::ProcessCache(pkgDepCache &Cache,pkgProblemResolver &Fix)
324 {
325    RPMPackageData *rpmdata = RPMPackageData::Singleton();
326    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
327    {
328       // Ignore virtual packages
329       if (I->VersionList == 0)
330          continue;
331          
332       // Do package holding
333       if (I->CurrentVer != 0)
334       {
335          if (rpmdata->HoldPackage(I.Name()))
336          {
337             Cache.MarkKeep(I);
338             Fix.Protect(I);
339          }
340       }
341    }
342    return true;
343 }
344                                                                         /*}}}*/
345
346 // System::IgnoreDep - Check if this dependency should be ignored       /*{{{*/
347 // ---------------------------------------------------------------------
348 /* For strong hearts only */
349 bool rpmSystem::IgnoreDep(pkgVersioningSystem &VS,pkgCache::DepIterator &Dep)
350 {
351    RPMPackageData *rpmdata = RPMPackageData::Singleton();
352    return rpmdata->IgnoreDep(VS,Dep);
353 }
354                                                                         /*}}}*/
355
356 // System::CacheBuilt - free caches used during cache build             /*{{{*/
357 // ---------------------------------------------------------------------
358 /* */
359 void rpmSystem::CacheBuilt()
360 {
361    RPMPackageData *rpmdata = RPMPackageData::Singleton();
362    rpmdata->CacheBuilt();
363 }
364                                                                         /*}}}*/
365
366 // System::OptionsHash - Identify options which change the cache        /*{{{*/
367 // ---------------------------------------------------------------------
368 /* */
369 static void HashString(unsigned long &Hash, const char *Str)
370 {
371    for (const char *I = Str; *I != 0; I++)
372       Hash = 5*Hash + *I;
373 }
374 static void HashEnv(unsigned long &Hash, const char *Name)
375 {
376    const char *Value = getenv(Name);
377    if (Value)
378       HashString(Hash, Value);
379 }
380 static void HashOption(unsigned long &Hash, const char *Name)
381 {
382    const Configuration::Item *Top = _config->Tree(Name);
383    if (Top != 0)
384       HashString(Hash, Top->Value.c_str());
385 }
386 static void HashOptionTree(unsigned long &Hash, const char *Name)
387 {
388    const Configuration::Item *Top = _config->Tree(Name);
389    if (Top != 0)
390       for (Top = Top->Child; Top != 0; Top = Top->Next)
391          HashString(Hash, Top->Value.c_str());
392 }
393 static void HashOptionFile(unsigned long &Hash, const char *Name)
394 {
395    string FileName = _config->FindFile(Name);
396    struct stat st;
397    stat(FileName.c_str(), &st);
398    Hash += st.st_mtime;
399 }
400
401 #if RPM_VERSION >= 0x040404
402 static void HashTime(unsigned long &Hash)
403 {
404    Hash += time(NULL);
405 }
406 #endif
407
408 unsigned long rpmSystem::OptionsHash() const
409 {
410    unsigned long Hash = 0;
411    HashOption(Hash, "RPM::Architecture");
412    HashOptionTree(Hash, "RPM::Allow-Duplicated");
413    HashOptionTree(Hash, "RPM::Ignore");
414    HashOptionFile(Hash, "Dir::Etc::rpmpriorities");
415    HashEnv(Hash, "LANG");
416    HashEnv(Hash, "LC_ALL");
417    HashEnv(Hash, "LC_MESSAGES");
418 #if RPM_VERSION >= 0x040404
419    // This is really draconian but until apt can made somehow deal with
420    // runtime dependencies the cache has to be rebuilt for each run for
421    // accuracy. Allow turning it off via configuration if not needed.
422    if (_config->FindB("RPM::RuntimeDeps", true) == true)
423       HashTime(Hash);
424 #endif
425    return Hash;
426 }
427                                                                         /*}}}*/
428
429 #endif /* HAVE_RPM */
430
431 // vim:sts=3:sw=3