~ubuntu-branches/ubuntu/lucid/dpkg/lucid

« back to all changes in this revision

Viewing changes to lib/dpkg/dbmodify.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover, Guillem Jover, Raphael Hertzog, Modestas Vainius, Updated dpkg translations, Updated dselect translations, Updated man page translations, Updated scripts translations
  • Date: 2009-09-06 09:37:45 UTC
  • mto: (1.4.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 68.
  • Revision ID: james.westby@ubuntu.com-20090906093745-orb3im04ozfxypis
Tags: 1.15.4
[ Guillem Jover ]
* Call _g instead of g_ in dpkg-name.
* Fix inverted logic when deciding to assume the architecture in dpkg-name
  when the package didn't have such field.
* Do not take into account Revision and Package_Revision fields in dpkg-name
  and dpkg-scanpackages as they have been handled already by “dpkg-deb -I”.
* Switch dpkg-scansources to use Dpkg::Cdata instead of duplicating the
  .dsc parsing code. As a side effect it now handles properly bogus files.
* Do not remap obsolete fields in dpkg-scanpackages as they have been
  handled already by “dpkg-deb -I”.
* Properly mark packages being purged for disappearance from the database.
  This will make the status database not be left behind with traces of old
  not-installed packages. Closes: #472208
* On parse mark not-installed leftover packages for automatic removal from
  the database on next dump. This obsoletes the --forget-old-unavail option,
  thus making it now a no-op. Closes: #33394, #429262
* Document “hold” under package selection states instead of flags in dpkg(1).
* Remove trailing ‘/’ and ‘/.’ from the directory name to be used as the
  package name on “dpkg-deb -b”. Closes: #218018, #373602
* Remove obsolete ‘hold’ and ‘hold-reinstreq’ internal status flags.
* Add fakeroot to dpkg-dev Recommends. Closes: #536821
* Fix an always false test when trying to decide which package to deselect
  to resolve a dependency problem in dselect.
* Add uClibc Linux support to ostable and triplettable. Closes: #455501
* Add uClinux support to ostable and triplettable.
  Thanks to Simon Richter <sjr@debian.org>.
* When aborting due to file conflicts print the version of the conflicted
  package. Closes: #540019
* Remove double slash in database path visible to the user in some error
  conditions.
* Stop macthing sparc64-*-* GNU triplets with sparc Debian architecture.
* Add support for config.d style directories in dpkg and dselect,
  (/etc/dpkg/dpkg.cfg.d and /etc/dpkg/dselect.cfg.d respectively).
* Define DPKG_MAINTSCRIPT_ARCH on the maintainer script environment to the
  architecture the package got built for.
* Document DPKG_MAINTSCRIPT_PACKAGE maintainer script environment variable
  in dpkg man page.
* Document DPKG_RUNNING_VERSION maintainer script environment variable
  in dpkg man page.
* Change po4a usage to not create unwated changes depending if doing out or
  in-tree builds.
* Use po4a “--previous” support when updating the man pages.
  Suggested by Christian Perrier <bubulle@debian.org>.
* On configuration error print file name and line number.
* Allow quoting values in configuration file options.
* Add new --pre-invoke and --post-invoke hooks in dpkg.
* Add new --control-path command to dpkg-query.
* Use ohshit on bad version syntax in --compare-versions.
* Add Multi-Arch to the list of known binary package fields for dpkg-dev.
  Thanks to Steve Langasek <vorlon@debian.org>.

[ Raphael Hertzog ]
* Replace install-info by a wrapper around GNU's install-info. The wrapper
  will be dropped in squeeze+1. dpkg now Breaks: old versions of
  info-browsers that do not depend on the new install-info package
  that provides the real functionality. Closes: #9771, #523980
  See http://wiki.debian.org/Transitions/DpkgToGnuInstallInfo for details.
* Fix dpkg's preinst in case /var/lib/dpkg/alternatives contains unexpected
  sub-directories. Closes: #535138
  And also when one of the file doesn't contain correct alternatives
  information (improper number of lines). Closes: #537558
* Upgrade Standards-Version to 3.8.2 (no changes).
* Update deb-substvars(5) to list fields that do not support substvars.
  Closes: #535353
* Fix dpkg-parsechangelog to include all entries with -v0 parameter.
  Closes: #537800
* Fix update-alternatives to mention the correct slave link that can't
  be installed due to a conflicting file instead of quoting the master link.
* Add support for extra override file in dpkg-scanpackages. Thanks to Robert
  Millan for the patch. Closes: #537559
* Add support for extra override file in dpkg-scansources.
* Document format of extra override file in a new manual page
  deb-extra-override(5).
* Update sample in dpkg-gensymbols(1) to give an accurate listing of
  64 bit arches. Thanks to Julien Cristau for the patch. Closes: #540382
* Create /etc/cron.daily/dpkg to handle the backup of
  /var/lib/dpkg/status in /var/backups. This is taken out of the cron
  package and need no conflicts/breaks as the code does nothing if
  the current status file is already backupped. Thanks to Leo 'costela'
  Antunes <costela@debian.org> for the patch. Closes: #541412
* Change behaviour of dpkg --merge-avail to not update a package's
  information if the version provided is older than the one already listed
  in the available file. Thanks to Ian Jackson
  <ian@davenant.greenend.org.uk> for the patch. Closes: #496114
* dpkg-architecture can now export DEB_{HOST,BUILD}_ARCH_{BITS,ENDIAN}
  (pointer size and endianness):
  - cputable (in dpkg) modified to contain those information
  - dpkg-dev depends on dpkg (>= 1.15.4) to ensure that we have an updated
    cputable (and so that a versioned build-dependency on dpkg-dev is enough
    to use this new feature)
  Closes: #531307
* Split overly long Binary: field values over multiple lines. This is
  allowed since policy 3.8.3. Closes: #494714
* Improve performance of dpkg-shlibdeps by caching minimal version
  associated to each library in Dpkg::Shlib::SymbolFile. Thanks to
  Jiří Paleček <jpalecek@web.de> for the patch.
* Slightly improve dpkg-source(1) by giving the section name that we're
  referring to. Closes: #544037
* Fix translation error in german manpage of dpkg-buildpackage. Thanks
  to Joachim Breitner <nomeata@debian.org>. Closes: #541829

[ Modestas Vainius ]
* Provide a meaningful label for dpkg-gensymbols diff.

[ Updated dpkg translations ]
* Asturian (Marcos Alvarez Costales). Closes: #535327
* French (Christian Perrier).
* German (Sven Joachim).
* Italian (Milo Casagrande). Closes: #536538
* Russian (Yuri Kozlov). Closes: #542254
* Slovak (Ivan Masár). Closes: #537742
* Swedish (Peter Krefting).

[ Updated dselect translations ]
* Russian (Yuri Kozlov). Closes: #542254
* Slovak (Ivan Masár). Closes: #537741

[ Updated man page translations ]
* French (Christian Perrier).
* German (Helge Kreutzmann), proofread by Jens Seidel.
* Swedish (Peter Krefting).

[ Updated scripts translations ]
* French completed (Christian Perrier).
* German (Helge Kreutzmann).
* Russian (Yuri Kozlov). Closes: #542254
* Swedish (Peter Krefting).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * dpkg - main program for package management
 
3
 * dbmodify.c - routines for managing dpkg database updates
 
4
 *
 
5
 * Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
 
6
 * Copyright © 2001 Wichert Akkerman <wichert@debian.org>
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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.
 
21
 */
 
22
#include <config.h>
 
23
#include <compat.h>
 
24
 
 
25
#include <dpkg/i18n.h>
 
26
 
 
27
#include <stdio.h>
 
28
#include <string.h>
 
29
#include <stdlib.h>
 
30
#include <signal.h>
 
31
#include <sys/stat.h>
 
32
#include <sys/types.h>
 
33
#include <sys/wait.h>
 
34
#include <errno.h>
 
35
#include <unistd.h>
 
36
#include <dirent.h>
 
37
#include <limits.h>
 
38
#include <ctype.h>
 
39
#include <time.h>
 
40
#include <assert.h>
 
41
 
 
42
#include <dpkg/dpkg.h>
 
43
#include <dpkg/dpkg-db.h>
 
44
 
 
45
char *statusfile=NULL, *availablefile=NULL;
 
46
char *triggersdir, *triggersfilefile, *triggersnewfilefile;
 
47
 
 
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;
 
56
 
 
57
static int ulist_select(const struct dirent *de) {
 
58
  const char *p;
 
59
  int l;
 
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);
 
69
  return 1;
 
70
}
 
