LCOV - code coverage report
Current view: top level - libpkg - pkg_jobs_conflicts.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 118 202 58.4 %
Date: 2015-08-15 Functions: 14 23 60.9 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       3             :  * All rights reserved.
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions
       7             :  * are met:
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer
      10             :  *    in this position and unchanged.
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  *
      15             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      16             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      17             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      18             :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      19             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      20             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      21             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      22             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      23             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      24             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      25             :  */
      26             : 
      27             : #include <sys/param.h>
      28             : #include <sys/types.h>
      29             : #include <stdbool.h>
      30             : #include <stdlib.h>
      31             : #include <string.h>
      32             : #include <openssl/rand.h>
      33             : 
      34             : #include "pkg.h"
      35             : #include "private/event.h"
      36             : #include "private/pkg.h"
      37             : #include "private/pkgdb.h"
      38             : #include "private/pkg_jobs.h"
      39             : #include "siphash.h"
      40             : 
      41             : struct pkg_conflict_chain {
      42             :         struct pkg_job_request *req;
      43             :         struct pkg_conflict_chain *next;
      44             : };
      45             : 
      46             : 
      47         141 : TREE_DEFINE(pkg_jobs_conflict_item, entry);
      48             : 
      49             : static struct sipkey *
      50          31 : pkg_conflicts_sipkey_init(void)
      51             : {
      52             :         static struct sipkey *kinit;
      53             : 
      54          31 :         if (kinit == NULL) {
      55           7 :                 kinit = malloc(sizeof(*kinit));
      56           7 :                 RAND_bytes((unsigned char*)kinit, sizeof(*kinit));
      57             :         }
      58             : 
      59          31 :         return (kinit);
      60             : }
      61             : 
      62             : static int
      63           0 : pkg_conflicts_chain_cmp_cb(struct pkg_conflict_chain *a, struct pkg_conflict_chain *b)
      64             : {
      65             :         const char *vera, *verb;
      66             : 
      67           0 :         if (a->req->skip || b->req->skip) {
      68           0 :                 return (a->req->skip - b->req->skip);
      69             :         }
      70             : 
      71           0 :         vera = a->req->item->pkg->version;
      72           0 :         verb = b->req->item->pkg->version;
      73             : 
      74             :         /* Inverse sort to get the maximum version as the first element */
      75           0 :         return (pkg_version_cmp(vera, verb));
      76             : }
      77             : 
      78             : static int
      79           0 : pkg_conflicts_request_resolve_chain(struct pkg *req, struct pkg_conflict_chain *chain)
      80             : {
      81           0 :         struct pkg_conflict_chain *elt, *selected = NULL;
      82             :         const char *slash_pos;
      83             : 
      84             :         /*
      85             :          * First of all prefer pure origins, where the last element of
      86             :          * an origin is pkg name
      87             :          */
      88           0 :         LL_FOREACH(chain, elt) {
      89           0 :                 slash_pos = strrchr(elt->req->item->pkg->origin, '/');
      90           0 :                 if (slash_pos != NULL) {
      91           0 :                         if (strcmp(slash_pos + 1, req->name) == 0) {
      92           0 :                                 selected = elt;
      93           0 :                                 break;
      94             :                         }
      95             :                 }
      96             :         }
      97             : 
      98           0 :         if (selected == NULL) {
      99             :                 /* XXX: add manual selection here */
     100             :                 /* Sort list by version of package */
     101           0 :                 LL_SORT(chain, pkg_conflicts_chain_cmp_cb);
     102           0 :                 selected = chain;
     103             :         }
     104             : 
     105           0 :         pkg_debug(2, "select %s in the chain of conflicts for %s",
     106           0 :             selected->req->item->pkg->name, req->name);
     107             :         /* Disable conflicts from a request */
     108           0 :         LL_FOREACH(chain, elt) {
     109           0 :                 if (elt != selected)
     110           0 :                         elt->req->skip = true;
     111             :         }
     112             : 
     113           0 :         return (EPKG_OK);
     114             : }
     115             : 
     116             : static void
     117           0 : pkg_conflicts_request_add_chain(struct pkg_conflict_chain **chain, struct pkg_job_request *req)
     118             : {
     119             :         struct pkg_conflict_chain *elt;
     120             : 
     121           0 :         elt = calloc(1, sizeof(struct pkg_conflict_chain));
     122           0 :         if (elt == NULL) {
     123           0 :                 pkg_emit_errno("resolve_request_conflicts", "calloc: struct pkg_conflict_chain");
     124             :         }
     125           0 :         elt->req = req;
     126           0 :         LL_PREPEND(*chain, elt);
     127           0 : }
     128             : 
     129             : int
     130          11 : pkg_conflicts_request_resolve(struct pkg_jobs *j)
     131             : {
     132             :         struct pkg_job_request *req, *rtmp, *found;
     133             :         struct pkg_conflict *c, *ctmp;
     134             :         struct pkg_conflict_chain *chain;
     135             :         struct pkg_job_universe_item *unit;
     136             : 
     137          30 :         HASH_ITER(hh, j->request_add, req, rtmp) {
     138          19 :                 chain = NULL;
     139          19 :                 if (req->skip)
     140           0 :                         continue;
     141             : 
     142          20 :                 HASH_ITER(hh, req->item->pkg->conflicts, c, ctmp) {
     143           1 :                         unit = pkg_jobs_universe_find(j->universe, c->uid);
     144           1 :                         if (unit != NULL) {
     145           1 :                                 HASH_FIND_STR(j->request_add, unit->pkg->uid, found);
     146           1 :                                 if (found && !found->skip) {
     147           0 :                                         pkg_conflicts_request_add_chain(&chain, found);
     148             :                                 }
     149             :                         }
     150             :                 }
     151          19 :                 if (chain != NULL) {
     152             :                         /* Add package itself */
     153           0 :                         pkg_conflicts_request_add_chain(&chain, req);
     154             : 
     155           0 :                         if (pkg_conflicts_request_resolve_chain(req->item->pkg, chain) != EPKG_OK) {
     156           0 :                                 LL_FREE(chain, free);
     157           0 :                                 return (EPKG_FATAL);
     158             :                         }
     159           0 :                         LL_FREE(chain, free);
     160             :                 }
     161             :         }
     162             : 
     163          11 :         return (EPKG_OK);
     164             : }
     165             : 
     166             : void
     167           0 : pkg_conflicts_register(struct pkg *p1, struct pkg *p2, enum pkg_conflict_type type)
     168             : {
     169             :         struct pkg_conflict *c1, *c2, *test;
     170             : 
     171           0 :         pkg_conflict_new(&c1);
     172           0 :         pkg_conflict_new(&c2);
     173           0 :         if (c1 != NULL && c2 != NULL) {
     174           0 :                 c1->type = c2->type = type;
     175           0 :                 HASH_FIND_STR(p1->conflicts, p2->uid, test);
     176           0 :                 if (test == NULL) {
     177           0 :                         c1->uid = strdup(p2->uid);
     178           0 :                         HASH_ADD_KEYPTR(hh, p1->conflicts, c1->uid, strlen(c1->uid), c1);
     179           0 :                         pkg_debug(2, "registering conflict between %s(%s) and %s(%s)",
     180           0 :                                         p1->uid, p1->type == PKG_INSTALLED ? "l" : "r",
     181           0 :                                         p2->uid, p2->type == PKG_INSTALLED ? "l" : "r");
     182             :                 }
     183             : 
     184           0 :                 HASH_FIND_STR(p2->conflicts, p1->uid, test);
     185           0 :                 if (test == NULL) {
     186           0 :                         c1->uid = strdup(p1->uid);
     187           0 :                         HASH_ADD_KEYPTR(hh, p2->conflicts, c2->uid, strlen(c2->uid), c2);
     188           0 :                         pkg_debug(2, "registering conflict between %s(%s) and %s(%s)",
     189           0 :                                         p2->uid, p2->type == PKG_INSTALLED ? "l" : "r",
     190           0 :                                         p1->uid, p1->type == PKG_INSTALLED ? "l" : "r");
     191             :                 }
     192             :         }
     193           0 : }
     194             : 
     195             : 
     196             : 
     197             : static int
     198          95 : pkg_conflicts_item_cmp(struct pkg_jobs_conflict_item *a,
     199             :         struct pkg_jobs_conflict_item *b)
     200             : {
     201          95 :         return (b->hash - a->hash);
     202             : }
     203             : 
     204             : /*
     205             :  * Checks whether we need to add a conflict between two packages
     206             :  */
     207             : static bool
     208           6 : pkg_conflicts_need_conflict(struct pkg_jobs *j, struct pkg *p1, struct pkg *p2)
     209             : {
     210             :         struct pkg_file *fcur;
     211             :         struct pkg_conflict *c1, *c2;
     212             : 
     213          12 :         if (pkgdb_ensure_loaded(j->db, p1, PKG_LOAD_FILES|PKG_LOAD_DIRS) != EPKG_OK ||
     214           6 :                         pkgdb_ensure_loaded(j->db, p2, PKG_LOAD_FILES|PKG_LOAD_DIRS)
     215             :                                                 != EPKG_OK) {
     216             :                 /*
     217             :                  * If some of packages are not loaded we could silently and safely
     218             :                  * ignore them
     219             :                  */
     220           0 :                 pkg_debug(1, "cannot load files from %s and %s to check conflicts",
     221             :                         p1->name, p2->name);
     222             : 
     223           0 :                 return (false);
     224             :         }
     225             : 
     226             :         /*
     227             :          * Check if we already have this conflict registered
     228             :          */
     229           6 :         HASH_FIND_STR(p1->conflicts, p2->uid, c1);
     230           6 :         HASH_FIND_STR(p2->conflicts, p1->uid, c2);
     231           6 :         if (c1 != NULL && c2 != NULL)
     232           0 :                 return false;
     233             : 
     234             :         /*
     235             :          * We need to check all files and dirs and find the similar ones
     236             :          */
     237           6 :         kh_each_value(p1->files, fcur, {
     238             :                 if (pkg_has_file(p2, fcur->path))
     239             :                         return (true);
     240             :                 if (pkg_has_dir(p2, fcur->path))
     241             :                         return (true);
     242             :         });
     243             :         /* XXX pkg dirs are terribly broken */
     244             : 
     245             :         /* No common paths are found in p1 and p2 */
     246           2 :         return (false);
     247             : }
     248             : 
     249             : /*
     250             :  * Just insert new conflicts items to the packages
     251             :  */
     252             : static void
     253           4 : pkg_conflicts_register_unsafe(struct pkg *p1, struct pkg *p2,
     254             :         const char *path,
     255             :         enum pkg_conflict_type type,
     256             :         bool use_digest)
     257             : {
     258             :         struct pkg_conflict *c1, *c2;
     259             : 
     260           4 :         HASH_FIND_STR(p1->conflicts, p2->uid, c1);
     261           4 :         HASH_FIND_STR(p2->conflicts, p1->uid, c2);
     262             : 
     263           4 :         if (c1 == NULL) {
     264           4 :                 pkg_conflict_new(&c1);
     265           4 :                 c1->type = type;
     266           4 :                 c1->uid = strdup(p2->uid);
     267             : 
     268           4 :                 if (use_digest) {
     269           4 :                         c1->digest = strdup(p2->digest);
     270             :                 }
     271             : 
     272           4 :                 HASH_ADD_KEYPTR(hh, p1->conflicts, c1->uid, strlen(c1->uid), c1);
     273             :         }
     274             : 
     275           4 :         if (c2 == NULL) {
     276           4 :                 pkg_conflict_new(&c2);
     277           4 :                 c2->type = type;
     278             : 
     279           4 :                 c2->uid = strdup(p1->uid);
     280             : 
     281           4 :                 if (use_digest) {
     282             :                         /* We also add digest information into account */
     283             : 
     284           4 :                         c2->digest = strdup(p1->digest);
     285             :                 }
     286             : 
     287           4 :                 HASH_ADD_KEYPTR(hh, p2->conflicts, c2->uid, strlen(c2->uid), c2);
     288             :         }
     289             : 
     290           8 :         pkg_debug(2, "registering conflict between %s(%s) and %s(%s) on path %s",
     291           4 :                         p1->uid, p1->type == PKG_INSTALLED ? "l" : "r",
     292           4 :                         p2->uid, p2->type == PKG_INSTALLED ? "l" : "r", path);
     293           4 : }
     294             : 
     295             : /*
     296             :  * Register conflicts between packages in the universe chains
     297             :  */
     298             : static bool
     299           4 : pkg_conflicts_register_chain(struct pkg_jobs *j, struct pkg_job_universe_item *u1,
     300             :         struct pkg_job_universe_item *u2, const char *path)
     301             : {
     302             :         struct pkg_job_universe_item *cur1, *cur2;
     303           4 :         bool ret = false;
     304             : 
     305           4 :         cur1 = u1;
     306             : 
     307             :         do {
     308             : 
     309           4 :                 cur2 = u2;
     310             :                 do {
     311           6 :                         struct pkg *p1 = cur1->pkg, *p2 = cur2->pkg;
     312             : 
     313           6 :                         if (p1->type == PKG_INSTALLED && p2->type == PKG_INSTALLED) {
     314             :                                 /* Local and local packages cannot conflict */
     315           0 :                                 cur2 = cur2->prev;
     316           0 :                                 continue;
     317             :                         }
     318           6 :                         else if (p1->type == PKG_INSTALLED || p2->type == PKG_INSTALLED) {
     319             :                                 /* local <-> remote conflict */
     320           8 :                                 if (pkg_conflicts_need_conflict(j, p1, p2)) {
     321           4 :                                         pkg_conflicts_register_unsafe(p1, p2, path,
     322             :                                                 PKG_CONFLICT_REMOTE_LOCAL, true);
     323           4 :                                         j->conflicts_registered ++;
     324           4 :                                         ret = true;
     325             :                                 }
     326             :                         }
     327             :                         else {
     328             :                                 /* two remote packages */
     329           2 :                                 if (pkg_conflicts_need_conflict(j, p1, p2)) {
     330           0 :                                         pkg_conflicts_register_unsafe(p1, p2, path,
     331             :                                                 PKG_CONFLICT_REMOTE_REMOTE, true);
     332           0 :                                         j->conflicts_registered ++;
     333           0 :                                         ret = true;
     334             :                                 }
     335             :                         }
     336           6 :                         cur2 = cur2->prev;
     337           6 :                 } while (cur2 != u2);
     338             : 
     339           4 :                 cur1 = cur1->prev;
     340           4 :         } while (cur1 != u1);
     341             : 
     342           4 :         return (ret);
     343             : }
     344             : 
     345             : /*
     346             :  * Check whether the specified path is registered locally and returns
     347             :  * the package that contains that path or NULL if no conflict was found
     348             :  */
     349             : static struct pkg *
     350          17 : pkg_conflicts_check_local_path(const char *path, const char *uid,
     351             :         struct pkg_jobs *j)
     352             : {
     353          17 :         const char sql_local_conflict[] = ""
     354             :                 "SELECT p.name as uniqueid FROM packages AS p "
     355             :                 "INNER JOIN files AS f "
     356             :                 "ON p.id = f.package_id "
     357             :                 "WHERE f.path = ?1;";
     358             :         sqlite3_stmt *stmt;
     359             :         int ret;
     360          17 :         struct pkg *p = NULL;
     361             :         struct pkg_conflict *c;
     362             : 
     363          17 :         pkg_debug(4, "Pkgdb: running '%s'", sql_local_conflict);
     364          17 :         ret = sqlite3_prepare_v2(j->db->sqlite, sql_local_conflict, -1,
     365             :                 &stmt, NULL);
     366          17 :         if (ret != SQLITE_OK) {
     367           0 :                 ERROR_SQLITE(j->db->sqlite, sql_local_conflict);
     368           0 :                 return (NULL);
     369             :         }
     370             : 
     371          17 :         sqlite3_bind_text(stmt, 1,
     372             :                 path, -1, SQLITE_STATIC);
     373          17 :         sqlite3_bind_text(stmt, 2,
     374             :                 uid, -1, SQLITE_STATIC);
     375             : 
     376          17 :         if (sqlite3_step(stmt) == SQLITE_ROW) {
     377             :                 /*
     378             :                  * We have found the conflict with some other chain, so find that chain
     379             :                  * or update the universe
     380             :                  */
     381           8 :                 const char *uid_local = sqlite3_column_text(stmt, 0);
     382             : 
     383           8 :                 p = pkg_jobs_universe_get_local(j->universe,
     384             :                         uid_local, 0);
     385           8 :                 assert(p != NULL);
     386             : 
     387           8 :                 assert(strcmp(uid, p->uid) != 0);
     388             : 
     389           8 :                 HASH_FIND_STR(p->conflicts, uid, c);
     390           8 :                 if (c == NULL) {
     391             :                         /* We need to register the conflict between two universe chains */
     392           4 :                         sqlite3_finalize(stmt);
     393           4 :                         return (p);
     394             :                 }
     395             :         }
     396             : 
     397          13 :         sqlite3_finalize(stmt);
     398          13 :         return (NULL);
     399             : }
     400             : 
     401             : static struct pkg_job_universe_item *
     402          31 : pkg_conflicts_check_all_paths(struct pkg_jobs *j, const char *path,
     403             :         struct pkg_job_universe_item *it, struct sipkey *k)
     404             : {
     405             :         const char *uid1, *uid2;
     406             :         struct pkg_jobs_conflict_item *cit, test;
     407             :         struct pkg_conflict *c;
     408             :         uint64_t hv;
     409             : 
     410          31 :         hv = siphash24(path, strlen(path), k);
     411          31 :         test.hash = hv;
     412          31 :         cit = TREE_FIND(j->conflict_items, pkg_jobs_conflict_item, entry, &test);
     413             : 
     414          31 :         if (cit == NULL) {
     415             :                 /* New entry */
     416          24 :                 cit = calloc(1, sizeof(*cit));
     417          24 :                 if (cit == NULL) {
     418           0 :                         pkg_emit_errno("malloc failed", "pkg_conflicts_check_all_paths");
     419             :                 }
     420             :                 else {
     421          24 :                         cit->hash = hv;
     422          24 :                         cit->item = it;
     423          24 :                         TREE_INSERT(j->conflict_items, pkg_jobs_conflict_item, entry, cit);
     424             :                 }
     425             :         }
     426             :         else {
     427             :                 /* Check the same package */
     428           7 :                 if (cit->item == it)
     429           7 :                         return (NULL);
     430             : 
     431           0 :                 uid1 = it->pkg->uid;
     432           0 :                 uid2 = cit->item->pkg->uid;
     433           0 :                 if (strcmp(uid1, uid2) == 0) {
     434             :                         /* The same upgrade chain, just upgrade item for speed */
     435           0 :                         cit->item = it;
     436           0 :                         return (NULL);
     437             :                 }
     438             : 
     439             :                 /* Here we can have either collision or a real conflict */
     440           0 :                 HASH_FIND_STR(it->pkg->conflicts, uid2, c);
     441           0 :                 if (c != NULL || !pkg_conflicts_register_chain(j, it, cit->item, path)) {
     442             :                         /*
     443             :                          * Collision found, change the key following the
     444             :                          * Cuckoo principle
     445             :                          */
     446             :                         struct sipkey nk;
     447             : 
     448           0 :                         pkg_debug(2, "found a collision on path %s between %s and %s, key: %lu",
     449             :                                 path, uid1, uid2, (unsigned long)k->k[0]);
     450             : 
     451           0 :                         nk = *k;
     452           0 :                         nk.k[0] ++;
     453           0 :                         return (pkg_conflicts_check_all_paths(j, path, it, &nk));
     454             :                 }
     455             : 
     456           0 :                 return (cit->item);
     457             :         }
     458             : 
     459          24 :         return (NULL);
     460             : }
     461             : 
     462             : static void
     463          35 : pkg_conflicts_check_chain_conflict(struct pkg_job_universe_item *it,
     464             :         struct pkg_job_universe_item *local, struct pkg_jobs *j)
     465             : {
     466             :         struct pkg_file *fcur;
     467             :         struct pkg *p;
     468             :         struct pkg_job_universe_item *cun;
     469             :         struct sipkey *k;
     470             : 
     471          35 :         kh_each_value(it->pkg->files, fcur, {
     472             :                 k = pkg_conflicts_sipkey_init();
     473             :                 /* Check in hash tree */
     474             :                 cun = pkg_conflicts_check_all_paths(j, fcur->path, it, k);
     475             : 
     476             :                 if (local != NULL) {
     477             :                         /* Filter only new files for remote packages */
     478             :                         if (pkg_has_file(local->pkg, fcur->path))
     479             :                                 continue;
     480             :                 }
     481             :                 /* Check for local conflict in db */
     482             :                 p = pkg_conflicts_check_local_path(fcur->path, it->pkg->uid, j);
     483             :                 pkg_debug(4, "integrity: check path %s of package %s", fcur->path,
     484             :                         it->pkg->uid);
     485             : 
     486             :                 if (p != NULL) {
     487             :                         pkg_jobs_universe_process_item(j->universe, p, &cun);
     488             :                         assert(cun != NULL);
     489             :                         pkg_conflicts_register_chain(j, it, cun, fcur->path);
     490             :                 }
     491             :         });
     492             :         /* XXX: dirs are currently broken terribly */
     493             : #if 0
     494             :         struct pkg_dir *dcur, *dtmp, *df;
     495             :         HASH_ITER(hh, it->pkg->dirs, dcur, dtmp) {
     496             :                 memset(&k, 0, sizeof(k));
     497             :                 cun = pkg_conflicts_check_all_paths(j, dcur->path, it, &k);
     498             : 
     499             :                 if (local != NULL) {
     500             :                         HASH_FIND_STR(local->pkg->dirs, dcur->path, df);
     501             :                         if (df != NULL)
     502             :                                 continue;
     503             :                 }
     504             :                 /* Check for local conflict in db */
     505             :                 p = pkg_conflicts_check_local_path(dcur->path, uid, j);
     506             :                 if (p != NULL) {
     507             :                         pkg_jobs_universe_process_item(j->universe, p, &cun);
     508             :                         assert(cun != NULL);
     509             :                         pkg_conflicts_register_chain(j, it, cun, dcur->path);
     510             :                 }
     511             :         }
     512             : #endif
     513          35 : }
     514             : 
     515             : int
     516          35 : pkg_conflicts_append_chain(struct pkg_job_universe_item *it,
     517             :         struct pkg_jobs *j)
     518             : {
     519          35 :         struct pkg_job_universe_item *lp = NULL, *cur;
     520             : 
     521             :         /* Ensure that we have a tree initialized */
     522          35 :         if (j->conflict_items == NULL) {
     523           8 :                 j->conflict_items = malloc(sizeof(*j->conflict_items));
     524           8 :                 TREE_INIT(j->conflict_items, pkg_conflicts_item_cmp);
     525             :         }
     526             : 
     527             :         /* Find local package */
     528          35 :         cur = it->prev;
     529          70 :         while (cur != it) {
     530          16 :                 if (cur->pkg->type == PKG_INSTALLED) {
     531          16 :                         lp = cur;
     532          16 :                         if (pkgdb_ensure_loaded(j->db, cur->pkg, PKG_LOAD_FILES|PKG_LOAD_DIRS)
     533             :                                                         != EPKG_OK)
     534           0 :                                 return (EPKG_FATAL);
     535             : 
     536             :                         /* Local package is found */
     537          16 :                         break;
     538             :                 }
     539           0 :                 cur = cur->prev;
     540             :         }
     541             : 
     542             :         /*
     543             :          * Now we go through the all packages in the chain and check them against
     544             :          * conflicts with the locally installed files
     545             :          */
     546          35 :         cur = it;
     547             :         do {
     548          51 :                 if (cur != lp) {
     549          35 :                         if (pkgdb_ensure_loaded(j->db, cur->pkg, PKG_LOAD_FILES|PKG_LOAD_DIRS)
     550             :                                                         != EPKG_OK) {
     551             :                                 /*
     552             :                                  * This means that a package was not downloaded, so we can safely
     553             :                                  * ignore this conflict, since we are not going to install it
     554             :                                  * anyway
     555             :                                  */
     556           0 :                                 pkg_debug (3, "cannot load files from %s to check integrity",
     557           0 :                                         cur->pkg->name);
     558             :                         }
     559             :                         else {
     560          35 :                                 pkg_conflicts_check_chain_conflict(cur, lp, j);
     561             :                         }
     562             :                 }
     563             : 
     564          51 :                 cur = cur->prev;
     565          51 :         } while (cur != it);
     566             : 
     567          35 :         return (EPKG_OK);
     568             : }

Generated by: LCOV version 1.10