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