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