71
 
 
72
static void cleanupdates(void) {
 
73
  struct dirent **cdlist;
 
74
  int cdn, i;
 
75
 
 
76
  parsedb(statusfile, pdb_weakclassification, NULL,NULL,NULL);
 
77
 
 
78
  *updatefnrest = '\0';
 
79
  updateslength= -1;
 
80
  cdn= scandir(updatefnbuf, &cdlist, &ulist_select, alphasort);
 
81
  if (cdn == -1) ohshite(_("cannot scan updates directory `%.255s'"),updatefnbuf);
 
82
 
 
83
  if (cdn) {
 
84
    
 
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]);
 
89
    }
 
90
 
 
91
    if (cstatus >= msdbrw_write) {
 
92
      writedb(statusfile,0,1);
 
93
    
 
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);
 
98
        free(cdlist[i]);
 
99
      }
 
100
    }
 
101
    
 
102
  }
 
103
  free(cdlist);
 
104
 
 
105
  nextupdate= 0;
 
106
}
 
107
 
 
108
static void createimptmp(void) {
 
109
  int i;
 
110
  
 
111
  onerr_abort++;
 
112
  
 
113
  importanttmp= fopen(importanttmpfile,"w");
 
114
  if (!importanttmp)
 
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"),
 
124
            importanttmpfile);
 
