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