LCOV - code coverage report
Current view: top level - libpkg - pkg_jobs.c (source / functions) Hit Total Coverage
Test: rapport Lines: 936 1348 69.4 %
Date: 2021-12-10 16:22:55 Functions: 51 58 87.9 %
Branches: 531 885 60.0 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2016 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       5                 :            :  * Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
       6                 :            :  * Copyright (c) 2013-2016 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       7                 :            :  * All rights reserved.
       8                 :            :  *
       9                 :            :  * Redistribution and use in source and binary forms, with or without
      10                 :            :  * modification, are permitted provided that the following conditions
      11                 :            :  * are met:
      12                 :            :  * 1. Redistributions of source code must retain the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer
      14                 :            :  *    in this position and unchanged.
      15                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      16                 :            :  *    notice, this list of conditions and the following disclaimer in the
      17                 :            :  *    documentation and/or other materials provided with the distribution.
      18                 :            :  *
      19                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      20                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      21                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      22                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      23                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      24                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      28                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :            :  */
      30                 :            : 
      31                 :            : #ifdef HAVE_CONFIG_H
      32                 :            : #include "pkg_config.h"
      33                 :            : #endif
      34                 :            : 
      35                 :            : #include <bsd_compat.h>
      36                 :            : 
      37                 :            : #include <sys/param.h>
      38                 :            : #include <sys/mount.h>
      39                 :            : #include <sys/types.h>
      40                 :            : 
      41                 :            : #include <archive.h>
      42                 :            : #include <archive_entry.h>
      43                 :            : #include <assert.h>
      44                 :            : #include <errno.h>
      45                 :            : #ifdef HAVE_LIBUTIL_H
      46                 :            : #include <libutil.h>
      47                 :            : #endif
      48                 :            : #include <search.h>
      49                 :            : #include <stdbool.h>
      50                 :            : #include <stdlib.h>
      51                 :            : #include <string.h>
      52                 :            : #include <sys/wait.h>
      53                 :            : #include <ctype.h>
      54                 :            : 
      55                 :            : #ifdef HAVE_SYS_STATFS_H
      56                 :            : #include <sys/statfs.h>
      57                 :            : #endif
      58                 :            : #if defined(HAVE_SYS_STATVFS_H)
      59                 :            : #include <sys/statvfs.h>
      60                 :            : #endif
      61                 :            : 
      62                 :            : #include "pkg.h"
      63                 :            : #include "private/event.h"
      64                 :            : #include "private/pkg.h"
      65                 :            : #include "private/pkgdb.h"
      66                 :            : #include "private/pkg_jobs.h"
      67                 :            : #include "kvec.h"
      68                 :            : 
      69                 :            : extern struct pkg_ctx ctx;
      70                 :            : 
      71                 :            : static int pkg_jobs_installed_local_pkg(struct pkg_jobs *j, struct pkg *pkg);
      72                 :            : static int pkg_jobs_find_upgrade(struct pkg_jobs *j, const char *pattern, match_t m);
      73                 :            : static int pkg_jobs_fetch(struct pkg_jobs *j);
      74                 :            : static bool new_pkg_version(struct pkg_jobs *j);
      75                 :            : static int pkg_jobs_check_conflicts(struct pkg_jobs *j);
      76                 :            : struct pkg_jobs_locked {
      77                 :            :         int (*locked_pkg_cb)(struct pkg *, void *);
      78                 :            :         void *context;
      79                 :            : };
      80                 :            : static __thread struct pkg_jobs_locked *pkgs_job_lockedpkg;
      81                 :            : 
      82                 :            : #define IS_DELETE(j) ((j)->type == PKG_JOBS_DEINSTALL || (j)->type == PKG_JOBS_AUTOREMOVE)
      83                 :            : 
      84                 :            : int
      85                 :        611 : pkg_jobs_new(struct pkg_jobs **j, pkg_jobs_t t, struct pkgdb *db)
      86                 :            : {
      87         [ +  - ]:        611 :         assert(db != NULL);
      88                 :            : 
      89                 :        611 :         *j = xcalloc(1, sizeof(struct pkg_jobs));
      90                 :            : 
      91                 :        611 :         (*j)->universe = pkg_jobs_universe_new(*j);
      92                 :            : 
      93         [ +  - ]:        611 :         if ((*j)->universe == NULL) {
      94                 :          0 :                 free(*j);
      95                 :          0 :                 return (EPKG_FATAL);
      96                 :            :         }
      97                 :            : 
      98                 :        611 :         (*j)->db = db;
      99                 :        611 :         (*j)->type = t;
     100                 :        611 :         (*j)->solved = 0;
     101                 :        611 :         (*j)->pinning = true;
     102                 :        611 :         (*j)->flags = PKG_FLAG_NONE;
     103                 :        611 :         (*j)->conservative = pkg_object_bool(pkg_config_get("CONSERVATIVE_UPGRADE"));
     104                 :            : 
     105                 :        611 :         return (EPKG_OK);
     106                 :        611 : }
     107                 :            : 
     108                 :            : void
     109                 :        611 : pkg_jobs_set_flags(struct pkg_jobs *j, pkg_flags flags)
     110                 :            : {
     111                 :        611 :         j->flags = flags;
     112                 :        611 : }
     113                 :            : 
     114                 :            : int
     115                 :         13 : pkg_jobs_set_repository(struct pkg_jobs *j, const char *ident)
     116                 :            : {
     117         [ -  + ]:         13 :         if ((pkg_repo_find(ident)) == NULL) {
     118                 :          0 :                 pkg_emit_error("Unknown repository: %s", ident);
     119                 :          0 :                 return (EPKG_FATAL);
     120                 :            :         }
     121                 :            : 
     122                 :         13 :         j->reponame = ident;
     123                 :            : 
     124                 :         13 :         return (EPKG_OK);
     125                 :         13 : }
     126                 :            : 
     127                 :            : int
     128                 :          0 : pkg_jobs_set_destdir(struct pkg_jobs *j, const char *dir)
     129                 :            : {
     130         [ #  # ]:          0 :         if (dir == NULL)
     131                 :          0 :                 return (EPKG_FATAL);
     132                 :            : 
     133                 :          0 :         j->destdir = dir;
     134                 :            : 
     135                 :          0 :         return (EPKG_OK);
     136                 :          0 : }
     137                 :            : 
     138                 :            : const char*
     139                 :        521 : pkg_jobs_destdir(struct pkg_jobs *j)
     140                 :            : {
     141                 :        521 :         return (j->destdir);
     142                 :            : }
     143                 :            : 
     144                 :            : static void
     145                 :        482 : pkg_jobs_pattern_free(struct job_pattern *jp)
     146                 :            : {
     147                 :        482 :         free(jp->pattern);
     148                 :        482 :         free(jp->path);
     149                 :        482 :         free(jp);
     150                 :        482 : }
     151                 :            : 
     152                 :            : void
     153                 :        635 : pkg_jobs_request_free(struct pkg_job_request *req)
     154                 :            : {
     155                 :            :         struct pkg_job_request_item *it, *tmp;
     156                 :            : 
     157         [ +  - ]:        635 :         if (req != NULL) {
     158   [ +  +  +  + ]:       1319 :                 DL_FOREACH_SAFE(req->item, it, tmp) {
     159                 :        684 :                         free(it);
     160                 :        684 :                 }
     161                 :            : 
     162                 :        635 :                 free(req);
     163                 :        635 :         }
     164                 :        635 : }
     165                 :            : 
     166                 :            : void
     167                 :        611 : pkg_jobs_free(struct pkg_jobs *j)
     168                 :            : {
     169                 :            :         pkghash_it it;
     170                 :            : 
     171         [ -  + ]:        611 :         if (j == NULL)
     172                 :          0 :                 return;
     173                 :            : 
     174                 :        611 :         it = pkghash_iterator(j->request_add);
     175         [ +  + ]:       1097 :         while (pkghash_next(&it))
     176                 :        486 :                 pkg_jobs_request_free(it.value);
     177                 :        611 :         pkghash_destroy(j->request_add);
     178                 :        611 :         j->request_add = NULL;
     179                 :            : 
     180                 :        611 :         it = pkghash_iterator(j->request_delete);
     181         [ +  + ]:        760 :         while (pkghash_next(&it))
     182                 :        149 :                 pkg_jobs_request_free(it.value);
     183                 :        611 :         pkghash_destroy(j->request_delete);
     184                 :        611 :         j->request_delete = NULL;
     185                 :            : 
     186                 :        611 :         pkg_jobs_universe_free(j->universe);
     187   [ +  +  +  +  :       1402 :         LL_FREE(j->jobs, free);
          +  -  #  #  #  
                #  #  # ]
     188   [ +  +  +  +  :       1093 :         LL_FREE(j->patterns, pkg_jobs_pattern_free);
          +  -  #  #  #  
                #  #  # ]
     189                 :        611 :         free(j);
     190                 :        611 : }
     191                 :            : 
     192                 :            : static bool
     193                 :        371 : pkg_jobs_maybe_match_file(struct job_pattern *jp, const char *pattern)
     194                 :            : {
     195                 :            :         const char *dot_pos;
     196                 :            :         char *pkg_path;
     197                 :            : 
     198         [ +  - ]:        371 :         assert(jp != NULL);
     199         [ -  + ]:        371 :         assert(pattern != NULL);
     200                 :            : 
     201                 :        371 :         dot_pos = strrchr(pattern, '.');
     202         [ +  + ]:        371 :         if (dot_pos != NULL) {
     203                 :            :                 /*
     204                 :            :                  * Compare suffix with .txz or .tbz
     205                 :            :                  */
     206                 :        220 :                 dot_pos ++;
     207   [ +  +  +  - ]:        228 :                 if (strcmp(dot_pos, "pkg") == 0 ||
     208         [ +  - ]:          8 :                     strcmp(dot_pos, "tzst") == 0 ||
     209         [ +  - ]:          8 :                     strcmp(dot_pos, "txz") == 0 ||
     210         [ +  - ]:          8 :                     strcmp(dot_pos, "tbz") == 0 ||
     211         [ +  - ]:          8 :                     strcmp(dot_pos, "tgz") == 0 ||
     212                 :          8 :                     strcmp(dot_pos, "tar") == 0) {
     213         [ +  - ]:        212 :                         if ((pkg_path = realpath(pattern, NULL)) != NULL) {
     214                 :            :                                 /* Dot pos is one character after the dot */
     215                 :        212 :                                 int len = dot_pos - pattern;
     216                 :            : 
     217                 :        212 :                                 pkg_debug(1, "Jobs> Adding file: %s", pattern);
     218                 :        212 :                                 jp->flags |= PKG_PATTERN_FLAG_FILE;
     219                 :        212 :                                 jp->path = pkg_path;
     220                 :        212 :                                 jp->pattern = xmalloc(len);
     221                 :        212 :                                 strlcpy(jp->pattern, pattern, len);
     222                 :            : 
     223                 :        212 :                                 return (true);
     224                 :            :                         }
     225                 :          0 :                 }
     226                 :          8 :         }
     227         [ +  - ]:        151 :         else if (strcmp(pattern, "-") == 0) {
     228                 :            :                 /*
     229                 :            :                  * Read package from stdin
     230                 :            :                  */
     231                 :          0 :                 jp->flags = PKG_PATTERN_FLAG_FILE;
     232                 :          0 :                 jp->path = xstrdup(pattern);
     233                 :          0 :                 jp->pattern = xstrdup(pattern);
     234                 :          0 :         }
     235                 :            : 
     236                 :        159 :         return (false);
     237                 :        371 : }
     238                 :            : 
     239                 :            : int
     240                 :        474 : pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc)
     241                 :            : {
     242                 :            :         struct job_pattern *jp;
     243                 :        474 :         int i = 0;
     244                 :            : 
     245         [ -  + ]:        474 :         if (j->solved) {
     246                 :          0 :                 pkg_emit_error("The job has already been solved. "
     247                 :            :                     "Impossible to append new elements");
     248                 :          0 :                 return (EPKG_FATAL);
     249                 :            :         }
     250                 :            : 
     251         [ +  + ]:        952 :         for (i = 0; i < argc; i++) {
     252                 :        478 :                 jp = xcalloc(1, sizeof(struct job_pattern));
     253   [ +  +  +  + ]:        478 :                 if (j->type == PKG_JOBS_DEINSTALL ||
     254                 :        371 :                     !pkg_jobs_maybe_match_file(jp, argv[i])) {
     255                 :        266 :                         jp->pattern = xstrdup(argv[i]);
     256                 :        266 :                         jp->match = match;
     257                 :        266 :                 }
     258   [ +  +  -  + ]:        478 :                 LL_APPEND(j->patterns, jp);
     259                 :        478 :         }
     260                 :            : 
     261   [ +  +  -  + ]:        474 :         if (argc == 0 && match == MATCH_ALL) {
     262                 :          4 :                 jp = xcalloc(1, sizeof(struct job_pattern));
     263                 :          4 :                 jp->pattern = NULL;
     264                 :          4 :                 jp->match = match;
     265   [ +  -  #  # ]:          4 :                 LL_APPEND(j->patterns, jp);
     266                 :          4 :         }
     267                 :            : 
     268                 :        474 :         return (EPKG_OK);
     269                 :        474 : }
     270                 :            : 
     271                 :            : bool
     272                 :        826 : pkg_jobs_iter(struct pkg_jobs *jobs, void **iter,
     273                 :            :                                 struct pkg **new, struct pkg **old,
     274                 :            :                                 int *type)
     275                 :            : {
     276                 :            :         struct pkg_solved *s;
     277         [ +  - ]:        826 :         assert(iter != NULL);
     278         [ +  - ]:        826 :         if (jobs->jobs == NULL) {
     279                 :          0 :                 return (false);
     280                 :            :         }
     281         [ +  + ]:        826 :         if (*iter == NULL) {
     282                 :        305 :                 s = jobs->jobs;
     283                 :        305 :         }
     284         [ +  + ]:        521 :         else if (*iter == jobs->jobs) {
     285                 :        305 :                 return (false);
     286                 :            :         }
     287                 :            :         else {
     288                 :        216 :                 s = *iter;
     289                 :            :         }
     290                 :        521 :         *new = s->items[0]->pkg;
     291         [ +  + ]:        521 :         *old = s->items[1] ? s->items[1]->pkg : NULL;
     292                 :        521 :         *type = s->type;
     293         [ +  + ]:        521 :         *iter = s->next ? s->next : jobs->jobs;
     294                 :        521 :         return (true);
     295                 :        826 : }
     296                 :            : 
     297                 :            : static struct pkg_job_request_item*
     298                 :        381 : pkg_jobs_add_req_from_universe(pkghash **head, struct pkg_job_universe_item *un,
     299                 :            :     bool local, bool automatic)
     300                 :            : {
     301                 :            :         struct pkg_job_request *req;
     302                 :            :         struct pkg_job_request_item *nit;
     303                 :            :         struct pkg_job_universe_item *uit;
     304                 :        381 :         bool new_req = false;
     305                 :            : 
     306         [ +  - ]:        381 :         assert(un != NULL);
     307                 :        381 :         req = pkghash_get_value(*head, un->pkg->uid);
     308                 :            : 
     309         [ +  + ]:        381 :         if (req == NULL) {
     310                 :        308 :                 req = xcalloc(1, sizeof(*req));
     311                 :        308 :                 new_req = true;
     312                 :        308 :                 req->automatic = automatic;
     313                 :        308 :                 pkg_debug(4, "add new uid %s to the request", un->pkg->uid);
     314                 :        308 :         }
     315                 :            :         else {
     316         [ +  + ]:         73 :                 if (req->item->unit == un) {
     317                 :            :                         /* We have exactly the same request, skip it */
     318                 :         20 :                         return (req->item);
     319                 :            :                 }
     320                 :            :         }
     321                 :            : 
     322         [ +  + ]:       1081 :         DL_FOREACH(un, uit) {
     323   [ +  +  +  + ]:       1177 :                 if ((uit->pkg->type == PKG_INSTALLED && local) ||
     324         [ +  + ]:        651 :                                 (uit->pkg->type != PKG_INSTALLED && !local)) {
     325                 :        457 :                         nit = xcalloc(1, sizeof(*nit));
     326                 :        457 :                         nit->pkg = uit->pkg;
     327                 :        457 :                         nit->unit = uit;
     328         [ +  + ]:        457 :                         DL_APPEND(req->item, nit);
     329                 :        457 :                 }
     330                 :       1108 :         }
     331                 :            : 
     332         [ +  + ]:        361 :         if (new_req) {
     333         [ +  + ]:        308 :                 if (req->item != NULL) {
     334   [ +  +  -  + ]:        326 :                         pkghash_safe_add(*head, un->pkg->uid, req, NULL);
     335                 :        278 :                 }
     336                 :            :                 else {
     337                 :         30 :                         free(req);
     338                 :         30 :                         return (NULL);
     339                 :            :                 }
     340                 :        278 :         }
     341                 :            : 
     342                 :        331 :         return (req->item);
     343                 :        381 : }
     344                 :            : 
     345                 :            : static struct pkg_job_request_item*
     346                 :        361 : pkg_jobs_add_req(struct pkg_jobs *j, struct pkg *pkg)
     347                 :            : {
     348                 :            :         pkghash **head;
     349                 :            :         struct pkg_job_request *req;
     350                 :            :         struct pkg_job_request_item *nit;
     351                 :            :         struct pkg_job_universe_item *un;
     352                 :            :         int rc;
     353                 :            : 
     354         [ +  - ]:        361 :         assert(pkg != NULL);
     355                 :            : 
     356   [ +  +  +  + ]:        361 :         if (!IS_DELETE(j)) {
     357                 :        212 :                 head = &j->request_add;
     358         [ -  + ]:        212 :                 assert(pkg->type != PKG_INSTALLED);
     359                 :        212 :         }
     360                 :            :         else {
     361                 :        149 :                 head = &j->request_delete;
     362         [ +  - ]:        149 :                 assert(pkg->type == PKG_INSTALLED);
     363                 :            :         }
     364                 :            : 
     365                 :        722 :         pkg_debug(4, "universe: add package %s-%s to the request", pkg->name,
     366                 :        361 :                         pkg->version);
     367                 :        361 :         rc = pkg_jobs_universe_add_pkg(j->universe, pkg, false, &un);
     368                 :            : 
     369         [ -  + ]:        361 :         if (rc == EPKG_END) {
     370                 :            :                 /*
     371                 :            :                  * This means that we have a package in the universe with the same
     372                 :            :                  * digest. In turn, that means that two upgrade candidates are equal,
     373                 :            :                  * we thus won't do anything with this item, as it is definitely useless
     374                 :            :                  */
     375                 :          0 :                 req = pkghash_get_value(*head, pkg->uid);
     376         [ #  # ]:          0 :                 if (req != NULL) {
     377         [ #  # ]:          0 :                         DL_FOREACH(req->item, nit) {
     378         [ #  # ]:          0 :                                 if (nit->unit == un)
     379                 :          0 :                                         return (nit);
     380                 :          0 :                         }
     381                 :          0 :                 }
     382                 :            :                 else {
     383                 :            :                         /*
     384                 :            :                          * We need to add request chain from the universe chain
     385                 :            :                          */
     386         [ #  # ]:          0 :                         return (pkg_jobs_add_req_from_universe(head, un, IS_DELETE(j), false));
     387                 :            :                 }
     388                 :            : 
     389                 :          0 :                 return (NULL);
     390                 :            :         }
     391         [ -  + ]:        361 :         else if (rc == EPKG_FATAL) {
     392                 :            :                 /*
     393                 :            :                  * Something bad has happened
     394                 :            :                  */
     395                 :          0 :                 return (NULL);
     396                 :            :         }
     397                 :            : 
     398         [ -  + ]:        361 :         if (pkg->locked) {
     399                 :          0 :                 pkg_emit_locked(pkg);
     400                 :          0 :                 return (NULL);
     401                 :            :         }
     402                 :            : 
     403                 :        361 :         req = pkghash_get_value(*head, pkg->uid);
     404                 :            : 
     405                 :        361 :         nit = xcalloc(1, sizeof(*nit));
     406                 :        361 :         nit->pkg = pkg;
     407                 :        361 :         nit->unit = un;
     408                 :            : 
     409         [ -  + ]:        361 :         if (req == NULL) {
     410                 :            :                 /* Allocate new unique request item */
     411                 :        361 :                 req = xcalloc(1, sizeof(*req));
     412   [ +  +  -  + ]:        373 :                 pkghash_safe_add(*head, pkg->uid, req, NULL);
     413                 :        361 :         }
     414                 :            : 
     415                 :            :         /* Append candidate to the list of candidates */
     416         [ -  + ]:        361 :         DL_APPEND(req->item, nit);
     417                 :            : 
     418                 :        361 :         return (nit);
     419                 :        361 : }
     420                 :            : 
     421                 :            : /*
     422                 :            :  * Post-process add request and handle flags:
     423                 :            :  * upgrade - search for upgrades for dependencies and add them to the request
     424                 :            :  * force - all upgrades are forced
     425                 :            :  * reverse - try to upgrade reverse deps as well
     426                 :            :  */
     427                 :            : static void
     428                 :            : pkg_jobs_process_add_request(struct pkg_jobs *j)
     429                 :            : {
     430                 :            :         bool force = j->flags & PKG_FLAG_FORCE,
     431                 :            :                  reverse = j->flags & PKG_FLAG_RECURSIVE,
     432                 :            :                  upgrade = j->type == PKG_JOBS_UPGRADE;
     433                 :            :         struct pkg_job_request *req;
     434                 :            :         struct pkg_job_request_item *it;
     435                 :            :         struct pkg_job_universe_item *un, *cur;
     436                 :            :         struct pkg_dep *d;
     437                 :            :         struct pkg *lp;
     438                 :            :         int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
     439                 :            :         kvec_t(struct pkg_job_universe_item *) to_process;
     440                 :            :         pkghash_it hit;
     441                 :            : 
     442                 :            :         if (!upgrade && !reverse)
     443                 :            :                 return;
     444                 :            : 
     445                 :            :         kv_init(to_process);
     446                 :            :         hit = pkghash_iterator(j->request_add);
     447                 :            :         while (pkghash_next(&hit)) {
     448                 :            :                 req = hit.value;
     449                 :            :                 it = req->item;
     450                 :            : 
     451                 :            :                 if (reverse)
     452                 :            :                         deps_func = pkg_rdeps;
     453                 :            :                 else
     454                 :            :                         deps_func = pkg_deps;
     455                 :            : 
     456                 :            :                 d = NULL;
     457                 :            :                 /*
     458                 :            :                  * Here we get deps of local packages only since we are pretty sure
     459                 :            :                  * that they are completely expanded
     460                 :            :                  */
     461                 :            :                 lp = pkg_jobs_universe_get_local(j->universe,
     462                 :            :                     it->pkg->uid, 0);
     463                 :            :                 while (lp != NULL && deps_func(lp, &d) == EPKG_OK) {
     464                 :            :                         /*
     465                 :            :                          * Do not add duplicated upgrade candidates
     466                 :            :                          */
     467                 :            :                         if (pkghash_get(j->request_add, d->uid))
     468                 :            :                                 continue;
     469                 :            : 
     470                 :            :                         pkg_debug(4, "adding dependency %s to request", d->uid);
     471                 :            :                         lp = pkg_jobs_universe_get_local(j->universe,
     472                 :            :                                 d->uid, 0);
     473                 :            :                         /*
     474                 :            :                          * Here we need to check whether specific remote package
     475                 :            :                          * is newer than a local one
     476                 :            :                          */
     477                 :            :                         un = pkg_jobs_universe_get_upgrade_candidates(j->universe,
     478                 :            :                                 d->uid, lp, force, NULL);
     479                 :            :                         if (un == NULL)
     480                 :            :                                 continue;
     481                 :            : 
     482                 :            :                         cur = un->prev;
     483                 :            :                         while (cur != un) {
     484                 :            :                                 if (cur->pkg->type != PKG_INSTALLED) {
     485                 :            :                                         kv_push(typeof(un), to_process, un);
     486                 :            :                                         break;
     487                 :            :                                 }
     488                 :            :                                 cur = cur->prev;
     489                 :            :                         }
     490                 :            :                 }
     491                 :            :         }
     492                 :            : 
     493                 :            :         /* Add all items to the request */
     494                 :            :         for (int i = 0; i < kv_size(to_process); i++) {
     495                 :            :                 un = kv_A(to_process, i);
     496                 :            :                 pkg_jobs_add_req_from_universe(&j->request_add, un, false, true);
     497                 :            :         }
     498                 :            :         /* Now recursively process all items checked */
     499                 :            :         if (kv_size(to_process) > 0)
     500                 :            :                 pkg_jobs_process_add_request(j);
     501                 :            : 
     502                 :            :         kv_destroy(to_process);
     503                 :            : }
     504                 :            : 
     505                 :            : /*
     506                 :            :  * For delete request we merely check rdeps and force flag
     507                 :            :  */
     508                 :            : static int
     509                 :        141 : pkg_jobs_process_delete_request(struct pkg_jobs *j)
     510                 :            : {
     511                 :        141 :         bool force = j->flags & PKG_FLAG_FORCE;
     512                 :            :         struct pkg_job_request *req;
     513                 :        141 :         struct pkg_dep *d = NULL;
     514                 :            :         struct pkg *lp;
     515                 :        141 :         int rc = EPKG_OK;
     516                 :            :         kvec_t(struct pkg *) to_process;
     517                 :            :         pkghash_it it;
     518                 :            : 
     519         [ +  + ]:        141 :         if (force)
     520                 :         46 :                 return (EPKG_OK);
     521                 :            : 
     522                 :         95 :         kv_init(to_process);
     523                 :            :         /*
     524                 :            :          * Need to add also all reverse deps here
     525                 :            :          */
     526                 :         95 :         it = pkghash_iterator(j->request_delete);
     527         [ +  + ]:        194 :         while (pkghash_next(&it)) {
     528                 :         99 :                 req = it.value;
     529                 :         99 :                 d = NULL;
     530         [ -  + ]:         99 :                 while (pkg_rdeps(req->item->pkg, &d) == EPKG_OK) {
     531         [ #  # ]:          0 :                         if (pkghash_get(j->request_delete, d->uid))
     532                 :          0 :                                 continue;
     533                 :            : 
     534                 :          0 :                         lp = pkg_jobs_universe_get_local(j->universe, d->uid, 0);
     535         [ #  # ]:          0 :                         if (lp) {
     536         [ #  # ]:          0 :                                 if (lp->locked) {
     537                 :          0 :                                         pkg_emit_error("%s is locked, "
     538                 :          0 :                                             "cannot delete %s", lp->name,
     539                 :          0 :                                            req->item->pkg->name);
     540                 :          0 :                                         rc = EPKG_FATAL;
     541                 :          0 :                                 }
     542   [ #  #  #  # ]:          0 :                                 kv_push(typeof(lp), to_process, lp);
     543                 :          0 :                         }
     544                 :            :                 }
     545                 :            :         }
     546                 :            : 
     547         [ -  + ]:         95 :         if (rc == EPKG_FATAL)
     548                 :          0 :                 return (rc);
     549                 :            : 
     550         [ -  + ]:         95 :         for (int i = 0; i < kv_size(to_process); i++) {
     551                 :          0 :                 lp = kv_A(to_process, i);
     552         [ #  # ]:          0 :                 if (pkg_jobs_add_req(j, lp) == NULL) {
     553                 :          0 :                         kv_destroy(to_process);
     554                 :          0 :                         return (EPKG_FATAL);
     555                 :            :                 }
     556                 :          0 :         }
     557         [ +  - ]:         95 :         if (kv_size(to_process) > 0)
     558                 :          0 :                 rc = pkg_jobs_process_delete_request(j);
     559                 :         95 :         kv_destroy(to_process);
     560                 :            : 
     561                 :         95 :         return (rc);
     562                 :        141 : }
     563                 :            : 
     564                 :            : static int
     565                 :        738 : pkg_jobs_set_execute_priority(struct pkg_jobs *j, struct pkg_solved *solved)
     566                 :            : {
     567                 :            :         struct pkg_solved *ts;
     568                 :            : 
     569   [ +  +  +  + ]:        738 :         if (solved->type == PKG_SOLVED_UPGRADE && solved->items[1]->pkg->conflicts != NULL) {
     570                 :            :                 /*
     571                 :            :                  * We have an upgrade request that has some conflicting packages, therefore
     572                 :            :                  * update priorities of local packages and try to update priorities of remote ones
     573                 :            :                  */
     574         [ -  + ]:          8 :                 if (solved->items[0]->priority == 0)
     575                 :          8 :                         pkg_jobs_update_conflict_priority(j->universe, solved);
     576                 :            : 
     577         [ +  - ]:          8 :                 if (solved->items[1]->priority > solved->items[0]->priority) {
     578                 :            :                         /*
     579                 :            :                          * Split conflicting upgrade request into delete -> upgrade request
     580                 :            :                          */
     581                 :          8 :                         ts = xcalloc(1, sizeof(struct pkg_solved));
     582                 :          8 :                         ts->type = PKG_SOLVED_UPGRADE_REMOVE;
     583                 :          8 :                         ts->items[0] = solved->items[1];
     584                 :          8 :                         solved->items[1] = NULL;
     585                 :          8 :                         solved->type = PKG_SOLVED_UPGRADE_INSTALL;
     586         [ +  - ]:          8 :                         DL_APPEND(j->jobs, ts);
     587                 :          8 :                         j->count++;
     588                 :          8 :                         pkg_debug(2, "split upgrade request for %s",
     589                 :          8 :                            ts->items[0]->pkg->uid);
     590                 :          8 :                         return (EPKG_CONFLICT);
     591                 :            :                 }
     592                 :          0 :         }
     593         [ +  + ]:        730 :         else if (solved->type == PKG_SOLVED_DELETE) {
     594         [ +  + ]:        176 :                 if (solved->items[0]->priority == 0)
     595                 :        160 :                         pkg_jobs_update_universe_priority(j->universe, solved->items[0],
     596                 :            :                                         PKG_PRIORITY_UPDATE_DELETE);
     597                 :        176 :         }
     598         [ +  + ]:        554 :         else if (solved->items[0]->priority == 0) {
     599                 :        482 :                 pkg_jobs_update_universe_priority(j->universe, solved->items[0],
     600                 :            :                                 PKG_PRIORITY_UPDATE_REQUEST);
     601                 :        482 :         }
     602                 :            : 
     603                 :        730 :         return (EPKG_OK);
     604                 :        738 : }
     605                 :            : 
     606                 :            : static bool
     607                 :        160 : pkg_jobs_is_delete(struct pkg_solved *req)
     608                 :            : {
     609         [ +  + ]:        160 :         return (req->type == PKG_SOLVED_DELETE ||
     610                 :         48 :             req->type == PKG_SOLVED_UPGRADE_REMOVE);
     611                 :            : }
     612                 :            : 
     613                 :            : static int
     614                 :        264 : pkg_jobs_sort_priority(struct pkg_solved *r1, struct pkg_solved *r2)
     615                 :            : {
     616         [ +  + ]:        264 :         if (r1->items[0]->priority == r2->items[0]->priority) {
     617   [ +  +  +  - ]:         52 :                 if (pkg_jobs_is_delete(r1) && !pkg_jobs_is_delete(r2))
     618                 :          0 :                         return (-1);
     619   [ +  +  -  + ]:         52 :                 if (pkg_jobs_is_delete(r2) && !pkg_jobs_is_delete(r1))
     620                 :          0 :                         return (1);
     621                 :            : 
     622                 :         52 :                 return (0);
     623                 :            :         }
     624                 :        212 :         return (r2->items[0]->priority - r1->items[0]->priority);
     625                 :        264 : }
     626                 :            : 
     627                 :            : static void
     628                 :        542 : pkg_jobs_set_priorities(struct pkg_jobs *j)
     629                 :            : {
     630                 :        542 :         struct pkg_solved *req;
     631                 :            : 
     632                 :            : iter_again:
     633         [ +  + ]:       1292 :         LL_FOREACH(j->jobs, req) {
     634                 :        742 :                 req->items[0]->priority = 0;
     635         [ +  + ]:        742 :                 if (req->items[1] != NULL)
     636                 :        144 :                         req->items[1]->priority = 0;
     637                 :        742 :         }
     638         [ +  + ]:       1280 :         LL_FOREACH(j->jobs, req) {
     639         [ +  + ]:        738 :                 if (pkg_jobs_set_execute_priority(j, req) == EPKG_CONFLICT)
     640                 :          8 :                         goto iter_again;
     641                 :        730 :         }
     642                 :            : 
     643   [ +  -  +  +  :       3084 :         DL_SORT(j->jobs, pkg_jobs_sort_priority);
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  + ]
     644                 :        542 : }
     645                 :            : 
     646                 :            : 
     647                 :            : /**
     648                 :            :  * Test whether package specified is automatic with all its rdeps
     649                 :            :  * @param j
     650                 :            :  * @param p
     651                 :            :  * @return
     652                 :            :  */
     653                 :            : static bool
     654                 :         34 : pkg_jobs_test_automatic(struct pkg_jobs *j, struct pkg *p)
     655                 :            : {
     656                 :         34 :         struct pkg_dep *d = NULL;
     657                 :            :         struct pkg_job_universe_item *unit;
     658                 :            :         struct pkg *npkg;
     659                 :         34 :         bool ret = true;
     660                 :            : 
     661   [ +  -  -  + ]:         34 :         while (pkg_rdeps(p, &d) == EPKG_OK && ret) {
     662                 :          0 :                 unit = pkg_jobs_universe_find(j->universe, d->uid);
     663         [ #  # ]:          0 :                 if (unit != NULL) {
     664         [ #  # ]:          0 :                         if (!unit->pkg->automatic) {
     665                 :          0 :                                 return (false);
     666                 :            :                         }
     667                 :          0 :                         npkg = unit->pkg;
     668                 :          0 :                 }
     669                 :            :                 else {
     670                 :          0 :                         npkg = pkg_jobs_universe_get_local(j->universe, d->uid,
     671                 :            :                                         PKG_LOAD_BASIC|PKG_LOAD_RDEPS|PKG_LOAD_ANNOTATIONS);
     672         [ #  # ]:          0 :                         if (npkg == NULL)
     673                 :          0 :                                 return (false);
     674         [ #  # ]:          0 :                         if (!npkg->automatic) {
     675                 :            :                                 /*
     676                 :            :                                  * Safe to free, as d->uid is not in the universe
     677                 :            :                                  */
     678                 :          0 :                                 pkg_free(npkg);
     679                 :          0 :                                 return (false);
     680                 :            :                         }
     681         [ #  # ]:          0 :                         if (pkg_jobs_universe_process(j->universe, npkg) != EPKG_OK)
     682                 :          0 :                                 return (false);
     683                 :            :                 }
     684                 :            : 
     685                 :          0 :                 ret = pkg_jobs_test_automatic(j, npkg);
     686                 :            :         }
     687                 :            : 
     688                 :         34 :         return (ret);
     689                 :         34 : }
     690                 :            : 
     691                 :            : 
     692                 :            : 
     693                 :            : static bool
     694                 :        478 : new_pkg_version(struct pkg_jobs *j)
     695                 :            : {
     696                 :            :         struct pkg *p;
     697                 :        478 :         const char *uid = "pkg";
     698                 :            :         pkg_flags old_flags;
     699                 :        478 :         bool ret = false;
     700                 :            :         struct pkg_job_universe_item *nit, *cit;
     701                 :            : 
     702                 :            :         /* Disable -f for pkg self-check, and restore at end. */
     703                 :        478 :         old_flags = j->flags;
     704                 :        478 :         j->flags &= ~(PKG_FLAG_FORCE|PKG_FLAG_RECURSIVE);
     705                 :            : 
     706                 :            :         /* determine local pkgng */
     707                 :        478 :         p = pkg_jobs_universe_get_local(j->universe, uid, 0);
     708                 :            : 
     709         [ +  + ]:        478 :         if (p == NULL) {
     710                 :        442 :                 uid = "pkg-devel";
     711                 :        442 :                 p = pkg_jobs_universe_get_local(j->universe, uid, 0);
     712                 :        442 :         }
     713                 :            : 
     714                 :            :         /* you are using git version skip */
     715         [ +  + ]:        478 :         if (p == NULL) {
     716                 :        442 :                 ret = false;
     717                 :        442 :                 goto end;
     718                 :            :         }
     719                 :            : 
     720                 :            :         /* Use maximum priority for pkg */
     721         [ +  + ]:         49 :         if (pkg_jobs_find_upgrade(j, uid, MATCH_EXACT) == EPKG_OK) {
     722                 :            :                 /*
     723                 :            :                  * Now we can have *potential* upgrades, but we can have a situation,
     724                 :            :                  * when our upgrade candidate comes from another repo
     725                 :            :                  */
     726                 :         13 :                 nit = pkg_jobs_universe_find(j->universe, uid);
     727                 :            : 
     728         [ -  + ]:         13 :                 if (nit) {
     729         [ -  + ]:         26 :                         DL_FOREACH(nit, cit) {
     730         [ +  + ]:         26 :                                 if (pkg_version_change_between (cit->pkg, p) == PKG_UPGRADE) {
     731                 :            :                                         /* We really have newer version which is not installed */
     732                 :         13 :                                         ret = true;
     733                 :         13 :                                         break;
     734                 :            :                                 }
     735                 :         13 :                         }
     736                 :         13 :                 }
     737                 :         13 :         }
     738                 :            : 
     739                 :            : end:
     740                 :        478 :         j->flags = old_flags;
     741                 :            : 
     742                 :        478 :         return (ret);
     743                 :            : }
     744                 :            : 
     745                 :            : static int
     746                 :        424 : pkg_jobs_process_remote_pkg(struct pkg_jobs *j, struct pkg *rp,
     747                 :            :         struct pkg_job_request_item **req, int with_version)
     748                 :            : {
     749                 :            :         struct pkg_job_universe_item *nit, *cur;
     750                 :        424 :         struct pkg_job_request_item *nrit = NULL;
     751                 :        424 :         struct pkg *lp = NULL;
     752                 :        424 :         struct pkg_dep *rdep = NULL;
     753                 :            : 
     754         [ +  - ]:        424 :         if (rp->digest == NULL) {
     755         [ #  # ]:          0 :                 if (pkg_checksum_calculate(rp, j->db, false, true, false) != EPKG_OK) {
     756                 :          0 :                         return (EPKG_FATAL);
     757                 :            :                 }
     758                 :          0 :         }
     759         [ +  + ]:        424 :         if (j->type != PKG_JOBS_FETCH) {
     760                 :        420 :                 lp = pkg_jobs_universe_get_local(j->universe, rp->uid, 0);
     761   [ +  +  +  - ]:        420 :                 if (lp && lp->locked)
     762                 :          0 :                         return (EPKG_LOCKED);
     763                 :        420 :         }
     764                 :            : 
     765                 :        848 :         nit = pkg_jobs_universe_get_upgrade_candidates(j->universe, rp->uid, lp,
     766                 :        424 :                 j->flags & PKG_FLAG_FORCE,
     767         [ +  + ]:        424 :                 with_version != 0 ? rp->version : NULL);
     768                 :            : 
     769         [ +  + ]:        424 :         if (nit != NULL) {
     770                 :        381 :                 nrit = pkg_jobs_add_req_from_universe(&j->request_add, nit, false, false);
     771                 :            : 
     772         [ +  - ]:        381 :                 if (req != NULL)
     773                 :          0 :                         *req = nrit;
     774                 :            : 
     775         [ +  - ]:        381 :                 if (j->flags & PKG_FLAG_UPGRADE_VULNERABLE) {
     776                 :            :                         /* Set the proper reason */
     777         [ #  # ]:          0 :                         DL_FOREACH(nit, cur) {
     778         [ #  # ]:          0 :                                 if (cur->pkg->type != PKG_INSTALLED) {
     779                 :          0 :                                         free(cur->pkg->reason);
     780                 :          0 :                                         xasprintf(&cur->pkg->reason, "vulnerability found");
     781                 :          0 :                                 }
     782                 :          0 :                         }
     783                 :            :                         /* Also process all rdeps recursively */
     784         [ #  # ]:          0 :                         while (pkg_rdeps(nrit->pkg, &rdep) == EPKG_OK) {
     785                 :          0 :                                 lp = pkg_jobs_universe_get_local(j->universe, rdep->uid, 0);
     786                 :            : 
     787         [ #  # ]:          0 :                                 if (lp) {
     788                 :          0 :                                         (void)pkg_jobs_process_remote_pkg(j, lp, NULL, 0);
     789                 :          0 :                                 }
     790                 :            :                         }
     791                 :          0 :                 }
     792                 :        381 :         }
     793                 :            : 
     794   [ +  +  -  + ]:        424 :         if (nrit == NULL && lp)
     795                 :         73 :                 return (EPKG_INSTALLED);
     796                 :            : 
     797                 :        351 :         return (nrit != NULL ? EPKG_OK : EPKG_FATAL);
     798                 :        424 : }
     799                 :            : 
     800                 :            : static bool
     801                 :          0 : pkg_jobs_has_replacement(struct pkg_jobs *j, const char *uid)
     802                 :            : {
     803                 :            :         struct pkg_job_replace *cur;
     804                 :            : 
     805         [ #  # ]:          0 :         LL_FOREACH(j->universe->uid_replaces, cur) {
     806         [ #  # ]:          0 :                 if (strcmp (cur->new_uid, uid) == 0) {
     807                 :          0 :                         return (true);
     808                 :            :                 }
     809                 :          0 :         }
     810                 :            : 
     811                 :          0 :         return (false);
     812                 :          0 : }
     813                 :            : 
     814                 :            : static int
     815                 :          0 : pkg_jobs_try_remote_candidate(struct pkg_jobs *j, const char *cond, const char *pattern,
     816                 :            :     const char *uid, match_t m)
     817                 :            : {
     818                 :          0 :         struct pkg *p = NULL;
     819                 :            :         struct pkgdb_it *it;
     820                 :          0 :         unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
     821                 :            :                                 PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
     822                 :            :                                 PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
     823                 :            :                                 PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
     824                 :          0 :         int rc = EPKG_FATAL;
     825                 :          0 :         xstring *qmsg = NULL;
     826                 :            :         struct pkg_job_universe_item *unit;
     827                 :            : 
     828         [ #  # ]:          0 :         if ((it = pkgdb_repo_query_cond(j->db, cond, pattern, m, j->reponame)) == NULL)
     829                 :          0 :                 return (EPKG_FATAL);
     830                 :            : 
     831   [ #  #  #  # ]:          0 :         while (it != NULL && pkgdb_it_next(it, &p, flags) == EPKG_OK) {
     832         [ #  # ]:          0 :                 xstring_renew(qmsg);
     833         [ #  # ]:          0 :                 if (pkg_jobs_has_replacement(j, p->uid)) {
     834                 :          0 :                         pkg_debug(1, "replacement %s is already used", p->uid);
     835                 :          0 :                         continue;
     836                 :            :                 }
     837                 :            : 
     838                 :          0 :                 fprintf(qmsg->fp, "%s has no direct installation candidates, change it to "
     839                 :          0 :                                 "%s? ", uid, p->uid);
     840                 :          0 :                 fflush(qmsg->fp);
     841         [ #  # ]:          0 :                 if (pkg_emit_query_yesno(true, qmsg->buf)) {
     842                 :            :                         /* Change the origin of the local package */
     843                 :          0 :                         pkg_validate(p, j->db);
     844                 :          0 :                         unit = pkg_jobs_universe_find(j->universe, uid);
     845         [ #  # ]:          0 :                         if (unit != NULL)
     846                 :          0 :                                 pkg_jobs_universe_change_uid(j->universe, unit,
     847                 :          0 :                                     p->uid, false);
     848                 :            :                         else
     849                 :          0 :                                 assert(0);
     850                 :            : 
     851                 :          0 :                         rc = EPKG_OK;
     852                 :          0 :                         pkg_jobs_process_remote_pkg(j, p, NULL, 0);
     853         [ #  # ]:          0 :                         if (rc == EPKG_OK) {
     854                 :            :                                 /* Avoid freeing */
     855                 :          0 :                                 p = NULL;
     856                 :          0 :                         }
     857                 :          0 :                         break;
     858                 :            :                 }
     859                 :            :         }
     860                 :            : 
     861                 :            : 
     862                 :          0 :         pkg_free(p);
     863                 :            : 
     864                 :          0 :         xstring_free(qmsg);
     865                 :          0 :         pkgdb_it_free(it);
     866                 :            : 
     867                 :          0 :         return (rc);
     868                 :          0 : }
     869                 :            : 
     870                 :            : static int
     871                 :          0 : pkg_jobs_guess_upgrade_candidate(struct pkg_jobs *j, const char *pattern)
     872                 :            : {
     873                 :            : 
     874                 :          0 :         int rc = EPKG_FATAL;
     875                 :          0 :         const char *pos, *opattern = pattern;
     876                 :            :         char *cpy;
     877                 :            :         size_t len, olen;
     878                 :            : 
     879                 :            :         /* First of all, try to search a package with the same name */
     880                 :          0 :         pos = strchr(pattern, '/');
     881   [ #  #  #  # ]:          0 :         if (pos != NULL && pos[1] != '\0') {
     882   [ #  #  #  # ]:          0 :                 if (pkg_jobs_try_remote_candidate(j, pos + 1, NULL, opattern, MATCH_EXACT)
     883                 :          0 :                                                 == EPKG_OK)
     884                 :          0 :                         return (EPKG_OK);
     885                 :            : 
     886                 :          0 :                 pos ++;
     887                 :          0 :         } else {
     888                 :          0 :                 pos = pattern;
     889                 :            :         }
     890                 :            : 
     891                 :            :         /* Figure, if we have any numbers at the end of the package */
     892                 :          0 :         olen = strlen(pos);
     893                 :          0 :         len = olen;
     894         [ #  # ]:          0 :         while (len > 0) {
     895   [ #  #  #  # ]:          0 :                 if (isdigit(pos[len - 1]) || pos[len - 1] == '.')
     896                 :          0 :                         len --;
     897                 :            :                 else
     898                 :          0 :                         break;
     899                 :            :         }
     900                 :            : 
     901         [ #  # ]:          0 :         if (olen != len) {
     902                 :            :                 /* Try exact pattern without numbers */
     903                 :          0 :                 cpy = xmalloc(len + 1);
     904                 :          0 :                 strlcpy(cpy, pos, len + 1);
     905         [ #  # ]:          0 :                 if (pkg_jobs_try_remote_candidate(j, cpy, NULL, opattern, MATCH_EXACT) != EPKG_OK) {
     906                 :          0 :                         free(cpy);
     907                 :          0 :                         cpy = sqlite3_mprintf(" WHERE name REGEXP ('^' || %.*Q || '[0-9.]*$')",
     908                 :          0 :                                         len, pos);
     909                 :            : 
     910   [ #  #  #  # ]:          0 :                         if (pkg_jobs_try_remote_candidate(j, cpy, opattern, NULL, MATCH_ALL)
     911                 :          0 :                                         == EPKG_OK)
     912                 :          0 :                                 rc = EPKG_OK;
     913                 :          0 :                         sqlite3_free(cpy);
     914                 :          0 :                 }
     915                 :            :                 else {
     916                 :          0 :                         free(cpy);
     917                 :          0 :                         rc = EPKG_OK;
     918                 :            :                 }
     919                 :          0 :         }
     920                 :            : 
     921                 :          0 :         return (rc);
     922                 :          0 : }
     923                 :            : 
     924                 :            : static int
     925                 :        335 : pkg_jobs_find_upgrade(struct pkg_jobs *j, const char *pattern, match_t m)
     926                 :            : {
     927                 :        335 :         struct pkg *p = NULL;
     928                 :            :         struct pkgdb_it *it;
     929                 :        335 :         bool checklocal, found = false;
     930                 :        335 :         int rc = EPKG_FATAL;
     931                 :            :         int with_version;
     932                 :        335 :         struct pkg_dep *rdep = NULL;
     933                 :        335 :         unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
     934                 :            :                         PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
     935                 :            :                         PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
     936                 :            :                         PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
     937                 :        335 :         struct pkg_job_universe_item *unit = NULL;
     938                 :            : 
     939         [ +  - ]:        335 :         if ((it = pkgdb_repo_query(j->db, pattern, m, j->reponame)) == NULL)
     940                 :          0 :                 rc = EPKG_FATAL;
     941                 :            : 
     942                 :            :         /*
     943                 :            :          * MATCH_EXACT is handled at a higher level, so that we can complain if a
     944                 :            :          * specific upgrade was requested without the package being locally installed.
     945                 :            :          *
     946                 :            :          * MATCH_ALL is a non-issue, because we will not get that from pkg-upgrade
     947                 :            :          * anyways.
     948                 :            : 
     949                 :            :          * Pattern matches are the main target, as the above query may grab packages
     950                 :            :          * that are not installed that we can ignore.
     951                 :            :          */
     952   [ +  +  +  + ]:        335 :         checklocal = j->type == PKG_JOBS_UPGRADE && m != MATCH_EXACT && m != MATCH_ALL;
     953   [ -  +  +  + ]:        775 :         while (it != NULL && pkgdb_it_next(it, &p, flags) == EPKG_OK) {
     954   [ +  +  +  + ]:        440 :                 if (checklocal && pkg_jobs_installed_local_pkg(j, p) != EPKG_OK)
     955                 :         16 :                         continue;
     956         [ +  - ]:        424 :                 if (pattern != NULL) {
     957                 :        424 :                         with_version = strcmp(p->name, pattern);
     958                 :        424 :                 } else {
     959                 :          0 :                         with_version = 0;
     960                 :            :                 }
     961                 :        424 :                 rc = pkg_jobs_process_remote_pkg(j, p, NULL, with_version);
     962         [ +  - ]:        424 :                 if (rc == EPKG_FATAL)
     963                 :          0 :                         break;
     964         [ +  + ]:        424 :                 else if (rc == EPKG_OK)
     965                 :        351 :                         found = true;
     966                 :            : 
     967                 :        424 :                 p = NULL;
     968                 :            :         }
     969                 :            : 
     970                 :        335 :         pkgdb_it_free(it);
     971                 :            : 
     972   [ +  +  +  + ]:        335 :         if (!found && rc != EPKG_INSTALLED) {
     973                 :            :                 /*
     974                 :            :                  * Here we need to ensure that this package has no
     975                 :            :                  * reverse deps installed
     976                 :            :                  */
     977                 :          4 :                 p = pkg_jobs_universe_get_local(j->universe, pattern,
     978                 :            :                         PKG_LOAD_BASIC|PKG_LOAD_RDEPS);
     979         [ -  + ]:          4 :                 if (p == NULL)
     980                 :          4 :                         return (EPKG_FATAL);
     981                 :            : 
     982         [ #  # ]:          0 :                 while(pkg_rdeps(p, &rdep) == EPKG_OK) {
     983                 :            :                         struct pkg *rdep_package;
     984                 :            : 
     985                 :          0 :                         rdep_package = pkg_jobs_universe_get_local(j->universe, rdep->uid,
     986                 :            :                                         PKG_LOAD_BASIC);
     987         [ #  # ]:          0 :                         if (rdep_package != NULL)
     988                 :          0 :                                 return (EPKG_END);
     989                 :            :                 }
     990                 :            : 
     991                 :          0 :                 pkg_debug(2, "non-automatic package with pattern %s has not been found in "
     992                 :          0 :                                 "remote repo", pattern);
     993                 :          0 :                 rc = pkg_jobs_universe_add_pkg(j->universe, p, false, &unit);
     994         [ #  # ]:          0 :                 if (rc == EPKG_OK) {
     995                 :          0 :                         rc = pkg_jobs_guess_upgrade_candidate(j, pattern);
     996                 :          0 :                 }
     997                 :          0 :         }
     998                 :            : 
     999                 :        331 :         return (rc);
    1000                 :        335 : }
    1001                 :            : 
    1002                 :            : static int
    1003                 :         56 : pkg_jobs_check_local_pkg(struct pkg_jobs *j, struct job_pattern *jp)
    1004                 :            : {
    1005                 :            :         struct pkgdb_it *it;
    1006                 :         56 :         struct pkg *pkg = NULL;
    1007                 :         56 :         int rc = EPKG_OK;
    1008                 :            : 
    1009                 :         56 :         it = pkgdb_query(j->db, jp->pattern, jp->match);
    1010         [ +  - ]:         56 :         if (it != NULL) {
    1011         [ +  + ]:         56 :                 if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_ANNOTATIONS) != EPKG_OK)
    1012                 :         16 :                         rc = EPKG_FATAL;
    1013                 :            :                 else
    1014                 :         40 :                         pkg_free(pkg);
    1015                 :            : 
    1016                 :         56 :                 pkgdb_it_free(it);
    1017                 :         56 :         }
    1018                 :            :         else {
    1019                 :          0 :                 rc = EPKG_FATAL;
    1020                 :            :         }
    1021                 :            : 
    1022                 :         56 :         return (rc);
    1023                 :            : }
    1024                 :            : 
    1025                 :            : static int
    1026                 :         28 : pkg_jobs_installed_local_pkg(struct pkg_jobs *j, struct pkg *pkg)
    1027                 :            : {
    1028                 :            :         struct job_pattern jfp;
    1029                 :            : 
    1030                 :         28 :         jfp.match = MATCH_EXACT;
    1031                 :         28 :         jfp.pattern = pkg->name;
    1032                 :         28 :         return (pkg_jobs_check_local_pkg(j, &jfp));
    1033                 :            : }
    1034                 :            : 
    1035                 :            : static int
    1036                 :        363 : pkg_jobs_find_remote_pattern(struct pkg_jobs *j, struct job_pattern *jp)
    1037                 :            : {
    1038                 :        363 :         int rc = EPKG_OK;
    1039                 :        363 :         struct pkg *pkg = NULL;
    1040                 :        363 :         struct pkg_manifest_key *keys = NULL;
    1041                 :            :         struct pkg_job_request *req;
    1042                 :            : 
    1043         [ +  + ]:        363 :         if (!(jp->flags & PKG_PATTERN_FLAG_FILE)) {
    1044   [ +  +  +  + ]:        151 :                 if (j->type == PKG_JOBS_UPGRADE && jp->match == MATCH_EXACT) {
    1045                 :            :                         /*
    1046                 :            :                          * For upgrade patterns we must ensure that a local package is
    1047                 :            :                          * installed as well.  This only works if we're operating on an
    1048                 :            :                          * exact match, as we otherwise don't know exactly what packages
    1049                 :            :                          * are in store for us.
    1050                 :            :                          */
    1051         [ +  - ]:         28 :                         if (pkg_jobs_check_local_pkg(j, jp) != EPKG_OK) {
    1052                 :          0 :                                 pkg_emit_error("%s is not installed, therefore upgrade is impossible",
    1053                 :          0 :                                                 jp->pattern);
    1054                 :          0 :                                 return (EPKG_NOTINSTALLED);
    1055                 :            :                         }
    1056                 :         28 :                 }
    1057                 :        151 :                 rc = pkg_jobs_find_upgrade(j, jp->pattern, jp->match);
    1058                 :        151 :         }
    1059                 :            :         else {
    1060                 :        212 :                 pkg_manifest_keys_new(&keys);
    1061         [ -  + ]:        212 :                 if (pkg_open(&pkg, jp->path, keys, PKG_OPEN_MANIFEST_ONLY) != EPKG_OK) {
    1062                 :          0 :                         rc = EPKG_FATAL;
    1063         [ -  + ]:        212 :                 } else if (pkg_validate(pkg, j->db) == EPKG_OK) {
    1064   [ -  +  #  # ]:        212 :                         if (j->type == PKG_JOBS_UPGRADE && pkg_jobs_installed_local_pkg(j, pkg) != EPKG_OK) {
    1065                 :          0 :                                 pkg_emit_error("%s is not installed, therefore upgrade is impossible",
    1066                 :          0 :                                                         pkg->name);
    1067                 :          0 :                                 pkg_manifest_keys_free(keys);
    1068                 :          0 :                                 return (EPKG_NOTINSTALLED);
    1069                 :            :                         }
    1070                 :        212 :                         pkg->type = PKG_FILE;
    1071                 :        212 :                         pkg_jobs_add_req(j, pkg);
    1072                 :            : 
    1073                 :        212 :                         req = pkghash_get_value(j->request_add, pkg->uid);
    1074         [ -  + ]:        212 :                         if (req != NULL)
    1075                 :        212 :                                 req->item->jp = jp;
    1076                 :        212 :                 }
    1077                 :            :                 else {
    1078                 :          0 :                         pkg_emit_error("cannot load %s: invalid format",
    1079                 :          0 :                                         jp->pattern);
    1080                 :          0 :                         rc = EPKG_FATAL;
    1081                 :            :                 }
    1082                 :        212 :                 pkg_manifest_keys_free(keys);
    1083                 :            :         }
    1084                 :            : 
    1085                 :        363 :         return (rc);
    1086                 :        363 : }
    1087                 :            : 
    1088                 :            : bool
    1089                 :        301 : pkg_jobs_need_upgrade(struct pkg *rp, struct pkg *lp)
    1090                 :            : {
    1091                 :            :         int ret, ret1, ret2;
    1092                 :        301 :         struct pkg_option *lo = NULL, *ro = NULL;
    1093                 :        301 :         struct pkg_dep *ld = NULL, *rd = NULL;
    1094                 :        301 :         struct pkg_conflict *lc = NULL, *rc = NULL;
    1095                 :            :         pkghash_it it1, it2;
    1096                 :            : 
    1097                 :            :         /* If no local package, then rp is obviously need to be added */
    1098         [ +  - ]:        301 :         if (lp == NULL)
    1099                 :          0 :                 return true;
    1100                 :            : 
    1101                 :            :         /* Do not upgrade locked packages */
    1102         [ -  + ]:        301 :         if (lp->locked) {
    1103                 :          0 :                 pkg_emit_locked(lp);
    1104                 :          0 :                 return (false);
    1105                 :            :         }
    1106                 :            : 
    1107   [ +  -  +  -  :        301 :         if (lp->digest != NULL && rp->digest != NULL &&
                   +  + ]
    1108                 :        301 :             strcmp(lp->digest, rp->digest) == 0) {
    1109                 :            :                 /* Remote and local packages has the same digest, hence they are the same */
    1110                 :         80 :                 return (false);
    1111                 :            :         }
    1112                 :            :         /*
    1113                 :            :          * XXX: for a remote package we also need to check whether options
    1114                 :            :          * are compatible.
    1115                 :            :          */
    1116                 :        221 :         ret = pkg_version_cmp(lp->version, rp->version);
    1117         [ +  + ]:        221 :         if (ret > 0)
    1118                 :         10 :                 return (false);
    1119         [ +  + ]:        211 :         else if (ret < 0)
    1120                 :        135 :                 return (true);
    1121                 :            : 
    1122                 :            :         /* Compare archs */
    1123         [ -  + ]:         76 :         if (strcmp (lp->arch, rp->arch) != 0) {
    1124                 :          0 :                 free(rp->reason);
    1125                 :          0 :                 xasprintf(&rp->reason, "ABI changed: '%s' -> '%s'",
    1126                 :          0 :                     lp->arch, rp->arch);
    1127         [ #  # ]:          0 :                 assert(rp->reason != NULL);
    1128                 :          0 :                 return (true);
    1129                 :            :         }
    1130                 :            : 
    1131                 :            :         /* compare options */
    1132                 :         76 :         for (;;) {
    1133                 :         76 :                 ret1 = pkg_options(rp, &ro);
    1134                 :         76 :                 ret2 = pkg_options(lp, &lo);
    1135         [ +  - ]:         76 :                 if (ret1 != ret2) {
    1136                 :          0 :                         free(rp->reason);
    1137         [ #  # ]:          0 :                         if (ro == NULL)
    1138                 :          0 :                                 xasprintf(&rp->reason, "option removed: %s",
    1139                 :          0 :                                     lo->key);
    1140         [ #  # ]:          0 :                         else if (lo == NULL)
    1141                 :          0 :                                 xasprintf(&rp->reason, "option added: %s",
    1142                 :          0 :                                     ro->key);
    1143                 :            :                         else
    1144                 :          0 :                                 xasprintf(&rp->reason, "option changed: %s",
    1145                 :          0 :                                     ro->key);
    1146         [ #  # ]:          0 :                         assert(rp->reason != NULL);
    1147                 :          0 :                         return (true);
    1148                 :            :                 }
    1149         [ +  + ]:         76 :                 if (ret1 == EPKG_OK) {
    1150   [ +  -  -  + ]:          4 :                         if (strcmp(lo->key, ro->key) != 0 ||
    1151                 :          4 :                             strcmp(lo->value, ro->value) != 0) {
    1152                 :          4 :                                 free(rp->reason);
    1153                 :          4 :                                 xasprintf(&rp->reason, "options changed");
    1154                 :          4 :                                 return (true);
    1155                 :            :                         }
    1156                 :          0 :                 }
    1157                 :            :                 else
    1158                 :         72 :                         break;
    1159                 :            :         }
    1160                 :            : 
    1161                 :            :         /* What about the direct deps */
    1162                 :         92 :         for (;;) {
    1163                 :         92 :                 ret1 = pkg_deps(rp, &rd);
    1164                 :         92 :                 ret2 = pkg_deps(lp, &ld);
    1165         [ +  + ]:         92 :                 if (ret1 != ret2) {
    1166                 :          4 :                         free(rp->reason);
    1167         [ +  - ]:          4 :                         if (rd == NULL)
    1168                 :          0 :                                 xasprintf(&rp->reason, "direct dependency removed: %s",
    1169                 :          0 :                                     ld->name);
    1170         [ -  + ]:          4 :                         else if (ld == NULL)
    1171                 :          8 :                                 xasprintf(&rp->reason, "direct dependency added: %s",
    1172                 :          4 :                                     rd->name);
    1173                 :            :                         else
    1174                 :          0 :                                 xasprintf(&rp->reason, "direct dependency changed: %s",
    1175                 :          0 :                                     rd->name);
    1176         [ -  + ]:          4 :                         assert (rp->reason != NULL);
    1177                 :          4 :                         return (true);
    1178                 :            :                 }
    1179         [ +  + ]:         88 :                 if (ret1 == EPKG_OK) {
    1180   [ +  +  +  + ]:         40 :                         if ((strcmp(rd->name, ld->name) != 0) ||
    1181                 :         32 :                             (strcmp(rd->origin, ld->origin) != 0)) {
    1182                 :         20 :                                 free(rp->reason);
    1183                 :         40 :                                 xasprintf(&rp->reason, "direct dependency changed: %s",
    1184                 :         20 :                                     rd->name);
    1185         [ +  - ]:         20 :                                 assert (rp->reason != NULL);
    1186                 :         20 :                                 return (true);
    1187                 :            :                         }
    1188                 :         20 :                 }
    1189                 :            :                 else
    1190                 :         48 :                         break;
    1191                 :            :         }
    1192                 :            : 
    1193                 :            :         /* Conflicts */
    1194                 :         48 :         for (;;) {
    1195                 :         48 :                 ret1 = pkg_conflicts(rp, &rc);
    1196                 :         48 :                 ret2 = pkg_conflicts(lp, &lc);
    1197         [ +  - ]:         48 :                 if (ret1 != ret2) {
    1198                 :          0 :                         free(rp->reason);
    1199                 :          0 :                         rp->reason = xstrdup("direct conflict changed");
    1200                 :          0 :                         return (true);
    1201                 :            :                 }
    1202         [ -  + ]:         48 :                 if (ret1 == EPKG_OK) {
    1203         [ #  # ]:          0 :                         if (strcmp(rc->uid, lc->uid) != 0) {
    1204                 :          0 :                                 free(rp->reason);
    1205                 :          0 :                                 rp->reason = xstrdup("direct conflict changed");
    1206                 :          0 :                                 return (true);
    1207                 :            :                         }
    1208                 :          0 :                 }
    1209                 :            :                 else
    1210                 :         48 :                         break;
    1211                 :            :         }
    1212                 :            : 
    1213                 :            :         /* Provides */
    1214                 :         48 :         it1 = pkghash_iterator(rp->provides);
    1215                 :         48 :         it2 = pkghash_iterator(lp->provides);
    1216                 :         48 :         for (;;) {
    1217                 :         48 :                 ret1 = pkghash_next(&it1);
    1218                 :         48 :                 ret2 = pkghash_next(&it2);
    1219         [ +  - ]:         48 :                 if (ret1 != ret2) {
    1220                 :          0 :                         free(rp->reason);
    1221                 :          0 :                         rp->reason = xstrdup("provides changed");
    1222                 :          0 :                         return (true);
    1223                 :            :                 }
    1224         [ -  + ]:         48 :                 if (ret1) {
    1225         [ #  # ]:          0 :                         if (strcmp(it1.key, it2.key) != 0) {
    1226                 :          0 :                                 free(rp->reason);
    1227                 :          0 :                                 rp->reason = xstrdup("provides changed");
    1228                 :          0 :                                 return (true);
    1229                 :            :                         }
    1230                 :          0 :                 }
    1231                 :            :                 else
    1232                 :         48 :                         break;
    1233                 :            :         }
    1234                 :            :         /* Requires */
    1235                 :         48 :         it1 = pkghash_iterator(rp->requires);
    1236                 :         48 :         it2 = pkghash_iterator(lp->requires);
    1237                 :         48 :         for (;;) {
    1238                 :         48 :                 ret1 = pkghash_next(&it1);
    1239                 :         48 :                 ret2 = pkghash_next(&it2);
    1240         [ +  - ]:         48 :                 if (ret1 != ret2) {
    1241                 :          0 :                         free(rp->reason);
    1242                 :          0 :                         rp->reason = xstrdup("requires changed");
    1243                 :          0 :                         return (true);
    1244                 :            :                 }
    1245         [ +  + ]:         48 :                 if (ret1) {
    1246         [ -  + ]:          8 :                         if (strcmp(it1.key, it2.key) != 0) {
    1247                 :          8 :                                 free(rp->reason);
    1248                 :          8 :                                 rp->reason = xstrdup("requires changed");
    1249                 :          8 :                                 return (true);
    1250                 :            :                         }
    1251                 :          0 :                 }
    1252                 :            :                 else
    1253                 :         40 :                         break;
    1254                 :            :         }
    1255                 :            : 
    1256                 :            :         /* Finish by the shlibs */
    1257                 :         40 :         it1 = pkghash_iterator(rp->shlibs_provided);
    1258                 :         40 :         it2 = pkghash_iterator(lp->shlibs_provided);
    1259                 :         48 :         for (;;) {
    1260                 :         48 :                 ret1 = pkghash_next(&it1);
    1261                 :         48 :                 ret2 = pkghash_next(&it2);
    1262         [ +  - ]:         48 :                 if (ret1 != ret2) {
    1263                 :          0 :                         free(rp->reason);
    1264                 :          0 :                         rp->reason = xstrdup("provided shared library changed");
    1265                 :          0 :                         return (true);
    1266                 :            :                 }
    1267         [ +  + ]:         48 :                 if (ret1) {
    1268         [ +  - ]:          8 :                         if (strcmp(it1.key, it2.key) != 0) {
    1269                 :          0 :                                 free(rp->reason);
    1270                 :          0 :                                 rp->reason = xstrdup("provided shared library changed");
    1271                 :          0 :                                 pkg_debug(1, "provided shlib changed %s -> %s",
    1272                 :          0 :                                     it2.key, it1.key);
    1273                 :          0 :                                 return (true);
    1274                 :            :                         }
    1275                 :          8 :                 }
    1276                 :            :                 else
    1277                 :         40 :                         break;
    1278                 :            :         }
    1279                 :            : 
    1280                 :         40 :         it1 = pkghash_iterator(rp->shlibs_required);
    1281                 :         40 :         it2 = pkghash_iterator(lp->shlibs_required);
    1282                 :         40 :         for (;;) {
    1283                 :         40 :                 ret1 = pkghash_next(&it1);
    1284                 :         40 :                 ret2 = pkghash_next(&it2);
    1285         [ +  - ]:         40 :                 if (ret1 != ret2) {
    1286                 :          0 :                         free(rp->reason);
    1287                 :          0 :                         rp->reason = xstrdup("needed shared library changed");
    1288                 :          0 :                         return (true);
    1289                 :            :                 }
    1290         [ +  + ]:         40 :                 if (ret1) {
    1291         [ -  + ]:          4 :                         if (strcmp(it1.key, it2.key) != 0) {
    1292                 :          4 :                                 free(rp->reason);
    1293                 :          4 :                                 rp->reason = xstrdup("needed shared library changed");
    1294                 :          4 :                                 pkg_debug(1, "Required shlib changed %s -> %s",
    1295                 :          4 :                                     it2.key, it1.key);
    1296                 :          4 :                                 return (true);
    1297                 :            :                         }
    1298                 :          0 :                 }
    1299                 :            :                 else
    1300                 :         36 :                         break;
    1301                 :            :         }
    1302                 :            : 
    1303                 :         36 :         return (false);
    1304                 :        301 : }
    1305                 :            : 
    1306                 :            : static void
    1307                 :        481 : pkg_jobs_propagate_automatic(struct pkg_jobs *j)
    1308                 :            : {
    1309                 :            :         struct pkg_job_universe_item *unit, *cur, *local;
    1310                 :            :         struct pkg_job_request *req;
    1311                 :            :         bool automatic;
    1312                 :            :         pkghash_it it;
    1313                 :            : 
    1314                 :        481 :         it = pkghash_iterator(j->universe->items);
    1315         [ +  + ]:       1272 :         while (pkghash_next(&it)) {
    1316                 :        791 :                 unit = (struct pkg_job_universe_item *)it.value;
    1317         [ +  + ]:        791 :                 if (unit->next == NULL) {
    1318                 :            :                         /*
    1319                 :            :                          * For packages that are alone in the installation list
    1320                 :            :                          * we search them in the corresponding request
    1321                 :            :                          */
    1322                 :        528 :                         req = pkghash_get_value(j->request_add, unit->pkg->uid);
    1323   [ +  +  +  + ]:        528 :                         if ((req == NULL || req->automatic) &&
    1324                 :        528 :                             unit->pkg->type != PKG_INSTALLED) {
    1325                 :        140 :                                 automatic = true;
    1326                 :        140 :                                 pkg_debug(2, "set automatic flag for %s", unit->pkg->uid);
    1327                 :        140 :                                 unit->pkg->automatic = automatic;
    1328                 :        140 :                         }
    1329                 :            :                         else {
    1330         [ +  + ]:        388 :                                 if (j->type == PKG_JOBS_INSTALL) {
    1331                 :        294 :                                         unit->pkg->automatic = false;
    1332                 :        294 :                                 }
    1333                 :            :                         }
    1334                 :        528 :                 }
    1335                 :            :                 else {
    1336                 :            :                         /*
    1337                 :            :                          * For packages that are in the conflict chain we need to inherit
    1338                 :            :                          * automatic flag from the local package
    1339                 :            :                          */
    1340                 :        263 :                         local = NULL;
    1341                 :        263 :                         automatic = false;
    1342         [ +  + ]:        303 :                         LL_FOREACH(unit, cur) {
    1343         [ +  + ]:        283 :                                 if (cur->pkg->type == PKG_INSTALLED) {
    1344                 :        243 :                                         local = cur;
    1345                 :        243 :                                         automatic = local->pkg->automatic;
    1346                 :        243 :                                         break;
    1347                 :            :                                 }
    1348                 :         40 :                         }
    1349         [ +  + ]:        263 :                         if (local != NULL) {
    1350         [ +  + ]:        785 :                                 LL_FOREACH(unit, cur) {
    1351                 :            :                                         /*
    1352                 :            :                                          * Propagate automatic from local package
    1353                 :            :                                          */
    1354         [ +  + ]:        542 :                                         if (cur->pkg->type != PKG_INSTALLED) {
    1355                 :        299 :                                                 cur->pkg->automatic = automatic;
    1356                 :        299 :                                         }
    1357                 :        542 :                                 }
    1358                 :        243 :                         }
    1359                 :            :                         else {
    1360                 :            :                                 /*
    1361                 :            :                                  * For packages that are not unique, we might still have
    1362                 :            :                                  * a situation when we need to set automatic for all
    1363                 :            :                                  * non-local packages
    1364                 :            :                                  *
    1365                 :            :                                  * See #1374
    1366                 :            :                                  */
    1367                 :         20 :                                 req = pkghash_get_value(j->request_add, unit->pkg->uid);
    1368   [ +  -  -  + ]:         20 :                                 if ((req == NULL || req->automatic)) {
    1369                 :          0 :                                         automatic = true;
    1370                 :          0 :                                         pkg_debug(2, "set automatic flag for %s", unit->pkg->uid);
    1371         [ #  # ]:          0 :                                         LL_FOREACH(unit, cur) {
    1372                 :          0 :                                                 cur->pkg->automatic = automatic;
    1373                 :          0 :                                         }
    1374                 :          0 :                                 }
    1375                 :            :                         }
    1376                 :            :                 }
    1377                 :            :         }
    1378                 :        481 : }
    1379                 :            : 
    1380                 :            : static struct pkg_job_request *
    1381                 :        115 : pkg_jobs_find_deinstall_request(struct pkg_job_universe_item *item,
    1382                 :            :                 struct pkg_jobs *j, int rec_level)
    1383                 :            : {
    1384                 :            :         struct pkg_job_request *found;
    1385                 :            :         struct pkg_job_universe_item *dep_item;
    1386                 :        115 :         struct pkg_dep *d = NULL;
    1387                 :        115 :         struct pkg *pkg = item->pkg;
    1388                 :            : 
    1389         [ -  + ]:        115 :         if (rec_level > 128) {
    1390                 :          0 :                 pkg_debug(2, "cannot find deinstall request after 128 iterations for %s,"
    1391                 :          0 :                     "circular dependency maybe", pkg->uid);
    1392                 :          0 :                 return (NULL);
    1393                 :            :         }
    1394                 :            : 
    1395                 :        115 :         found = pkghash_get_value(j->request_delete, pkg->uid);
    1396         [ +  - ]:        115 :         if (found == NULL) {
    1397         [ #  # ]:          0 :                 while (pkg_deps(pkg, &d) == EPKG_OK) {
    1398                 :          0 :                         dep_item = pkg_jobs_universe_find(j->universe, d->uid);
    1399         [ #  # ]:          0 :                         if (dep_item) {
    1400                 :          0 :                                 found = pkg_jobs_find_deinstall_request(dep_item, j, rec_level + 1);
    1401         [ #  # ]:          0 :                                 if (found)
    1402                 :          0 :                                         return (found);
    1403                 :          0 :                         }
    1404                 :            :                 }
    1405                 :          0 :         }
    1406                 :            :         else {
    1407                 :        115 :                 return (found);
    1408                 :            :         }
    1409                 :            : 
    1410                 :          0 :         return (NULL);
    1411                 :        115 : }
    1412                 :            : 
    1413                 :            : static void
    1414                 :        111 : pkg_jobs_set_deinstall_reasons(struct pkg_jobs *j)
    1415                 :            : {
    1416                 :            :         struct pkg_solved *sit;
    1417                 :            :         struct pkg_job_request *jreq;
    1418                 :            :         struct pkg *req_pkg, *pkg;
    1419                 :            : 
    1420         [ +  + ]:        226 :         LL_FOREACH(j->jobs, sit) {
    1421                 :        115 :                 jreq = pkg_jobs_find_deinstall_request(sit->items[0], j, 0);
    1422   [ +  -  +  - ]:        115 :                 if (jreq != NULL && jreq->item->unit != sit->items[0]) {
    1423                 :          0 :                         req_pkg = jreq->item->pkg;
    1424                 :          0 :                         pkg = sit->items[0]->pkg;
    1425                 :            :                         /* Set the reason */
    1426                 :          0 :                         free(pkg->reason);
    1427                 :          0 :                         pkg_asprintf(&pkg->reason, "depends on %n-%v", req_pkg, req_pkg);
    1428                 :          0 :                 }
    1429                 :        115 :         }
    1430                 :        111 : }
    1431                 :            : 
    1432                 :            : static int
    1433                 :          0 : comp(const void *a, const void *b)
    1434                 :            : {
    1435                 :          0 :         const struct pkg *pa = a;
    1436                 :          0 :         const struct pkg *pb = b;
    1437                 :            : 
    1438                 :          0 :         return strcmp(pa->name, pb->name);
    1439                 :            : }
    1440                 :            : 
    1441                 :            : static int
    1442                 :        111 : jobs_solve_deinstall(struct pkg_jobs *j)
    1443                 :            : {
    1444                 :            :         struct job_pattern *jp;
    1445                 :        111 :         struct pkg *pkg = NULL;
    1446                 :            :         struct pkgdb_it *it;
    1447         [ +  + ]:        222 :         LL_FOREACH(j->patterns, jp) {
    1448         [ +  - ]:        111 :                 if ((it = pkgdb_query(j->db, jp->pattern, jp->match)) == NULL)
    1449                 :          0 :                         return (EPKG_FATAL);
    1450                 :            : 
    1451         [ +  - ]:        111 :                 if (pkgdb_it_count(it) == 0) {
    1452                 :          0 :                         pkg_emit_notice("No packages matched for pattern '%s'\n", jp->pattern);
    1453                 :          0 :                 }
    1454                 :            : 
    1455   [ +  +  +  + ]:        230 :                 while (pkgdb_it_next(it, &pkg,
    1456                 :        230 :                                 PKG_LOAD_BASIC|PKG_LOAD_RDEPS|PKG_LOAD_DEPS|PKG_LOAD_ANNOTATIONS) == EPKG_OK) {
    1457         [ +  + ]:        119 :                         if(pkg->locked) {
    1458         [ -  + ]:          4 :                                 if (tsearch(pkg, &j->lockedpkgs, comp) == NULL) {
    1459                 :          0 :                                         return (EPKG_FATAL);
    1460                 :            :                                 }
    1461                 :          4 :                         }
    1462                 :            :                         else {
    1463                 :        115 :                                 pkg_jobs_add_req(j, pkg);
    1464                 :            :                         }
    1465                 :        119 :                         pkg = NULL;
    1466                 :            :                 }
    1467                 :        111 :                 pkgdb_it_free(it);
    1468                 :        111 :         }
    1469                 :            : 
    1470                 :        111 :         j->solved = 1;
    1471                 :            : 
    1472                 :        111 :         return (pkg_jobs_process_delete_request(j));
    1473                 :        111 : }
    1474                 :            : 
    1475                 :            : static int
    1476                 :         30 : jobs_solve_autoremove(struct pkg_jobs *j)
    1477                 :            : {
    1478                 :         30 :         struct pkg *pkg = NULL;
    1479                 :            :         struct pkgdb_it *it;
    1480                 :            : 
    1481         [ +  - ]:         30 :         if ((it = pkgdb_query_cond(j->db, " WHERE automatic=1 AND vital=0 ", NULL, MATCH_ALL)) == NULL)
    1482                 :          0 :                 return (EPKG_FATAL);
    1483                 :            : 
    1484   [ +  +  +  + ]:         64 :         while (pkgdb_it_next(it, &pkg,
    1485                 :            :                         PKG_LOAD_BASIC|PKG_LOAD_RDEPS|PKG_LOAD_DEPS|PKG_LOAD_ANNOTATIONS)
    1486                 :         64 :                         == EPKG_OK) {
    1487         [ -  + ]:         34 :                 if(pkg->locked) {
    1488                 :          0 :                         pkg_emit_locked(pkg);
    1489                 :          0 :                 }
    1490         [ -  + ]:         34 :                 else if (pkg_jobs_test_automatic(j, pkg)) {
    1491         [ +  - ]:         34 :                         assert(pkg_jobs_add_req(j, pkg));
    1492                 :         34 :                 }
    1493                 :            : 
    1494                 :         34 :                 pkg = NULL;
    1495                 :            :         }
    1496                 :         30 :         pkgdb_it_free(it);
    1497                 :            : 
    1498                 :         30 :         j->solved = true;
    1499                 :         30 :         pkg_jobs_process_delete_request(j);
    1500                 :            : 
    1501                 :         30 :         return (EPKG_OK);
    1502                 :         30 : }
    1503                 :            : 
    1504                 :            : struct pkg_jobs_install_candidate {
    1505                 :            :         int64_t id;
    1506                 :            :         struct pkg_jobs_install_candidate *next;
    1507                 :            : };
    1508                 :            : 
    1509                 :            : static struct pkg_jobs_install_candidate *
    1510                 :        140 : pkg_jobs_new_candidate(struct pkg *pkg)
    1511                 :            : {
    1512                 :            :         struct pkg_jobs_install_candidate *n;
    1513                 :            : 
    1514                 :        140 :         n = xmalloc(sizeof(*n));
    1515                 :        140 :         n->id = pkg->id;
    1516                 :        140 :         return (n);
    1517                 :            : }
    1518                 :            : 
    1519                 :            : static bool
    1520                 :        190 : pkg_jobs_check_remote_candidate(struct pkg_jobs *j, struct pkg *pkg)
    1521                 :            : {
    1522                 :            :         struct pkgdb_it *it;
    1523                 :        190 :         struct pkg *p = NULL;
    1524                 :            : 
    1525                 :            :         /* If we have no digest, we need to check this package */
    1526         [ +  - ]:        190 :         if (pkg->digest == NULL)
    1527                 :          0 :                 return (true);
    1528                 :            : 
    1529                 :        190 :         it = pkgdb_repo_query(j->db, pkg->uid, MATCH_EXACT, j->reponame);
    1530         [ -  + ]:        190 :         if (it != NULL) {
    1531                 :            :                 /*
    1532                 :            :                  * If we have the same package in a remote repo, it is not an
    1533                 :            :                  * installation candidate
    1534                 :            :                  */
    1535                 :        190 :                 int npkg = 0;
    1536                 :            : 
    1537         [ +  + ]:        394 :                 while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
    1538                 :            :                         /*
    1539                 :            :                          * Check package with the same uid and explore whether digest
    1540                 :            :                          * has been changed
    1541                 :            :                          */
    1542         [ +  + ]:        204 :                         if (strcmp(p->digest, pkg->digest) != 0)
    1543                 :        140 :                                 npkg ++;
    1544                 :            : 
    1545                 :        204 :                         pkg_free(p);
    1546                 :        204 :                         p = NULL;
    1547                 :            :                 }
    1548                 :            : 
    1549                 :        190 :                 pkgdb_it_free(it);
    1550                 :            : 
    1551         [ +  + ]:        190 :                 if (npkg == 0)
    1552                 :         50 :                         return (false);
    1553                 :        140 :         }
    1554                 :            : 
    1555                 :        140 :         return (true);
    1556                 :        190 : }
    1557                 :            : 
    1558                 :            : static struct pkg_jobs_install_candidate *
    1559                 :         94 : pkg_jobs_find_install_candidates(struct pkg_jobs *j, size_t *count)
    1560                 :            : {
    1561                 :         94 :         struct pkg *pkg = NULL;
    1562                 :            :         struct pkgdb_it *it;
    1563                 :         94 :         struct pkg_jobs_install_candidate *candidates = NULL, *c;
    1564                 :            : 
    1565         [ -  + ]:         94 :         if ((it = pkgdb_query(j->db, NULL, MATCH_ALL)) == NULL)
    1566                 :          0 :                 return (NULL);
    1567                 :            : 
    1568         [ +  + ]:        284 :         while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
    1569   [ +  -  +  + ]:        190 :                 if ((j->flags & PKG_FLAG_FORCE) ||
    1570                 :        190 :                                                 pkg_jobs_check_remote_candidate(j, pkg)) {
    1571                 :        140 :                         c = pkg_jobs_new_candidate(pkg);
    1572                 :        140 :                         LL_PREPEND(candidates, c);
    1573                 :        140 :                         (*count)++;
    1574                 :        140 :                 }
    1575                 :        190 :                 pkg_free(pkg);
    1576                 :        190 :                 pkg = NULL;
    1577                 :            :         }
    1578                 :         94 :         pkgdb_it_free(it);
    1579                 :            : 
    1580                 :         94 :         return (candidates);
    1581                 :         94 : }
    1582                 :            : 
    1583                 :            : static int
    1584                 :         94 : jobs_solve_full_upgrade(struct pkg_jobs *j)
    1585                 :            : {
    1586                 :         94 :         struct pkg *pkg = NULL;
    1587                 :         94 :         size_t jcount = 0;
    1588                 :         94 :         size_t elt_num = 0;
    1589                 :            :         char sqlbuf[256];
    1590                 :            :         struct pkg_jobs_install_candidate *candidates, *c;
    1591                 :            :         struct pkg_job_request *req;
    1592                 :            :         struct pkgdb_it *it;
    1593                 :            :         pkghash_it hit;
    1594                 :         94 :         unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|PKG_LOAD_REQUIRES|
    1595                 :            :                         PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
    1596                 :            : 
    1597                 :         94 :         candidates = pkg_jobs_find_install_candidates(j, &jcount);
    1598                 :            : 
    1599                 :         94 :         pkg_emit_progress_start("Checking for upgrades (%zd candidates)",
    1600                 :         94 :                         jcount);
    1601                 :            : 
    1602         [ +  + ]:        234 :         LL_FOREACH(candidates, c) {
    1603                 :        140 :                 pkg_emit_progress_tick(++elt_num, jcount);
    1604                 :        280 :                 sqlite3_snprintf(sizeof(sqlbuf), sqlbuf, " WHERE id=%" PRId64,
    1605                 :        140 :                     c->id);
    1606         [ -  + ]:        140 :                 if ((it = pkgdb_query_cond(j->db, sqlbuf, NULL, MATCH_ALL)) == NULL)
    1607                 :          0 :                         return (EPKG_FATAL);
    1608                 :            : 
    1609                 :        140 :                 pkg = NULL;
    1610         [ +  + ]:        280 :                 while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
    1611                 :            :                         /* Do not test we ignore what doesn't exists remotely */
    1612                 :        140 :                         pkg_jobs_find_upgrade(j, pkg->uid, MATCH_EXACT);
    1613                 :            :                 }
    1614                 :        140 :                 pkg_free(pkg);
    1615                 :        140 :                 pkgdb_it_free(it);
    1616                 :        140 :         }
    1617                 :         94 :         pkg_emit_progress_tick(jcount, jcount);
    1618   [ +  +  +  +  :        234 :         LL_FREE(candidates, free);
          -  +  #  #  #  
                #  #  # ]
    1619                 :            : 
    1620                 :         94 :         pkg_emit_progress_start("Processing candidates (%zd candidates)",
    1621                 :         94 :                         jcount);
    1622                 :         94 :         elt_num = 0;
    1623                 :            : 
    1624                 :         94 :         hit = pkghash_iterator(j->request_add);
    1625         [ +  + ]:        208 :         while (pkghash_next(&hit)) {
    1626                 :        114 :                 req = hit.value;
    1627                 :        114 :                 pkg_emit_progress_tick(++elt_num, jcount);
    1628                 :        114 :                 pkg_jobs_universe_process(j->universe, req->item->pkg);
    1629                 :            :         }
    1630                 :         94 :         pkg_emit_progress_tick(jcount, jcount);
    1631                 :            : 
    1632                 :         94 :         pkg_jobs_universe_process_upgrade_chains(j);
    1633                 :            : 
    1634                 :         94 :         return (EPKG_OK);
    1635                 :         94 : }
    1636                 :            : 
    1637                 :            : static int
    1638                 :        355 : jobs_solve_partial_upgrade(struct pkg_jobs *j)
    1639                 :            : {
    1640                 :            :         struct job_pattern *jp;
    1641                 :            :         struct pkg_job_request *req;
    1642                 :        355 :         bool error_found = false;
    1643                 :            :         int retcode;
    1644                 :            :         pkghash_it it;
    1645                 :            : 
    1646         [ +  + ]:        718 :         LL_FOREACH(j->patterns, jp) {
    1647                 :        363 :                 retcode = pkg_jobs_find_remote_pattern(j, jp);
    1648         [ +  - ]:        363 :                 if (retcode == EPKG_FATAL) {
    1649                 :          0 :                         pkg_emit_error("No packages available to %s matching '%s' "
    1650                 :            :                                         "have been found in the "
    1651                 :            :                                         "repositories",
    1652                 :          0 :                                         (j->type == PKG_JOBS_UPGRADE) ? "upgrade" : "install",
    1653                 :          0 :                                         jp->pattern);
    1654                 :            :                         /* delay the return to be sure we print a message for all issues */
    1655         [ #  # ]:          0 :                         if ((j->flags & PKG_FLAG_UPGRADE_VULNERABLE) == 0)
    1656                 :          0 :                                 error_found = true;
    1657                 :          0 :                 }
    1658         [ +  - ]:        363 :                 if (retcode == EPKG_LOCKED) {
    1659                 :          0 :                         return (retcode);
    1660                 :            :                 }
    1661                 :        363 :         }
    1662         [ -  + ]:        355 :         if (error_found)
    1663                 :          0 :                 return (EPKG_FATAL);
    1664                 :            :         /*
    1665                 :            :          * Here we have not selected the proper candidate among all
    1666                 :            :          * possible choices.
    1667                 :            :          * Hence, we want to perform this procedure now to ensure that
    1668                 :            :          * we are processing the correct packages.
    1669                 :            :          */
    1670                 :        355 :         pkg_jobs_universe_process_upgrade_chains(j);
    1671                 :            :         /*
    1672                 :            :          * Need to iterate request one more time to recurse depends
    1673                 :            :          */
    1674                 :            : 
    1675                 :        355 :         it = pkghash_iterator(j->request_add);
    1676         [ +  + ]:        710 :         while (pkghash_next(&it)) {
    1677                 :        359 :                 req = it.value;
    1678                 :        359 :                 retcode = pkg_jobs_universe_process(j->universe, req->item->pkg);
    1679         [ +  + ]:        359 :                 if (retcode != EPKG_OK)
    1680                 :          4 :                         return (retcode);
    1681                 :            :         }
    1682                 :        351 :         return (EPKG_OK);
    1683                 :        355 : }
    1684                 :            : 
    1685                 :            : static int
    1686                 :        498 : jobs_solve_install_upgrade(struct pkg_jobs *j)
    1687                 :            : {
    1688                 :            :         struct pkg_job_request *req;
    1689                 :        498 :         int retcode = 0;
    1690                 :            :         pkghash_it it;
    1691                 :            : 
    1692                 :            :         /* Check for new pkg. Skip for 'upgrade -F'. */
    1693   [ +  -  -  + ]:        976 :         if (((j->flags & PKG_FLAG_SKIP_INSTALL) == 0 &&
    1694         [ +  + ]:        498 :             (j->flags & PKG_FLAG_DRY_RUN) == 0) &&
    1695                 :        478 :             (j->flags & PKG_FLAG_PKG_VERSION_TEST) == PKG_FLAG_PKG_VERSION_TEST)
    1696         [ +  + ]:        478 :                 if (new_pkg_version(j)) {
    1697                 :         13 :                         j->flags &= ~PKG_FLAG_PKG_VERSION_TEST;
    1698                 :         13 :                         j->conservative = false;
    1699                 :         13 :                         j->pinning = false;
    1700                 :         13 :                         pkg_emit_newpkgversion();
    1701                 :         13 :                         goto order;
    1702                 :            :                 }
    1703                 :            : 
    1704   [ +  +  +  - ]:        485 :         if (j->patterns == NULL && j->type == PKG_JOBS_INSTALL) {
    1705                 :          0 :                 pkg_emit_error("no patterns are specified for install job");
    1706                 :          0 :                 return (EPKG_FATAL);
    1707                 :            :         }
    1708                 :            : 
    1709         [ +  + ]:        485 :         if (j->solved == 0) {
    1710         [ +  + ]:        449 :                 if (j->patterns == NULL) {
    1711                 :         94 :                         retcode = jobs_solve_full_upgrade(j);
    1712         [ +  - ]:         94 :                         if (retcode != EPKG_OK)
    1713                 :          0 :                                 return (retcode);
    1714                 :         94 :                 } else {
    1715                 :        355 :                         retcode = jobs_solve_partial_upgrade(j);
    1716         [ +  + ]:        355 :                         if (retcode != EPKG_OK)
    1717                 :          4 :                                 return (retcode);
    1718                 :            :                 }
    1719                 :        445 :         }
    1720                 :            :         else {
    1721                 :            :                 /*
    1722                 :            :                  * If we have tried to solve request, then we just want to re-add all
    1723                 :            :                  * request packages to the universe to find out any potential conflicts
    1724                 :            :                  */
    1725                 :         36 :                 it = pkghash_iterator(j->request_add);
    1726         [ +  + ]:        104 :                 while (pkghash_next(&it)) {
    1727                 :         68 :                         req = it.value;
    1728                 :         68 :                         pkg_jobs_universe_process(j->universe, req->item->pkg);
    1729                 :            :                 }
    1730                 :            :         }
    1731                 :            : 
    1732                 :            : #if 0
    1733                 :            :         /* XXX: check if we can safely remove this function */
    1734                 :            :         pkg_jobs_process_add_request(j);
    1735                 :            : #endif
    1736         [ -  + ]:        481 :         if (pkg_conflicts_request_resolve(j) != EPKG_OK) {
    1737                 :          0 :                 pkg_emit_error("Cannot resolve conflicts in a request");
    1738                 :          0 :                 return (EPKG_FATAL);
    1739                 :            :         }
    1740                 :            : 
    1741                 :        481 :         pkg_jobs_propagate_automatic(j);
    1742                 :            : 
    1743                 :            : order:
    1744                 :            : 
    1745                 :        494 :         j->solved ++;
    1746                 :            : 
    1747                 :        494 :         return (EPKG_OK);
    1748                 :        498 : }
    1749                 :            : 
    1750                 :            : static int
    1751                 :          8 : jobs_solve_fetch(struct pkg_jobs *j)
    1752                 :            : {
    1753                 :            :         struct job_pattern *jp;
    1754                 :          8 :         struct pkg *pkg = NULL;
    1755                 :            :         struct pkgdb_it *it;
    1756                 :            :         struct pkg_job_request *req;
    1757                 :            :         pkghash_it hit;
    1758                 :            :         pkg_error_t rc;
    1759                 :            : 
    1760         [ -  + ]:          8 :         if ((j->flags & PKG_FLAG_UPGRADES_FOR_INSTALLED) == PKG_FLAG_UPGRADES_FOR_INSTALLED) {
    1761         [ #  # ]:          0 :                 if ((it = pkgdb_query(j->db, NULL, MATCH_ALL)) == NULL)
    1762                 :          0 :                         return (EPKG_FATAL);
    1763                 :            : 
    1764         [ #  # ]:          0 :                 while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
    1765         [ #  # ]:          0 :                         if(pkg->locked) {
    1766                 :          0 :                                 pkg_emit_locked(pkg);
    1767                 :          0 :                         }
    1768                 :            :                         else {
    1769                 :            :                                 /* Do not test we ignore what doesn't exists remotely */
    1770                 :          0 :                                 pkg_jobs_find_upgrade(j, pkg->uid, MATCH_EXACT);
    1771                 :            :                         }
    1772                 :          0 :                         pkg = NULL;
    1773                 :            :                 }
    1774                 :          0 :                 pkgdb_it_free(it);
    1775                 :          0 :         } else {
    1776         [ +  + ]:         16 :                 LL_FOREACH(j->patterns, jp) {
    1777                 :            :                         /* TODO: use repository priority here */
    1778         [ +  + ]:          8 :                         if (pkg_jobs_find_upgrade(j, jp->pattern, jp->match) == EPKG_FATAL)
    1779                 :          4 :                                 pkg_emit_error("No packages matching '%s' have been found in the "
    1780                 :          4 :                                                 "repositories", jp->pattern);
    1781                 :          8 :                 }
    1782                 :          8 :                 hit = pkghash_iterator(j->request_add);
    1783         [ +  + ]:          8 :                 while (pkghash_next(&hit)) {
    1784                 :          4 :                         req = hit.value;
    1785                 :          4 :                         rc = pkg_jobs_universe_process(j->universe, req->item->pkg);
    1786         [ -  + ]:          4 :                         if (rc != EPKG_OK)
    1787                 :          4 :                                 return (rc);
    1788                 :            :                 }
    1789                 :            :         }
    1790                 :            : 
    1791                 :          4 :         j->solved ++;
    1792                 :            : 
    1793                 :          4 :         return (EPKG_OK);
    1794                 :          8 : }
    1795                 :            : 
    1796                 :            : static void
    1797                 :        639 : pkg_jobs_apply_replacements(struct pkg_jobs *j)
    1798                 :            : {
    1799                 :            :         struct pkg_job_replace *r;
    1800                 :            :         static const char sql[] = ""
    1801                 :            :                 "UPDATE packages SET name=?1 "
    1802                 :            :                 " WHERE name=?2;" ;
    1803                 :            :         sqlite3_stmt *stmt;
    1804                 :            :         int ret;
    1805                 :            : 
    1806                 :        639 :         pkg_debug(4, "jobs: running '%s'", sql);
    1807                 :        639 :         ret = sqlite3_prepare_v2(j->db->sqlite, sql, -1, &stmt, NULL);
    1808         [ +  - ]:        639 :         if (ret != SQLITE_OK) {
    1809                 :          0 :                 ERROR_SQLITE(j->db->sqlite, sql);
    1810                 :          0 :                 return;
    1811                 :            :         }
    1812                 :            : 
    1813         [ -  + ]:        639 :         LL_FOREACH(j->universe->uid_replaces, r) {
    1814                 :          0 :                 pkg_debug(4, "changing uid %s -> %s", r->old_uid, r->new_uid);
    1815                 :          0 :                 sqlite3_bind_text(stmt, 1, r->new_uid, -1, SQLITE_TRANSIENT);
    1816                 :          0 :                 sqlite3_bind_text(stmt, 2, r->old_uid, -1, SQLITE_TRANSIENT);
    1817                 :            : 
    1818         [ #  # ]:          0 :                 if (sqlite3_step(stmt) != SQLITE_DONE)
    1819                 :          0 :                         ERROR_STMT_SQLITE(j->db->sqlite, stmt);
    1820                 :            : 
    1821                 :          0 :                 sqlite3_reset(stmt);
    1822                 :          0 :         }
    1823                 :            : 
    1824                 :        639 :         sqlite3_finalize(stmt);
    1825                 :        639 : }
    1826                 :            : 
    1827                 :            : static int
    1828                 :          0 : solve_with_external_cudf_solver(struct pkg_jobs *j, const char *solver)
    1829                 :            : {
    1830                 :            :         int ret, pstatus;
    1831                 :            :         FILE *spipe[2];
    1832                 :            :         pid_t pchild;
    1833                 :            : 
    1834                 :          0 :         pchild = process_spawn_pipe(spipe, solver);
    1835         [ #  # ]:          0 :         if (pchild == -1)
    1836                 :          0 :                 return (EPKG_FATAL);
    1837                 :            : 
    1838                 :          0 :         ret = pkg_jobs_cudf_emit_file(j, j->type, spipe[1]);
    1839                 :          0 :         fclose(spipe[1]);
    1840                 :            : 
    1841         [ #  # ]:          0 :         if (ret == EPKG_OK)
    1842                 :          0 :                 ret = pkg_jobs_cudf_parse_output(j, spipe[0]);
    1843                 :            : 
    1844                 :          0 :         fclose(spipe[0]);
    1845                 :          0 :         waitpid(pchild, &pstatus, WNOHANG);
    1846                 :            : 
    1847                 :          0 :         return (ret);
    1848                 :          0 : }
    1849                 :            : 
    1850                 :            : static int
    1851                 :          0 : solve_with_external_sat_solver(struct pkg_solve_problem *pb, const char *solver)
    1852                 :            : {
    1853                 :            :         int ret, pstatus;
    1854                 :            :         FILE *spipe[2];
    1855                 :            :         pid_t pchild;
    1856                 :            : 
    1857                 :          0 :         pchild = process_spawn_pipe(spipe, solver);
    1858         [ #  # ]:          0 :         if (pchild == -1)
    1859                 :          0 :                 return (EPKG_FATAL);
    1860                 :            : 
    1861                 :          0 :         ret = pkg_solve_dimacs_export(pb, spipe[1]);
    1862                 :          0 :         fclose(spipe[1]);
    1863                 :            : 
    1864         [ #  # ]:          0 :         if (ret == EPKG_OK)
    1865                 :          0 :                 ret = pkg_solve_parse_sat_output(spipe[0], pb);
    1866                 :            : 
    1867                 :          0 :         fclose(spipe[0]);
    1868                 :          0 :         waitpid(pchild, &pstatus, WNOHANG);
    1869                 :            : 
    1870                 :          0 :         return (ret);
    1871                 :          0 : }
    1872                 :            : 
    1873                 :            : static int
    1874                 :        639 : solve_with_sat_solver(struct pkg_jobs *j)
    1875                 :            : {
    1876                 :        639 :         const char *sat_solver = pkg_object_string(pkg_config_get("SAT_SOLVER"));
    1877                 :            :         struct pkg_solve_problem *problem;
    1878                 :            :         const char *dotfile;
    1879                 :        639 :         FILE *dot = NULL;
    1880                 :            :         int ret;
    1881                 :            : 
    1882                 :        639 :         pkg_jobs_universe_process_upgrade_chains(j);
    1883                 :        639 :         problem = pkg_solve_jobs_to_sat(j);
    1884         [ +  - ]:        639 :         if (problem == NULL) {
    1885                 :          0 :                 pkg_emit_error("cannot convert job to SAT problem");
    1886                 :          0 :                 j->solved = 0;
    1887                 :          0 :                 return (EPKG_FATAL);
    1888                 :            :         }
    1889                 :            : 
    1890         [ -  + ]:        639 :         if (sat_solver != NULL)
    1891                 :          0 :                 return (solve_with_external_sat_solver(problem, sat_solver));
    1892                 :            : 
    1893   [ +  -  +  - ]:       1278 :         if ((dotfile = pkg_object_string(pkg_config_get("DOT_FILE")))
    1894                 :        639 :                 != NULL) {
    1895                 :          0 :                 dot = fopen(dotfile, "we");
    1896                 :            : 
    1897         [ #  # ]:          0 :                 if (dot == NULL) {
    1898                 :          0 :                         pkg_emit_errno("fopen", dotfile);
    1899                 :          0 :                 }
    1900                 :          0 :         }
    1901                 :            : 
    1902                 :        639 :         ret = pkg_solve_sat_problem(problem);
    1903         [ -  + ]:        639 :         if (ret == EPKG_AGAIN) {
    1904                 :          0 :                 pkg_solve_problem_free(problem);
    1905                 :          0 :                 return (solve_with_sat_solver(j));
    1906                 :            :         }
    1907                 :            : 
    1908         [ -  + ]:        639 :         if (ret == EPKG_FATAL) {
    1909                 :          0 :                 pkg_emit_error("cannot solve job using SAT solver");
    1910                 :          0 :                 pkg_solve_problem_free(problem);
    1911                 :          0 :                 j->solved = 0;
    1912                 :          0 :         } else {
    1913                 :        639 :                 ret = pkg_solve_sat_to_jobs(problem);
    1914                 :            :         }
    1915                 :            : 
    1916   [ +  -  +  - ]:       1278 :         if ((dotfile = pkg_object_string(pkg_config_get("DOT_FILE")))
    1917                 :        639 :                 != NULL) {
    1918                 :          0 :                 dot = fopen(dotfile, "we");
    1919                 :            : 
    1920         [ #  # ]:          0 :                 if (dot == NULL) {
    1921                 :          0 :                         pkg_emit_errno("fopen", dotfile);
    1922                 :          0 :                 } else {
    1923                 :          0 :                         pkg_solve_dot_export(problem, dot);
    1924                 :          0 :                         fclose(dot);
    1925                 :            :                 }
    1926                 :          0 :         }
    1927                 :        639 :         pkg_solve_problem_free(problem);
    1928                 :            : 
    1929                 :        639 :         return (ret);
    1930                 :        639 : }
    1931                 :            : 
    1932                 :            : int
    1933                 :        647 : pkg_jobs_solve(struct pkg_jobs *j)
    1934                 :            : {
    1935                 :            :         int ret;
    1936                 :            :         struct pkg_solved *job;
    1937                 :            :         const char *cudf_solver;
    1938                 :            : 
    1939                 :        647 :         pkgdb_begin_solver(j->db);
    1940                 :            : 
    1941   [ +  +  +  -  :        647 :         switch (j->type) {
                      + ]
    1942                 :            :         case PKG_JOBS_AUTOREMOVE:
    1943                 :         30 :                 ret = jobs_solve_autoremove(j);
    1944                 :         30 :                 break;
    1945                 :            :         case PKG_JOBS_DEINSTALL:
    1946                 :        111 :                 ret = jobs_solve_deinstall(j);
    1947                 :        111 :                 break;
    1948                 :            :         case PKG_JOBS_UPGRADE:
    1949                 :            :         case PKG_JOBS_INSTALL:
    1950                 :        498 :                 ret = jobs_solve_install_upgrade(j);
    1951                 :        498 :                 break;
    1952                 :            :         case PKG_JOBS_FETCH:
    1953                 :          8 :                 ret = jobs_solve_fetch(j);
    1954                 :          8 :                 break;
    1955                 :            :         default:
    1956                 :          0 :                 pkgdb_end_solver(j->db);
    1957                 :          0 :                 return (EPKG_FATAL);
    1958                 :            :         }
    1959                 :            : 
    1960                 :        647 :         cudf_solver = pkg_object_string(pkg_config_get("CUDF_SOLVER"));
    1961                 :            : 
    1962         [ +  + ]:        647 :         if (ret == EPKG_OK) {
    1963         [ -  + ]:        639 :                 if (cudf_solver != NULL) {
    1964                 :          0 :                         ret = solve_with_external_cudf_solver(j, cudf_solver);
    1965                 :          0 :                 } else {
    1966                 :        639 :                         ret = solve_with_sat_solver(j);
    1967                 :            :                 }
    1968                 :        639 :         }
    1969                 :            : 
    1970   [ +  +  +  - ]:        647 :         if (j->type == PKG_JOBS_DEINSTALL && j->solved)
    1971                 :        111 :                 pkg_jobs_set_deinstall_reasons(j);
    1972                 :            : 
    1973                 :        647 :         pkgdb_end_solver(j->db);
    1974                 :            : 
    1975         [ +  + ]:        647 :         if (ret != EPKG_OK)
    1976                 :          8 :                 return (ret);
    1977                 :            : 
    1978                 :        639 :         pkg_jobs_apply_replacements(j);
    1979                 :            : 
    1980                 :            :         /* Check if we need to fetch and re-run the solver */
    1981         [ +  + ]:       1514 :         DL_FOREACH(j->jobs, job) {
    1982                 :            :                 struct pkg *p;
    1983                 :            : 
    1984                 :        879 :                 p = job->items[0]->pkg;
    1985         [ +  + ]:        879 :                 if (p->type != PKG_REMOTE)
    1986                 :        401 :                         continue;
    1987                 :            : 
    1988   [ +  +  +  + ]:        956 :                 if (pkgdb_ensure_loaded(j->db, p, PKG_LOAD_FILES|PKG_LOAD_DIRS)
    1989                 :        478 :                                 == EPKG_FATAL) {
    1990                 :          4 :                         j->need_fetch = true;
    1991                 :          4 :                         break;
    1992                 :            :                 }
    1993                 :        474 :         }
    1994                 :            : 
    1995   [ +  +  +  +  :        639 :         if (j->solved == 1 && !j->need_fetch && j->type != PKG_JOBS_FETCH) {
                   +  + ]
    1996                 :            :                 int rc;
    1997                 :        595 :                 bool has_conflicts = false;
    1998                 :        595 :                 do {
    1999                 :        631 :                         j->conflicts_registered = 0;
    2000                 :        631 :                         rc = pkg_jobs_check_conflicts(j);
    2001         [ +  + ]:        631 :                         if (rc == EPKG_CONFLICT) {
    2002                 :            :                                 /* Cleanup results */
    2003   [ +  +  +  +  :        132 :                                 LL_FREE(j->jobs, free);
          -  +  #  #  #  
                #  #  # ]
    2004                 :         36 :                                 j->jobs = NULL;
    2005                 :         36 :                                 j->count = 0;
    2006                 :         36 :                                 has_conflicts = true;
    2007                 :         36 :                                 pkg_jobs_solve(j);
    2008                 :         36 :                         }
    2009   [ +  -  +  + ]:        595 :                         else if (rc == EPKG_OK && !has_conflicts) {
    2010                 :        559 :                                 break;
    2011                 :            :                         }
    2012         [ +  + ]:         72 :                 } while (j->conflicts_registered > 0);
    2013                 :        595 :         }
    2014                 :            : 
    2015                 :        639 :         return (ret);
    2016                 :        647 : }
    2017                 :            : 
    2018                 :            : int
    2019                 :        603 : pkg_jobs_count(struct pkg_jobs *j)
    2020                 :            : {
    2021         [ +  - ]:        603 :         assert(j != NULL);
    2022                 :            : 
    2023                 :        603 :         return (j->count);
    2024                 :            : }
    2025                 :            : 
    2026                 :            : int
    2027                 :        283 : pkg_jobs_total(struct pkg_jobs *j)
    2028                 :            : {
    2029         [ +  - ]:        283 :         assert(j != NULL);
    2030                 :            : 
    2031                 :        283 :         return (j->total);
    2032                 :            : }
    2033                 :            : 
    2034                 :            : pkg_jobs_t
    2035                 :        305 : pkg_jobs_type(struct pkg_jobs *j)
    2036                 :            : {
    2037         [ +  - ]:        305 :         assert(j != NULL);
    2038                 :            : 
    2039                 :        305 :         return (j->type);
    2040                 :            : }
    2041                 :            : 
    2042                 :            : static int
    2043                 :        538 : pkg_jobs_handle_install(struct pkg_solved *ps, struct pkg_jobs *j,
    2044                 :            :                 struct pkg_manifest_key *keys)
    2045                 :            : {
    2046                 :            :         struct pkg *new, *old;
    2047                 :            :         struct pkg_job_request *req;
    2048                 :            :         char path[MAXPATHLEN], *target;
    2049                 :        538 :         int flags = 0;
    2050                 :        538 :         int retcode = EPKG_FATAL;
    2051                 :            : 
    2052         [ +  + ]:        538 :         old = ps->items[1] ? ps->items[1]->pkg : NULL;
    2053                 :        538 :         new = ps->items[0]->pkg;
    2054                 :            : 
    2055                 :        538 :         req = pkghash_get_value(j->request_add, new->uid);
    2056   [ +  +  +  +  :        538 :         if (req != NULL && req->item->jp != NULL &&
                   +  - ]
    2057                 :        212 :                         (req->item->jp->flags & PKG_PATTERN_FLAG_FILE)) {
    2058                 :            :                 /*
    2059                 :            :                  * We have package as a file, set special repository name
    2060                 :            :                  */
    2061                 :        212 :                 target = req->item->jp->path;
    2062                 :        212 :                 free(new->reponame);
    2063                 :        212 :                 new->reponame = xstrdup("local file");
    2064                 :        212 :         }
    2065                 :            :         else {
    2066                 :        326 :                 pkg_snprintf(path, sizeof(path), "%R", new);
    2067         [ -  + ]:        326 :                 if (*path != '/')
    2068                 :        326 :                         pkg_repo_cached_name(new, path, sizeof(path));
    2069                 :        326 :                 target = path;
    2070                 :            :         }
    2071                 :            : 
    2072         [ +  + ]:        538 :         if (old != NULL)
    2073                 :        132 :                 new->old_version = xstrdup(old->version);
    2074                 :            : 
    2075         [ +  + ]:        538 :         if ((j->flags & PKG_FLAG_FORCE) == PKG_FLAG_FORCE)
    2076                 :        189 :                 flags |= PKG_ADD_FORCE;
    2077         [ +  - ]:        538 :         if ((j->flags & PKG_FLAG_NOSCRIPT) == PKG_FLAG_NOSCRIPT)
    2078                 :          0 :                 flags |= PKG_ADD_NOSCRIPT;
    2079         [ +  - ]:        538 :         if ((j->flags & PKG_FLAG_FORCE_MISSING) == PKG_FLAG_FORCE_MISSING)
    2080                 :          0 :                 flags |= PKG_ADD_FORCE_MISSING;
    2081                 :        538 :         flags |= PKG_ADD_UPGRADE;
    2082         [ +  + ]:        538 :         if (ps->type == PKG_SOLVED_UPGRADE_INSTALL)
    2083                 :          8 :                 flags |= PKG_ADD_SPLITTED_UPGRADE;
    2084   [ +  +  -  + ]:        538 :         if (new->automatic || (j->flags & PKG_FLAG_AUTOMATIC) == PKG_FLAG_AUTOMATIC)
    2085                 :        108 :                 flags |= PKG_ADD_AUTOMATIC;
    2086                 :            : 
    2087         [ +  + ]:        538 :         if (old != NULL)
    2088                 :        132 :                 retcode = pkg_add_upgrade(j->db, target, flags, keys, NULL, new, old);
    2089                 :            :         else
    2090                 :        406 :                 retcode = pkg_add_from_remote(j->db, target, flags, keys, NULL, new);
    2091                 :            : 
    2092                 :        538 :         return (retcode);
    2093                 :            : }
    2094                 :            : 
    2095                 :            : static int
    2096                 :        542 : pkg_jobs_execute(struct pkg_jobs *j)
    2097                 :            : {
    2098                 :        542 :         struct pkg *p = NULL;
    2099                 :            :         struct pkg_solved *ps;
    2100                 :        542 :         struct pkg_manifest_key *keys = NULL;
    2101                 :        542 :         int flags = 0;
    2102                 :        542 :         int retcode = EPKG_FATAL;
    2103                 :            :         pkg_plugin_hook_t pre, post;
    2104                 :            :         struct trigger *cleanup_triggers;
    2105                 :            : 
    2106                 :        542 :         cleanup_triggers = triggers_load(true);
    2107         [ +  + ]:        542 :         if (j->type == PKG_JOBS_INSTALL) {
    2108                 :        303 :                 pre = PKG_PLUGIN_HOOK_PRE_INSTALL;
    2109                 :        303 :                 post = PKG_PLUGIN_HOOK_POST_INSTALL;
    2110                 :        303 :         }
    2111         [ +  + ]:        239 :         else if (j->type == PKG_JOBS_UPGRADE) {
    2112                 :        111 :                 pre = PKG_PLUGIN_HOOK_PRE_UPGRADE;
    2113                 :        111 :                 post = PKG_PLUGIN_HOOK_POST_UPGRADE;
    2114                 :        111 :         }
    2115         [ +  + ]:        128 :         else if (j->type == PKG_JOBS_AUTOREMOVE){
    2116                 :         21 :                 pre = PKG_PLUGIN_HOOK_PRE_AUTOREMOVE;
    2117                 :         21 :                 post = PKG_PLUGIN_HOOK_POST_AUTOREMOVE;
    2118                 :         21 :         }
    2119                 :            :         else {
    2120                 :        107 :                 pre = PKG_PLUGIN_HOOK_PRE_DEINSTALL;
    2121                 :        107 :                 post = PKG_PLUGIN_HOOK_POST_DEINSTALL;
    2122                 :            :         }
    2123                 :            : 
    2124         [ -  + ]:        542 :         if (j->flags & PKG_FLAG_SKIP_INSTALL)
    2125                 :          0 :                 return (EPKG_OK);
    2126                 :            : 
    2127         [ +  + ]:        542 :         if ((j->flags & PKG_FLAG_FORCE) == PKG_FLAG_FORCE)
    2128                 :        222 :                 flags |= PKG_DELETE_FORCE;
    2129                 :            : 
    2130         [ +  - ]:        542 :         if ((j->flags & PKG_FLAG_NOSCRIPT) == PKG_FLAG_NOSCRIPT)
    2131                 :          0 :                 flags |= PKG_DELETE_NOSCRIPT;
    2132                 :            : 
    2133                 :        542 :         retcode = pkgdb_upgrade_lock(j->db, PKGDB_LOCK_ADVISORY,
    2134                 :            :                         PKGDB_LOCK_EXCLUSIVE);
    2135         [ -  + ]:        542 :         if (retcode != EPKG_OK)
    2136                 :          0 :                 return (retcode);
    2137                 :            : 
    2138                 :        542 :         pkg_plugins_hook_run(pre, j, j->db);
    2139                 :            : 
    2140                 :        542 :         p = NULL;
    2141                 :        542 :         pkg_manifest_keys_new(&keys);
    2142                 :            : 
    2143                 :        542 :         pkg_jobs_set_priorities(j);
    2144                 :            : 
    2145         [ +  + ]:       1252 :         DL_FOREACH(j->jobs, ps) {
    2146   [ +  +  -  +  :        722 :                 switch (ps->type) {
                      - ]
    2147                 :            :                 case PKG_SOLVED_DELETE:
    2148                 :            :                 case PKG_SOLVED_UPGRADE_REMOVE:
    2149                 :        184 :                         p = ps->items[0]->pkg;
    2150   [ +  +  +  +  :        184 :                         if (ps->type == PKG_SOLVED_DELETE && p->vital && ((flags & PKG_DELETE_FORCE) == 0)) {
                   +  + ]
    2151                 :          4 :                                 pkg_emit_error("Cannot delete vital package: %s!", p->name);
    2152                 :          4 :                                 pkg_emit_error("If you are sure you want to remove %s, ", p->name);
    2153                 :          4 :                                 pkg_emit_error("unset the 'vital' flag with: pkg set -v 0 %s", p->name);
    2154                 :          4 :                                 retcode = EPKG_FATAL;
    2155                 :          4 :                                 goto cleanup;
    2156                 :            :                         }
    2157   [ +  +  +  + ]:        192 :                         if (ps->type == PKG_SOLVED_DELETE &&
    2158         [ +  + ]:        172 :                             (strcmp(p->name, "pkg") == 0 ||
    2159                 :        160 :                             strcmp(p->name, "pkg-devel") == 0) &&
    2160                 :         12 :                             (flags & PKG_DELETE_FORCE) == 0) {
    2161         [ +  + ]:          8 :                                 if (j->patterns->match == MATCH_ALL) {
    2162                 :          4 :                                         continue;
    2163                 :            :                                 } else {
    2164                 :          4 :                                         pkg_emit_error("Cannot delete pkg itself without force flag");
    2165                 :          4 :                                         retcode = EPKG_FATAL;
    2166                 :          4 :                                         goto cleanup;
    2167                 :            :                                 }
    2168                 :            :                         }
    2169                 :            :                         /*
    2170                 :            :                          * Assume that in upgrade we can remove packages with rdeps as
    2171                 :            :                          * in further they will be upgraded correctly.
    2172                 :            :                          */
    2173         [ +  + ]:        172 :                         if (j->type == PKG_JOBS_UPGRADE)
    2174                 :         40 :                                 retcode = pkg_delete(p, j->db, flags | PKG_DELETE_CONFLICT);
    2175                 :            :                         else
    2176                 :        132 :                                 retcode = pkg_delete(p, j->db, flags);
    2177         [ +  - ]:        172 :                         if (retcode != EPKG_OK)
    2178                 :          0 :                                 goto cleanup;
    2179                 :        172 :                         break;
    2180                 :            :                 case PKG_SOLVED_INSTALL:
    2181                 :            :                 case PKG_SOLVED_UPGRADE_INSTALL:
    2182                 :        406 :                         retcode = pkg_jobs_handle_install(ps, j, keys);
    2183         [ +  + ]:        406 :                         if (retcode != EPKG_OK)
    2184                 :          4 :                                 goto cleanup;
    2185                 :        402 :                         break;
    2186                 :            :                 case PKG_SOLVED_UPGRADE:
    2187                 :        132 :                         retcode = pkg_jobs_handle_install(ps, j, keys);
    2188         [ +  - ]:        132 :                         if (retcode != EPKG_OK)
    2189                 :          0 :                                 goto cleanup;
    2190                 :        132 :                         break;
    2191                 :            :                 case PKG_SOLVED_FETCH:
    2192                 :          0 :                         retcode = EPKG_FATAL;
    2193                 :          0 :                         pkg_emit_error("internal error: bad job type");
    2194                 :          0 :                         goto cleanup;
    2195                 :            :                         break;
    2196                 :            :                 }
    2197                 :            : 
    2198                 :        706 :         }
    2199                 :            : 
    2200                 :        530 :         pkg_plugins_hook_run(post, j, j->db);
    2201                 :        530 :         triggers_execute(cleanup_triggers);
    2202                 :            : 
    2203                 :            : cleanup:
    2204                 :        542 :         pkgdb_release_lock(j->db, PKGDB_LOCK_EXCLUSIVE);
    2205                 :        542 :         pkg_manifest_keys_free(keys);
    2206                 :            : 
    2207                 :        542 :         return (retcode);
    2208                 :        542 : }
    2209                 :            : 
    2210                 :            : int
    2211                 :        542 : pkg_jobs_apply(struct pkg_jobs *j)
    2212                 :            : {
    2213                 :            :         int rc;
    2214                 :        542 :         bool has_conflicts = false;
    2215                 :            : 
    2216         [ +  - ]:        542 :         if (!j->solved) {
    2217                 :          0 :                 pkg_emit_error("The jobs hasn't been solved");
    2218                 :          0 :                 return (EPKG_FATAL);
    2219                 :            :         }
    2220                 :            : 
    2221      [ +  -  - ]:        542 :         switch (j->type) {
    2222                 :            :         case PKG_JOBS_INSTALL:
    2223                 :            :         case PKG_JOBS_UPGRADE:
    2224                 :            :         case PKG_JOBS_DEINSTALL:
    2225                 :            :         case PKG_JOBS_AUTOREMOVE:
    2226         [ +  + ]:        542 :                 if (j->need_fetch) {
    2227                 :          4 :                         pkg_plugins_hook_run(PKG_PLUGIN_HOOK_PRE_FETCH, j, j->db);
    2228                 :          4 :                         rc = pkg_jobs_fetch(j);
    2229                 :          4 :                         pkg_plugins_hook_run(PKG_PLUGIN_HOOK_POST_FETCH, j, j->db);
    2230         [ -  + ]:          4 :                         if (rc == EPKG_OK) {
    2231                 :            :                                 /* Check local conflicts in the first run */
    2232         [ +  - ]:          4 :                                 if (j->solved == 1) {
    2233                 :          4 :                                         do {
    2234                 :          4 :                                                 j->conflicts_registered = 0;
    2235                 :          4 :                                                 rc = pkg_jobs_check_conflicts(j);
    2236         [ -  + ]:          4 :                                                 if (rc == EPKG_CONFLICT) {
    2237                 :            :                                                         /* Cleanup results */
    2238   [ #  #  #  #  :          0 :                                                         LL_FREE(j->jobs, free);
          #  #  #  #  #  
                #  #  # ]
    2239                 :          0 :                                                         j->jobs = NULL;
    2240                 :          0 :                                                         j->count = 0;
    2241                 :          0 :                                                         has_conflicts = true;
    2242                 :          0 :                                                         rc = pkg_jobs_solve(j);
    2243                 :          0 :                                                 }
    2244   [ +  -  +  - ]:          4 :                                                 else if (rc == EPKG_OK && !has_conflicts) {
    2245                 :          4 :                                                         rc = pkg_jobs_execute(j);
    2246                 :          4 :                                                         break;
    2247                 :            :                                                 }
    2248         [ #  # ]:          0 :                                         } while (j->conflicts_registered > 0);
    2249                 :            : 
    2250         [ -  + ]:          4 :                                         if (has_conflicts) {
    2251         [ #  # ]:          0 :                                                 if (j->conflicts_registered == 0)
    2252                 :          0 :                                                         pkg_jobs_set_priorities(j);
    2253                 :            : 
    2254                 :          0 :                                                 return (EPKG_CONFLICT);
    2255                 :            :                                         }
    2256                 :          4 :                                 }
    2257                 :            :                                 else {
    2258                 :            :                                         /* Not the first run, conflicts are resolved already */
    2259                 :          0 :                                         rc = pkg_jobs_execute(j);
    2260                 :            :                                 }
    2261                 :          4 :                         }
    2262                 :          4 :                 }
    2263                 :            :                 else {
    2264                 :        538 :                         rc = pkg_jobs_execute(j);
    2265                 :            :                 }
    2266                 :            : 
    2267                 :        542 :                 break;
    2268                 :            :         case PKG_JOBS_FETCH:
    2269                 :          0 :                 pkg_plugins_hook_run(PKG_PLUGIN_HOOK_PRE_FETCH, j, j->db);
    2270                 :          0 :                 rc = pkg_jobs_fetch(j);
    2271                 :          0 :                 pkg_plugins_hook_run(PKG_PLUGIN_HOOK_POST_FETCH, j, j->db);
    2272                 :          0 :                 break;
    2273                 :            :         default:
    2274                 :          0 :                 rc = EPKG_FATAL;
    2275                 :          0 :                 pkg_emit_error("bad jobs argument");
    2276                 :          0 :                 break;
    2277                 :            :         }
    2278                 :            : 
    2279                 :        542 :         return (rc);
    2280                 :        542 : }
    2281                 :            : 
    2282                 :            : 
    2283                 :            : static int
    2284                 :          4 : pkg_jobs_fetch(struct pkg_jobs *j)
    2285                 :            : {
    2286                 :          4 :         struct pkg *p = NULL;
    2287                 :            :         struct pkg_solved *ps;
    2288                 :            :         struct stat st;
    2289                 :          4 :         int64_t dlsize = 0, fs_avail = -1;
    2290                 :          4 :         const char *cachedir = NULL;
    2291                 :            :         char cachedpath[MAXPATHLEN];
    2292                 :          4 :         bool mirror = (j->flags & PKG_FLAG_FETCH_MIRROR) ? true : false;
    2293                 :            : 
    2294                 :            : 
    2295   [ -  +  #  # ]:          4 :         if (j->destdir == NULL || !mirror)
    2296                 :          4 :                 cachedir = ctx.cachedir;
    2297                 :            :         else
    2298                 :          0 :                 cachedir = j->destdir;
    2299                 :            : 
    2300                 :            :         /* check for available size to fetch */
    2301         [ +  + ]:          8 :         DL_FOREACH(j->jobs, ps) {
    2302   [ +  -  -  + ]:          4 :                 if (ps->type != PKG_SOLVED_DELETE && ps->type != PKG_SOLVED_UPGRADE_REMOVE) {
    2303                 :          4 :                         p = ps->items[0]->pkg;
    2304         [ -  + ]:          4 :                         if (p->type != PKG_REMOTE)
    2305                 :          0 :                                 continue;
    2306                 :            : 
    2307         [ -  + ]:          4 :                         if (mirror) {
    2308                 :          0 :                                 snprintf(cachedpath, sizeof(cachedpath),
    2309                 :          0 :                                    "%s/%s", cachedir, p->repopath);
    2310                 :          0 :                         }
    2311                 :            :                         else
    2312                 :          4 :                                 pkg_repo_cached_name(p, cachedpath, sizeof(cachedpath));
    2313                 :            : 
    2314         [ -  + ]:          4 :                         if (stat(cachedpath, &st) == -1)
    2315                 :          4 :                                 dlsize += p->pkgsize;
    2316                 :            :                         else
    2317                 :          0 :                                 dlsize += p->pkgsize - st.st_size;
    2318                 :          4 :                 }
    2319                 :          4 :         }
    2320                 :            : 
    2321         [ +  - ]:          4 :         if (dlsize == 0)
    2322                 :          0 :                 return (EPKG_OK);
    2323                 :            : 
    2324                 :            : #ifdef HAVE_FSTATFS
    2325                 :            :         struct statfs fs;
    2326         [ +  + ]:          8 :         while (statfs(cachedir, &fs) == -1) {
    2327         [ +  - ]:          4 :                 if (errno == ENOENT) {
    2328         [ +  - ]:          4 :                         if (mkdirs(cachedir) != EPKG_OK)
    2329                 :          0 :                                 return (EPKG_FATAL);
    2330                 :          4 :                 } else {
    2331                 :          0 :                         pkg_emit_errno("statfs", cachedir);
    2332                 :          0 :                         return (EPKG_FATAL);
    2333                 :            :                 }
    2334                 :            :         }
    2335                 :          4 :         fs_avail = fs.f_bsize * (int64_t)fs.f_bavail;
    2336                 :            : #elif defined(HAVE_SYS_STATVFS_H)
    2337                 :            :         struct statvfs fs;
    2338                 :            :         while (statvfs(cachedir, &fs) == -1) {
    2339                 :            :                 if (errno == ENOENT) {
    2340                 :            :                         if (mkdirs(cachedir) != EPKG_OK)
    2341                 :            :                                 return (EPKG_FATAL);
    2342                 :            :                 } else {
    2343                 :            :                         pkg_emit_errno("statvfs", cachedir);
    2344                 :            :                         return (EPKG_FATAL);
    2345                 :            :                 }
    2346                 :            :         }
    2347                 :            :         fs_avail = fs.f_bsize * (int64_t)fs.f_bavail;
    2348                 :            : #endif
    2349                 :            : 
    2350   [ +  -  +  - ]:          4 :         if (fs_avail != -1 && dlsize > fs_avail) {
    2351                 :            :                 char dlsz[9], fsz[9];
    2352                 :            : 
    2353                 :          0 :                 humanize_number(dlsz, sizeof(dlsz), dlsize, "B",
    2354                 :            :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
    2355                 :          0 :                 humanize_number(fsz, sizeof(fsz), fs_avail, "B",
    2356                 :            :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
    2357                 :          0 :                 pkg_emit_error("Not enough space in %s, needed %s available %s",
    2358                 :          0 :                     cachedir, dlsz, fsz);
    2359                 :          0 :                 return (EPKG_FATAL);
    2360                 :            :         }
    2361                 :            : 
    2362         [ -  + ]:          4 :         if ((j->flags & PKG_FLAG_DRY_RUN) == PKG_FLAG_DRY_RUN)
    2363                 :          0 :                 return (EPKG_OK); /* don't download anything */
    2364                 :            : 
    2365                 :            :         /* Fetch */
    2366         [ +  + ]:          8 :         DL_FOREACH(j->jobs, ps) {
    2367   [ +  -  -  + ]:          4 :                 if (ps->type != PKG_SOLVED_DELETE && ps->type != PKG_SOLVED_UPGRADE_REMOVE) {
    2368                 :          4 :                         p = ps->items[0]->pkg;
    2369         [ -  + ]:          4 :                         if (p->type != PKG_REMOTE)
    2370                 :          0 :                                 continue;
    2371                 :            : 
    2372         [ -  + ]:          4 :                         if (mirror) {
    2373         [ #  # ]:          0 :                                 if (pkg_repo_mirror_package(p, cachedir) != EPKG_OK)
    2374                 :          0 :                                         return (EPKG_FATAL);
    2375                 :          0 :                         }
    2376                 :            :                         else {
    2377         [ +  - ]:          4 :                                 if (pkg_repo_fetch_package(p) != EPKG_OK)
    2378                 :          0 :                                         return (EPKG_FATAL);
    2379                 :            :                         }
    2380                 :          4 :                 }
    2381                 :          4 :         }
    2382                 :            : 
    2383                 :          4 :         return (EPKG_OK);
    2384                 :          4 : }
    2385                 :            : 
    2386                 :            : static int
    2387                 :        635 : pkg_jobs_check_conflicts(struct pkg_jobs *j)
    2388                 :            : {
    2389                 :            :         struct pkg_solved *ps;
    2390                 :        635 :         struct pkg *p = NULL;
    2391                 :        635 :         int ret = EPKG_OK, res, added = 0;
    2392                 :            : 
    2393                 :        635 :         pkg_emit_integritycheck_begin();
    2394                 :        635 :         j->conflicts_registered = 0;
    2395                 :            : 
    2396         [ +  + ]:       1514 :         DL_FOREACH(j->jobs, ps) {
    2397   [ +  +  -  + ]:        879 :                 if (ps->type == PKG_SOLVED_DELETE || ps->type == PKG_SOLVED_UPGRADE_REMOVE) {
    2398                 :        189 :                         continue;
    2399                 :            :                 }
    2400                 :            :                 else {
    2401                 :        690 :                         p = ps->items[0]->pkg;
    2402                 :            : 
    2403         [ +  + ]:        690 :                         if (p->type == PKG_REMOTE)
    2404                 :        478 :                                 pkgdb_ensure_loaded(j->db, p, PKG_LOAD_FILES|PKG_LOAD_DIRS);
    2405                 :            :                 }
    2406         [ -  + ]:        690 :                 if ((res = pkg_conflicts_append_chain(ps->items[0], j)) != EPKG_OK)
    2407                 :          0 :                         ret = res;
    2408                 :            :                 else
    2409                 :        690 :                         added ++;
    2410                 :        690 :         }
    2411                 :            : 
    2412                 :        635 :         pkg_debug(1, "check integrity for %d items added", added);
    2413                 :            : 
    2414                 :        635 :         pkg_emit_integritycheck_finished(j->conflicts_registered);
    2415         [ +  + ]:        635 :         if (j->conflicts_registered > 0)
    2416                 :         36 :                 ret = EPKG_CONFLICT;
    2417                 :            : 
    2418                 :        635 :         return (ret);
    2419                 :            : }
    2420                 :            : 
    2421                 :            : bool
    2422                 :        111 : pkg_jobs_has_lockedpkgs(struct pkg_jobs *j)
    2423                 :            : {
    2424                 :            : 
    2425                 :        111 :         return j->lockedpkgs ? true : false;
    2426                 :            : }
    2427                 :            : 
    2428                 :            : static void
    2429                 :          4 : pkg_jobs_visit_lockedpkgs(const void * node, VISIT v, int i __unused)
    2430                 :            : {
    2431                 :            : 
    2432   [ +  -  +  - ]:          4 :         if (v == postorder || v == leaf) {
    2433                 :          8 :                 pkgs_job_lockedpkg->locked_pkg_cb(*(struct pkg **)node,
    2434                 :          4 :                     pkgs_job_lockedpkg->context);
    2435                 :          4 :         }
    2436                 :          4 : }
    2437                 :            : 
    2438                 :            : void
    2439                 :          4 : pkg_jobs_iter_lockedpkgs(struct pkg_jobs *j, locked_pkgs_cb cb, void * ctx)
    2440                 :            : {
    2441                 :            :         struct pkg_jobs_locked foo;
    2442                 :            : 
    2443                 :          4 :         foo.locked_pkg_cb = cb;
    2444                 :          4 :         foo.context = ctx;
    2445                 :          4 :         pkgs_job_lockedpkg = &foo;
    2446                 :            : 
    2447                 :          4 :         twalk(j->lockedpkgs, pkg_jobs_visit_lockedpkgs);
    2448                 :          4 : }

Generated by: LCOV version 1.15