125
 
 
126
  onerr_abort--;
 
127
}
 
128
 
 
129
static const struct fni {
 
130
  const char *suffix;
 
131
  char **store;
 
132
} fnis[] = {
 
133
  {   STATUSFILE,                 &statusfile         },
 
134
  {   AVAILFILE,                  &availablefile      },
 
135
  {   UPDATESDIR IMPORTANTTMP,    &importanttmpfile   },
 
136
  {   TRIGGERSDIR,                &triggersdir        },
 
137
  {   TRIGGERSDIR "/File",        &triggersfilefile   },
 
138
  {   TRIGGERSDIR "/File.new",    &triggersnewfilefile},
 
139
  {   NULL, NULL                                      }
 
140
};
 
141
 
 
142
enum modstatdb_rw modstatdb_init(const char *adir, enum modstatdb_rw readwritereq) {
 
143
  const struct fni *fnip;
 
144
  
 
145
  admindir= adir;
 
146
 
 
147
  for (fnip=fnis; fnip->suffix; fnip++) {
 
148
    free(*fnip->store);
 
149
    *fnip->store= m_malloc(strlen(adir)+strlen(fnip->suffix)+2);
 
150
    sprintf(*fnip->store, "%s/%s", adir, fnip->suffix);
 
151
  }
 
152
 
 
153
  cflags= readwritereq & msdbrw_flagsmask;
 
154
  readwritereq &= ~msdbrw_flagsmask;
 
155
 
 
156
  switch (readwritereq) {
 
157
  case msdbrw_needsuperuser:
 
158
  case msdbrw_needsuperuserlockonly:
 
159
    if (getuid() || geteuid())
 
160
      ohshit(_("requested operation requires superuser privilege"));
 
161
    /* fall through */
 
162
  case msdbrw_write: case msdbrw_writeifposs:
 
163
    if (access(adir,W_OK)) {
 
164
      if (errno != EACCES)
 
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;
 
169
    } else {
 
170
      lockdatabase(adir);
 
171
      cstatus= (readwritereq == msdbrw_needsuperuserlockonly ?
 
172
                msdbrw_needsuperuserlockonly :
 
173
                msdbrw_write);
 
174
    }
 
175
    break;
 
176
  case msdbrw_readonly:
 
177
    cstatus= msdbrw_readonly; break;
 
178
  default:
 
179
    internerr("unknown modstatdb_rw '%d'", readwritereq);
 
180
  }
 
181
 
 
182
  updatefnbuf= m_malloc(strlen(adir)+sizeof(UPDATESDIR)+IMPORTANTMAXLEN+5);
 
183
  strcpy(updatefnbuf,adir);
 
184
  strcat(updatefnbuf,"/" UPDATESDIR);
 
185
  updatefnrest= updatefnbuf+strlen(updatefnbuf);
 
186
 
 
187
  if (cstatus != msdbrw_needsuperuserlockonly) {
 
188
    cleanupdates();
 
189
    if(!(cflags & msdbrw_noavail))
 
190
    parsedb(availablefile,
 
191
            pdb_recordavailable|pdb_rejectstatus,
 
192
            NULL,NULL,NULL);
 
193
  }
 
194
 
 
195
  if (cstatus >= msdbrw_write) {
 
196
    createimptmp();
 
197
    varbufinit(&uvb, 10240);
 
198
  }
 
199
 
 
200
  trig_fixup_awaiters(cstatus);
 
201
  trig_incorporate(cstatus, admindir);
 
202
 
 
203
  return cstatus;
 
204
}
 
