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