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

« back to all changes in this revision

Viewing changes to lib/dump.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
 
 * libdpkg - Debian packaging suite library routines
3
 
 * dump.c - code to write in-core database to a file
4
 
 *
5
 
 * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
6
 
 * Copyright © 2001 Wichert Akkerman
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
 
 
23
 
/* FIXME: don't write uninteresting packages */
24
 
#include <config.h>
25
 
#include <compat.h>
26
 
 
27
 
#include <dpkg-i18n.h>
28
 
 
29
 
#include <stdio.h>
30
 
#include <stdlib.h>
31
 
#include <string.h>
32
 
#include <errno.h>
33
 
#include <unistd.h>
34
 
#include <ctype.h>
35
 
#include <assert.h>
36
 
#include <sys/types.h>
37
 
#include <sys/stat.h>
38
 
 
39
 
#include <dpkg.h>
40
 
#include <dpkg-db.h>
41
 
#include "parsedump.h"
42
 
 
43
 
void w_name(struct varbuf *vb,
44
 
            const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
45
 
            enum fwriteflags flags, const struct fieldinfo *fip) {
46
 
  assert(pigp->name);
47
 
  if (flags&fw_printheader)
48
 
    varbufaddstr(vb,"Package: ");
49
 
  varbufaddstr(vb, pigp->name);
50
 
  if (flags&fw_printheader)
51
 
    varbufaddc(vb,'\n');
52
 
}
53
 
 
54
 
void w_version(struct varbuf *vb,
55
 
               const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
56
 
               enum fwriteflags flags, const struct fieldinfo *fip) {
57
 
  /* Epoch and revision information is printed in version field too. */
58
 
  if (!informativeversion(&pifp->version)) return;
59
 
  if (flags&fw_printheader)
60
 
    varbufaddstr(vb,"Version: ");
61
 
  varbufversion(vb,&pifp->version,vdew_nonambig);
62
 
  if (flags&fw_printheader)
63
 
    varbufaddc(vb,'\n');
64
 
}
65
 
 
66
 
void w_configversion(struct varbuf *vb,
67
 
                     const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
68
 
                     enum fwriteflags flags, const struct fieldinfo *fip) {
69
 
  if (pifp != &pigp->installed) return;
70
 
  if (!informativeversion(&pigp->configversion)) return;
71
 
  if (pigp->status == stat_installed ||
72
 
      pigp->status == stat_notinstalled ||
73
 
      pigp->status == stat_triggerspending ||
74
 
      pigp->status == stat_triggersawaited)
75
 
    return;
76
 
  if (flags&fw_printheader)
77
 
    varbufaddstr(vb,"Config-Version: ");
78
 
  varbufversion(vb,&pigp->configversion,vdew_nonambig);
79
 
  if (flags&fw_printheader)
80
 
    varbufaddc(vb,'\n');
81
 
}
82
 
 
83
 
void w_null(struct varbuf *vb,
84
 
            const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
85
 
            enum fwriteflags flags, const struct fieldinfo *fip) {
86
 
}
87
 
 
88
 
void w_section(struct varbuf *vb,
89
 
               const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
90
 
               enum fwriteflags flags, const struct fieldinfo *fip) {
91
 
  const char *value= pigp->section;
92
 
  if (!value || !*value) return;
93
 
  if (flags&fw_printheader)
94
 
    varbufaddstr(vb,"Section: ");
95
 
  varbufaddstr(vb,value);
96
 
  if (flags&fw_printheader)
97
 
    varbufaddc(vb,'\n');
98
 
}
99
 
 
100
 
void w_charfield(struct varbuf *vb,
101
 
                 const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
102
 
                 enum fwriteflags flags, const struct fieldinfo *fip) {
103
 
  const char *value= pifp->valid ? PKGPFIELD(pifp,fip->integer,const char*) : NULL;
104
 
  if (!value || !*value) return;
105
 
  if (flags&fw_printheader) {
106
 
    varbufaddstr(vb,fip->name);
107
 
    varbufaddstr(vb, ": ");
108
 
  }
109
 
  varbufaddstr(vb,value);
110
 
  if (flags&fw_printheader)
111
 
    varbufaddc(vb,'\n');
112
 
}
113
 
 
114
 
