Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/pkg.c
2065 views
1
/*-
2
* Copyright (c) 2011-2025 Baptiste Daroussin <[email protected]>
3
* Copyright (c) 2011-2012 Julien Laffaye <[email protected]>
4
* Copyright (c) 2012 Bryan Drewery <[email protected]>
5
* Copyright (c) 2013 Matthew Seaman <[email protected]>
6
* Copyright (c) 2017 Vsevolod Stakhov <[email protected]>
7
* Copyright (c) 2023, Serenity Cyber Security, LLC
8
* Author: Gleb Popov <[email protected]>
9
*
10
* SPDX-License-Identifier: BSD-2-Clause
11
*/
12
13
#include <archive.h>
14
#include <archive_entry.h>
15
#include <assert.h>
16
#include <errno.h>
17
#include <fcntl.h>
18
#include <string.h>
19
20
#include "pkg.h"
21
#include "private/event.h"
22
#include "private/pkg.h"
23
#include "private/pkgdb.h"
24
#include "private/utils.h"
25
#include "xmalloc.h"
26
27
#define dbg(x, ...) pkg_dbg(PKG_DBG_PACKAGE, x, __VA_ARGS__)
28
29
int
30
pkg_new(struct pkg **pkg, pkg_t type)
31
{
32
*pkg = xcalloc(1, sizeof(struct pkg));
33
(*pkg)->type = type;
34
(*pkg)->rootfd = -1;
35
(*pkg)->list_sorted = false;
36
37
return (EPKG_OK);
38
}
39
40
static void
41
pkg_message_free(struct pkg_message *m)
42
{
43
free(m->str);
44
free(m->maximum_version);
45
free(m->minimum_version);
46
free(m);
47
}
48
49
void
50
pkg_free(struct pkg *pkg)
51
{
52
if (pkg == NULL)
53
return;
54
55
free(pkg->name);
56
free(pkg->origin);
57
free(pkg->old_version);
58
free(pkg->version);
59
free(pkg->maintainer);
60
free(pkg->www);
61
free(pkg->altabi);
62
free(pkg->abi);
63
free(pkg->uid);
64
free(pkg->digest);
65
free(pkg->old_digest);
66
free(pkg->prefix);
67
free(pkg->oprefix);
68
free(pkg->comment);
69
free(pkg->desc);
70
free(pkg->sum);
71
free(pkg->repopath);
72
free(pkg->reponame);
73
free(pkg->repourl);
74
free(pkg->reason);
75
free(pkg->dep_formula);
76
77
for (int i = 0; i < PKG_NUM_SCRIPTS; i++)
78
xstring_free(pkg->scripts[i]);
79
for (int i = 0; i < PKG_NUM_LUA_SCRIPTS; i++)
80
vec_free_and_free(&pkg->lua_scripts[i], free);
81
82
pkg_list_free(pkg, PKG_DEPS);
83
pkg_list_free(pkg, PKG_RDEPS);
84
pkg_list_free(pkg, PKG_FILES);
85
pkg_list_free(pkg, PKG_DIRS);
86
pkg_list_free(pkg, PKG_OPTIONS);
87
pkg_list_free(pkg, PKG_CONFIG_FILES);
88
89
vec_free_and_free(&pkg->users, free);
90
pkg->flags &= ~PKG_LOAD_USERS;
91
vec_free_and_free(&pkg->groups, free);
92
pkg->flags &= ~PKG_LOAD_GROUPS;
93
vec_free_and_free(&pkg->shlibs_required, free);
94
pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
95
vec_free_and_free(&pkg->shlibs_provided, free);
96
pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
97
vec_free_and_free(&pkg->provides, free);
98
pkg->flags &= ~PKG_LOAD_PROVIDES;
99
vec_free_and_free(&pkg->requires, free);
100
pkg->flags &= ~PKG_LOAD_REQUIRES;
101
vec_free_and_free(&pkg->categories, free);
102
pkg->flags &= ~PKG_LOAD_CATEGORIES;
103
vec_free_and_free(&pkg->licenses, free);
104
pkg->flags &= ~PKG_LOAD_LICENSES;
105
106
vec_free_and_free(&pkg->message, pkg_message_free);
107
vec_free_and_free(&pkg->annotations, pkg_kv_free);
108
109
vec_free_and_free(&pkg->dir_to_del, free);
110
111
if (pkg->rootfd != -1)
112
close(pkg->rootfd);
113
114
free(pkg);
115
}
116
117
pkg_t
118
pkg_type(const struct pkg * restrict pkg)
119
{
120
assert(pkg != NULL);
121
122
return (pkg->type);
123
}
124
125
int
126
pkg_is_valid(const struct pkg * restrict pkg)
127
{
128
if (pkg == NULL) {
129
pkg_emit_error("Invalid package: not allocated");
130
return (EPKG_FATAL);
131
}
132
133
if (pkg->origin == NULL) {
134
pkg_emit_error("Invalid package: object has missing property origin");
135
return (EPKG_FATAL);
136
}
137
138
if (pkg->name == NULL) {
139
pkg_emit_error("Invalid package: object has missing property name");
140
return (EPKG_FATAL);
141
}
142
143
if (pkg->comment == NULL) {
144
pkg_emit_error("Invalid package: object has missing property comment");
145
return (EPKG_FATAL);
146
}
147
148
if (pkg->version == NULL) {
149
pkg_emit_error("Invalid package: object has missing property version");
150
return (EPKG_FATAL);
151
}
152
153
if (pkg->desc == NULL) {
154
pkg_emit_error("Invalid package: object has missing property desc");
155
return (EPKG_FATAL);
156
}
157
158
if (pkg->maintainer == NULL) {
159
pkg_emit_error("Invalid package: object has missing property maintainer");
160
return (EPKG_FATAL);
161
}
162
163
if (pkg->www == NULL) {
164
pkg_emit_error("Invalid package: object has missing property www");
165
return (EPKG_FATAL);
166
}
167
168
if (pkg->prefix == NULL) {
169
pkg_emit_error("Invalid package: object has missing property prefix");
170
return (EPKG_FATAL);
171
}
172
173
return (EPKG_OK);
174
}
175
176
int
177
pkg_set_i(struct pkg *pkg, pkg_attr attr, int64_t val)
178
{
179
switch (attr) {
180
case PKG_ATTR_FLATSIZE:
181
pkg->flatsize = val;
182
break;
183
case PKG_ATTR_OLD_FLATSIZE:
184
pkg->old_flatsize = val;
185
break;
186
case PKG_ATTR_PKGSIZE:
187
pkg->pkgsize = val;
188
break;
189
case PKG_ATTR_TIME:
190
pkg->timestamp = val;
191
break;
192
default:
193
pkg_emit_error("%d does not accept int64_t values", attr);
194
return (EPKG_FATAL);
195
}
196
return (EPKG_OK);
197
}
198
199
int
200
pkg_set_b(struct pkg *pkg, pkg_attr attr, bool boolean)
201
{
202
switch (attr) {
203
case PKG_ATTR_AUTOMATIC:
204
pkg->automatic = boolean;
205
break;
206
case PKG_ATTR_LOCKED:
207
pkg->locked = boolean;
208
break;
209
case PKG_ATTR_VITAL:
210
pkg->vital = boolean;
211
break;
212
default:
213
pkg_emit_error("%d does not accept bool values", attr);
214
return (EPKG_FATAL);
215
}
216
return (EPKG_OK);
217
}
218
219
int
220
pkg_set_s(struct pkg *pkg, pkg_attr attr, const char *str)
221
{
222
char *endptr;
223
ucl_object_t *obj;
224
int64_t i;
225
226
switch (attr) {
227
case PKG_ATTR_NAME:
228
free(pkg->name);
229
pkg->name = xstrdup(str);
230
free(pkg->uid);
231
pkg->uid = xstrdup(str);
232
break;
233
case PKG_ATTR_ORIGIN:
234
free(pkg->origin);
235
pkg->origin = xstrdup(str);
236
break;
237
case PKG_ATTR_VERSION:
238
free(pkg->version);
239
pkg->version = xstrdup(str);
240
break;
241
case PKG_ATTR_DESC:
242
free(pkg->desc);
243
pkg->desc = xstrdup(str);
244
break;
245
case PKG_ATTR_COMMENT:
246
free(pkg->comment);
247
pkg->comment = xstrdup(str);
248
break;
249
case PKG_ATTR_MESSAGE:
250
vec_free_and_free(&pkg->message, pkg_message_free);
251
if (*str == '[') {
252
pkg_message_from_str(pkg, str, strlen(str));
253
} else {
254
obj = ucl_object_fromstring_common(str, strlen(str),
255
UCL_STRING_RAW|UCL_STRING_TRIM);
256
pkg_message_from_ucl(pkg, obj);
257
ucl_object_unref(obj);
258
}
259
break;
260
case PKG_ATTR_ARCH:
261
free(pkg->altabi);
262
pkg->altabi = xstrdup(str);
263
break;
264
case PKG_ATTR_ABI:
265
free(pkg->abi);
266
pkg->abi = xstrdup(str);
267
break;
268
case PKG_ATTR_MAINTAINER:
269
free(pkg->maintainer);
270
pkg->maintainer = xstrdup(str);
271
break;
272
case PKG_ATTR_WWW:
273
free(pkg->www);
274
pkg->www = xstrdup(str);
275
break;
276
case PKG_ATTR_PREFIX:
277
free(pkg->prefix);
278
pkg->prefix = xstrdup(str);
279
break;
280
case PKG_ATTR_REPOPATH:
281
free(pkg->repopath);
282
pkg->repopath = xstrdup(str);
283
break;
284
case PKG_ATTR_CKSUM:
285
free(pkg->sum);
286
pkg->sum = xstrdup(str);
287
break;
288
case PKG_ATTR_OLD_VERSION:
289
free(pkg->old_version);
290
pkg->old_version = xstrdup(str);
291
break;
292
case PKG_ATTR_REPONAME:
293
free(pkg->reponame);
294
pkg->reponame = xstrdup(str);
295
break;
296
case PKG_ATTR_REPOURL:
297
free(pkg->repourl);
298
pkg->repourl = xstrdup(str);
299
break;
300
case PKG_ATTR_DIGEST:
301
free(pkg->digest);
302
pkg->digest = xstrdup(str);
303
break;
304
case PKG_ATTR_REASON:
305
free(pkg->reason);
306
pkg->reason = xstrdup(str);
307
break;
308
case PKG_ATTR_DEP_FORMULA:
309
free(pkg->dep_formula);
310
pkg->dep_formula = xstrdup(str);
311
break;
312
case PKG_ATTR_FLATSIZE:
313
i = strtoimax(str, &endptr, 10);
314
if (endptr != NULL) {
315
pkg_emit_error("Impossible to convert '%s' to int64_t",
316
str);
317
return (EPKG_FATAL);
318
}
319
pkg->flatsize = i;
320
break;
321
case PKG_ATTR_OLD_FLATSIZE:
322
i = strtoimax(str, &endptr, 10);
323
if (endptr != NULL) {
324
pkg_emit_error("Impossible to convert '%s' to int64_t",
325
str);
326
return (EPKG_FATAL);
327
}
328
pkg->old_flatsize = i;
329
break;
330
case PKG_ATTR_PKGSIZE:
331
i = strtoimax(str, &endptr, 10);
332
if (endptr != NULL) {
333
pkg_emit_error("Impossible to convert '%s' to int64_t",
334
str);
335
return (EPKG_FATAL);
336
}
337
pkg->pkgsize = i;
338
break;
339
case PKG_ATTR_TIME:
340
i = strtoimax(str, &endptr, 10);
341
if (endptr != NULL) {
342
pkg_emit_error("Impossible to convert '%s' to int64_t",
343
str);
344
return (EPKG_FATAL);
345
}
346
pkg->timestamp = i;
347
break;
348
default:
349
pkg_emit_error("%d does not accept string values", attr);
350
return (EPKG_FATAL);
351
}
352
return (EPKG_OK);
353
}
354
355
int
356
pkg_set_from_fileat(int fd, struct pkg *pkg, pkg_attr attr, const char *path,
357
bool trimcr)
358
{
359
char *buf = NULL;
360
char *cp;
361
off_t size = 0;
362
int ret = EPKG_OK;
363
364
assert(pkg != NULL);
365
assert(path != NULL);
366
367
if ((ret = file_to_bufferat(fd, path, &buf, &size)) != EPKG_OK)
368
return (ret);
369
370
if (trimcr) {
371
cp = buf + strlen(buf) - 1;
372
while (cp > buf && *cp == '\n') {
373
*cp = 0;
374
cp--;
375
}
376
}
377
378
ret = pkg_set(pkg, attr, buf);
379
380
free(buf);
381
382
return (ret);
383
}
384
385
#define pkg_each(name, type, field) \
386
int \
387
pkg_##name(const struct pkg *p, type **t) { \
388
assert(p != NULL); \
389
if ((*t) == NULL) \
390
(*t) = p->field; \
391
else \
392
(*t) = (*t)->next; \
393
if ((*t) == NULL) \
394
return (EPKG_END); \
395
return (EPKG_OK); \
396
}
397
398
pkg_each(dirs, struct pkg_dir, dirs);
399
pkg_each(files, struct pkg_file, files);
400
pkg_each(deps, struct pkg_dep, depends);
401
pkg_each(rdeps, struct pkg_dep, rdepends);
402
pkg_each(options, struct pkg_option, options);
403
pkg_each(conflicts, struct pkg_conflict, conflicts);
404
pkg_each(config_files, struct pkg_config_file, config_files);
405
406
int
407
pkg_adduser(struct pkg *pkg, const char *name)
408
{
409
return (pkg_addstring(&pkg->users, name, "user"));
410
}
411
412
int
413
pkg_addgroup(struct pkg *pkg, const char *name)
414
{
415
return (pkg_addstring(&pkg->groups, name, "group"));
416
}
417
418
int
419
pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked)
420
{
421
if (pkg_adddep_chain(NULL, pkg, name, origin, version, locked) == NULL) {
422
return (EPKG_FATAL);
423
}
424
425
return (EPKG_OK);
426
}
427
428
struct pkg_dep *
429
pkg_adddep_chain(struct pkg_dep *chain,
430
struct pkg *pkg,
431
const char *name,
432
const char *origin,
433
const char *version, bool locked)
434
{
435
struct pkg_dep *d = NULL;
436
437
assert(pkg != NULL);
438
assert(name != NULL && name[0] != '\0');
439
440
dbg(3, "add a new dependency origin: %s, name: %s", origin ? origin : "", name);
441
if (pkghash_get(pkg->depshash, name) != NULL) {
442
pkg_emit_error("%s: duplicate dependency listing: %s",
443
pkg->name, name);
444
return (NULL);
445
}
446
447
d = xcalloc(1, sizeof(*d));
448
if (origin != NULL && origin[0] != '\0')
449
d->origin = xstrdup(origin);
450
d->name = xstrdup(name);
451
if (version != NULL && version[0] != '\0')
452
d->version = xstrdup(version);
453
d->uid = xstrdup(name);
454
d->locked = locked;
455
456
pkghash_safe_add(pkg->depshash, d->name, d, NULL);
457
if (chain == NULL) {
458
DL_APPEND(pkg->depends, d);
459
chain = pkg->depends;
460
}
461
else {
462
DL_APPEND2(chain, d, alt_prev, alt_next);
463
}
464
465
return (chain);
466
}
467
468
int
469
pkg_addrdep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked)
470
{
471
struct pkg_dep *d;
472
473
assert(pkg != NULL);
474
assert(name != NULL && name[0] != '\0');
475
476
dbg(3, "add a new reverse dependency origin: %s, name: %s", origin ? origin : "", name);
477
478
d = xcalloc(1, sizeof(*d));
479
if (origin != NULL && origin[0] != '\0')
480
d->origin = xstrdup(origin);
481
d->name = xstrdup(name);
482
if (version != NULL && version[0] != '\0')
483
d->version = xstrdup(version);
484
d->uid = xstrdup(name);
485
d->locked = locked;
486
487
pkghash_safe_add(pkg->rdepshash, d->name, d, NULL);
488
LL_PREPEND(pkg->rdepends, d);
489
490
return (EPKG_OK);
491
}
492
493
int
494
pkg_addfile(struct pkg *pkg, const char *path, const char *sum, bool check_duplicates)
495
{
496
return (pkg_addfile_attr(pkg, path, sum, NULL, NULL, 0, 0, check_duplicates));
497
}
498
499
int
500
pkg_addfile_attr(struct pkg *pkg, const char *path, const char *sum,
501
const char *uname, const char *gname, mode_t perm, u_long fflags,
502
bool check_duplicates)
503
{
504
struct pkg_file *f = NULL;
505
char abspath[MAXPATHLEN];
506
507
assert(pkg != NULL);
508
assert(path != NULL && path[0] != '\0');
509
510
path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
511
dbg(3, "add new file '%s'", path);
512
513
if (check_duplicates && pkghash_get(pkg->filehash, path) != NULL) {
514
if (ctx.developer_mode) {
515
pkg_emit_error("duplicate file listing: %s, fatal (developer mode)", path);
516
return (EPKG_FATAL);
517
} else {
518
pkg_emit_error("duplicate file listing: %s, ignoring", path);
519
return (EPKG_OK);
520
}
521
}
522
523
f = xcalloc(1, sizeof(*f));
524
strlcpy(f->path, path, sizeof(f->path));
525
526
if (sum != NULL)
527
f->sum = xstrdup(sum);
528
529
if (uname != NULL)
530
strlcpy(f->uname, uname, sizeof(f->uname));
531
532
if (gname != NULL)
533
strlcpy(f->gname, gname, sizeof(f->gname));
534
535
if (perm != 0)
536
f->perm = perm;
537
538
if (fflags != 0)
539
f->fflags = fflags;
540
541
pkghash_safe_add(pkg->filehash, f->path, f, NULL);
542
DL_APPEND(pkg->files, f);
543
544
return (EPKG_OK);
545
}
546
547
int
548
pkg_addconfig_file(struct pkg *pkg, const char *path, const char *content)
549
{
550
struct pkg_config_file *f = NULL;
551
char abspath[MAXPATHLEN];
552
553
path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
554
dbg(3, "add new config file '%s'", path);
555
556
if (pkghash_get(pkg->config_files_hash, path) != NULL) {
557
pkg_emit_error("duplicate file listing: %s", path);
558
return (EPKG_FATAL);
559
}
560
f = xcalloc(1, sizeof(*f));
561
strlcpy(f->path, path, sizeof(f->path));
562
563
if (content != NULL)
564
f->content = xstrdup(content);
565
566
pkghash_safe_add(pkg->config_files_hash, f->path, f, NULL);
567
DL_APPEND(pkg->config_files, f);
568
569
return (EPKG_OK);
570
}
571
572
int
573
pkg_addstring(charv_t *list, const char *val, const char *title)
574
{
575
assert(val != NULL);
576
assert(title != NULL);
577
578
char *tmp = xstrdup(val);
579
if (charv_insert_sorted(list, tmp) != NULL) {
580
free(tmp);
581
if (ctx.developer_mode) {
582
pkg_emit_error("duplicate %s listing: %s, fatal"
583
" (developer mode)", title, val);
584
return (EPKG_FATAL);
585
}
586
pkg_emit_error("duplicate %s listing: %s, "
587
"ignoring", title, val);
588
return (EPKG_OK);
589
}
590
591
return (EPKG_OK);
592
}
593
594
int
595
pkg_adddir(struct pkg *pkg, const char *path, bool check_duplicates)
596
{
597
return(pkg_adddir_attr(pkg, path, NULL, NULL, 0, 0, check_duplicates));
598
}
599
600
int
601
pkg_adddir_attr(struct pkg *pkg, const char *path, const char *uname,
602
const char *gname, mode_t perm, u_long fflags, bool check_duplicates)
603
{
604
struct pkg_dir *d = NULL;
605
char abspath[MAXPATHLEN];
606
607
assert(pkg != NULL);
608
assert(path != NULL && path[0] != '\0');
609
610
if (STREQ(path, "/")) {
611
pkg_emit_error("skipping useless directory: '%s'\n", path);
612
return (EPKG_OK);
613
}
614
path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
615
dbg(3, "add new directory '%s'", path);
616
if (check_duplicates && pkghash_get(pkg->dirhash, path) != NULL) {
617
if (ctx.developer_mode) {
618
pkg_emit_error("duplicate directory listing: %s, fatal (developer mode)", path);
619
return (EPKG_FATAL);
620
} else {
621
pkg_emit_error("duplicate directory listing: %s, ignoring", path);
622
return (EPKG_OK);
623
}
624
}
625
626
d = xcalloc(1, sizeof(*d));
627
strlcpy(d->path, path, sizeof(d->path));
628
629
if (uname != NULL)
630
strlcpy(d->uname, uname, sizeof(d->uname));
631
632
if (gname != NULL)
633
strlcpy(d->gname, gname, sizeof(d->gname));
634
635
if (perm != 0)
636
d->perm = perm;
637
638
if (fflags != 0)
639
d->fflags = fflags;
640
641
pkghash_safe_add(pkg->dirhash, d->path, d, NULL);
642
DL_APPEND(pkg->dirs, d);
643
644
return (EPKG_OK);
645
}
646
647
int
648
pkg_addscript(struct pkg *pkg, const char *data, pkg_script type)
649
{
650
651
assert(pkg != NULL);
652
xstring_renew(pkg->scripts[type]);
653
fprintf(pkg->scripts[type]->fp, "%s", data);
654
655
return (EPKG_OK);
656
}
657
658
int
659
pkg_add_lua_script(struct pkg *pkg, const char *data, pkg_lua_script type)
660
{
661
assert(pkg != NULL);
662
663
if (type >= PKG_LUA_UNKNOWN)
664
return (EPKG_FATAL);
665
666
vec_push(&pkg->lua_scripts[type], xstrdup(data));
667
668
return (EPKG_OK);
669
}
670
671
int
672
pkg_addluascript_fileat(int fd, struct pkg *pkg, const char *filename)
673
{
674
char *data;
675
pkg_lua_script type;
676
int ret = EPKG_OK;
677
off_t sz = 0;
678
679
assert(pkg != NULL);
680
assert(filename != NULL);
681
682
dbg(1, "Adding script from: '%s'", filename);
683
684
if ((ret = file_to_bufferat(fd, filename, &data, &sz)) != EPKG_OK)
685
return (ret);
686
687
if (STREQ(filename, "pkg-pre-install.lua")) {
688
type = PKG_LUA_PRE_INSTALL;
689
} else if (STREQ(filename, "pkg-post-install.lua")) {
690
type = PKG_LUA_POST_INSTALL;
691
} else if (STREQ(filename, "pkg-pre-deinstall.lua")) {
692
type = PKG_LUA_PRE_DEINSTALL;
693
} else if (STREQ(filename, "pkg-post-deinstall.lua")) {
694
type = PKG_LUA_POST_DEINSTALL;
695
} else {
696
pkg_emit_error("unknown lua script '%s'", filename);
697
ret = EPKG_FATAL;
698
goto cleanup;
699
}
700
701
ret = pkg_add_lua_script(pkg, data, type);
702
cleanup:
703
free(data);
704
return (ret);
705
}
706
707
int
708
pkg_addscript_fileat(int fd, struct pkg *pkg, const char *filename)
709
{
710
char *data;
711
pkg_script type;
712
int ret = EPKG_OK;
713
off_t sz = 0;
714
715
assert(pkg != NULL);
716
assert(filename != NULL);
717
718
dbg(1, "Adding script from: '%s'", filename);
719
720
if ((ret = file_to_bufferat(fd, filename, &data, &sz)) != EPKG_OK)
721
return (ret);
722
723
if (STREQ(filename, "pkg-pre-install") ||
724
STREQ(filename, "+PRE_INSTALL")) {
725
type = PKG_SCRIPT_PRE_INSTALL;
726
} else if (STREQ(filename, "pkg-post-install") ||
727
STREQ(filename, "+POST_INSTALL")) {
728
type = PKG_SCRIPT_POST_INSTALL;
729
} else if (STREQ(filename, "pkg-install") ||
730
STREQ(filename, "+INSTALL")) {
731
type = PKG_SCRIPT_INSTALL;
732
} else if (STREQ(filename, "pkg-pre-deinstall") ||
733
STREQ(filename, "+PRE_DEINSTALL")) {
734
type = PKG_SCRIPT_PRE_DEINSTALL;
735
} else if (STREQ(filename, "pkg-post-deinstall") ||
736
STREQ(filename, "+POST_DEINSTALL")) {
737
type = PKG_SCRIPT_POST_DEINSTALL;
738
} else if (STREQ(filename, "pkg-deinstall") ||
739
STREQ(filename, "+DEINSTALL")) {
740
type = PKG_SCRIPT_DEINSTALL;
741
} else {
742
pkg_emit_error("unknown script '%s'", filename);
743
ret = EPKG_FATAL;
744
goto cleanup;
745
}
746
747
ret = pkg_addscript(pkg, data, type);
748
cleanup:
749
free(data);
750
return (ret);
751
}
752
753
int
754
pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script type)
755
{
756
757
assert(pkg != NULL);
758
assert(cmd != NULL && cmd[0] != '\0');
759
760
if (pkg->scripts[type] == NULL)
761
pkg->scripts[type] = xstring_new();
762
763
fprintf(pkg->scripts[type]->fp, "%s", cmd);
764
765
return (EPKG_OK);
766
}
767
768
int
769
pkg_addoption(struct pkg *pkg, const char *key, const char *value)
770
{
771
struct pkg_option *o = NULL;
772
773
assert(pkg != NULL);
774
assert(key != NULL && key[0] != '\0');
775
assert(value != NULL && value[0] != '\0');
776
777
/* There might be a default or description for the option
778
already, so we only count it as a duplicate if the value
779
field is already set. Which implies there could be a
780
default value or description for an option but no actual
781
value. */
782
783
dbg(2,"adding options: %s = %s", key, value);
784
if (pkghash_get(pkg->optionshash, key) != NULL) {
785
if (ctx.developer_mode) {
786
pkg_emit_error("duplicate options listing: %s, fatal (developer mode)", key);
787
return (EPKG_FATAL);
788
} else {
789
pkg_emit_error("duplicate options listing: %s, ignoring", key);
790
return (EPKG_OK);
791
}
792
}
793
o = xcalloc(1, sizeof(*o));
794
o->key = xstrdup(key);
795
o->value = xstrdup(value);
796
pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
797
DL_APPEND(pkg->options, o);
798
799
return (EPKG_OK);
800
}
801
802
int
803
pkg_addoption_default(struct pkg *pkg, const char *key,
804
const char *default_value)
805
{
806
struct pkg_option *o = NULL;
807
808
assert(pkg != NULL);
809
assert(key != NULL && key[0] != '\0');
810
assert(default_value != NULL && default_value[0] != '\0');
811
812
/* There might be a value or description for the option
813
already, so we only count it as a duplicate if the
814
default_value field is already set. Which implies there
815
could be a default value or description for an option but
816
no actual value. */
817
818
if (pkghash_get(pkg->optionshash, key) != NULL) {
819
if (ctx.developer_mode) {
820
pkg_emit_error("duplicate default value for option: %s, fatal (developer mode)", key);
821
return (EPKG_FATAL);
822
} else {
823
pkg_emit_error("duplicate default value for option: %s, ignoring", key);
824
return (EPKG_OK);
825
}
826
}
827
o = xcalloc(1, sizeof(*o));
828
o->key = xstrdup(key);
829
o->default_value = xstrdup(default_value);
830
pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
831
DL_APPEND(pkg->options, o);
832
833
return (EPKG_OK);
834
}
835
836
int
837
pkg_addoption_description(struct pkg *pkg, const char *key,
838
const char *description)
839
{
840
struct pkg_option *o = NULL;
841
842
assert(pkg != NULL);
843
assert(key != NULL && key[0] != '\0');
844
assert(description != NULL && description[0] != '\0');
845
846
/* There might be a value or default for the option already,
847
so we only count it as a duplicate if the description field
848
is already set. Which implies there could be a default
849
value or description for an option but no actual value. */
850
851
if (pkghash_get(pkg->optionshash, key) != NULL) {
852
if (ctx.developer_mode) {
853
pkg_emit_error("duplicate description for option: %s, fatal (developer mode)", key);
854
return (EPKG_FATAL);
855
} else {
856
pkg_emit_error("duplicate description for option: %s, ignoring", key);
857
return (EPKG_OK);
858
}
859
}
860
861
o = xcalloc(1, sizeof(*o));
862
o->key = xstrdup(key);
863
o->description = xstrdup(description);
864
pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
865
DL_APPEND(pkg->options, o);
866
867
return (EPKG_OK);
868
}
869
870
enum pkg_shlib_flags
871
pkg_shlib_flags_from_abi(const struct pkg_abi *shlib_abi)
872
{
873
enum pkg_shlib_flags flags = PKG_SHLIB_FLAGS_NONE;
874
875
if (ctx.abi.os == PKG_OS_FREEBSD) {
876
if (shlib_abi->os == PKG_OS_LINUX && ctx.track_linux_compat_shlibs)
877
flags |= PKG_SHLIB_FLAGS_COMPAT_LINUX;
878
879
switch (ctx.abi.arch) {
880
case PKG_ARCH_AMD64:
881
if (shlib_abi->arch == PKG_ARCH_I386) {
882
flags |= PKG_SHLIB_FLAGS_COMPAT_32;
883
}
884
break;
885
case PKG_ARCH_AARCH64:
886
if (shlib_abi->arch == PKG_ARCH_ARMV7) {
887
flags |= PKG_SHLIB_FLAGS_COMPAT_32;
888
}
889
break;
890
case PKG_ARCH_POWERPC64:
891
if (shlib_abi->arch == PKG_ARCH_POWERPC) {
892
flags |= PKG_SHLIB_FLAGS_COMPAT_32;
893
}
894
break;
895
}
896
}
897
898
return (flags);
899
}
900
901
/*
902
* Format examples:
903
*
904
* libfoo.so.1.0.0 - native
905
* libfoo.so.1.0.0:32 - compat 32
906
* libfoo.so.1.0.0:Linux - compat Linux
907
* libfoo.so.1.0.0:Linux:32 - compat Linux 32
908
*/
909
char *
910
pkg_shlib_name_with_flags(const char *name, enum pkg_shlib_flags flags)
911
{
912
const char *compat_os = "";
913
if ((flags & PKG_SHLIB_FLAGS_COMPAT_LINUX) != 0) {
914
compat_os = ":Linux";
915
}
916
917
const char *compat_arch = "";
918
if ((flags & PKG_SHLIB_FLAGS_COMPAT_32) != 0) {
919
compat_arch = ":32";
920
}
921
922
char *ret;
923
xasprintf(&ret, "%s%s%s", name, compat_os, compat_arch);
924
return (ret);
925
}
926
927
int
928
pkg_addshlib_required(struct pkg *pkg, const char *name,
929
enum pkg_shlib_flags flags)
930
{
931
assert(pkg != NULL);
932
assert(name != NULL && name[0] != '\0');
933
934
char *full_name = pkg_shlib_name_with_flags(name, flags);
935
936
/* silently ignore duplicates in case of shlibs */
937
if (charv_insert_sorted(&pkg->shlibs_required, full_name) != NULL) {
938
free(full_name);
939
return (EPKG_OK);
940
}
941
942
dbg(3, "added shlib deps for %s on %s", pkg->name, full_name);
943
944
return (EPKG_OK);
945
}
946
947
int
948
pkg_addshlib_provided(struct pkg *pkg, const char *name,
949
enum pkg_shlib_flags flags)
950
{
951
assert(pkg != NULL);
952
assert(name != NULL && name[0] != '\0');
953
954
char *full_name = pkg_shlib_name_with_flags(name, flags);
955
956
/* silently ignore duplicates in case of shlibs */
957
if (charv_insert_sorted(&pkg->shlibs_provided, full_name) != NULL) {
958
free(full_name);
959
return (EPKG_OK);
960
}
961
962
dbg(3, "added shlib provide %s for %s", full_name, pkg->name);
963
964
return (EPKG_OK);
965
}
966
967
int
968
pkg_addconflict(struct pkg *pkg, const char *uniqueid)
969
{
970
struct pkg_conflict *c = NULL;
971
972
assert(pkg != NULL);
973
assert(uniqueid != NULL && uniqueid[0] != '\0');
974
975
if (pkghash_get(pkg->conflictshash, uniqueid) != NULL) {
976
/* silently ignore duplicates in case of conflicts */
977
return (EPKG_OK);
978
}
979
980
c = xcalloc(1, sizeof(*c));
981
c->uid = xstrdup(uniqueid);
982
dbg(3, "add a new conflict origin: %s, with %s", pkg->uid, uniqueid);
983
984
pkghash_safe_add(pkg->conflictshash, c->uid, c, NULL);
985
DL_APPEND(pkg->conflicts, c);
986
987
return (EPKG_OK);
988
}
989
990
int
991
pkg_addrequire(struct pkg *pkg, const char *name)
992
{
993
assert(pkg != NULL);
994
assert(name != NULL && name[0] != '\0');
995
996
char *tmp = xstrdup(name);
997
998
if (charv_insert_sorted(&pkg->requires, tmp) != NULL) {
999
/* silently ignore duplicates in case of conflicts */
1000
free(tmp);
1001
return (EPKG_OK);
1002
}
1003
1004
return (EPKG_OK);
1005
}
1006
1007
int
1008
pkg_addprovide(struct pkg *pkg, const char *name)
1009
{
1010
assert(pkg != NULL);
1011
assert(name != NULL && name[0] != '\0');
1012
1013
char *tmp = xstrdup(name);
1014
1015
if (charv_insert_sorted(&pkg->provides, tmp) != NULL) {
1016
/* silently ignore duplicates in case of conflicts */
1017
free(tmp);
1018
return (EPKG_OK);
1019
}
1020
1021
return (EPKG_OK);
1022
}
1023
1024
const char *
1025
pkg_kv_get(const kvlist_t *kv, const char *tag)
1026
{
1027
assert(tag != NULL);
1028
1029
vec_foreach(*kv, i) {
1030
if (STREQ(kv->d[i]->key, tag))
1031
return (kv->d[i]->value);
1032
}
1033
1034
return (NULL);
1035
}
1036
1037
int
1038
pkg_kv_add(kvlist_t *list, const char *key, const char *val, const char *title)
1039
{
1040
struct pkg_kv *kv;
1041
1042
assert(val != NULL);
1043
assert(title != NULL);
1044
1045
kv = pkg_kv_new(key, val);
1046
if (pkg_kv_insert_sorted(list, kv) != NULL) {
1047
pkg_kv_free(kv);
1048
if (ctx.developer_mode) {
1049
pkg_emit_error("duplicate %s: %s, fatal"
1050
" (developer mode)", title, key);
1051
return (EPKG_FATAL);
1052
}
1053
pkg_emit_error("duplicate %s: %s, "
1054
"ignoring", title, val);
1055
return (EPKG_OK);
1056
}
1057
1058
return (EPKG_OK);
1059
}
1060
1061
int
1062
pkg_list_count(const struct pkg *pkg, pkg_list list)
1063
{
1064
switch (list) {
1065
case PKG_DEPS:
1066
return (pkghash_count(pkg->depshash));
1067
case PKG_RDEPS:
1068
return (pkghash_count(pkg->rdepshash));
1069
case PKG_OPTIONS:
1070
return (pkghash_count(pkg->optionshash));
1071
case PKG_FILES:
1072
return (pkghash_count(pkg->filehash));
1073
case PKG_DIRS:
1074
return (pkghash_count(pkg->dirhash));
1075
case PKG_CONFLICTS:
1076
return (pkghash_count(pkg->conflictshash));
1077
case PKG_CONFIG_FILES:
1078
return (pkghash_count(pkg->config_files_hash));
1079
case PKG_USERS:
1080
return (vec_len(&pkg->users));
1081
case PKG_GROUPS:
1082
return (vec_len(&pkg->groups));
1083
case PKG_SHLIBS_REQUIRED:
1084
return (vec_len(&pkg->shlibs_required));
1085
case PKG_SHLIBS_PROVIDED:
1086
return (vec_len(&pkg->shlibs_provided));
1087
case PKG_REQUIRES:
1088
return (vec_len(&pkg->requires));
1089
case PKG_PROVIDES:
1090
return (vec_len(&pkg->provides));
1091
}
1092
1093
return (0);
1094
}
1095
1096
void
1097
pkg_list_free(struct pkg *pkg, pkg_list list) {
1098
struct pkg_dep *cur;
1099
1100
switch (list) {
1101
case PKG_DEPS:
1102
DL_FOREACH (pkg->depends, cur) {
1103
if (cur->alt_next) {
1104
DL_FREE2(cur->alt_next, pkg_dep_free, alt_prev, alt_next);
1105
}
1106
}
1107
DL_FREE(pkg->depends, pkg_dep_free);
1108
pkghash_destroy(pkg->depshash);
1109
pkg->depshash = NULL;
1110
pkg->flags &= ~PKG_LOAD_DEPS;
1111
break;
1112
case PKG_RDEPS:
1113
LL_FREE(pkg->rdepends, pkg_dep_free);
1114
pkghash_destroy(pkg->rdepshash);
1115
pkg->depshash = NULL;
1116
pkg->flags &= ~PKG_LOAD_RDEPS;
1117
break;
1118
case PKG_OPTIONS:
1119
DL_FREE(pkg->options, pkg_option_free);
1120
pkghash_destroy(pkg->optionshash);
1121
pkg->optionshash = NULL;
1122
pkg->flags &= ~PKG_LOAD_OPTIONS;
1123
break;
1124
case PKG_FILES:
1125
case PKG_CONFIG_FILES:
1126
DL_FREE(pkg->files, pkg_file_free);
1127
pkghash_destroy(pkg->filehash);
1128
pkg->filehash = NULL;
1129
DL_FREE(pkg->config_files, pkg_config_file_free);
1130
pkghash_destroy(pkg->config_files_hash);
1131
pkg->config_files_hash = NULL;
1132
pkg->flags &= ~PKG_LOAD_FILES;
1133
break;
1134
case PKG_DIRS:
1135
DL_FREE(pkg->dirs, free);
1136
pkghash_destroy(pkg->dirhash);
1137
pkg->dirhash = NULL;
1138
pkg->flags &= ~PKG_LOAD_DIRS;
1139
break;
1140
case PKG_CONFLICTS:
1141
DL_FREE(pkg->conflicts, pkg_conflict_free);
1142
pkghash_destroy(pkg->conflictshash);
1143
pkg->conflictshash = NULL;
1144
pkg->flags &= ~PKG_LOAD_CONFLICTS;
1145
break;
1146
}
1147
}
1148
1149
int
1150
pkg_open(struct pkg **pkg_p, const char *path, int flags)
1151
{
1152
struct archive *a;
1153
struct archive_entry *ae;
1154
int ret;
1155
1156
ret = pkg_open2(pkg_p, &a, &ae, path, flags, -1);
1157
1158
if (ret != EPKG_OK && ret != EPKG_END)
1159
return (EPKG_FATAL);
1160
1161
archive_read_close(a);
1162
archive_read_free(a);
1163
1164
return (EPKG_OK);
1165
}
1166
1167
int
1168
pkg_open_fd(struct pkg **pkg_p, int fd, int flags)
1169
{
1170
struct archive *a;
1171
struct archive_entry *ae;
1172
int ret;
1173
1174
ret = pkg_open2(pkg_p, &a, &ae, NULL, flags, fd);
1175
1176
if (ret != EPKG_OK && ret != EPKG_END)
1177
return (EPKG_FATAL);
1178
1179
archive_read_close(a);
1180
archive_read_free(a);
1181
1182
return (EPKG_OK);
1183
}
1184
1185
static int
1186
pkg_parse_archive(struct pkg *pkg, struct archive *a, size_t len)
1187
{
1188
void *buffer;
1189
int rc;
1190
1191
buffer = xmalloc(len);
1192
1193
archive_read_data(a, buffer, len);
1194
rc = pkg_parse_manifest(pkg, buffer, len);
1195
free(buffer);
1196
return (rc);
1197
}
1198
1199
int
1200
pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
1201
const char *path, int flags, int fd)
1202
{
1203
struct pkg *pkg = NULL;
1204
pkg_error_t retcode = EPKG_OK;
1205
int ret;
1206
const char *fpath;
1207
bool manifest = false;
1208
bool read_from_stdin = 0;
1209
1210
*a = archive_read_new();
1211
archive_read_support_filter_all(*a);
1212
archive_read_support_format_tar(*a);
1213
1214
/* archive_read_open_filename() treats a path of NULL as
1215
* meaning "read from stdin," but we want this behaviour if
1216
* path is exactly "-". In the unlikely event of wanting to
1217
* read an on-disk file called "-", just say "./-" or some
1218
* other leading path. */
1219
1220
if (fd == -1) {
1221
if (path == NULL) {
1222
pkg_emit_error("bad usage of pkg_open2");
1223
retcode = EPKG_FATAL;
1224
goto cleanup;
1225
}
1226
read_from_stdin = (strncmp(path, "-", 2) == 0);
1227
1228
if (archive_read_open_filename(*a,
1229
read_from_stdin ? NULL : path, 4096) != ARCHIVE_OK) {
1230
if ((flags & PKG_OPEN_TRY) == 0)
1231
pkg_emit_error("archive_read_open_filename(%s): %s", path,
1232
archive_error_string(*a));
1233
1234
retcode = EPKG_FATAL;
1235
goto cleanup;
1236
}
1237
} else {
1238
if (archive_read_open_fd(*a, fd, 4096) != ARCHIVE_OK) {
1239
if ((flags & PKG_OPEN_TRY) == 0)
1240
pkg_emit_error("archive_read_open_fd: %s",
1241
archive_error_string(*a));
1242
1243
retcode = EPKG_FATAL;
1244
goto cleanup;
1245
}
1246
}
1247
1248
retcode = pkg_new(pkg_p, PKG_FILE);
1249
if (retcode != EPKG_OK)
1250
goto cleanup;
1251
1252
pkg = *pkg_p;
1253
1254
while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
1255
fpath = archive_entry_pathname(*ae);
1256
if (fpath[0] != '+')
1257
break;
1258
1259
if (!manifest &&
1260
(flags & PKG_OPEN_MANIFEST_COMPACT) &&
1261
STREQ(fpath, "+COMPACT_MANIFEST")) {
1262
manifest = true;
1263
1264
ret = pkg_parse_archive(pkg, *a, archive_entry_size(*ae));
1265
if (ret != EPKG_OK) {
1266
retcode = EPKG_FATAL;
1267
goto cleanup;
1268
}
1269
/* Do not read anything more */
1270
break;
1271
}
1272
if (!manifest && STREQ(fpath, "+MANIFEST")) {
1273
manifest = true;
1274
1275
ret = pkg_parse_archive(pkg, *a, archive_entry_size(*ae));
1276
if (ret != EPKG_OK) {
1277
if ((flags & PKG_OPEN_TRY) == 0)
1278
pkg_emit_error("%s is not a valid package: "
1279
"Invalid manifest", path);
1280
1281
retcode = EPKG_FATAL;
1282
goto cleanup;
1283
}
1284
1285
if (flags & PKG_OPEN_MANIFEST_ONLY)
1286
break;
1287
}
1288
}
1289
1290
if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) {
1291
if ((flags & PKG_OPEN_TRY) == 0)
1292
pkg_emit_error("archive_read_next_header(): %s",
1293
archive_error_string(*a));
1294
1295
retcode = EPKG_FATAL;
1296
}
1297
1298
if (ret == ARCHIVE_EOF)
1299
retcode = EPKG_END;
1300
1301
if (!manifest) {
1302
retcode = EPKG_FATAL;
1303
if ((flags & PKG_OPEN_TRY) == 0)
1304
pkg_emit_error("%s is not a valid package: no manifest found", path);
1305
}
1306
1307
cleanup:
1308
if (retcode != EPKG_OK && retcode != EPKG_END) {
1309
if (*a != NULL) {
1310
archive_read_close(*a);
1311
archive_read_free(*a);
1312
}
1313
free(pkg);
1314
*pkg_p = NULL;
1315
*a = NULL;
1316
*ae = NULL;
1317
}
1318
1319
return (retcode);
1320
}
1321
1322
int
1323
pkg_validate(struct pkg *pkg, struct pkgdb *db)
1324
{
1325
assert(pkg != NULL);
1326
unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
1327
PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
1328
PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
1329
PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
1330
1331
if (pkg->uid == NULL) {
1332
/* Keep that part for the day we have to change it */
1333
/* Generate uid from name*/
1334
if (pkg->name == NULL)
1335
return (EPKG_FATAL);
1336
1337
pkg->uid = xstrdup(pkg->name);
1338
}
1339
1340
if (pkg->digest == NULL || !pkg_checksum_is_valid(pkg->digest,
1341
strlen(pkg->digest))) {
1342
/* Calculate new digest */
1343
if (pkgdb_ensure_loaded(db, pkg, flags)) {
1344
return (pkg_checksum_calculate(pkg, db, false, true, false));
1345
}
1346
return (EPKG_FATAL);
1347
}
1348
1349
return (EPKG_OK);
1350
}
1351
1352
int
1353
pkg_test_filesum(struct pkg *pkg)
1354
{
1355
struct pkg_file *f = NULL;
1356
int rc = EPKG_OK;
1357
int ret;
1358
1359
assert(pkg != NULL);
1360
1361
while (pkg_files(pkg, &f) == EPKG_OK) {
1362
if (f->sum != NULL &&
1363
/* skip config files as they can be modified */
1364
pkghash_get_value(pkg->config_files_hash, f->path) == NULL) {
1365
ret = pkg_checksum_validate_file(f->path, f->sum);
1366
if (ret != 0) {
1367
if (ret == ENOENT)
1368
pkg_emit_file_missing(pkg, f);
1369
else
1370
pkg_emit_file_mismatch(pkg, f, f->sum);
1371
rc = EPKG_FATAL;
1372
}
1373
}
1374
}
1375
1376
return (rc);
1377
}
1378
1379
int
1380
pkg_try_installed(struct pkgdb *db, const char *name,
1381
struct pkg **pkg, unsigned flags) {
1382
struct pkgdb_it *it = NULL;
1383
int ret = EPKG_FATAL;
1384
1385
if ((it = pkgdb_query(db, name, MATCH_INTERNAL)) == NULL)
1386
return (EPKG_FATAL);
1387
1388
ret = pkgdb_it_next(it, pkg, flags);
1389
pkgdb_it_free(it);
1390
1391
return (ret);
1392
}
1393
1394
int
1395
pkg_is_installed(struct pkgdb *db, const char *name)
1396
{
1397
struct pkg *pkg = NULL;
1398
int ret = EPKG_FATAL;
1399
1400
ret = pkg_try_installed(db, name, &pkg, PKG_LOAD_BASIC);
1401
pkg_free(pkg);
1402
1403
return (ret);
1404
}
1405
1406
bool
1407
pkg_has_message(struct pkg *p)
1408
{
1409
return (vec_len(&p->message) > 0);
1410
}
1411
1412
bool
1413
pkg_is_locked(const struct pkg * restrict p)
1414
{
1415
assert(p != NULL);
1416
1417
return (p->locked);
1418
}
1419
1420
bool
1421
pkg_is_config_file(struct pkg *p, const char *path,
1422
const struct pkg_file **file,
1423
struct pkg_config_file **cfile)
1424
{
1425
*file = NULL;
1426
*cfile = NULL;
1427
1428
if (pkghash_count(p->config_files_hash) == 0)
1429
return (false);
1430
1431
*file = pkghash_get_value(p->filehash, path);
1432
if (*file == NULL)
1433
return (false);
1434
*cfile = pkghash_get_value(p->config_files_hash, path);
1435
if (*cfile == NULL) {
1436
*file = NULL;
1437
return (false);
1438
}
1439
1440
return (true);
1441
}
1442
1443
struct pkg_dir *
1444
pkg_get_dir(struct pkg *p, const char *path)
1445
{
1446
return (pkghash_get_value(p->dirhash, path));
1447
}
1448
1449
struct pkg_file *
1450
pkg_get_file(struct pkg *p, const char *path)
1451
{
1452
return (pkghash_get_value(p->filehash, path));
1453
}
1454
1455
bool
1456
pkg_has_file(struct pkg *p, const char *path)
1457
{
1458
return (pkghash_get(p->filehash, path) != NULL);
1459
}
1460
1461
bool
1462
pkg_has_dir(struct pkg *p, const char *path)
1463
{
1464
return (pkghash_get(p->dirhash, path) != NULL);
1465
}
1466
1467
int
1468
pkg_open_root_fd(struct pkg *pkg)
1469
{
1470
const char *path;
1471
1472
if (pkg->rootfd != -1)
1473
return (EPKG_OK);
1474
1475
path = pkg_kv_get(&pkg->annotations, "relocated");
1476
if (path == NULL) {
1477
if ((pkg->rootfd = dup(ctx.rootfd)) == -1) {
1478
pkg_emit_errno("dup", "rootfd");
1479
return (EPKG_FATAL);
1480
}
1481
return (EPKG_OK);
1482
}
1483
1484
pkg_absolutepath(path, pkg->rootpath, sizeof(pkg->rootpath), false);
1485
1486
if ((pkg->rootfd = openat(ctx.rootfd, pkg->rootpath + 1, O_DIRECTORY)) >= 0 )
1487
return (EPKG_OK);
1488
1489
pkg->rootpath[0] = '\0';
1490
pkg_emit_errno("open", path);
1491
1492
return (EPKG_FATAL);
1493
}
1494
1495
int
1496
pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj)
1497
{
1498
struct pkg_message *msg = NULL;
1499
const ucl_object_t *elt, *cur;
1500
ucl_object_iter_t it = NULL;
1501
1502
if (ucl_object_type(obj) == UCL_STRING) {
1503
msg = xcalloc(1, sizeof(*msg));
1504
msg->str = xstrdup(ucl_object_tostring(obj));
1505
msg->type = PKG_MESSAGE_ALWAYS;
1506
vec_push(&pkg->message, msg);
1507
return (EPKG_OK);
1508
}
1509
1510
/* New format of pkg message */
1511
if (ucl_object_type(obj) != UCL_ARRAY)
1512
pkg_emit_error("package message badly formatted, an array was"
1513
" expected");
1514
1515
while ((cur = ucl_iterate_object(obj, &it, true))) {
1516
elt = ucl_object_find_key(cur, "message");
1517
1518
if (elt == NULL || ucl_object_type(elt) != UCL_STRING) {
1519
pkg_emit_error("package message lacks 'message' key"
1520
" that is required");
1521
1522
return (EPKG_FATAL);
1523
}
1524
1525
msg = xcalloc(1, sizeof(*msg));
1526
1527
msg->str = xstrdup(ucl_object_tostring(elt));
1528
msg->type = PKG_MESSAGE_ALWAYS;
1529
elt = ucl_object_find_key(cur, "type");
1530
if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1531
if (STRIEQ(ucl_object_tostring(elt), "install"))
1532
msg->type = PKG_MESSAGE_INSTALL;
1533
else if (STRIEQ(ucl_object_tostring(elt), "remove"))
1534
msg->type = PKG_MESSAGE_REMOVE;
1535
else if (STRIEQ(ucl_object_tostring(elt), "upgrade"))
1536
msg->type = PKG_MESSAGE_UPGRADE;
1537
else
1538
pkg_emit_error("Unknown message type,"
1539
" message will always be printed");
1540
}
1541
if (msg->type != PKG_MESSAGE_UPGRADE) {
1542
vec_push(&pkg->message, msg);
1543
continue;
1544
}
1545
1546
elt = ucl_object_find_key(cur, "minimum_version");
1547
if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1548
msg->minimum_version = xstrdup(ucl_object_tostring(elt));
1549
}
1550
1551
elt = ucl_object_find_key(cur, "maximum_version");
1552
if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1553
msg->maximum_version = xstrdup(ucl_object_tostring(elt));
1554
}
1555
1556
vec_push(&pkg->message, msg);
1557
}
1558
1559
return (EPKG_OK);
1560
}
1561
1562
int
1563
pkg_message_from_str(struct pkg *pkg, const char *str, size_t len)
1564
{
1565
struct ucl_parser *parser;
1566
ucl_object_t *obj;
1567
int ret = EPKG_FATAL;
1568
1569
assert(str != NULL);
1570
1571
if (len == 0) {
1572
len = strlen(str);
1573
}
1574
1575
parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
1576
if (pkg->prefix != NULL) {
1577
ucl_parser_register_variable(parser, "PREFIX", pkg->prefix);
1578
}
1579
if (pkg->name != NULL) {
1580
ucl_parser_register_variable(parser, "PKGNAME", pkg->name);
1581
}
1582
if (pkg->origin != NULL) {
1583
ucl_parser_register_variable(parser, "PKGORIGIN", pkg->origin);
1584
}
1585
if (pkg->maintainer != NULL) {
1586
ucl_parser_register_variable(parser, "MAINTAINER", pkg->maintainer);
1587
}
1588
1589
if (ucl_parser_add_chunk(parser, (const unsigned char*)str, len)) {
1590
obj = ucl_parser_get_object(parser);
1591
ucl_parser_free(parser);
1592
1593
ret = pkg_message_from_ucl(pkg, obj);
1594
ucl_object_unref(obj);
1595
1596
return (ret);
1597
}
1598
1599
ucl_parser_free (parser);
1600
1601
return (ret);
1602
}
1603
1604
ucl_object_t*
1605
pkg_message_to_ucl(const struct pkg *pkg)
1606
{
1607
struct pkg_message *msg;
1608
ucl_object_t *array;
1609
ucl_object_t *obj;
1610
1611
array = ucl_object_typed_new(UCL_ARRAY);
1612
vec_foreach(pkg->message, i) {
1613
msg = pkg->message.d[i];
1614
obj = ucl_object_typed_new (UCL_OBJECT);
1615
1616
ucl_object_insert_key(obj,
1617
ucl_object_fromstring_common(msg->str, 0,
1618
UCL_STRING_RAW|UCL_STRING_TRIM),
1619
"message", 0, false);
1620
1621
switch (msg->type) {
1622
case PKG_MESSAGE_ALWAYS:
1623
break;
1624
case PKG_MESSAGE_INSTALL:
1625
ucl_object_insert_key(obj,
1626
ucl_object_fromstring("install"),
1627
"type", 0, false);
1628
break;
1629
case PKG_MESSAGE_UPGRADE:
1630
ucl_object_insert_key(obj,
1631
ucl_object_fromstring("upgrade"),
1632
"type", 0, false);
1633
break;
1634
case PKG_MESSAGE_REMOVE:
1635
ucl_object_insert_key(obj,
1636
ucl_object_fromstring("remove"),
1637
"type", 0, false);
1638
break;
1639
}
1640
if (msg->maximum_version) {
1641
ucl_object_insert_key(obj,
1642
ucl_object_fromstring(msg->maximum_version),
1643
"maximum_version", 0, false);
1644
}
1645
if (msg->minimum_version) {
1646
ucl_object_insert_key(obj,
1647
ucl_object_fromstring(msg->minimum_version),
1648
"minimum_version", 0, false);
1649
}
1650
ucl_array_append(array, obj);
1651
}
1652
1653
return (array);
1654
}
1655
1656
char*
1657
pkg_message_to_str(struct pkg *pkg)
1658
{
1659
ucl_object_t *obj;
1660
char *ret = NULL;
1661
1662
if (vec_len(&pkg->message) <= 0)
1663
return (NULL);
1664
1665
obj = pkg_message_to_ucl(pkg);
1666
ret = ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
1667
ucl_object_unref(obj);
1668
1669
return (ret);
1670
}
1671
1672
static int
1673
pkg_dep_cmp(struct pkg_dep *a, struct pkg_dep *b)
1674
{
1675
return (STREQ(a->name, b->name));
1676
}
1677
1678
static int
1679
pkg_file_cmp(struct pkg_file *a, struct pkg_file *b)
1680
{
1681
return (STREQ(a->path, b->path));
1682
}
1683
1684
static int
1685
pkg_dir_cmp(struct pkg_dir *a, struct pkg_dir *b)
1686
{
1687
return (STREQ(a->path, b->path));
1688
}
1689
1690
static int
1691
pkg_option_cmp(struct pkg_option *a, struct pkg_option *b)
1692
{
1693
return (STREQ(a->key, b->key));
1694
}
1695
1696
static int
1697
pkg_cf_cmp(struct pkg_config_file *a, struct pkg_config_file *b)
1698
{
1699
return (STREQ(a->path, b->path));
1700
}
1701
1702
void
1703
pkg_lists_sort(struct pkg *p)
1704
{
1705
if (p->list_sorted)
1706
return;
1707
p->list_sorted = true;
1708
1709
DL_SORT(p->depends, pkg_dep_cmp);
1710
DL_SORT(p->files, pkg_file_cmp);
1711
DL_SORT(p->dirs, pkg_dir_cmp);
1712
DL_SORT(p->options, pkg_option_cmp);
1713
DL_SORT(p->config_files, pkg_cf_cmp);
1714
}
1715
1716
static int
1717
pkgs_cmp(const void *a, const void *b)
1718
{
1719
struct pkg *pa = *(struct pkg **)a;
1720
struct pkg *pb = *(struct pkg **)b;
1721
1722
return (strcmp(pa->name, pb->name));
1723
}
1724
1725
void
1726
pkgs_sort(pkgs_t *pkgs)
1727
{
1728
if (pkgs->len == 0)
1729
return;
1730
qsort(pkgs->d, pkgs->len, sizeof(pkgs->d[0]), pkgs_cmp);
1731
}
1732
1733
DEFINE_VEC_INSERT_SORTED_FUNC(pkgs_t, pkgs, struct pkg *, pkgs_cmp)
1734
1735
struct pkg **
1736
pkgs_search(pkgs_t *pkgs, char *el)
1737
{
1738
struct pkg target = { .name = el };
1739
struct pkg *tgt = &target;
1740
if (pkgs->len == 0)
1741
return (NULL);
1742
struct pkg **res = bsearch(&tgt, pkgs->d, pkgs->len, sizeof(pkgs->d[0]), pkgs_cmp);
1743
return (res);
1744
}
1745
1746