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