void w_filecharf(struct varbuf *vb,
115
 
                 const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
116
 
                 enum fwriteflags flags, const struct fieldinfo *fip) {
117
 
  struct filedetails *fdp;
118
 
  
119
 
  if (pifp != &pigp->available) return;
120
 
  fdp= pigp->files;
121
 
  if (!fdp || !FILEFFIELD(fdp,fip->integer,const char*)) return;
122
 
 
123
 
  if (flags&fw_printheader) {
124
 
    varbufaddstr(vb,fip->name);
125
 
    varbufaddc(vb,':');
126
 
  }
127
 
 
128
 
  while (fdp) {
129
 
    varbufaddc(vb,' ');
130
 
    varbufaddstr(vb,FILEFFIELD(fdp,fip->integer,const char*));
131
 
    fdp= fdp->next;
132
 
  }
133
 
 
134
 
  if (flags&fw_printheader)
135
 
    varbufaddc(vb,'\n');
136
 
}
137
 
 
138
 
void w_booleandefno(struct varbuf *vb,
139
 
                    const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
140
 
                    enum fwriteflags flags, const struct fieldinfo *fip) {
141
 
  int value= pifp->valid ? PKGPFIELD(pifp,fip->integer,int) : -1;
142
 
  if (!(flags&fw_printheader)) {
143
 
    varbufaddstr(vb, (value==1) ? "yes" : "no");
144
 
    return;
145
 
  }
146
 
  if (!value) return;
147
 
  assert(value==1);
148
 
  varbufaddstr(vb,fip->name); varbufaddstr(vb, ": yes\n"); 
149
 
}
150
 
 
151
 
void w_priority(struct varbuf *vb,
152
 
                const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
153
 
                enum fwriteflags flags, const struct fieldinfo *fip) {
154
 
  if (pigp->priority == pri_unknown) return;
155
 
  assert(pigp->priority <= pri_unknown);
156
 
  if (flags&fw_printheader)
157
 
    varbufaddstr(vb,"Priority: ");
158
 
  varbufaddstr(vb,
159
 
               pigp->priority == pri_other
160
 
               ? pigp->otherpriority
161
 
               : priorityinfos[pigp->priority].name);
162
 
  if (flags&fw_printheader)
163
 
    varbufaddc(vb,'\n');
164
 
}
165
 
 
166
 
void w_status(struct varbuf *vb,
167
 
              const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
168
 
              enum fwriteflags flags, const struct fieldinfo *fip) {
169
 
  if (pifp != &pigp->installed) return;
170
 
  assert(pigp->want <= want_purge);
171
 
  assert(pigp->eflag <= eflagv_reinstreq); /* hold and hold-reinstreq NOT allowed */
172
 
 
173
 
#define PEND pigp->trigpend_head
174
 
#define AW pigp->trigaw.head
175
 
  switch (pigp->status) {
176
 
  case stat_notinstalled:
177
 
  case stat_configfiles:
178
 
    assert(!PEND);
179
 
    assert(!AW);
180
 
    break;
181
 
  case stat_halfinstalled:
182
 
  case stat_unpacked:
183
 
  case stat_halfconfigured:
184
 
    assert(!PEND);
185
 
    break;
186
 
  case stat_triggersawaited:
187
 
    assert(AW);
188
 
    break;
189
 
  case stat_triggerspending:
190
 
    assert(PEND);
191
 
    assert(!AW);
192
 
    break;
193
 
  case stat_installed:
194
 
    assert(!PEND);
195
 
    assert(!AW);
196
 
    break;
197
 
  default:
198
 
    internerr("unknown package status '%d'", pigp->status);
199
 
  }
200
 
#undef PEND
201
 
#undef AW
202
 
 
203
 
  if (flags&fw_printheader)
204
 
    varbufaddstr(vb,"Status: ");
205
 
  varbufaddstr(vb,wantinfos[pigp->want].name); varbufaddc(vb,' ');
206
 
  varbufaddstr(vb,eflaginfos[pigp->eflag].name); varbufaddc(vb,' ');
207
 
  varbufaddstr(vb,statusinfos[pigp->status].name);
208
 
  if (flags&fw_printheader)
209
 
    varbufaddc(vb,'\n');
210
 
}
211
 
 
212
 
void varbufdependency(struct varbuf *vb, struct dependency *dep) {
213
 
  struct deppossi *dop;
214
 
  const char *possdel;
215
 
 
216
 
  possdel= "";
217
 
  for (dop= dep->list; dop; dop= dop->next) {
218
 
    assert(dop->up == dep);
219
 
    varbufaddstr(vb,possdel); possdel= " | ";
220
 
    varbufaddstr(vb,dop->ed->name);
221
 
    if (dop->verrel != dvr_none) {
222
 
      varbufaddstr(vb," (");
223
 
      switch (dop->verrel) {
224
 
      case dvr_exact: varbufaddc(vb,'='); break;
225
 
      case dvr_laterequal: varbufaddstr(vb,">="); break;
226
 
      case dvr_earlierequal: varbufaddstr(vb,"<="); break;
227
 
      case dvr_laterstrict: varbufaddstr(vb,">>"); break;
228
 
      case dvr_earlierstrict: varbufaddstr(vb,"<<"); break;
229
 
      default:
230
 
        internerr("unknown verrel '%d'", dop->verrel);
231
 
      }
232
 
      varbufaddc(vb,' ');
233
 
      varbufversion(vb,&dop->version,vdew_nonambig);
234
 
      varbufaddc(vb,')');
235
 
    }
236
 
  }
237
 
}
238
 
 
239
 
