LCOV - code coverage report
Current view: top level - lib/dpkg - parse.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 68.6 % 373 256
Test Date: 2024-07-17 02:53:43 Functions: 100.0 % 15 15
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 51.2 % 340 174

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

Generated by: LCOV version 2.0-1