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