void w_dependency(struct varbuf *vb,
240
 
                  const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
241
 
                  enum fwriteflags flags, const struct fieldinfo *fip) {
242
 
  char fnbuf[50];
243
 
  const char *depdel;
244
 
  struct dependency *dyp;
245
 
 
246
 
  if (!pifp->valid) return;
247
 
  if (flags&fw_printheader)
248
 
    sprintf(fnbuf,"%s: ",fip->name);
249
 
  else
250
 
    fnbuf[0] = '\0';
251
 
 
252
 
  depdel= fnbuf;
253
 
  for (dyp= pifp->depends; dyp; dyp= dyp->next) {
254
 
    if (dyp->type != fip->integer) continue;
255
 
    assert(dyp->up == pigp);
256
 
    varbufaddstr(vb,depdel); depdel= ", ";
257
 
    varbufdependency(vb,dyp);
258
 
  }
259
 
  if ((flags&fw_printheader) && (depdel!=fnbuf))
260
 
    varbufaddc(vb,'\n');
261
 
}
262
 
 
263
 
void w_conffiles(struct varbuf *vb,
264
 
                 const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
265
 
                 enum fwriteflags flags, const struct fieldinfo *fip) {
266
 
  struct conffile *i;
267
 
 
268
 
  if (!pifp->valid || !pifp->conffiles || pifp == &pigp->available) return;
269
 
  if (flags&fw_printheader)
270
 
    varbufaddstr(vb,"Conffiles:\n");
271
 
  for (i=pifp->conffiles; i; i= i->next) {
272
 
    if (i!=pifp->conffiles) varbufaddc(vb,'\n');
273
 
    varbufaddc(vb,' '); varbufaddstr(vb,i->name); varbufaddc(vb,' ');
274
 
    varbufaddstr(vb,i->hash);
275
 
    if (i->obsolete) varbufaddstr(vb," obsolete");
276
 
  }
277
 
  if (flags&fw_printheader)
278
 
    varbufaddc(vb,'\n');
279
 
}
280
 
 
281
 
void
282
 
w_trigpend(struct varbuf *vb,
283
 
           const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
284
 
           enum fwriteflags flags, const struct fieldinfo *fip)
285
 
{
286
 
  struct trigpend *tp;
287
 
 
288
 
  if (!pifp->valid || pifp == &pigp->available || !pigp->trigpend_head)
289
 
    return;
290
 
 
291
 
  assert(pigp->status >= stat_triggersawaited &&
292
 
         pigp->status <= stat_triggerspending);
293
 
 
294
 
  if (flags & fw_printheader)
295
 
    varbufaddstr(vb, "Triggers-Pending:");
296
 
  for (tp = pigp->trigpend_head; tp; tp = tp->next) {
297
 
    varbufaddc(vb, ' ');
298
 
    varbufaddstr(vb, tp->name);
299
 
  }
300
 
  if (flags & fw_printheader)
301
 
    varbufaddc(vb, '\n');
302
 
}
303
 
 
304
 
void
305
 
w_trigaw(struct varbuf *vb,
306
 
         const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
307
 
         enum fwriteflags flags, const struct fieldinfo *fip)
308
 
{
309
 
  struct trigaw *ta;
310
 
 
311
 
  if (!pifp->valid || pifp == &pigp->available || !pigp->trigaw.head)
312
 
    return;
313
 
 
314
 
  assert(pigp->status > stat_configfiles &&
315
 
         pigp->status <= stat_triggersawaited);
316
 
 
317
 
  if (flags & fw_printheader)
318
 
    varbufaddstr(vb, "Triggers-Awaited:");
319
 
  for (ta = pigp->trigaw.head; ta; ta = ta->sameaw.next) {
320
 
    varbufaddc(vb, ' ');
321
 
    varbufaddstr(vb, ta->pend->name);
322
 
  }
323
 
  if (flags & fw_printheader)
324
 
    varbufaddc(vb, '\n');
325
 
}
326
 
 
327
 
