Branch data Line data Source code
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 <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2001 Wichert Akkerman
7 : : * Copyright © 2006,2008-2014 Guillem Jover <guillem@debian.org>
8 : : * Copyright © 2011 Linaro Limited
9 : : * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
10 : : *
11 : : * This is free software; you can redistribute it and/or modify
12 : : * it under the terms of the GNU General Public License as published by
13 : : * the Free Software Foundation; either version 2 of the License, or
14 : : * (at your option) any later version.
15 : : *
16 : : * This is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU General Public License for more details.
20 : : *
21 : : * You should have received a copy of the GNU General Public License
22 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 : : */
24 : :
25 : : #include <config.h>
26 : : #include <compat.h>
27 : :
28 : : #include <sys/types.h>
29 : : #include <sys/stat.h>
30 : :
31 : : #include <errno.h>
32 : : #include <string.h>
33 : : #include <unistd.h>
34 : : #include <stdio.h>
35 : : #include <stdlib.h>
36 : : #include <stdbool.h>
37 : :
38 : : #include <dpkg/i18n.h>
39 : : #include <dpkg/dpkg.h>
40 : : #include <dpkg/dpkg-db.h>
41 : : #include <dpkg/pkg-array.h>
42 : : #include <dpkg/pkg-show.h>
43 : : #include <dpkg/string.h>
44 : : #include <dpkg/dir.h>
45 : : #include <dpkg/parsedump.h>
46 : :
47 : : static inline void
48 : 2 : varbuf_add_fieldname(struct varbuf *vb, const struct fieldinfo *fip)
49 : : {
50 : 2 : varbuf_add_str(vb, fip->name);
51 : 2 : varbuf_add_str(vb, ": ");
52 : 2 : }
53 : :
54 : : void
55 : 1 : w_name(struct varbuf *vb,
56 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
57 : : enum fwriteflags flags, const struct fieldinfo *fip)
58 : : {
59 [ - + ]: 1 : if (pkg->set->name == NULL)
60 : 0 : internerr("pkgset has no name");
61 : :
62 [ - + ]: 1 : if (flags&fw_printheader)
63 : 0 : varbuf_add_str(vb, "Package: ");
64 : 1 : varbuf_add_str(vb, pkg->set->name);
65 [ - + ]: 1 : if (flags&fw_printheader)
66 : 0 : varbuf_add_char(vb, '\n');
67 : 1 : }
68 : :
69 : : void
70 : 2 : w_version(struct varbuf *vb,
71 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
72 : : enum fwriteflags flags, const struct fieldinfo *fip)
73 : : {
74 [ - + ]: 2 : if (!dpkg_version_is_informative(&pkgbin->version))
75 : 0 : return;
76 [ + + ]: 2 : if (flags&fw_printheader)
77 : 1 : varbuf_add_str(vb, "Version: ");
78 : 2 : varbufversion(vb, &pkgbin->version, vdew_nonambig);
79 [ + + ]: 2 : if (flags&fw_printheader)
80 : 1 : varbuf_add_char(vb, '\n');
81 : : }
82 : :
83 : : void
84 : 0 : w_configversion(struct varbuf *vb,
85 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
86 : : enum fwriteflags flags, const struct fieldinfo *fip)
87 : : {
88 [ # # ]: 0 : if (pkgbin != &pkg->installed)
89 : 0 : return;
90 [ # # ]: 0 : if (!dpkg_version_is_informative(&pkg->configversion))
91 : 0 : return;
92 [ # # ]: 0 : if (pkg->status == PKG_STAT_INSTALLED ||
93 [ # # ]: 0 : pkg->status == PKG_STAT_NOTINSTALLED ||
94 [ # # ]: 0 : pkg->status == PKG_STAT_TRIGGERSPENDING)
95 : 0 : return;
96 [ # # ]: 0 : if (flags&fw_printheader)
97 : 0 : varbuf_add_str(vb, "Config-Version: ");
98 : 0 : varbufversion(vb, &pkg->configversion, vdew_nonambig);
99 [ # # ]: 0 : if (flags&fw_printheader)
100 : 0 : varbuf_add_char(vb, '\n');
101 : : }
102 : :
103 : : void
104 : 0 : w_null(struct varbuf *vb,
105 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
106 : : enum fwriteflags flags, const struct fieldinfo *fip)
107 : : {
108 : 0 : }
109 : :
110 : : void
111 : 0 : w_section(struct varbuf *vb,
112 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
113 : : enum fwriteflags flags, const struct fieldinfo *fip)
114 : : {
115 : 0 : const char *value = pkg->section;
116 : :
117 [ # # ]: 0 : if (str_is_unset(value))
118 : 0 : return;
119 [ # # ]: 0 : if (flags&fw_printheader)
120 : 0 : varbuf_add_str(vb, "Section: ");
121 : 0 : varbuf_add_str(vb, value);
122 [ # # ]: 0 : if (flags&fw_printheader)
123 : 0 : varbuf_add_char(vb, '\n');
124 : : }
125 : :
126 : : void
127 : 0 : w_charfield(struct varbuf *vb,
128 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
129 : : enum fwriteflags flags, const struct fieldinfo *fip)
130 : : {
131 : 0 : const char *value = STRUCTFIELD(pkgbin, fip->integer, const char *);
132 : :
133 [ # # ]: 0 : if (str_is_unset(value))
134 : 0 : return;
135 [ # # ]: 0 : if (flags & fw_printheader)
136 : 0 : varbuf_add_fieldname(vb, fip);
137 : 0 : varbuf_add_str(vb, value);
138 [ # # ]: 0 : if (flags&fw_printheader)
139 : 0 : varbuf_add_char(vb, '\n');
140 : : }
141 : :
142 : : void
143 : 0 : w_archives(struct varbuf *vb,
144 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
145 : : enum fwriteflags flags, const struct fieldinfo *fip)
146 : : {
147 : : struct archivedetails *archive;
148 : :
149 [ # # ]: 0 : if (pkgbin != &pkg->available)
150 : 0 : return;
151 : 0 : archive = pkg->archives;
152 [ # # # # ]: 0 : if (!archive || !STRUCTFIELD(archive, fip->integer, const char *))
153 : 0 : return;
154 : :
155 [ # # ]: 0 : if (flags&fw_printheader) {
156 : 0 : varbuf_add_str(vb, fip->name);
157 : 0 : varbuf_add_char(vb, ':');
158 : : }
159 : :
160 [ # # ]: 0 : while (archive) {
161 : 0 : varbuf_add_char(vb, ' ');
162 : 0 : varbuf_add_str(vb, STRUCTFIELD(archive, fip->integer, const char *));
163 : 0 : archive = archive->next;
164 : : }
165 : :
166 [ # # ]: 0 : if (flags&fw_printheader)
167 : 0 : varbuf_add_char(vb, '\n');
168 : : }
169 : :
170 : : void
171 : 0 : w_booleandefno(struct varbuf *vb,
172 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
173 : : enum fwriteflags flags, const struct fieldinfo *fip)
174 : : {
175 : 0 : bool value = STRUCTFIELD(pkgbin, fip->integer, bool);
176 : :
177 [ # # # # ]: 0 : if ((flags & fw_printheader) && !value)
178 : 0 : return;
179 : :
180 [ # # ]: 0 : if (flags & fw_printheader)
181 : 0 : varbuf_add_fieldname(vb, fip);
182 : :
183 [ # # # # ]: 0 : varbuf_add_str(vb, value ? "yes" : "no");
184 : :
185 [ # # ]: 0 : if (flags & fw_printheader)
186 : 0 : varbuf_add_char(vb, '\n');
187 : : }
188 : :
189 : : void
190 : 0 : w_multiarch(struct varbuf *vb,
191 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
192 : : enum fwriteflags flags, const struct fieldinfo *fip)
193 : : {
194 : 0 : int value = STRUCTFIELD(pkgbin, fip->integer, int);
195 : :
196 [ # # # # ]: 0 : if ((flags & fw_printheader) && !value)
197 : 0 : return;
198 : :
199 [ # # ]: 0 : if (flags & fw_printheader)
200 : 0 : varbuf_add_fieldname(vb, fip);
201 : :
202 : 0 : varbuf_add_str(vb, multiarchinfos[value].name);
203 : :
204 [ # # ]: 0 : if (flags & fw_printheader)
205 : 0 : varbuf_add_char(vb, '\n');
206 : : }
207 : :
208 : : void
209 : 1 : w_architecture(struct varbuf *vb,
210 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
211 : : enum fwriteflags flags, const struct fieldinfo *fip)
212 : : {
213 [ - + ]: 1 : if (!pkgbin->arch)
214 : 0 : return;
215 [ - + ]: 1 : if (pkgbin->arch->type == DPKG_ARCH_NONE)
216 : 0 : return;
217 [ - + ]: 1 : if (pkgbin->arch->type == DPKG_ARCH_EMPTY)
218 : 0 : return;
219 : :
220 [ - + ]: 1 : if (flags & fw_printheader)
221 : 0 : varbuf_add_fieldname(vb, fip);
222 : 1 : varbuf_add_str(vb, pkgbin->arch->name);
223 [ - + ]: 1 : if (flags & fw_printheader)
224 : 0 : varbuf_add_char(vb, '\n');
225 : : }
226 : :
227 : : void
228 : 1 : w_priority(struct varbuf *vb,
229 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
230 : : enum fwriteflags flags, const struct fieldinfo *fip)
231 : : {
232 [ - + ]: 1 : if (pkg->priority == PKG_PRIO_UNKNOWN)
233 : 0 : return;
234 : :
235 [ - + ]: 1 : if (pkg->priority > PKG_PRIO_UNKNOWN)
236 : 0 : internerr("package %s has out-of-range priority %d",
237 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg->priority);
238 : :
239 [ + - ]: 1 : if (flags&fw_printheader)
240 : 1 : varbuf_add_str(vb, "Priority: ");
241 : 1 : varbuf_add_str(vb, pkg_priority_name(pkg));
242 [ + - ]: 1 : if (flags&fw_printheader)
243 : 1 : varbuf_add_char(vb, '\n');
244 : : }
245 : :
246 : : void
247 : 0 : w_status(struct varbuf *vb,
248 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
249 : : enum fwriteflags flags, const struct fieldinfo *fip)
250 : : {
251 [ # # ]: 0 : if (pkgbin != &pkg->installed)
252 : 0 : return;
253 : :
254 [ # # ]: 0 : if (pkg->want > PKG_WANT_PURGE)
255 : 0 : internerr("package %s has unknown want state %d",
256 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg->want);
257 [ # # ]: 0 : if (pkg->eflag > PKG_EFLAG_REINSTREQ)
258 : 0 : internerr("package %s has unknown error state %d",
259 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg->eflag);
260 : :
261 [ # # # # : 0 : switch (pkg->status) {
# # ]
262 : 0 : case PKG_STAT_NOTINSTALLED:
263 : : case PKG_STAT_CONFIGFILES:
264 [ # # # # ]: 0 : if (pkg->trigpend_head || pkg->trigaw.head)
265 : 0 : internerr("package %s in state %s, has awaited or pending triggers",
266 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
267 : 0 : break;
268 : 0 : case PKG_STAT_HALFINSTALLED:
269 : : case PKG_STAT_UNPACKED:
270 : : case PKG_STAT_HALFCONFIGURED:
271 [ # # ]: 0 : if (pkg->trigpend_head)
272 : 0 : internerr("package %s in state %s, has pending triggers",
273 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
274 : 0 : break;
275 : 0 : case PKG_STAT_TRIGGERSAWAITED:
276 [ # # ]: 0 : if (pkg->trigaw.head == NULL)
277 : 0 : internerr("package %s in state %s, has no awaited triggers",
278 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
279 : 0 : break;
280 : 0 : case PKG_STAT_TRIGGERSPENDING:
281 [ # # # # ]: 0 : if (pkg->trigpend_head == NULL || pkg->trigaw.head)
282 : 0 : internerr("package %s in stata %s, has awaited or no pending triggers",
283 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
284 : 0 : break;
285 : 0 : case PKG_STAT_INSTALLED:
286 [ # # # # ]: 0 : if (pkg->trigpend_head || pkg->trigaw.head)
287 : 0 : internerr("package %s in state %s, has awaited or pending triggers",
288 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
289 : 0 : break;
290 : 0 : default:
291 : 0 : internerr("unknown package status '%d'", pkg->status);
292 : : }
293 : :
294 [ # # ]: 0 : if (flags&fw_printheader)
295 : 0 : varbuf_add_str(vb, "Status: ");
296 : 0 : varbuf_add_str(vb, pkg_want_name(pkg));
297 : 0 : varbuf_add_char(vb, ' ');
298 : 0 : varbuf_add_str(vb, pkg_eflag_name(pkg));
299 : 0 : varbuf_add_char(vb, ' ');
300 : 0 : varbuf_add_str(vb, pkg_status_name(pkg));
301 [ # # ]: 0 : if (flags&fw_printheader)
302 : 0 : varbuf_add_char(vb, '\n');
303 : : }
304 : :
305 : 2 : void varbufdependency(struct varbuf *vb, struct dependency *dep) {
306 : : struct deppossi *dop;
307 : : const char *possdel;
308 : :
309 : 2 : possdel= "";
310 [ + + ]: 4 : for (dop= dep->list; dop; dop= dop->next) {
311 [ - + ]: 2 : if (dop->up != dep)
312 : 0 : internerr("dependency and deppossi not linked properly");
313 : :
314 : 2 : varbuf_add_str(vb, possdel);
315 : 2 : possdel = " | ";
316 : 2 : varbuf_add_str(vb, dop->ed->name);
317 [ - + ]: 2 : if (!dop->arch_is_implicit)
318 : 0 : varbuf_add_archqual(vb, dop->arch);
319 [ - + ]: 2 : if (dop->verrel != DPKG_RELATION_NONE) {
320 : 0 : varbuf_add_str(vb, " (");
321 [ # # # # : 0 : switch (dop->verrel) {
# # ]
322 : 0 : case DPKG_RELATION_EQ:
323 : 0 : varbuf_add_char(vb, '=');
324 : 0 : break;
325 : 0 : case DPKG_RELATION_GE:
326 : 0 : varbuf_add_str(vb, ">=");
327 : 0 : break;
328 : 0 : case DPKG_RELATION_LE:
329 : 0 : varbuf_add_str(vb, "<=");
330 : 0 : break;
331 : 0 : case DPKG_RELATION_GT:
332 : 0 : varbuf_add_str(vb, ">>");
333 : 0 : break;
334 : 0 : case DPKG_RELATION_LT:
335 : 0 : varbuf_add_str(vb, "<<");
336 : 0 : break;
337 : 0 : default:
338 : 0 : internerr("unknown dpkg_relation %d", dop->verrel);
339 : : }
340 : 0 : varbuf_add_char(vb, ' ');
341 : 0 : varbufversion(vb,&dop->version,vdew_nonambig);
342 : 0 : varbuf_add_char(vb, ')');
343 : : }
344 : : }
345 : 2 : }
346 : :
347 : : void
348 : 2 : w_dependency(struct varbuf *vb,
349 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
350 : : enum fwriteflags flags, const struct fieldinfo *fip)
351 : : {
352 : : struct dependency *dyp;
353 : 2 : bool dep_found = false;
354 : :
355 [ + + ]: 6 : for (dyp = pkgbin->depends; dyp; dyp = dyp->next) {
356 [ + + ]: 4 : if (dyp->type != fip->integer) continue;
357 : :
358 [ - + ]: 2 : if (dyp->up != pkg)
359 : 0 : internerr("dependency and package %s not linked properly",
360 : : pkgbin_name_const(pkg, pkgbin, pnaw_always));
361 : :
362 [ - + ]: 2 : if (dep_found) {
363 : 0 : varbuf_add_str(vb, ", ");
364 : : } else {
365 [ + - ]: 2 : if (flags & fw_printheader)
366 : 2 : varbuf_add_fieldname(vb, fip);
367 : 2 : dep_found = true;
368 : : }
369 : 2 : varbufdependency(vb,dyp);
370 : : }
371 [ + - + - ]: 2 : if ((flags & fw_printheader) && dep_found)
372 : 2 : varbuf_add_char(vb, '\n');
373 : 2 : }
374 : :
375 : : void
376 : 0 : w_conffiles(struct varbuf *vb,
377 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
378 : : enum fwriteflags flags, const struct fieldinfo *fip)
379 : : {
380 : : struct conffile *i;
381 : :
382 [ # # # # ]: 0 : if (!pkgbin->conffiles || pkgbin == &pkg->available)
383 : 0 : return;
384 [ # # ]: 0 : if (flags&fw_printheader)
385 : 0 : varbuf_add_str(vb, "Conffiles:\n");
386 [ # # ]: 0 : for (i = pkgbin->conffiles; i; i = i->next) {
387 [ # # ]: 0 : if (i != pkgbin->conffiles)
388 : 0 : varbuf_add_char(vb, '\n');
389 : 0 : varbuf_add_char(vb, ' ');
390 : 0 : varbuf_add_str(vb, i->name);
391 : 0 : varbuf_add_char(vb, ' ');
392 : 0 : varbuf_add_str(vb, i->hash);
393 [ # # ]: 0 : if (i->flags & CONFFILE_OBSOLETE)
394 : 0 : varbuf_add_str(vb, " obsolete");
395 [ # # ]: 0 : if (i->flags & CONFFILE_REMOVE_ON_UPGRADE)
396 : 0 : varbuf_add_str(vb, " remove-on-upgrade");
397 : : }
398 [ # # ]: 0 : if (flags&fw_printheader)
399 : 0 : varbuf_add_char(vb, '\n');
400 : : }
401 : :
402 : : void
403 : 0 : w_trigpend(struct varbuf *vb,
404 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
405 : : enum fwriteflags flags, const struct fieldinfo *fip)
406 : : {
407 : : struct trigpend *tp;
408 : :
409 [ # # # # ]: 0 : if (pkgbin == &pkg->available || !pkg->trigpend_head)
410 : 0 : return;
411 : :
412 [ # # ]: 0 : if (pkg->status < PKG_STAT_TRIGGERSAWAITED ||
413 [ # # ]: 0 : pkg->status > PKG_STAT_TRIGGERSPENDING)
414 : 0 : internerr("package %s in non-trigger state %s, has pending triggers",
415 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
416 : :
417 [ # # ]: 0 : if (flags & fw_printheader)
418 : 0 : varbuf_add_str(vb, "Triggers-Pending:");
419 [ # # ]: 0 : for (tp = pkg->trigpend_head; tp; tp = tp->next) {
420 : 0 : varbuf_add_char(vb, ' ');
421 : 0 : varbuf_add_str(vb, tp->name);
422 : : }
423 [ # # ]: 0 : if (flags & fw_printheader)
424 : 0 : varbuf_add_char(vb, '\n');
425 : : }
426 : :
427 : : void
428 : 0 : w_trigaw(struct varbuf *vb,
429 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
430 : : enum fwriteflags flags, const struct fieldinfo *fip)
431 : : {
432 : : struct trigaw *ta;
433 : :
434 [ # # # # ]: 0 : if (pkgbin == &pkg->available || !pkg->trigaw.head)
435 : 0 : return;
436 : :
437 [ # # ]: 0 : if (pkg->status <= PKG_STAT_CONFIGFILES ||
438 [ # # ]: 0 : pkg->status > PKG_STAT_TRIGGERSAWAITED)
439 : 0 : internerr("package %s in state %s, has awaited triggers",
440 : : pkgbin_name_const(pkg, pkgbin, pnaw_always), pkg_status_name(pkg));
441 : :
442 [ # # ]: 0 : if (flags & fw_printheader)
443 : 0 : varbuf_add_str(vb, "Triggers-Awaited:");
444 [ # # ]: 0 : for (ta = pkg->trigaw.head; ta; ta = ta->sameaw.next) {
445 : 0 : varbuf_add_char(vb, ' ');
446 : 0 : varbuf_add_pkgbin_name(vb, ta->pend, &ta->pend->installed, pnaw_nonambig);
447 : : }
448 [ # # ]: 0 : if (flags & fw_printheader)
449 : 0 : varbuf_add_char(vb, '\n');
450 : : }
451 : :
452 : : void
453 : 1 : varbuf_add_arbfield(struct varbuf *vb, const struct arbitraryfield *arbfield,
454 : : enum fwriteflags flags)
455 : : {
456 [ - + ]: 1 : if (flags & fw_printheader) {
457 : 0 : varbuf_add_str(vb, arbfield->name);
458 : 0 : varbuf_add_str(vb, ": ");
459 : : }
460 : 1 : varbuf_add_str(vb, arbfield->value);
461 [ - + ]: 1 : if (flags & fw_printheader)
462 : 0 : varbuf_add_char(vb, '\n');
463 : 1 : }
464 : :
465 : : void
466 : 0 : varbuf_stanza(struct varbuf *vb,
467 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin)
468 : : {
469 : : const struct fieldinfo *fip;
470 : : const struct arbitraryfield *afp;
471 : :
472 [ # # ]: 0 : for (fip= fieldinfos; fip->name; fip++) {
473 : 0 : fip->wcall(vb, pkg, pkgbin, fw_printheader, fip);
474 : : }
475 [ # # ]: 0 : for (afp = pkgbin->arbs; afp; afp = afp->next) {
476 : 0 : varbuf_add_arbfield(vb, afp, fw_printheader);
477 : : }
478 : 0 : }
479 : :
480 : : void
481 : 0 : write_stanza(FILE *file, const char *filename,
482 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin)
483 : : {
484 : 0 : struct varbuf vb = VARBUF_INIT;
485 : :
486 : 0 : varbuf_stanza(&vb, pkg, pkgbin);
487 : :
488 [ # # ]: 0 : if (fputs(varbuf_str(&vb), file) < 0)
489 : 0 : ohshite(_("failed to write details of '%.50s' to '%.250s'"),
490 : : pkgbin_name_const(pkg, pkgbin, pnaw_nonambig), filename);
491 : :
492 : 0 : varbuf_destroy(&vb);
493 : 0 : }
494 : :
495 : : void
496 : 0 : writedb_stanzas(FILE *fp, const char *filename, enum writedb_flags flags)
497 : : {
498 : : static char writebuf[8192];
499 : :
500 : : struct pkg_array array;
501 : : const char *which;
502 : 0 : struct varbuf vb = VARBUF_INIT;
503 : : int i;
504 : :
505 [ # # ]: 0 : which = (flags & wdb_dump_available) ? "available" : "status";
506 : :
507 [ # # ]: 0 : if (setvbuf(fp, writebuf, _IOFBF, sizeof(writebuf)))
508 : 0 : ohshite(_("unable to set buffering on %s database file"), which);
509 : :
510 : 0 : pkg_array_init_from_hash(&array);
511 : 0 : pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
512 : :
513 [ # # ]: 0 : for (i = 0; i < array.n_pkgs; i++) {
514 : : struct pkginfo *pkg;
515 : : struct pkgbin *pkgbin;
516 : :
517 : 0 : pkg = array.pkgs[i];
518 [ # # ]: 0 : pkgbin = (flags & wdb_dump_available) ? &pkg->available : &pkg->installed;
519 : :
520 : : /* Don't dump stanzas which have no useful content. */
521 [ # # ]: 0 : if (!pkg_is_informative(pkg, pkgbin))
522 : 0 : continue;
523 : :
524 : 0 : varbuf_stanza(&vb, pkg, pkgbin);
525 : 0 : varbuf_add_char(&vb, '\n');
526 [ # # ]: 0 : if (fputs(varbuf_str(&vb), fp) < 0)
527 : 0 : ohshite(_("failed to write %s database stanza about '%s' to '%s'"),
528 : : which, pkgbin_name(pkg, pkgbin, pnaw_nonambig), filename);
529 : 0 : varbuf_reset(&vb);
530 : : }
531 : :
532 : 0 : pkg_array_destroy(&array);
533 : 0 : varbuf_destroy(&vb);
534 : 0 : }
535 : :
536 : : void
537 : 0 : writedb(const char *filename, enum writedb_flags flags)
538 : : {
539 : : struct atomic_file *file;
540 : 0 : enum atomic_file_flags atomic_flags = ATOMIC_FILE_BACKUP;
541 : :
542 [ # # ]: 0 : if (flags & wdb_dump_available)
543 : 0 : atomic_flags = 0;
544 : :
545 : 0 : file = atomic_file_new(filename, atomic_flags);
546 : 0 : atomic_file_open(file);
547 : :
548 : 0 : writedb_stanzas(file->fp, filename, flags);
549 : :
550 [ # # ]: 0 : if (flags & wdb_must_sync)
551 : 0 : atomic_file_sync(file);
552 : :
553 : 0 : atomic_file_close(file);
554 : 0 : atomic_file_commit(file);
555 : 0 : atomic_file_free(file);
556 : :
557 [ # # ]: 0 : if (flags & wdb_must_sync)
558 : 0 : dir_sync_path_parent(filename);
559 : 0 : }
|