LCOV - code coverage report
Current view: top level - libpkg - pkg_jobs.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 563 1105 51.0 %
Date: 2015-08-15 Functions: 37 48 77.1 %

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

Generated by: LCOV version 1.10