205
 
 
206
void modstatdb_checkpoint(void) {
 
207
  int i;
 
208
 
 
209
  assert(cstatus >= msdbrw_write);
 
210
  writedb(statusfile,0,1);
 
211
  
 
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);
 
217
  }
 
218
  nextupdate= 0;
 
219
}
 
220
 
 
221
void modstatdb_shutdown(void) {
 
222
  const struct fni *fnip;
 
223
  switch (cstatus) {
 
224
  case msdbrw_write:
 
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);
 
230
    varbuffree(&uvb);
 
231
    /* fall through */
 
232
  case msdbrw_needsuperuserlockonly:
 
233
    unlockdatabase();
 
234
  default:
 
235
    break;
 
236
  }
 
237
 
 
238
  for (fnip=fnis; fnip->suffix; fnip++) {
 
239
    free(*fnip->store);
 
240
    *fnip->store= NULL;
 
241
  }
 
242
  free(updatefnbuf);
 
243
}
 
244
 
 
245
static void
 
246
modstatdb_note_core(struct pkginfo *pkg)
 
247
{
 
248
  assert(cstatus >= msdbrw_write);
 
249
 
 
250
  varbufreset(&uvb);
 
251
  varbufrecord(&uvb, pkg, &pkg->installed);
 
252
 
 
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);
 
266
 
 
267
  /* Have we made a real mess? */
 
268
  assert(strlen(updatefnrest) <= IMPORTANTMAXLEN);
 
269
 
 
270
  nextupdate++;
 
271
 
 
272
  if (nextupdate > MAXUPDATES) {
 
273
    modstatdb_checkpoint();
 
274
    nextupdate = 0;
 
275
  }
 
276
 
 
277
  createimptmp();
 
278
}
 
279
 
 
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
 
284
 * will be adjusted.
 
285
 */
 
286
void modstatdb_note(struct pkginfo *pkg) {
 
287
  struct trigaw *ta;
 
288
 
 
289
  onerr_abort++;
 
290
 
 
291
  /* Clear pending triggers here so that only code that sets the status
 
292
   * to interesting (for triggers) values has to care about triggers.
 
293
   */
 
294
  if (pkg->status != stat_triggerspending &&
 
295
      pkg->status != stat_triggersawaited)
 
296
    pkg->trigpend_head = NULL;
 
297
 
 
298
  if (pkg->status <= stat_configfiles) {
 
299
    for (ta = pkg->trigaw.head; ta; ta = ta->sameaw.next)
 
300
      ta->aw = NULL;
 
301
    pkg->trigaw.head = pkg->trigaw.tail = NULL;
 
302
  }
 
303
 
 
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);
 
307
 
 
308
  if (cstatus >= msdbrw_write)
 
309
    modstatdb_note_core(pkg);
 
310
 
 
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.
 
318
     */
 
319
    trig_clear_awaiters(pkg);
 
320
  }
 
321
 
 
322
  onerr_abort--;
 
323
}
 
324
 
 
325
void
 
326
modstatdb_note_ifwrite(struct pkginfo *pkg)
 
327
{
 
328
  if (cstatus >= msdbrw_write)
 
329
    modstatdb_note(pkg);
 
330
}
 
331
 
 
332
const char *pkgadminfile(struct pkginfo *pkg, const char *whichfile) {
 
333
  static struct varbuf vb;
 
334
  varbufreset(&vb);
 
335
  varbufaddstr(&vb,admindir);
 
336
  varbufaddstr(&vb,"/" INFODIR);
 
337
  varbufaddstr(&vb,pkg->name);
 
338
  varbufaddc(&vb,'.');
 
339
  varbufaddstr(&vb,whichfile);
 
340
  varbufaddc(&vb,0);
 
341
  return vb.buf;
 
342
}
 
343