LCOV - code coverage report
Current view: top level - libpkg - pkg_jobs.c (source / functions) Hit Total Coverage
Test: plop Lines: 1008 1380 73.0 %
Date: 2024-12-28 18:40:32 Functions: 53 60 88.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 625 1007 62.1 %

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

Generated by: LCOV version 1.15