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