- initial import of revision 374 from cnc
[apt.git] / apt-pkg / deb / debsystem.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: debsystem.cc,v 1.1 2002/07/23 17:54:51 niemeyer Exp $
4 /* ######################################################################
5
6    System - Abstraction for running on different systems.
7
8    Basic general structure..
9    
10    ##################################################################### */
11                                                                         /*}}}*/
12 // Include Files                                                        /*{{{*/
13 #ifdef __GNUG__
14 #pragma implementation "apt-pkg/debsystem.h"
15 #endif
16
17 #include <apt-pkg/debsystem.h>
18 #include <apt-pkg/debversion.h>
19 #include <apt-pkg/debindexfile.h>
20 #include <apt-pkg/dpkgpm.h>
21 #include <apt-pkg/configuration.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24     
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <dirent.h>
28 #include <errno.h>
29                                                                         /*}}}*/
30
31 debSystem debSys;
32
33 // System::debSystem - Constructor                                      /*{{{*/
34 // ---------------------------------------------------------------------
35 /* */
36 debSystem::debSystem()
37 {
38    LockFD = -1;
39    LockCount = 0;
40    
41    Label = "Debian dpkg interface";
42    VS = &debVS;
43 }
44                                                                         /*}}}*/
45 // System::~debSystem - Destructor                                      /*{{{*/
46 // ---------------------------------------------------------------------
47 /* */
48 debSystem::~debSystem()
49 {
50    delete StatusFile;
51 }
52                                                                         /*}}}*/
53 // System::Lock - Get the lock                                          /*{{{*/
54 // ---------------------------------------------------------------------
55 /* This mirrors the operations dpkg does when it starts up. Note the
56    checking of the updates directory. */
57 bool debSystem::Lock()
58 {
59    // Disable file locking
60    if (_config->FindB("Debug::NoLocking",false) == true || LockCount > 1)
61    {
62       LockCount++;
63       return true;
64    }
65
66    // Create the lockfile
67    string AdminDir = flNotFile(_config->Find("Dir::State::status"));
68    LockFD = GetLock(AdminDir + "lock");
69    if (LockFD == -1)
70    {
71       if (errno == EACCES || errno == EAGAIN)
72          return _error->Error("Unable to lock the administration directory (%s), "
73                               "is another process using it?",AdminDir.c_str());
74       else
75          return _error->Error("Unable to lock the administration directory (%s), "
76                               "are you root?",AdminDir.c_str());
77    }
78    
79    // See if we need to abort with a dirty journal
80    if (CheckUpdates() == true)
81    {
82       close(LockFD);
83       LockFD = -1;
84       return _error->Error("dpkg was interrupted, you must manually "
85                            "run 'dpkg --configure -a' to correct the problem. ");
86    }
87
88          LockCount++;
89       
90    return true;
91 }
92                                                                         /*}}}*/
93 // System::UnLock - Drop a lock                                         /*{{{*/
94 // ---------------------------------------------------------------------
95 /* */
96 bool debSystem::UnLock(bool NoErrors)
97 {
98    if (LockCount == 0 && NoErrors == true)
99       return false;
100    
101    if (LockCount < 1)
102       return _error->Error("Not locked");
103    if (--LockCount == 0)
104    {
105       close(LockFD);
106       LockCount = 0;
107    }
108    
109    return true;
110 }
111                                                                         /*}}}*/
112 // System::CheckUpdates - Check if the updates dir is dirty             /*{{{*/
113 // ---------------------------------------------------------------------
114 /* This does a check of the updates directory (dpkg journal) to see if it has 
115    any entries in it. */
116 bool debSystem::CheckUpdates()
117 {
118    // Check for updates.. (dirty)
119    string File = flNotFile(_config->Find("Dir::State::status")) + "updates/";
120    DIR *DirP = opendir(File.c_str());
121    if (DirP == 0)
122       return false;
123    
124    /* We ignore any files that are not all digits, this skips .,.. and 
125       some tmp files dpkg will leave behind.. */
126    bool Damaged = false;
127    for (struct dirent *Ent = readdir(DirP); Ent != 0; Ent = readdir(DirP))
128    {
129       Damaged = true;
130       for (unsigned int I = 0; Ent->d_name[I] != 0; I++)
131       {
132          // Check if its not a digit..
133          if (isdigit(Ent->d_name[I]) == 0)
134          {
135             Damaged = false;
136             break;
137          }
138       }
139       if (Damaged == true)
140          break;
141    }
142    closedir(DirP);
143
144    return Damaged;
145 }
146                                                                         /*}}}*/
147 // System::CreatePM - Create the underlying package manager             /*{{{*/
148 // ---------------------------------------------------------------------
149 /* */
150 pkgPackageManager *debSystem::CreatePM(pkgDepCache *Cache) const
151 {
152    return new pkgDPkgPM(Cache);
153 }
154                                                                         /*}}}*/
155 // System::Initialize - Setup the configuration space..                 /*{{{*/
156 // ---------------------------------------------------------------------
157 /* These are the Debian specific configuration variables.. */
158 bool debSystem::Initialize(Configuration &Cnf)
159 {
160    /* These really should be jammed into a generic 'Local Database' engine
161       which is yet to be determined. The functions in pkgcachegen should
162       be the only users of these */
163    Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct
164    Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status");
165    Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
166    
167    return true;
168 }
169                                                                         /*}}}*/
170 // System::ArchiveSupported - Is a file format supported                /*{{{*/
171 // ---------------------------------------------------------------------
172 /* The standard name for a deb is 'deb'.. There are no seperate versions
173    of .deb to worry about.. */
174 bool debSystem::ArchiveSupported(const char *Type)
175 {
176    if (strcmp(Type,"deb") == 0)
177       return true;
178    return false;
179 }
180                                                                         /*}}}*/
181 // System::Score - Determine how 'Debiany' this sys is..                /*{{{*/
182 // ---------------------------------------------------------------------
183 /* We check some files that are sure tell signs of this being a Debian
184    System.. */
185 signed debSystem::Score(Configuration const &Cnf)
186 {
187    signed Score = 0;
188    if (FileExists(Cnf.FindFile("Dir::State::status","/var/lib/dpkg/status")) == true)
189        Score += 10;
190    if (FileExists(Cnf.FindFile("Dir::Bin::dpkg","/usr/bin/dpkg")) == true)
191       Score += 10;
192    if (FileExists("/etc/debian_version") == true)
193       Score += 10;
194    return Score;
195 }
196                                                                         /*}}}*/
197 // System::AddStatusFiles - Register the status files                   /*{{{*/
198 // ---------------------------------------------------------------------
199 /* */
200 bool debSystem::AddStatusFiles(vector<pkgIndexFile *> &List)
201 {
202    if (StatusFile == 0)
203       StatusFile = new debStatusIndex(_config->FindFile("Dir::State::status"));
204    List.push_back(StatusFile);
205    return true;
206 }
207                                                                         /*}}}*/
208 // System::FindIndex - Get an index file for status files               /*{{{*/
209 // ---------------------------------------------------------------------
210 /* */
211 bool debSystem::FindIndex(pkgCache::PkgFileIterator File,
212                           pkgIndexFile *&Found) const
213 {
214    if (StatusFile == 0)
215       return false;
216    if (StatusFile->FindInCache(*File.Cache()) == File)
217    {
218       Found = StatusFile;
219       return true;
220    }
221    
222    return false;
223 }
224                                                                         /*}}}*/