Branch data Line data Source code
1 : : /*
2 : : * libdpkg - Debian packaging suite library routines
3 : : * parse.c - database file parsing, main package/field loop
4 : : *
5 : : * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2006, 2008-2015 Guillem Jover <guillem@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 published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : *
13 : : * This is distributed in the hope that it will be useful,
14 : : * but 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 License
19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include <config.h>
23 : : #include <compat.h>
24 : :
25 : : #include <sys/types.h>
26 : : #include <sys/stat.h>
27 : : #ifdef USE_MMAP
28 : : #include <sys/mman.h>
29 : : #endif
30 : :
31 : : #include <errno.h>
32 : : #include <fcntl.h>
33 : : #include <string.h>
34 : : #include <unistd.h>
35 : : #include <stdarg.h>
36 : : #include <stdlib.h>
37 : : #include <stdio.h>
38 : :
39 : : #include <dpkg/macros.h>
40 : : #include <dpkg/i18n.h>
41 : : #include <dpkg/c-ctype.h>
42 : : #include <dpkg/dpkg.h>
43 : : #include <dpkg/dpkg-db.h>
44 : : #include <dpkg/string.h>
45 : : #include <dpkg/pkg.h>
46 : : #include <dpkg/parsedump.h>
47 : : #include <dpkg/fdio.h>
48 : : #include <dpkg/buffer.h>
49 : :
50 : : /**
51 : : * Fields information.
52 : : */
53 : : const struct fieldinfo fieldinfos[]= {
54 : : /* Note: Capitalization of field name strings is important. */
55 : : { FIELD("Package"), f_name, w_name },
56 : : { FIELD("Essential"), f_boolean, w_booleandefno, PKGIFPOFF(essential) },
57 : : { FIELD("Protected"), f_boolean, w_booleandefno, PKGIFPOFF(is_protected) },
58 : : { FIELD("Status"), f_status, w_status },
59 : : { FIELD("Priority"), f_priority, w_priority },
60 : : { FIELD("Section"), f_section, w_section },
61 : : { FIELD("Installed-Size"), f_charfield, w_charfield, PKGIFPOFF(installedsize) },
62 : : { FIELD("Origin"), f_charfield, w_charfield, PKGIFPOFF(origin) },
63 : : { FIELD("Maintainer"), f_charfield, w_charfield, PKGIFPOFF(maintainer) },
64 : : { FIELD("Bugs"), f_charfield, w_charfield, PKGIFPOFF(bugs) },
65 : : { FIELD("Architecture"), f_architecture, w_architecture },
66 : : { FIELD("Multi-Arch"), f_multiarch, w_multiarch, PKGIFPOFF(multiarch) },
67 : : { FIELD("Source"), f_charfield, w_charfield, PKGIFPOFF(source) },
68 : : { FIELD("Version"), f_version, w_version, PKGIFPOFF(version) },
69 : : { FIELD("Config-Version"), f_configversion, w_configversion },
70 : : { FIELD("Replaces"), f_dependency, w_dependency, dep_replaces },
71 : : { FIELD("Provides"), f_dependency, w_dependency, dep_provides },
72 : : { FIELD("Depends"), f_dependency, w_dependency, dep_depends },
73 : : { FIELD("Pre-Depends"), f_dependency, w_dependency, dep_predepends },
74 : : { FIELD("Recommends"), f_dependency, w_dependency, dep_recommends },
75 : : { FIELD("Suggests"), f_dependency, w_dependency, dep_suggests },
76 : : { FIELD("Breaks"), f_dependency, w_dependency, dep_breaks },
77 : : { FIELD("Conflicts"), f_dependency, w_dependency, dep_conflicts },
78 : : { FIELD("Enhances"), f_dependency, w_dependency, dep_enhances },
79 : : { FIELD("Conffiles"), f_conffiles, w_conffiles },
80 : : { FIELD("Filename"), f_archives, w_archives, ARCHIVEFOFF(name) },
81 : : { FIELD("Size"), f_archives, w_archives, ARCHIVEFOFF(size) },
82 : : { FIELD("MD5sum"), f_archives, w_archives, ARCHIVEFOFF(md5sum) },
83 : : { FIELD("MSDOS-Filename"), f_archives, w_archives, ARCHIVEFOFF(msdosname) },
84 : : { FIELD("Description"), f_charfield, w_charfield, PKGIFPOFF(description) },
85 : : { FIELD("Triggers-Pending"), f_trigpend, w_trigpend },
86 : : { FIELD("Triggers-Awaited"), f_trigaw, w_trigaw },
87 : :
88 : : /* The following are the obsolete fields that get remapped to their
89 : : * modern forms, while emitting an obsolescence warning. */
90 : : { FIELD("Recommended"), f_obs_dependency, w_null, dep_recommends },
91 : : { FIELD("Optional"), f_obs_dependency, w_null, dep_suggests },
92 : : { FIELD("Class"), f_obs_class, w_null },
93 : : { FIELD("Revision"), f_obs_revision, w_null },
94 : : { FIELD("Package-Revision"), f_obs_revision, w_null },
95 : : { FIELD("Package_Revision"), f_obs_revision, w_null },
96 : : { NULL }
97 : : };
98 : :
99 : : /**
100 : : * Package object being parsed.
101 : : *
102 : : * Structure used to hold the parsed data for the package being constructed,
103 : : * before it gets properly inserted into the package database.
104 : : */
105 : : struct pkg_parse_object {
106 : : struct pkginfo *pkg;
107 : : struct pkgbin *pkgbin;
108 : : };
109 : :
110 : : /**
111 : : * Parse the field and value into the package being constructed.
112 : : */
113 : : static void
114 : 231 : pkg_parse_field(struct parsedb_state *ps, struct field_state *fs,
115 : : void *parse_obj)
116 : : {
117 : 231 : struct pkg_parse_object *pkg_obj = parse_obj;
118 : : const struct fieldinfo *fip;
119 : : int *ip;
120 : :
121 [ + + ]: 2769 : for (fip = fieldinfos, ip = fs->fieldencountered; fip->name; fip++, ip++)
122 [ + + ]: 2767 : if (fip->namelen == (size_t)fs->fieldlen &&
123 [ + + ]: 388 : strncasecmp(fip->name, fs->fieldstart, fs->fieldlen) == 0)
124 : 229 : break;
125 [ + + ]: 231 : if (fip->name) {
126 [ - + ]: 229 : if ((*ip)++)
127 : 0 : parse_error(ps,
128 : 0 : _("duplicate value for '%s' field"), fip->name);
129 : :
130 : 229 : varbuf_set_buf(&fs->value, fs->valuestart, fs->valuelen);
131 : :
132 : 229 : fip->rcall(pkg_obj->pkg, pkg_obj->pkgbin, ps, fs->value.buf, fip);
133 : : } else {
134 : : struct arbitraryfield *arp, **larpp;
135 : :
136 [ - + ]: 2 : if (fs->fieldlen < 2)
137 : 0 : parse_error(ps,
138 : 0 : _("user-defined field name '%.*s' too short"),
139 : : fs->fieldlen, fs->fieldstart);
140 : 2 : larpp = &pkg_obj->pkgbin->arbs;
141 [ - + ]: 2 : while ((arp = *larpp) != NULL) {
142 [ # # ]: 0 : if (strncasecmp(arp->name, fs->fieldstart, fs->fieldlen) == 0 &&
143 [ # # ]: 0 : strlen(arp->name) == (size_t)fs->fieldlen)
144 : 0 : parse_error(ps,
145 : 0 : _("duplicate value for user-defined field '%.*s'"),
146 : : fs->fieldlen, fs->fieldstart);
147 : 0 : larpp = &arp->next;
148 : : }
149 : 2 : arp = nfmalloc(sizeof(*arp));
150 : 2 : arp->name = nfstrnsave(fs->fieldstart, fs->fieldlen);
151 : 2 : arp->value = nfstrnsave(fs->valuestart, fs->valuelen);
152 : 2 : arp->next = NULL;
153 : 2 : *larpp = arp;
154 : : }
155 : 231 : }
156 : :
157 : : /**
158 : : * Verify and fixup the package structure being constructed.
159 : : */
160 : : static void
161 : 32 : pkg_parse_verify(struct parsedb_state *ps,
162 : : struct pkginfo *pkg, struct pkgbin *pkgbin)
163 : : {
164 : : struct dependency *dep;
165 : : struct deppossi *dop;
166 : :
167 : 32 : parse_must_have_field(ps, pkg->set->name, "Package");
168 : :
169 : : /* XXX: We need to check for status != PKG_STAT_HALFINSTALLED as while
170 : : * unpacking an unselected package, it will not have yet all data in
171 : : * place. But we cannot check for > PKG_STAT_HALFINSTALLED as
172 : : * PKG_STAT_CONFIGFILES always should have those fields. */
173 [ + + ]: 32 : if ((ps->flags & pdb_recordavailable) ||
174 [ + - ]: 1 : (pkg->status != PKG_STAT_NOTINSTALLED &&
175 [ + - ]: 1 : pkg->status != PKG_STAT_HALFINSTALLED)) {
176 : 32 : parse_ensure_have_field(ps, &pkgbin->description, "Description");
177 : 32 : parse_ensure_have_field(ps, &pkgbin->maintainer, "Maintainer");
178 : 32 : parse_must_have_field(ps, pkgbin->version.version, "Version");
179 : : }
180 : :
181 : : /* XXX: Versions before dpkg 1.10.19 did not preserve the Architecture
182 : : * field in the status file. So there's still live systems with packages
183 : : * in PKG_STAT_CONFIGFILES, ignore those too for now. */
184 [ + + ]: 32 : if ((ps->flags & pdb_recordavailable) ||
185 [ + - ]: 1 : pkg->status > PKG_STAT_HALFINSTALLED) {
186 : : /* We always want usable architecture information (as long as the package
187 : : * is in such a state that it makes sense), so that it can be used safely
188 : : * on string comparisons and the like. */
189 [ - + ]: 32 : if (pkgbin->arch->type == DPKG_ARCH_NONE)
190 : 0 : parse_warn(ps, _("missing '%s' field"), "Architecture");
191 [ - + ]: 32 : else if (pkgbin->arch->type == DPKG_ARCH_EMPTY)
192 : 0 : parse_warn(ps, _("empty value for '%s' field"), "Architecture");
193 : : }
194 : : /* Mark missing architectures as empty, to distinguish these from
195 : : * unused slots in the db. */
196 [ - + ]: 32 : if (pkgbin->arch->type == DPKG_ARCH_NONE)
197 : 0 : pkgbin->arch = dpkg_arch_get(DPKG_ARCH_EMPTY);
198 : :
199 [ - + ]: 32 : if (pkgbin->arch->type == DPKG_ARCH_EMPTY &&
200 [ # # ]: 0 : pkgbin->multiarch == PKG_MULTIARCH_SAME)
201 : 0 : parse_error(ps, _("package has '%s' field but is missing architecture"),
202 : : "Multi-Arch: same");
203 [ + + ]: 32 : if (pkgbin->arch->type == DPKG_ARCH_ALL &&
204 [ - + ]: 31 : pkgbin->multiarch == PKG_MULTIARCH_SAME)
205 : 0 : parse_error(ps, _("package has '%s' field but is architecture '%s'"),
206 : : "Multi-Arch: same", "all");
207 : :
208 : : /* Generate the cached fully qualified package name representation. */
209 : 32 : pkgbin->pkgname_archqual = pkgbin_name_archqual(pkg, pkgbin);
210 : :
211 : : /* Initialize deps to be arch-specific unless stated otherwise. */
212 [ + + ]: 36 : for (dep = pkgbin->depends; dep; dep = dep->next)
213 [ + + ]: 8 : for (dop = dep->list; dop; dop = dop->next)
214 [ + - ]: 4 : if (!dop->arch)
215 : 4 : dop->arch = pkgbin->arch;
216 : :
217 : : /*
218 : : * Check the Config-Version information:
219 : : *
220 : : * If there is a Config-Version it is definitely to be used, but there
221 : : * should not be one if the package is ‘installed’ or ‘triggers-pending’
222 : : * (in which case the Version will be copied) or if the package is
223 : : * ‘not-installed’ (in which case there is no Config-Version).
224 : : */
225 [ + + ]: 32 : if (!(ps->flags & pdb_recordavailable)) {
226 [ - + ]: 1 : if (pkg->configversion.version) {
227 [ # # ]: 0 : if (pkg->status == PKG_STAT_INSTALLED ||
228 [ # # ]: 0 : pkg->status == PKG_STAT_NOTINSTALLED ||
229 [ # # ]: 0 : pkg->status == PKG_STAT_TRIGGERSPENDING)
230 : 0 : parse_error(ps,
231 : 0 : _("'%s' field present for package with inappropriate '%s' field"),
232 : : "Config-Version", "Status");
233 : : } else {
234 [ - + ]: 1 : if (pkg->status == PKG_STAT_INSTALLED ||
235 [ # # ]: 0 : pkg->status == PKG_STAT_TRIGGERSPENDING)
236 : 1 : pkg->configversion = pkgbin->version;
237 : : }
238 : : }
239 : :
240 [ - + ]: 32 : if (pkg->trigaw.head &&
241 [ # # ]: 0 : (pkg->status <= PKG_STAT_CONFIGFILES ||
242 [ # # ]: 0 : pkg->status >= PKG_STAT_TRIGGERSPENDING))
243 : 0 : parse_error(ps,
244 : 0 : _("package has status %s but triggers are awaited"),
245 : : pkg_status_name(pkg));
246 [ - + - - ]: 32 : else if (pkg->status == PKG_STAT_TRIGGERSAWAITED && !pkg->trigaw.head)
247 : 0 : parse_error(ps,
248 : 0 : _("package has status %s but no triggers awaited"),
249 : : pkg_status_name(pkg));
250 : :
251 [ - + ]: 32 : if (pkg->trigpend_head &&
252 [ # # ]: 0 : !(pkg->status == PKG_STAT_TRIGGERSPENDING ||
253 [ # # ]: 0 : pkg->status == PKG_STAT_TRIGGERSAWAITED))
254 : 0 : parse_error(ps,
255 : 0 : _("package has status %s but triggers are pending"),
256 : : pkg_status_name(pkg));
257 [ - + - - ]: 32 : else if (pkg->status == PKG_STAT_TRIGGERSPENDING && !pkg->trigpend_head)
258 : 0 : parse_error(ps,
259 : 0 : _("package has status %s but no triggers pending"),
260 : : pkg_status_name(pkg));
261 : :
262 : : /* Note: There was a bug that could make a not-installed package have
263 : : * conffiles, so we check for them here and remove them (rather than
264 : : * calling it an error, which will do at some point). */
265 [ + + ]: 32 : if (!(ps->flags & pdb_recordavailable) &&
266 [ - + ]: 1 : pkg->status == PKG_STAT_NOTINSTALLED &&
267 [ # # ]: 0 : pkgbin->conffiles) {
268 : 0 : parse_warn(ps,
269 : 0 : _("package has status %s and has conffiles, forgetting them"),
270 : : pkg_status_name(pkg));
271 : 0 : pkgbin->conffiles = NULL;
272 : : }
273 : :
274 : : /* Note: Mark not-installed leftover packages for automatic removal on
275 : : * next database dump. */
276 [ + + ]: 32 : if (!(ps->flags & pdb_recordavailable) &&
277 [ - + ]: 1 : pkg->status == PKG_STAT_NOTINSTALLED &&
278 [ # # ]: 0 : pkg->eflag == PKG_EFLAG_OK &&
279 [ # # ]: 0 : (pkg->want == PKG_WANT_PURGE ||
280 [ # # ]: 0 : pkg->want == PKG_WANT_DEINSTALL)) {
281 : 0 : pkg_set_want(pkg, PKG_WANT_UNKNOWN);
282 : : }
283 : :
284 : : /* Note: Mark not-installed non-arch-qualified selections for automatic
285 : : * removal, as they do not make sense in a multiarch enabled world, and
286 : : * might cause those selections to be unreferencable from command-line
287 : : * interfaces when there's other more specific selections. */
288 [ + + ]: 32 : if (ps->type == pdb_file_status &&
289 [ - + ]: 1 : pkg->status == PKG_STAT_NOTINSTALLED &&
290 [ # # ]: 0 : pkg->eflag == PKG_EFLAG_OK &&
291 [ # # ]: 0 : pkg->want == PKG_WANT_INSTALL &&
292 [ # # ]: 0 : pkgbin->arch->type == DPKG_ARCH_EMPTY)
293 : 0 : pkg_set_want(pkg, PKG_WANT_UNKNOWN);
294 : :
295 : : /* Note: Versions before dpkg 1.13.10 did not blank the Origin and Bugs
296 : : * fields, so there can be packages that should be garbage collected but
297 : : * are lingering around. Blank them to make sure we will forget all about
298 : : * them on the next database dump. */
299 [ + + ]: 32 : if (!(ps->flags & pdb_recordavailable) &&
300 [ - + ]: 1 : pkg->status == PKG_STAT_NOTINSTALLED &&
301 [ # # ]: 0 : pkg->eflag == PKG_EFLAG_OK &&
302 [ # # ]: 0 : pkg->want == PKG_WANT_UNKNOWN) {
303 : 0 : pkgbin_blank(pkgbin);
304 : : }
305 : 32 : }
306 : :
307 : : struct pkgcount {
308 : : int single;
309 : : int multi;
310 : : int total;
311 : : };
312 : :
313 : : static void
314 : 33 : parse_count_pkg_instance(struct pkgcount *count,
315 : : struct pkginfo *pkg, struct pkgbin *pkgbin)
316 : : {
317 [ + + ]: 33 : if (pkg->status == PKG_STAT_NOTINSTALLED)
318 : 32 : return;
319 : :
320 [ - + ]: 1 : if (pkgbin->multiarch == PKG_MULTIARCH_SAME)
321 : 0 : count->multi++;
322 : : else
323 : 1 : count->single++;
324 : :
325 : 1 : count->total++;
326 : : }
327 : :
328 : : /**
329 : : * Lookup the package set slot for the parsed package.
330 : : *
331 : : * Perform various checks, to make sure the database is always in a sane
332 : : * state, and to not allow breaking it.
333 : : */
334 : : static struct pkgset *
335 : 32 : parse_find_set_slot(struct parsedb_state *ps,
336 : : struct pkginfo *new_pkg, struct pkgbin *new_pkgbin)
337 : : {
338 : 32 : struct pkgcount count = { .single = 0, .multi = 0, .total = 0 };
339 : : struct pkgset *set;
340 : : struct pkginfo *pkg;
341 : :
342 : 32 : set = pkg_hash_find_set(new_pkg->set->name);
343 : :
344 : : /* Sanity checks: verify that the db is in a consistent state. */
345 : :
346 [ + + ]: 32 : if (ps->type == pdb_file_status)
347 : 1 : parse_count_pkg_instance(&count, new_pkg, new_pkgbin);
348 : :
349 : 32 : count.total = 0;
350 : :
351 [ + + ]: 64 : for (pkg = &set->pkg; pkg; pkg = pkg->arch_next)
352 : 32 : parse_count_pkg_instance(&count, pkg, &pkg->installed);
353 : :
354 [ - + ]: 32 : if (count.single > 1)
355 : 0 : parse_error(ps, _("multiple non-coinstallable package instances present; "
356 : : "most probably due to an upgrade from an unofficial dpkg"));
357 : :
358 [ + + - + ]: 32 : if (count.single > 0 && count.multi > 0)
359 : 0 : parse_error(ps, _("mixed non-coinstallable and coinstallable package "
360 : : "instances present; most probably due to an upgrade "
361 : : "from an unofficial dpkg"));
362 : :
363 [ - + ]: 32 : if (pkgset_installed_instances(set) != count.total)
364 : 0 : internerr("in-core pkgset '%s' with inconsistent number of instances",
365 : : set->name);
366 : :
367 : 32 : return set;
368 : : }
369 : :
370 : : /**
371 : : * Lookup the package slot for the parsed package.
372 : : *
373 : : * Cross-grading (i.e. switching arch) is only possible when parsing an
374 : : * update entry or when installing a new package.
375 : : *
376 : : * Most of the time each pkginfo in a pkgset has the same architecture for
377 : : * both the installed and available pkgbin members. But when cross-grading
378 : : * there's going to be a temporary discrepancy, because we reuse the single
379 : : * instance and fill the available pkgbin with the candidate pkgbin, until
380 : : * that is copied over the installed pkgbin.
381 : : *
382 : : * If there's 0 or > 1 package instances, then we match against the pkginfo
383 : : * slot architecture, because cross-grading is just not possible.
384 : : *
385 : : * If there's 1 instance, we are cross-grading and both installed and
386 : : * candidate are not PKG_MULTIARCH_SAME, we have to reuse the existing single
387 : : * slot regardless of the arch differing between the two. If we are not
388 : : * cross-grading, then we use the entry with the matching arch.
389 : : */
390 : : static struct pkginfo *
391 : 32 : parse_find_pkg_slot(struct parsedb_state *ps,
392 : : struct pkginfo *new_pkg, struct pkgbin *new_pkgbin)
393 : : {
394 : : struct pkgset *db_set;
395 : :
396 : 32 : db_set = parse_find_set_slot(ps, new_pkg, new_pkgbin);
397 : :
398 [ - + ]: 32 : if (ps->type == pdb_file_available) {
399 : : /* If there's a single package installed and the new package is not
400 : : * “Multi-Arch: same”, then we preserve the previous behavior of
401 : : * possible architecture switch, for example from native to all. */
402 [ # # ]: 0 : if (pkgset_installed_instances(db_set) == 1 &&
403 [ # # ]: 0 : new_pkgbin->multiarch != PKG_MULTIARCH_SAME)
404 : 0 : return pkg_hash_get_singleton(db_set);
405 : : else
406 : 0 : return pkg_hash_get_pkg(db_set, new_pkgbin->arch);
407 : : } else {
408 : 32 : bool selection = false;
409 : :
410 : : /* If the package is part of the status file, and it's not installed
411 : : * then this means it's just a selection. */
412 [ + + - + ]: 32 : if (ps->type == pdb_file_status && new_pkg->status == PKG_STAT_NOTINSTALLED)
413 : 0 : selection = true;
414 : :
415 : : /* Verify we don't allow something that will mess up the db. */
416 [ - + ]: 32 : if (pkgset_installed_instances(db_set) > 1 &&
417 [ # # # # ]: 0 : !selection && new_pkgbin->multiarch != PKG_MULTIARCH_SAME)
418 : 0 : ohshit(_("package %s (%s) with field '%s: %s' is not co-installable "
419 : : "with %s which has multiple installed instances"),
420 : : pkgbin_name(new_pkg, new_pkgbin, pnaw_always),
421 : 0 : versiondescribe(&new_pkgbin->version, vdew_nonambig),
422 : 0 : "Multi-Arch", multiarchinfos[new_pkgbin->multiarch].name,
423 : : db_set->name);
424 : :
425 : : /* If we are parsing the status file, use a slot per arch. */
426 [ + + ]: 32 : if (ps->type == pdb_file_status)
427 : 1 : return pkg_hash_get_pkg(db_set, new_pkgbin->arch);
428 : :
429 : : /* If we are doing an update, from the log or a new package, then
430 : : * handle cross-grades. */
431 [ - + ]: 31 : if (pkgset_installed_instances(db_set) == 1) {
432 : : struct pkginfo *db_pkg;
433 : :
434 : 0 : db_pkg = pkg_hash_get_singleton(db_set);
435 : :
436 [ # # ]: 0 : if (db_pkg->installed.multiarch == PKG_MULTIARCH_SAME &&
437 [ # # ]: 0 : new_pkgbin->multiarch == PKG_MULTIARCH_SAME)
438 : 0 : return pkg_hash_get_pkg(db_set, new_pkgbin->arch);
439 : : else
440 : 0 : return db_pkg;
441 : : } else {
442 : 31 : return pkg_hash_get_pkg(db_set, new_pkgbin->arch);
443 : : }
444 : : }
445 : : }
446 : :
447 : : /**
448 : : * Copy into the in-core database the package being constructed.
449 : : */
450 : : static void
451 : 32 : pkg_parse_copy(struct parsedb_state *ps,
452 : : struct pkginfo *dst_pkg, struct pkgbin *dst_pkgbin,
453 : : struct pkginfo *src_pkg, struct pkgbin *src_pkgbin)
454 : : {
455 : : /* Copy the priority and section across, but don't overwrite existing
456 : : * values if the pdb_weakclassification flag is set. */
457 [ + + ]: 32 : if (str_is_set(src_pkg->section) &&
458 [ - + - - ]: 31 : !((ps->flags & pdb_weakclassification) &&
459 : 0 : str_is_set(dst_pkg->section)))
460 : 31 : dst_pkg->section = src_pkg->section;
461 [ + + ]: 32 : if (src_pkg->priority != PKG_PRIO_UNKNOWN &&
462 [ - + ]: 31 : !((ps->flags & pdb_weakclassification) &&
463 [ # # ]: 0 : dst_pkg->priority != PKG_PRIO_UNKNOWN)) {
464 : 31 : dst_pkg->priority = src_pkg->priority;
465 [ - + ]: 31 : if (src_pkg->priority == PKG_PRIO_OTHER)
466 : 0 : dst_pkg->otherpriority = src_pkg->otherpriority;
467 : : }
468 : :
469 : : /* Sort out the dependency mess. */
470 : 32 : copy_dependency_links(dst_pkg, &dst_pkgbin->depends, src_pkgbin->depends,
471 : 32 : (ps->flags & pdb_recordavailable) ? true : false);
472 : :
473 : : /* Copy across data. */
474 : 32 : memcpy(dst_pkgbin, src_pkgbin, sizeof(struct pkgbin));
475 [ + + ]: 32 : if (!(ps->flags & pdb_recordavailable)) {
476 : : struct trigaw *ta;
477 : :
478 : 1 : pkg_set_want(dst_pkg, src_pkg->want);
479 : 1 : pkg_copy_eflags(dst_pkg, src_pkg);
480 : 1 : pkg_set_status(dst_pkg, src_pkg->status);
481 : 1 : dst_pkg->configversion = src_pkg->configversion;
482 : 1 : dst_pkg->archives = NULL;
483 : :
484 : 1 : dst_pkg->trigpend_head = src_pkg->trigpend_head;
485 : 1 : dst_pkg->trigaw = src_pkg->trigaw;
486 [ - + ]: 1 : for (ta = dst_pkg->trigaw.head; ta; ta = ta->sameaw.next) {
487 [ # # ]: 0 : if (ta->aw != src_pkg)
488 : 0 : internerr("trigger awaited package %s and origin package %s not linked properly",
489 : : pkg_name(ta->aw, pnaw_always),
490 : : pkgbin_name(src_pkg, src_pkgbin, pnaw_always));
491 : 0 : ta->aw = dst_pkg;
492 : : /* ->othertrigaw_head is updated by trig_note_aw in *(pkg_hash_find())
493 : : * rather than in dst_pkg. */
494 : : }
495 [ + + ]: 31 : } else if (!(ps->flags & pdb_ignore_archives)) {
496 : 28 : dst_pkg->archives = src_pkg->archives;
497 : : }
498 : 32 : }
499 : :
500 : : /**
501 : : * Return a descriptive parser type.
502 : : */
503 : : static enum parsedbtype
504 : 105 : parse_get_type(struct parsedb_state *ps, enum parsedbflags flags)
505 : : {
506 [ + + ]: 105 : if (flags & pdb_recordavailable) {
507 [ + - ]: 31 : if (flags & pdb_single_stanza)
508 : 31 : return pdb_file_control;
509 : : else
510 : 0 : return pdb_file_available;
511 : : } else {
512 [ - + ]: 74 : if (flags & pdb_single_stanza)
513 : 0 : return pdb_file_update;
514 : : else
515 : 74 : return pdb_file_status;
516 : : }
517 : : }
518 : :
519 : : /**
520 : : * Create a new deb822 parser context.
521 : : */
522 : : struct parsedb_state *
523 : 105 : parsedb_new(const char *filename, int fd, enum parsedbflags flags)
524 : : {
525 : : struct parsedb_state *ps;
526 : :
527 : 105 : ps = m_malloc(sizeof(*ps));
528 : 105 : ps->err = DPKG_ERROR_OBJECT;
529 : 105 : ps->errmsg = VARBUF_OBJECT;
530 : 105 : ps->filename = filename;
531 : 105 : ps->type = parse_get_type(ps, flags);
532 : 105 : ps->flags = flags;
533 : 105 : ps->fd = fd;
534 : 105 : ps->lno = 0;
535 : 105 : ps->data = NULL;
536 : 105 : ps->dataptr = NULL;
537 : 105 : ps->endptr = NULL;
538 : 105 : ps->pkg = NULL;
539 : 105 : ps->pkgbin = NULL;
540 : :
541 : 105 : return ps;
542 : : }
543 : :
544 : : /**
545 : : * Open a file for deb822 parsing.
546 : : */
547 : : struct parsedb_state *
548 : 104 : parsedb_open(const char *filename, enum parsedbflags flags)
549 : : {
550 : : struct parsedb_state *ps;
551 : : int fd;
552 : :
553 : : /* Special case stdin handling. */
554 [ - + - - ]: 104 : if (flags & pdb_dash_is_stdin && strcmp(filename, "-") == 0)
555 : 0 : return parsedb_new(filename, STDIN_FILENO, flags);
556 : :
557 : 104 : fd = open(filename, O_RDONLY);
558 [ + + + - : 104 : if (fd < 0 && !(errno == ENOENT && (flags & pdb_allow_empty)))
- + ]
559 : 0 : ohshite(_("failed to open package info file '%.255s' for reading"),
560 : : filename);
561 : :
562 : 104 : ps = parsedb_new(filename, fd, flags | pdb_close_fd);
563 : :
564 : 104 : push_cleanup(cu_closefd, ~ehflag_normaltidy, 1, &ps->fd);
565 : :
566 : 104 : return ps;
567 : : }
568 : :
569 : : /**
570 : : * Load data for package deb822 style parsing.
571 : : */
572 : : void
573 : 105 : parsedb_load(struct parsedb_state *ps)
574 : : {
575 : : struct stat st;
576 : :
577 [ + + + - ]: 105 : if (ps->fd < 0 && (ps->flags & pdb_allow_empty))
578 : 73 : return;
579 : :
580 [ - + ]: 32 : if (fstat(ps->fd, &st) < 0)
581 : 0 : ohshite(_("can't stat package info file '%.255s'"), ps->filename);
582 : :
583 [ + + ]: 32 : if (S_ISFIFO(st.st_mode)) {
584 : 1 : struct varbuf buf = VARBUF_INIT;
585 : : struct dpkg_error err;
586 : : off_t size;
587 : :
588 : 1 : size = fd_vbuf_copy(ps->fd, &buf, -1, &err);
589 [ - + ]: 1 : if (size < 0)
590 : 0 : ohshit(_("reading package info file '%s': %s"), ps->filename, err.str);
591 : :
592 : :
593 : 1 : ps->dataptr = varbuf_detach(&buf);
594 : 1 : ps->endptr = ps->dataptr + size;
595 [ + - ]: 31 : } else if (st.st_size > 0) {
596 : : #ifdef USE_MMAP
597 : : ps->dataptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, ps->fd, 0);
598 : : if (ps->dataptr == MAP_FAILED)
599 : : ohshite(_("can't mmap package info file '%.255s'"), ps->filename);
600 : : #else
601 : 31 : ps->dataptr = m_malloc(st.st_size);
602 : :
603 [ - + ]: 31 : if (fd_read(ps->fd, ps->dataptr, st.st_size) < 0)
604 : 0 : ohshite(_("reading package info file '%.255s'"), ps->filename);
605 : : #endif
606 : 31 : ps->endptr = ps->dataptr + st.st_size;
607 : : } else {
608 : 0 : ps->dataptr = ps->endptr = NULL;
609 : : }
610 : 32 : ps->data = ps->dataptr;
611 : : }
612 : :
613 : : /**
614 : : * Parse an RFC-822 style stanza.
615 : : */
616 : : bool
617 : 32 : parse_stanza(struct parsedb_state *ps, struct field_state *fs,
618 : : parse_field_func *parse_field, void *parse_obj)
619 : : {
620 : 32 : int c = '\0';
621 : :
622 : : /* Skip adjacent new lines. */
623 [ + - ]: 32 : while (!parse_at_eof(ps)) {
624 : 32 : c = parse_getc(ps);
625 [ + - + - ]: 32 : if (c != '\n' && c != MSDOS_EOF_CHAR)
626 : 32 : break;
627 : 0 : ps->lno++;
628 : : }
629 : :
630 : : /* Nothing relevant parsed, bail out. */
631 [ + - ]: 32 : if (parse_at_eof(ps))
632 : 0 : return false;
633 : :
634 : : /* Loop per field. */
635 : 199 : for (;;) {
636 : : bool blank_line;
637 : :
638 : : /* Scan field name. */
639 : 231 : fs->fieldstart = ps->dataptr - 1;
640 [ + - + - : 2278 : while (!parse_at_eof(ps) && !c_isspace(c) && c != ':' && c != MSDOS_EOF_CHAR)
+ + + - ]
641 : 2047 : c = parse_getc(ps);
642 : 231 : fs->fieldlen = ps->dataptr - fs->fieldstart - 1;
643 [ - + ]: 231 : if (fs->fieldlen == 0)
644 : 0 : parse_error(ps, _("empty field name"));
645 [ - + ]: 231 : if (fs->fieldstart[0] == '-')
646 : 0 : parse_error(ps, _("field name '%.*s' cannot start with hyphen"),
647 : : fs->fieldlen, fs->fieldstart);
648 : :
649 : : /* Skip spaces before ‘:’. */
650 [ + - + - : 231 : while (!parse_at_eof(ps) && c != '\n' && c_isspace(c))
- + ]
651 : 0 : c = parse_getc(ps);
652 : :
653 : : /* Validate ‘:’. */
654 [ - + ]: 231 : if (parse_at_eof(ps))
655 : 0 : parse_error(ps, _("end of file after field name '%.*s'"),
656 : : fs->fieldlen, fs->fieldstart);
657 [ - + ]: 231 : if (c == '\n')
658 : 0 : parse_error(ps,
659 : 0 : _("newline in field name '%.*s'"), fs->fieldlen, fs->fieldstart);
660 [ - + ]: 231 : if (c == MSDOS_EOF_CHAR)
661 : 0 : parse_error(ps, _("MSDOS end of file (^Z) in field name '%.*s'"),
662 : : fs->fieldlen, fs->fieldstart);
663 [ - + ]: 231 : if (c != ':')
664 : 0 : parse_error(ps,
665 : 0 : _("field name '%.*s' must be followed by colon"),
666 : : fs->fieldlen, fs->fieldstart);
667 : :
668 : : /* Skip space after ‘:’ but before value and EOL. */
669 [ + - ]: 462 : while (!parse_at_eof(ps)) {
670 : 462 : c = parse_getc(ps);
671 [ + - + + ]: 462 : if (c == '\n' || !c_isspace(c))
672 : : break;
673 : : }
674 [ - + ]: 231 : if (parse_at_eof(ps))
675 : 0 : parse_error(ps, _("end of file before value of field '%.*s' (missing final newline)"),
676 : : fs->fieldlen, fs->fieldstart);
677 [ - + ]: 231 : if (c == MSDOS_EOF_CHAR)
678 : 0 : parse_error(ps, _("MSDOS end of file (^Z) in value of field '%.*s' (missing newline?)"),
679 : : fs->fieldlen, fs->fieldstart);
680 : :
681 : 231 : blank_line = false;
682 : :
683 : : /* Scan field value. */
684 : 231 : fs->valuestart = ps->dataptr - 1;
685 : : for (;;) {
686 [ + + - + ]: 3460 : if (c == '\n' || c == MSDOS_EOF_CHAR) {
687 [ - + ]: 231 : if (blank_line)
688 : 0 : parse_lax_problem(ps, pdb_lax_stanza_parser,
689 : 0 : _("blank line in value of field '%.*s'"),
690 : : fs->fieldlen, fs->fieldstart);
691 : 231 : ps->lno++;
692 : :
693 [ + + ]: 231 : if (parse_at_eof(ps))
694 : 32 : break;
695 : 199 : c = parse_getc(ps);
696 : :
697 : : /* Found double EOL, or start of new field. */
698 [ + - + - : 199 : if (parse_at_eof(ps) || c == '\n' || !c_isspace(c))
- + ]
699 : : break;
700 : :
701 : 0 : parse_ungetc(c, ps);
702 : 0 : blank_line = true;
703 [ - + - - ]: 3229 : } else if (blank_line && !c_isspace(c)) {
704 : 0 : blank_line = false;
705 : : }
706 : :
707 [ - + ]: 3229 : if (parse_at_eof(ps))
708 : 0 : parse_error(ps, _("end of file during value of field '%.*s' (missing final newline)"),
709 : : fs->fieldlen, fs->fieldstart);
710 : :
711 : 3229 : c = parse_getc(ps);
712 : : }
713 : 231 : fs->valuelen = ps->dataptr - fs->valuestart - 1;
714 : :
715 : : /* Trim ending space on value. */
716 [ + - + + ]: 430 : while (fs->valuelen && c_isspace(*(fs->valuestart + fs->valuelen - 1)))
717 : 199 : fs->valuelen--;
718 : :
719 : 231 : parse_field(ps, fs, parse_obj);
720 : :
721 [ + + + - : 231 : if (parse_at_eof(ps) || c == '\n' || c == MSDOS_EOF_CHAR)
+ - ]
722 : : break;
723 : : } /* Loop per field. */
724 : :
725 [ + - ]: 32 : if (c == '\n')
726 : 32 : ps->lno++;
727 : :
728 : 32 : return true;
729 : : }
730 : :
731 : : /**
732 : : * Teardown a package deb822 parser context.
733 : : */
734 : : void
735 : 105 : parsedb_close(struct parsedb_state *ps)
736 : : {
737 [ + + ]: 105 : if (ps->flags & pdb_close_fd) {
738 : 104 : pop_cleanup(ehflag_normaltidy);
739 : :
740 [ + + - + ]: 104 : if (ps->fd >= 0 && close(ps->fd) < 0)
741 : 0 : ohshite(_("failed to close after read: '%.255s'"), ps->filename);
742 : : }
743 : :
744 [ + + ]: 105 : if (ps->data != NULL) {
745 : : #ifdef USE_MMAP
746 : : munmap(ps->data, ps->endptr - ps->data);
747 : : #else
748 : 32 : free(ps->data);
749 : : #endif
750 : : }
751 : 105 : dpkg_error_destroy(&ps->err);
752 : 105 : varbuf_destroy(&ps->errmsg);
753 : 105 : free(ps);
754 : 105 : }
755 : :
756 : : /**
757 : : * Parse deb822 style package data from a buffer.
758 : : *
759 : : * donep may be NULL.
760 : : * If donep is not NULL only one package's information is expected.
761 : : */
762 : : int
763 : 105 : parsedb_parse(struct parsedb_state *ps, struct pkginfo **donep)
764 : : {
765 : : struct pkgset tmp_set;
766 : : struct pkginfo *new_pkg, *db_pkg;
767 : : struct pkgbin *new_pkgbin, *db_pkgbin;
768 : : struct pkg_parse_object pkg_obj;
769 : : int fieldencountered[array_count(fieldinfos)];
770 : : int pdone;
771 : : struct field_state fs;
772 : :
773 [ + + + - ]: 105 : if (ps->data == NULL && (ps->flags & pdb_allow_empty))
774 : 73 : return 0;
775 : :
776 : 32 : memset(&fs, 0, sizeof(fs));
777 : 32 : fs.fieldencountered = fieldencountered;
778 : :
779 : 32 : new_pkg = &tmp_set.pkg;
780 [ + + ]: 32 : if (ps->flags & pdb_recordavailable)
781 : 31 : new_pkgbin = &new_pkg->available;
782 : : else
783 : 1 : new_pkgbin = &new_pkg->installed;
784 : :
785 : 32 : ps->pkg = new_pkg;
786 : 32 : ps->pkgbin = new_pkgbin;
787 : :
788 : 32 : pkg_obj.pkg = new_pkg;
789 : 32 : pkg_obj.pkgbin = new_pkgbin;
790 : :
791 : 32 : pdone= 0;
792 : :
793 : : /* Loop per package. */
794 : : for (;;) {
795 : 32 : memset(fieldencountered, 0, sizeof(fieldencountered));
796 : 32 : pkgset_blank(&tmp_set);
797 : :
798 [ - + ]: 32 : if (!parse_stanza(ps, &fs, pkg_parse_field, &pkg_obj))
799 : 0 : break;
800 : :
801 [ - + - - ]: 32 : if (pdone && donep)
802 : 0 : parse_error(ps,
803 : 0 : _("several package info entries found, only one allowed"));
804 : :
805 : 32 : pkg_parse_verify(ps, new_pkg, new_pkgbin);
806 : :
807 : 32 : db_pkg = parse_find_pkg_slot(ps, new_pkg, new_pkgbin);
808 [ + + ]: 32 : if (ps->flags & pdb_recordavailable)
809 : 31 : db_pkgbin = &db_pkg->available;
810 : : else
811 : 1 : db_pkgbin = &db_pkg->installed;
812 : :
813 [ + - - + : 32 : if (((ps->flags & pdb_ignoreolder) || ps->type == pdb_file_available) &&
- - ]
814 [ # # ]: 0 : dpkg_version_is_informative(&db_pkgbin->version) &&
815 : 0 : dpkg_version_compare(&new_pkgbin->version, &db_pkgbin->version) < 0)
816 : 0 : continue;
817 : :
818 : 32 : pkg_parse_copy(ps, db_pkg, db_pkgbin, new_pkg, new_pkgbin);
819 : :
820 [ + + ]: 32 : if (donep)
821 : 31 : *donep = db_pkg;
822 : 32 : pdone++;
823 [ + - ]: 32 : if (parse_at_eof(ps))
824 : 32 : break;
825 : : }
826 : :
827 : 32 : varbuf_destroy(&fs.value);
828 [ + + - + ]: 32 : if (donep && !pdone)
829 : 0 : ohshit(_("no package information in '%.255s'"), ps->filename);
830 : :
831 : 32 : return pdone;
832 : : }
833 : :
834 : : /**
835 : : * Parse a deb822 style file.
836 : : *
837 : : * donep may be NULL.
838 : : * If donep is not NULL only one package's information is expected.
839 : : */
840 : : int
841 : 104 : parsedb(const char *filename, enum parsedbflags flags, struct pkginfo **pkgp)
842 : : {
843 : : struct parsedb_state *ps;
844 : : int count;
845 : :
846 : 104 : ps = parsedb_open(filename, flags);
847 : 104 : parsedb_load(ps);
848 : 104 : count = parsedb_parse(ps, pkgp);
849 : 104 : parsedb_close(ps);
850 : :
851 : 104 : return count;
852 : : }
853 : :
854 : : /**
855 : : * Copy dependency links structures.
856 : : *
857 : : * This routine is used to update the ‘reverse’ dependency pointers when
858 : : * new ‘forwards’ information has been constructed. It first removes all
859 : : * the links based on the old information. The old information starts in
860 : : * *updateme; after much brou-ha-ha the reverse structures are created
861 : : * and *updateme is set to the value from newdepends.
862 : : *
863 : : * @param pkg The package we're doing this for. This is used to construct
864 : : * correct uplinks.
865 : : * @param updateme The forwards dependency pointer that we are to update.
866 : : * This starts out containing the old forwards info, which we use to
867 : : * unthread the old reverse links. After we're done it is updated.
868 : : * @param newdepends The value that we ultimately want to have in updateme.
869 : : * @param available The pkgbin to modify, available or installed.
870 : : *
871 : : * It is likely that the backward pointer for the package in question
872 : : * (‘depended’) will be updated by this routine, but this will happen by
873 : : * the routine traversing the dependency data structures. It doesn't need
874 : : * to be told where to update that; just mentioned here as something that
875 : : * one should be cautious about.
876 : : */
877 : 32 : void copy_dependency_links(struct pkginfo *pkg,
878 : : struct dependency **updateme,
879 : : struct dependency *newdepends,
880 : : bool available)
881 : : {
882 : : struct dependency *dyp;
883 : : struct deppossi *dop, **revdeps;
884 : :
885 : : /* Delete ‘backward’ (‘depended’) links from other packages to
886 : : * dependencies listed in old version of this one. We do this by
887 : : * going through all the dependencies in the old version of this
888 : : * one and following them down to find which deppossi nodes to
889 : : * remove. */
890 [ - + ]: 32 : for (dyp= *updateme; dyp; dyp= dyp->next) {
891 [ # # ]: 0 : for (dop= dyp->list; dop; dop= dop->next) {
892 [ # # ]: 0 : if (dop->rev_prev)
893 : 0 : dop->rev_prev->rev_next = dop->rev_next;
894 [ # # ]: 0 : else if (available)
895 : 0 : dop->ed->depended.available = dop->rev_next;
896 : : else
897 : 0 : dop->ed->depended.installed = dop->rev_next;
898 [ # # ]: 0 : if (dop->rev_next)
899 : 0 : dop->rev_next->rev_prev = dop->rev_prev;
900 : : }
901 : : }
902 : :
903 : : /* Now fill in new ‘ed’ links from other packages to dependencies
904 : : * listed in new version of this one, and set our uplinks correctly. */
905 [ + + ]: 36 : for (dyp= newdepends; dyp; dyp= dyp->next) {
906 : 4 : dyp->up= pkg;
907 [ + + ]: 8 : for (dop= dyp->list; dop; dop= dop->next) {
908 [ + - ]: 4 : revdeps = available ? &dop->ed->depended.available :
909 : 0 : &dop->ed->depended.installed;
910 : 4 : dop->rev_next = *revdeps;
911 : 4 : dop->rev_prev = NULL;
912 [ - + ]: 4 : if (*revdeps)
913 : 0 : (*revdeps)->rev_prev = dop;
914 : 4 : *revdeps = dop;
915 : : }
916 : : }
917 : :
918 : : /* Finally, we fill in the new value. */
919 : 32 : *updateme= newdepends;
920 : 32 : }
|