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 : }
|