2
* dpkg - main program for package management
3
* dbmodify.c - routines for managing dpkg database updates
5
* Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
6
* Copyright © 2001 Wichert Akkerman <wichert@debian.org>
8
* This is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2,
11
* or (at your option) any later version.
13
* This is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public
19
* License along with dpkg; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
#include <dpkg/i18n.h>
32
#include <sys/types.h>
42
#include <dpkg/dpkg.h>
43
#include <dpkg/dpkg-db.h>
45
char *statusfile=NULL, *availablefile=NULL;
46
char *triggersdir, *triggersfilefile, *triggersnewfilefile;
48
static enum modstatdb_rw cstatus=-1, cflags=0;
49
static char *importanttmpfile=NULL;
50
static FILE *importanttmp;
51
static int nextupdate;
52
static int updateslength;
53
static char *updatefnbuf, *updatefnrest;
54
static const char *admindir;
55
static struct varbuf uvb;
57
static int ulist_select(const struct dirent *de) {
60
for (p= de->d_name, l=0; *p; p++, l++)
61
if (!cisdigit(*p)) return 0;
62
if (l > IMPORTANTMAXLEN)
63
ohshit(_("updates directory contains file `%.250s' whose name is too long "
64
"(length=%d, max=%d)"), de->d_name, l, IMPORTANTMAXLEN);
65
if (updateslength == -1) updateslength= l;
66
else if (l != updateslength)
67
ohshit(_("updates directory contains files with different length names "
68
"(both %d and %d)"), l, updateslength);
72
static void cleanupdates(void) {
73
struct dirent **cdlist;
76
parsedb(statusfile, pdb_weakclassification, NULL,NULL,NULL);
80
cdn= scandir(updatefnbuf, &cdlist, &ulist_select, alphasort);
81
if (cdn == -1) ohshite(_("cannot scan updates directory `%.255s'"),updatefnbuf);
85
for (i=0; i<cdn; i++) {
86
strcpy(updatefnrest, cdlist[i]->d_name);
87
parsedb(updatefnbuf, pdb_weakclassification, NULL,NULL,NULL);
88
if (cstatus < msdbrw_write) free(cdlist[i]);
91
if (cstatus >= msdbrw_write) {
92
writedb(statusfile,0,1);
94
for (i=0; i<cdn; i++) {
95
strcpy(updatefnrest, cdlist[i]->d_name);
96
if (unlink(updatefnbuf))
97
ohshite(_("failed to remove incorporated update file %.255s"),updatefnbuf);
108
static void createimptmp(void) {
113
importanttmp= fopen(importanttmpfile,"w");
115
ohshite(_("unable to create `%.255s'"), importanttmpfile);
116
setcloexec(fileno(importanttmp),importanttmpfile);
117
for (i=0; i<512; i++) fputs("#padding\n",importanttmp);
118
if (ferror(importanttmp))
119
ohshite(_("unable to fill %.250s with padding"),importanttmpfile);
120
if (fflush(importanttmp))
121
ohshite(_("unable to flush %.250s after padding"), importanttmpfile);
122
if (fseek(importanttmp,0,SEEK_SET))
123
ohshite(_("unable to seek to start of %.250s after padding"),
129
static const struct fni {
133
{ STATUSFILE, &statusfile },
134
{ AVAILFILE, &availablefile },
135
{ UPDATESDIR IMPORTANTTMP, &importanttmpfile },
136
{ TRIGGERSDIR, &triggersdir },
137
{ TRIGGERSDIR "/File", &triggersfilefile },
138
{ TRIGGERSDIR "/File.new", &triggersnewfilefile},
142
enum modstatdb_rw modstatdb_init(const char *adir, enum modstatdb_rw readwritereq) {
143
const struct fni *fnip;
147
for (fnip=fnis; fnip->suffix; fnip++) {
149
*fnip->store= m_malloc(strlen(adir)+strlen(fnip->suffix)+2);
150
sprintf(*fnip->store, "%s/%s", adir, fnip->suffix);
153
cflags= readwritereq & msdbrw_flagsmask;
154
readwritereq &= ~msdbrw_flagsmask;
156
switch (readwritereq) {
157
case msdbrw_needsuperuser:
158
case msdbrw_needsuperuserlockonly:
159
if (getuid() || geteuid())
160
ohshit(_("requested operation requires superuser privilege"));
162
case msdbrw_write: case msdbrw_writeifposs:
163
if (access(adir,W_OK)) {
165
ohshite(_("unable to access dpkg status area"));
166
else if (readwritereq == msdbrw_write)
167
ohshit(_("operation requires read/write access to dpkg status area"));
168
cstatus= msdbrw_readonly;
171
cstatus= (readwritereq == msdbrw_needsuperuserlockonly ?
172
msdbrw_needsuperuserlockonly :
176
case msdbrw_readonly:
177
cstatus= msdbrw_readonly; break;
179
internerr("unknown modstatdb_rw '%d'", readwritereq);
182
updatefnbuf= m_malloc(strlen(adir)+sizeof(UPDATESDIR)+IMPORTANTMAXLEN+5);
183
strcpy(updatefnbuf,adir);
184
strcat(updatefnbuf,"/" UPDATESDIR);
185
updatefnrest= updatefnbuf+strlen(updatefnbuf);
187
if (cstatus != msdbrw_needsuperuserlockonly) {
189
if(!(cflags & msdbrw_noavail))
190
parsedb(availablefile,
191
pdb_recordavailable|pdb_rejectstatus,
195
if (cstatus >= msdbrw_write) {
197
varbufinit(&uvb, 10240);
200
trig_fixup_awaiters(cstatus);
201
trig_incorporate(cstatus, admindir);
206
void modstatdb_checkpoint(void) {
209
assert(cstatus >= msdbrw_write);
210
writedb(statusfile,0,1);
212
for (i=0; i<nextupdate; i++) {
213
sprintf(updatefnrest, IMPORTANTFMT, i);
214
assert(strlen(updatefnrest)<=IMPORTANTMAXLEN); /* or we've made a real mess */
215
if (unlink(updatefnbuf))
216
ohshite(_("failed to remove my own update file %.255s"),updatefnbuf);
221
void modstatdb_shutdown(void) {
222
const struct fni *fnip;
225
modstatdb_checkpoint();
226
writedb(availablefile,1,0);
227
/* tidy up a bit, but don't worry too much about failure */
228
fclose(importanttmp);
229
unlink(importanttmpfile);
232
case msdbrw_needsuperuserlockonly:
238
for (fnip=fnis; fnip->suffix; fnip++) {
246
modstatdb_note_core(struct pkginfo *pkg)
248
assert(cstatus >= msdbrw_write);
251
varbufrecord(&uvb, pkg, &pkg->installed);
253
if (fwrite(uvb.buf, 1, uvb.used, importanttmp) != uvb.used)
254
ohshite(_("unable to write updated status of `%.250s'"), pkg->name);
255
if (fflush(importanttmp))
256
ohshite(_("unable to flush updated status of `%.250s'"), pkg->name);
257
if (ftruncate(fileno(importanttmp), uvb.used))
258
ohshite(_("unable to truncate for updated status of `%.250s'"), pkg->name);
259
if (fsync(fileno(importanttmp)))
260
ohshite(_("unable to fsync updated status of `%.250s'"), pkg->name);
261
if (fclose(importanttmp))
262
ohshite(_("unable to close updated status of `%.250s'"), pkg->name);
263
sprintf(updatefnrest, IMPORTANTFMT, nextupdate);
264
if (rename(importanttmpfile, updatefnbuf))
265
ohshite(_("unable to install updated status of `%.250s'"), pkg->name);
267
/* Have we made a real mess? */
268
assert(strlen(updatefnrest) <= IMPORTANTMAXLEN);
272
if (nextupdate > MAXUPDATES) {
273
modstatdb_checkpoint();
280
/* Note: If anyone wants to set some triggers-pending, they must also
281
* set status appropriately, or we will undo it. That is, it is legal
282
* to call this when pkg->status and pkg->trigpend_head disagree and
283
* in that case pkg->status takes precedence and pkg->trigpend_head
286
void modstatdb_note(struct pkginfo *pkg) {
291
/* Clear pending triggers here so that only code that sets the status
292
* to interesting (for triggers) values has to care about triggers.
294
if (pkg->status != stat_triggerspending &&
295
pkg->status != stat_triggersawaited)
296
pkg->trigpend_head = NULL;
298
if (pkg->status <= stat_configfiles) {
299
for (ta = pkg->trigaw.head; ta; ta = ta->sameaw.next)
301
pkg->trigaw.head = pkg->trigaw.tail = NULL;
304
log_message("status %s %s %s", statusinfos[pkg->status].name, pkg->name,
305
versiondescribe(&pkg->installed.version, vdew_nonambig));
306
statusfd_send("status: %s: %s", pkg->name, statusinfos[pkg->status].name);
308
if (cstatus >= msdbrw_write)
309
modstatdb_note_core(pkg);
311
if (!pkg->trigpend_head && pkg->othertrigaw_head) {
312
/* Automatically remove us from other packages' Triggers-Awaited.
313
* We do this last because we want to maximise our chances of
314
* successfully recording the status of the package we were
315
* pointed at by our caller, although there is some risk of
316
* leaving us in a slightly odd situation which is cleared up
317
* by the trigger handling logic in deppossi_ok_found.
319
trig_clear_awaiters(pkg);
326
modstatdb_note_ifwrite(struct pkginfo *pkg)
328
if (cstatus >= msdbrw_write)
332
const char *pkgadminfile(struct pkginfo *pkg, const char *whichfile) {
333
static struct varbuf vb;
335
varbufaddstr(&vb,admindir);
336
varbufaddstr(&vb,"/" INFODIR);
337
varbufaddstr(&vb,pkg->name);
339
varbufaddstr(&vb,whichfile);