void varbufrecord(struct varbuf *vb,
328
 
                  const struct pkginfo *pigp, const struct pkginfoperfile *pifp) {
329
 
  const struct fieldinfo *fip;
330
 
  const struct arbitraryfield *afp;
331
 
 
332
 
  for (fip= fieldinfos; fip->name; fip++) {
333
 
    fip->wcall(vb,pigp,pifp,fw_printheader,fip);
334
 
  }
335
 
  if (pifp->valid) {
336
 
    for (afp= pifp->arbs; afp; afp= afp->next) {
337
 
      varbufaddstr(vb,afp->name); varbufaddstr(vb,": ");
338
 
      varbufaddstr(vb,afp->value); varbufaddc(vb,'\n');
339
 
    }
340
 
  }
341
 
}
342
 
 
343
 
void writerecord(FILE *file, const char *filename,
344
 
                 const struct pkginfo *pigp, const struct pkginfoperfile *pifp) {
345
 
  struct varbuf vb = VARBUF_INIT;
346
 
 
347
 
  varbufrecord(&vb,pigp,pifp);
348
 
  varbufaddc(&vb,'\0');
349
 
  if (fputs(vb.buf,file) < 0)
350
 
    ohshite(_("failed to write details of `%.50s' to `%.250s'"), pigp->name,
351
 
            filename);
352
 
   varbuffree(&vb);
353
 
}
354
 
 
355
 
void writedb(const char *filename, int available, int mustsync) {
356
 
  static char writebuf[8192];
357
 
  
358
 
  struct pkgiterator *it;
359
 
  struct pkginfo *pigp;
360
 
  struct pkginfoperfile *pifp;
361
 
  char *oldfn, *newfn;
362
 
  const char *which;
363
 
  FILE *file;
364
 
  struct varbuf vb = VARBUF_INIT;
365
 
  int old_umask;
366
 
 
367
 
  which= available ? "available" : "status";
368
 
  oldfn= m_malloc(strlen(filename)+sizeof(OLDDBEXT));
369
 
  strcpy(oldfn,filename); strcat(oldfn,OLDDBEXT);
370
 
  newfn= m_malloc(strlen(filename)+sizeof(NEWDBEXT));
371
 
  strcpy(newfn,filename); strcat(newfn,NEWDBEXT);
372
 
 
373
 
  old_umask = umask(022);
374
 
  file= fopen(newfn,"w");
375
 
  umask(old_umask);
376
 
  if (!file) ohshite(_("failed to open `%s' for writing %s information"),filename,which);
377
 
  
378
 
  if (setvbuf(file,writebuf,_IOFBF,sizeof(writebuf)))
379
 
    ohshite(_("unable to set buffering on status file"));
380
 
 
381
 
  it= iterpkgstart();
382
 
  while ((pigp= iterpkgnext(it)) != NULL) {
383
 
    pifp= available ? &pigp->available : &pigp->installed;
384
 
    /* Don't dump records which have no useful content. */
385
 
    if (!informative(pigp,pifp)) continue;
386
 
    if (!pifp->valid) blankpackageperfile(pifp);
387
 
    varbufrecord(&vb,pigp,pifp);
388
 
    varbufaddc(&vb,'\n'); varbufaddc(&vb,0);
389
 
    if (fputs(vb.buf,file) < 0)
390
 
      ohshite(_("failed to write %s record about `%.50s' to `%.250s'"),
391
 
              which, pigp->name, filename);
392
 
    varbufreset(&vb);      
393
 
  }
394
 
  iterpkgend(it);
395
 
  varbuffree(&vb);
396
 
  if (mustsync) {
397
 
    if (fflush(file))
398
 
      ohshite(_("failed to flush %s information to `%.250s'"), which, filename);
399
 
    if (fsync(fileno(file)))
400
 
      ohshite(_("failed to fsync %s information to `%.250s'"), which, filename);
401
 
  }
402
 
  if (fclose(file)) ohshite(_("failed to close `%.250s' after writing %s information"),
403
 
                            filename, which);
404
 
  unlink(oldfn);
405
 
  if (link(filename,oldfn) && errno != ENOENT)
406
 
    ohshite(_("failed to link `%.250s' to `%.250s' for backup of %s info"),
407
 
            filename, oldfn, which);
408
 
  if (rename(newfn,filename))
409
 
    ohshite(_("failed to install `%.250s' as `%.250s' containing %s info"),
410
 
            newfn, filename, which);
411
 
  free(newfn);
412
 
  free(oldfn);
413
 
}