LCOV - code coverage report
Current view: top level - lib/dpkg - parse.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 258 376 68.6 %
Date: 2022-12-03 00:40:01 Functions: 15 15 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 174 342 50.9 %

           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 : }

Generated by: LCOV version 1.16