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