Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/pkg_config.c
2065 views
1
/*
2
* Copyright (c) 2011-2024 Baptiste Daroussin <[email protected]>
3
* Copyright (c) 2011-2012 Julien Laffaye <[email protected]>
4
* Copyright (c) 2014 Matthew Seaman <[email protected]>
5
* Copyright (c) 2016 Vsevolod Stakhov <[email protected]>
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer
13
* in this position and unchanged.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include "pkg_config.h"
31
32
#include <assert.h>
33
#include <sys/socket.h>
34
#include <sys/un.h>
35
#include <ctype.h>
36
#include <dirent.h>
37
#include <dlfcn.h>
38
#include <errno.h>
39
#include <fcntl.h>
40
#ifdef HAVE_OSRELDATE_H
41
#include <osreldate.h>
42
#endif
43
#include <ucl.h>
44
45
#include <curl/curl.h>
46
47
#include <archive.h>
48
#include <sqlite3.h>
49
#include <openssl/crypto.h>
50
51
#include "pkg.h"
52
#include "private/pkg.h"
53
#include "private/pkg_abi.h"
54
#include "private/event.h"
55
#include "private/fetch.h"
56
#include "pkg_repos.h"
57
58
#ifndef PORTSDIR
59
#define PORTSDIR "/usr/ports"
60
#endif
61
#ifndef DEFAULT_VULNXML_URL
62
#define DEFAULT_VULNXML_URL "https://vuxml.freebsd.org/freebsd/vuln.xml.xz"
63
#endif
64
65
#ifdef OSMAJOR
66
#define STRINGIFY(X) TEXT(X)
67
#define TEXT(X) #X
68
#define INDEXFILE "INDEX-" STRINGIFY(OSMAJOR)
69
#else
70
#define INDEXFILE "INDEX"
71
#endif
72
73
#define dbg(x, ...) pkg_dbg(PKG_DBG_CONFIG, x, __VA_ARGS__)
74
75
struct pkg_ctx ctx = {
76
.eventpipe = -1,
77
.debug_level = 0,
78
.developer_mode = false,
79
.pkg_rootdir = NULL,
80
.metalog = NULL,
81
.dbdir = NULL,
82
.cachedir = NULL,
83
.rootfd = -1,
84
.cachedirfd = -1,
85
.pkg_dbdirfd = -1,
86
.pkg_reposdirfd = -1,
87
.devnullfd = -1,
88
.backup_libraries = false,
89
.triggers = true,
90
.compression_format = NULL,
91
.compression_level = -1,
92
.compression_threads = -1,
93
.defer_triggers = false,
94
.no_version_for_deps = false,
95
};
96
97
struct config_entry {
98
uint8_t type;
99
const char *key;
100
const char *def;
101
};
102
103
static struct pkg_repo *repos = NULL;
104
ucl_object_t *config = NULL;
105
106
static struct config_entry c[] = {
107
{
108
PKG_STRING,
109
"PKG_DBDIR",
110
"/var/db/pkg",
111
},
112
{
113
PKG_STRING,
114
"PKG_CACHEDIR",
115
"/var/cache/pkg",
116
},
117
{
118
PKG_STRING,
119
"PORTSDIR",
120
"/usr/ports",
121
},
122
{
123
PKG_STRING,
124
"INDEXDIR",
125
NULL, /* Default to PORTSDIR unless defined */
126
},
127
{
128
PKG_STRING,
129
"INDEXFILE",
130
INDEXFILE,
131
},
132
{
133
PKG_BOOL,
134
"HANDLE_RC_SCRIPTS",
135
"NO",
136
},
137
{
138
PKG_BOOL,
139
"DEFAULT_ALWAYS_YES",
140
"NO",
141
},
142
{
143
PKG_BOOL,
144
"ASSUME_ALWAYS_YES",
145
"NO",
146
},
147
{
148
PKG_ARRAY,
149
"REPOS_DIR",
150
"/etc/pkg/,"PREFIX"/etc/pkg/repos/",
151
},
152
{
153
PKG_STRING,
154
"PLIST_KEYWORDS_DIR",
155
NULL,
156
},
157
{
158
PKG_BOOL,
159
"SYSLOG",
160
"YES",
161
},
162
{
163
PKG_BOOL,
164
"DEVELOPER_MODE",
165
"NO",
166
},
167
{
168
PKG_STRING,
169
"VULNXML_SITE",
170
DEFAULT_VULNXML_URL,
171
},
172
{
173
PKG_INT,
174
"FETCH_RETRY",
175
"3",
176
},
177
{
178
PKG_STRING,
179
"PKG_PLUGINS_DIR",
180
PREFIX"/lib/pkg/",
181
},
182
{
183
PKG_BOOL,
184
"PKG_ENABLE_PLUGINS",
185
"YES",
186
},
187
{
188
PKG_ARRAY,
189
"PLUGINS",
190
NULL,
191
},
192
{
193
PKG_BOOL,
194
"DEBUG_SCRIPTS",
195
"NO",
196
},
197
{
198
PKG_STRING,
199
"PLUGINS_CONF_DIR",
200
PREFIX"/etc/pkg/",
201
},
202
{
203
PKG_BOOL,
204
"PERMISSIVE",
205
"NO",
206
},
207
{
208
PKG_BOOL,
209
"REPO_AUTOUPDATE",
210
"YES",
211
},
212
{
213
PKG_STRING,
214
"NAMESERVER",
215
NULL,
216
},
217
{
218
PKG_STRING,
219
"HTTP_USER_AGENT",
220
"pkg/"PKGVERSION,
221
},
222
{
223
PKG_STRING,
224
"EVENT_PIPE",
225
NULL,
226
},
227
{
228
PKG_INT,
229
"FETCH_TIMEOUT",
230
"30",
231
},
232
{
233
PKG_BOOL,
234
"UNSET_TIMESTAMP",
235
"NO",
236
},
237
{
238
PKG_STRING,
239
"SSH_RESTRICT_DIR",
240
NULL,
241
},
242
{
243
PKG_OBJECT,
244
"PKG_ENV",
245
NULL,
246
},
247
{
248
PKG_STRING,
249
"PKG_SSH_ARGS",
250
NULL,
251
},
252
{
253
PKG_INT,
254
"DEBUG_LEVEL",
255
"0",
256
},
257
{
258
PKG_OBJECT,
259
"ALIAS",
260
NULL,
261
},
262
{
263
PKG_STRING,
264
"CUDF_SOLVER",
265
NULL,
266
},
267
{
268
PKG_STRING,
269
"SAT_SOLVER",
270
NULL,
271
},
272
{
273
PKG_BOOL,
274
"RUN_SCRIPTS",
275
"YES",
276
},
277
{
278
PKG_BOOL,
279
"CASE_SENSITIVE_MATCH",
280
"NO",
281
},
282
{
283
PKG_INT,
284
"LOCK_WAIT",
285
"1",
286
},
287
{
288
PKG_INT,
289
"LOCK_RETRIES",
290
"5",
291
},
292
{
293
PKG_BOOL,
294
"SQLITE_PROFILE",
295
"NO",
296
},
297
{
298
PKG_INT,
299
"WORKERS_COUNT",
300
"0",
301
},
302
{
303
PKG_BOOL,
304
"READ_LOCK",
305
"NO",
306
},
307
{
308
PKG_INT,
309
"IP_VERSION",
310
"0",
311
},
312
{
313
PKG_BOOL,
314
"AUTOMERGE",
315
"YES",
316
},
317
{
318
PKG_STRING,
319
"MERGETOOL",
320
NULL,
321
},
322
{
323
PKG_STRING,
324
"VERSION_SOURCE",
325
NULL,
326
},
327
{
328
PKG_BOOL,
329
"CONSERVATIVE_UPGRADE",
330
"YES",
331
},
332
{
333
PKG_BOOL,
334
"FORCE_CAN_REMOVE_VITAL",
335
"YES",
336
},
337
{
338
PKG_BOOL,
339
"PKG_CREATE_VERBOSE",
340
"NO",
341
},
342
{
343
PKG_BOOL,
344
"AUTOCLEAN",
345
"NO",
346
},
347
{
348
PKG_STRING,
349
"DOT_FILE",
350
NULL,
351
},
352
{
353
PKG_OBJECT,
354
"REPOSITORIES",
355
NULL,
356
},
357
{
358
PKG_ARRAY,
359
"VALID_URL_SCHEME",
360
"pkg+http,pkg+https,https,http,file,ssh,tcp",
361
},
362
{
363
PKG_INT,
364
"WARN_SIZE_LIMIT",
365
"1048576", /* 1 meg */
366
},
367
{
368
PKG_STRING,
369
"METALOG",
370
NULL,
371
},
372
{
373
PKG_BOOL,
374
"IGNORE_OSVERSION",
375
"NO",
376
},
377
{
378
PKG_BOOL,
379
"BACKUP_LIBRARIES",
380
"NO",
381
},
382
{
383
PKG_STRING,
384
"BACKUP_LIBRARY_PATH",
385
PREFIX "/lib/compat/pkg",
386
},
387
{
388
PKG_STRING,
389
"PKG_TRIGGERS_DIR",
390
PREFIX "/share/pkg/triggers",
391
},
392
{
393
PKG_BOOL,
394
"PKG_TRIGGERS_ENABLE",
395
"YES",
396
},
397
{
398
PKG_ARRAY,
399
"AUDIT_IGNORE_GLOB",
400
NULL,
401
},
402
{
403
PKG_ARRAY,
404
"AUDIT_IGNORE_REGEX",
405
NULL,
406
},
407
{
408
PKG_STRING,
409
"COMPRESSION_FORMAT",
410
NULL,
411
},
412
{
413
PKG_INT,
414
"COMPRESSION_LEVEL",
415
"-1",
416
},
417
{
418
PKG_BOOL,
419
"ARCHIVE_SYMLINK",
420
"FALSE",
421
},
422
{
423
PKG_BOOL,
424
"REPO_ACCEPT_LEGACY_PKG",
425
"FALSE",
426
},
427
{
428
PKG_ARRAY,
429
"FILES_IGNORE_GLOB",
430
NULL,
431
},
432
{
433
PKG_ARRAY,
434
"FILES_IGNORE_REGEX",
435
NULL,
436
},
437
{
438
PKG_ARRAY,
439
"SHLIB_PROVIDE_PATHS_NATIVE",
440
NULL,
441
},
442
{
443
PKG_ARRAY,
444
"SHLIB_PROVIDE_PATHS_COMPAT_32",
445
NULL,
446
},
447
{
448
PKG_ARRAY,
449
"SHLIB_PROVIDE_PATHS_COMPAT_LINUX",
450
NULL,
451
},
452
{
453
PKG_ARRAY,
454
"SHLIB_PROVIDE_PATHS_COMPAT_LINUX_32",
455
NULL,
456
},
457
{
458
PKG_ARRAY,
459
"SHLIB_PROVIDE_IGNORE_GLOB",
460
NULL,
461
},
462
{
463
PKG_ARRAY,
464
"SHLIB_PROVIDE_IGNORE_REGEX",
465
NULL,
466
},
467
{
468
PKG_ARRAY,
469
"SHLIB_REQUIRE_IGNORE_GLOB",
470
NULL,
471
},
472
{
473
PKG_ARRAY,
474
"SHLIB_REQUIRE_IGNORE_REGEX",
475
NULL,
476
},
477
{
478
PKG_ARRAY,
479
"PKG_DEBUG_FLAGS",
480
"all",
481
},
482
{
483
PKG_INT,
484
"COMPRESSION_THREADS",
485
"-1",
486
},
487
{
488
PKG_BOOL,
489
"PKG_REINSTALL_ON_OPTIONS_CHANGE",
490
"TRUE",
491
},
492
{
493
PKG_BOOL,
494
"TRACK_LINUX_COMPAT_SHLIBS",
495
"FALSE",
496
},
497
};
498
499
static bool parsed = false;
500
static size_t c_size = NELEM(c);
501
502
static struct pkg_repo* pkg_repo_new(const char *name,
503
const char *url, const char *type);
504
static void pkg_repo_overwrite(struct pkg_repo*, const char *name,
505
const char *url, const char *type);
506
static void pkg_repo_free(struct pkg_repo *r);
507
508
static void
509
connect_evpipe(const char *evpipe) {
510
struct stat st;
511
struct sockaddr_un sock;
512
int flag = O_WRONLY;
513
514
if (stat(evpipe, &st) != 0) {
515
pkg_emit_error("No such event pipe: %s", evpipe);
516
return;
517
}
518
519
if (!S_ISFIFO(st.st_mode) && !S_ISSOCK(st.st_mode)) {
520
pkg_emit_error("%s is not a fifo or socket", evpipe);
521
return;
522
}
523
524
if (S_ISFIFO(st.st_mode)) {
525
flag |= O_NONBLOCK;
526
if ((ctx.eventpipe = open(evpipe, flag)) == -1)
527
pkg_emit_errno("open event pipe", evpipe);
528
return;
529
}
530
531
if (S_ISSOCK(st.st_mode)) {
532
if ((ctx.eventpipe = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
533
pkg_emit_errno("Open event pipe", evpipe);
534
return;
535
}
536
memset(&sock, 0, sizeof(struct sockaddr_un));
537
sock.sun_family = AF_UNIX;
538
if (strlcpy(sock.sun_path, evpipe, sizeof(sock.sun_path)) >=
539
sizeof(sock.sun_path)) {
540
pkg_emit_error("Socket path too long: %s", evpipe);
541
close(ctx.eventpipe);
542
ctx.eventpipe = -1;
543
return;
544
}
545
546
if (connect(ctx.eventpipe, (struct sockaddr *)&sock, SUN_LEN(&sock)) == -1) {
547
pkg_emit_errno("Connect event pipe", evpipe);
548
close(ctx.eventpipe);
549
ctx.eventpipe = -1;
550
return;
551
}
552
}
553
554
}
555
556
const char *
557
pkg_libversion(void)
558
{
559
return PKGVERSION;
560
}
561
562
pkg_kvl_t *
563
pkg_external_libs_version(void)
564
{
565
pkg_kvl_t *kvl = xcalloc(1, sizeof(*kvl));
566
567
vec_push(kvl, pkg_kv_new("libcurl", curl_version()));
568
vec_push(kvl, pkg_kv_new("libarchive", archive_version_string()));
569
vec_push(kvl, pkg_kv_new("sqlite", sqlite3_libversion()));
570
vec_push(kvl, pkg_kv_new("openssl", OpenSSL_version(OPENSSL_VERSION)));
571
572
return (kvl);
573
}
574
575
576
int
577
pkg_initialized(void)
578
{
579
return (parsed);
580
}
581
582
const pkg_object *
583
pkg_config_get(const char *key) {
584
return (ucl_object_find_key(config, key));
585
}
586
587
char *
588
pkg_config_dump(void)
589
{
590
return (pkg_object_dump(config));
591
}
592
593
static void
594
disable_plugins_if_static(void)
595
{
596
void *dlh;
597
598
dlh = dlopen(0, RTLD_NOW);
599
600
/* if dlh is NULL then we are in static binary */
601
if (dlh == NULL)
602
ucl_object_replace_key(config, ucl_object_frombool(false), "PKG_ENABLE_PLUGINS", 18, false);
603
else
604
dlclose(dlh);
605
606
return;
607
}
608
609
static void
610
add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags)
611
{
612
const ucl_object_t *cur, *enabled, *env;
613
ucl_object_iter_t it = NULL;
614
struct pkg_kv *kv;
615
bool enable = true;
616
const char *url = NULL, *pubkey = NULL, *mirror_type = NULL;
617
const char *signature_type = NULL, *fingerprints = NULL;
618
const char *key;
619
const char *type = NULL;
620
int use_ipvx = 0;
621
int priority = 0;
622
623
dbg(1, "parsing repository object %s", rname);
624
625
env = NULL;
626
enabled = ucl_object_find_key(obj, "enabled");
627
if (enabled == NULL)
628
enabled = ucl_object_find_key(obj, "ENABLED");
629
if (enabled != NULL) {
630
enable = ucl_object_toboolean(enabled);
631
if (!enable && r != NULL) {
632
/*
633
* We basically want to remove the existing repo r and
634
* forget all stuff parsed
635
*/
636
dbg(1, "disabling repo %s", rname);
637
DL_DELETE(repos, r);
638
pkg_repo_free(r);
639
return;
640
}
641
}
642
643
while ((cur = ucl_iterate_object(obj, &it, true))) {
644
key = ucl_object_key(cur);
645
if (key == NULL)
646
continue;
647
648
if (STRIEQ(key, "url")) {
649
if (cur->type != UCL_STRING) {
650
pkg_emit_error("Expecting a string for the "
651
"'%s' key of the '%s' repo",
652
key, rname);
653
return;
654
}
655
url = ucl_object_tostring(cur);
656
} else if (STRIEQ(key, "pubkey")) {
657
if (cur->type != UCL_STRING) {
658
pkg_emit_error("Expecting a string for the "
659
"'%s' key of the '%s' repo",
660
key, rname);
661
return;
662
}
663
pubkey = ucl_object_tostring(cur);
664
} else if (STRIEQ(key, "mirror_type")) {
665
if (cur->type != UCL_STRING) {
666
pkg_emit_error("Expecting a string for the "
667
"'%s' key of the '%s' repo",
668
key, rname);
669
return;
670
}
671
mirror_type = ucl_object_tostring(cur);
672
} else if (STRIEQ(key, "signature_type")) {
673
if (cur->type != UCL_STRING) {
674
pkg_emit_error("Expecting a string for the "
675
"'%s' key of the '%s' repo",
676
key, rname);
677
return;
678
}
679
signature_type = ucl_object_tostring(cur);
680
} else if (STRIEQ(key, "fingerprints")) {
681
if (cur->type != UCL_STRING) {
682
pkg_emit_error("Expecting a string for the "
683
"'%s' key of the '%s' repo",
684
key, rname);
685
return;
686
}
687
fingerprints = ucl_object_tostring(cur);
688
} else if (STRIEQ(key, "type")) {
689
if (cur->type != UCL_STRING) {
690
pkg_emit_error("Expecting a string for the "
691
"'%s' key of the '%s' repo",
692
key, rname);
693
return;
694
}
695
type = ucl_object_tostring(cur);
696
} else if (STRIEQ(key, "ip_version")) {
697
if (cur->type != UCL_INT) {
698
pkg_emit_error("Expecting a integer for the "
699
"'%s' key of the '%s' repo",
700
key, rname);
701
return;
702
}
703
use_ipvx = ucl_object_toint(cur);
704
if (use_ipvx != 4 && use_ipvx != 6)
705
use_ipvx = 0;
706
} else if (STRIEQ(key, "priority")) {
707
if (cur->type != UCL_INT) {
708
pkg_emit_error("Expecting a integer for the "
709
"'%s' key of the '%s' repo",
710
key, rname);
711
return;
712
}
713
priority = ucl_object_toint(cur);
714
} else if (STRIEQ(key, "env")) {
715
if (cur->type != UCL_OBJECT) {
716
pkg_emit_error("Expecting an object for the "
717
"'%s' key of the '%s' repo",
718
key, rname);
719
}
720
env = cur;
721
}
722
}
723
724
if (r == NULL && url == NULL) {
725
dbg(1, "No repo and no url for %s", rname);
726
return;
727
}
728
729
if (r == NULL)
730
r = pkg_repo_new(rname, url, type);
731
else
732
pkg_repo_overwrite(r, rname, url, type);
733
734
if (signature_type != NULL) {
735
if (STRIEQ(signature_type, "pubkey"))
736
r->signature_type = SIG_PUBKEY;
737
else if (STRIEQ(signature_type, "fingerprints"))
738
r->signature_type = SIG_FINGERPRINT;
739
else
740
r->signature_type = SIG_NONE;
741
}
742
743
744
if (fingerprints != NULL) {
745
free(r->fingerprints);
746
r->fingerprints = xstrdup(fingerprints);
747
}
748
749
if (pubkey != NULL) {
750
free(r->pubkey);
751
r->pubkey = xstrdup(pubkey);
752
}
753
754
r->enable = enable;
755
r->priority = priority;
756
757
if (mirror_type != NULL) {
758
if (STRIEQ(mirror_type, "srv"))
759
r->mirror_type = SRV;
760
else if (STRIEQ(mirror_type, "http"))
761
r->mirror_type = HTTP;
762
else
763
r->mirror_type = NOMIRROR;
764
}
765
766
if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
767
use_ipvx = 4;
768
else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)
769
use_ipvx = 6;
770
771
if (use_ipvx != 4 && use_ipvx != 6)
772
use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION"));
773
774
if (use_ipvx == 4)
775
r->ip = IPV4;
776
else if (use_ipvx == 6)
777
r->ip = IPV6;
778
779
if (env != NULL) {
780
it = NULL;
781
while ((cur = ucl_iterate_object(env, &it, true))) {
782
kv = pkg_kv_new(ucl_object_key(cur),
783
ucl_object_tostring_forced(cur));
784
vec_push(&r->env, kv);
785
}
786
}
787
}
788
789
static void
790
add_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
791
{
792
struct pkg_repo *r;
793
const char *key;
794
795
key = ucl_object_key(obj);
796
dbg(1, "parsing repo key '%s' in file '%s'", key, file);
797
r = pkg_repo_find(key);
798
if (r != NULL)
799
dbg(1, "overwriting repository %s", key);
800
add_repo(obj, r, key, flags);
801
}
802
803
static void
804
walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
805
{
806
const ucl_object_t *cur;
807
ucl_object_iter_t it = NULL;
808
struct pkg_repo *r;
809
const char *key;
810
char *yaml;
811
812
while ((cur = ucl_iterate_object(obj, &it, true))) {
813
key = ucl_object_key(cur);
814
dbg(1, "parsing key '%s'", key);
815
r = pkg_repo_find(key);
816
if (r != NULL)
817
dbg(1, "overwriting repository %s", key);
818
if (cur->type == UCL_OBJECT)
819
add_repo(cur, r, key, flags);
820
else {
821
yaml = ucl_object_emit(cur, UCL_EMIT_YAML);
822
pkg_emit_error("Ignoring bad configuration entry in %s: %s",
823
file, yaml);
824
free(yaml);
825
}
826
}
827
}
828
829
struct config_parser_vars {
830
char *abi;
831
char *altabi;
832
char *osversion;
833
char *release;
834
char *version_major;
835
char *version_minor;
836
};
837
838
/* Register parser variables based on ctx.abi.
839
* The returned struct must be free'd with config_parser_variables_free()
840
* after parsing is complete. */
841
static struct config_parser_vars *
842
config_parser_vars_register(struct ucl_parser *p)
843
{
844
struct config_parser_vars *vars = xcalloc(1, sizeof(struct config_parser_vars));
845
846
vars->abi = pkg_abi_to_string(&ctx.abi);
847
ucl_parser_register_variable(p, "ABI", vars->abi);
848
849
char altabi_buffer[BUFSIZ];
850
pkg_arch_to_legacy(vars->abi, altabi_buffer, sizeof(altabi_buffer));
851
vars->altabi = xstrdup(altabi_buffer);
852
ucl_parser_register_variable(p, "ALTABI", vars->altabi);
853
854
if (ctx.abi.os == PKG_OS_FREEBSD) {
855
xasprintf(&vars->osversion, "%d",
856
pkg_abi_get_freebsd_osversion(&ctx.abi));
857
ucl_parser_register_variable(p, "OSVERSION", vars->osversion);
858
}
859
ucl_parser_register_variable(p, "OSNAME", pkg_os_to_string(ctx.abi.os));
860
861
if (pkg_abi_string_only_major_version(ctx.abi.os)) {
862
xasprintf(&vars->release, "%d", ctx.abi.major);
863
} else {
864
xasprintf(&vars->release, "%d.%d", ctx.abi.major, ctx.abi.minor);
865
}
866
ucl_parser_register_variable(p, "RELEASE", vars->release);
867
868
xasprintf(&vars->version_major, "%d", ctx.abi.major);
869
ucl_parser_register_variable(p, "VERSION_MAJOR", vars->version_major);
870
871
xasprintf(&vars->version_minor, "%d", ctx.abi.minor);
872
ucl_parser_register_variable(p, "VERSION_MINOR", vars->version_minor);
873
874
ucl_parser_register_variable(p, "ARCH",
875
pkg_arch_to_string(ctx.abi.os, ctx.abi.arch));
876
877
return vars;
878
}
879
880
static void
881
config_parser_vars_free(struct config_parser_vars *vars)
882
{
883
free(vars->abi);
884
free(vars->altabi);
885
free(vars->osversion);
886
free(vars->release);
887
free(vars->version_major);
888
free(vars->version_minor);
889
free(vars);
890
}
891
static void
892
load_repo_file(int dfd, const char *repodir, const char *repofile,
893
pkg_init_flags flags)
894
{
895
struct ucl_parser *p;
896
ucl_object_t *obj = NULL;
897
int fd;
898
899
p = ucl_parser_new(0);
900
901
struct config_parser_vars *parser_vars = config_parser_vars_register(p);
902
903
errno = 0;
904
obj = NULL;
905
906
dbg(1, "loading %s/%s", repodir, repofile);
907
fd = openat(dfd, repofile, O_RDONLY);
908
if (fd == -1) {
909
pkg_errno("Unable to open '%s/%s'", repodir, repofile);
910
goto out_parser_vars;
911
}
912
if (!ucl_parser_add_fd(p, fd)) {
913
pkg_emit_error("Error parsing: '%s/%s': %s", repodir,
914
repofile, ucl_parser_get_error(p));
915
goto out_fd;
916
}
917
918
obj = ucl_parser_get_object(p);
919
if (obj == NULL) {
920
goto out_fd;
921
}
922
923
if (obj->type == UCL_OBJECT)
924
walk_repo_obj(obj, repofile, flags);
925
926
ucl_object_unref(obj);
927
out_fd:
928
close(fd);
929
out_parser_vars:
930
ucl_parser_free(p);
931
config_parser_vars_free(parser_vars);
932
}
933
934
static int
935
configfile(const struct dirent *dp)
936
{
937
const char *p;
938
size_t n;
939
940
if (dp->d_name[0] == '.')
941
return (0);
942
943
n = strlen(dp->d_name);
944
if (n <= 5)
945
return (0);
946
947
p = &dp->d_name[n - 5];
948
if (!STREQ(p, ".conf"))
949
return (0);
950
return (1);
951
}
952
953
static void
954
load_repo_files(const char *repodir, pkg_init_flags flags)
955
{
956
struct dirent **ent;
957
int nents, i, fd;
958
959
dbg(1, "loading repositories in %s", repodir);
960
if ((fd = open(repodir, O_DIRECTORY|O_CLOEXEC)) == -1)
961
return;
962
963
nents = scandir(repodir, &ent, configfile, alphasort);
964
for (i = 0; i < nents; i++) {
965
load_repo_file(fd, repodir, ent[i]->d_name, flags);
966
free(ent[i]);
967
}
968
if (nents >= 0)
969
free(ent);
970
close(fd);
971
}
972
973
static void
974
load_repositories(const char *repodir, pkg_init_flags flags)
975
{
976
const pkg_object *reposlist, *cur;
977
pkg_iter it = NULL;
978
979
if (repodir != NULL) {
980
load_repo_files(repodir, flags);
981
return;
982
}
983
984
reposlist = pkg_config_get("REPOS_DIR");
985
while ((cur = pkg_object_iterate(reposlist, &it)))
986
load_repo_files(pkg_object_string(cur), flags);
987
}
988
989
bool
990
pkg_compiled_for_same_os_major(void)
991
{
992
#ifdef OSMAJOR
993
if (getenv("IGNORE_OSMAJOR") != NULL)
994
return (true);
995
996
return (ctx.abi.major == OSMAJOR);
997
#else
998
return (true); /* Can't tell, so assume yes */
999
#endif
1000
}
1001
1002
1003
int
1004
pkg_init(const char *path, const char *reposdir)
1005
{
1006
return (pkg_ini(path, reposdir, 0));
1007
}
1008
1009
static const char *
1010
type_to_string(int type)
1011
{
1012
if (type == UCL_ARRAY)
1013
return ("array");
1014
if (type == UCL_OBJECT)
1015
return ("object");
1016
if (type == UCL_STRING)
1017
return ("string");
1018
if (type == UCL_INT)
1019
return ("integer");
1020
if (type == UCL_BOOLEAN)
1021
return ("boolean");
1022
return ("unknown");
1023
}
1024
1025
const struct pkg_dbg_flags *
1026
_find_flag(const char *str)
1027
{
1028
for (size_t i = 0; i < NELEM(debug_flags); i++) {
1029
if (STRIEQ(debug_flags[i].name, str))
1030
return (&debug_flags[i]);
1031
}
1032
return (NULL);
1033
}
1034
static uint64_t
1035
config_validate_debug_flags(const ucl_object_t *o)
1036
{
1037
ucl_object_iter_t it = NULL;
1038
const ucl_object_t *cur;
1039
int ret = EPKG_OK;
1040
const struct pkg_dbg_flags *f;
1041
1042
if (o == NULL)
1043
return (ret);
1044
1045
while ((cur = ucl_iterate_object(o, &it, true))) {
1046
const char *str = ucl_object_tostring(cur);
1047
f = _find_flag(str);
1048
if (f == NULL) {
1049
pkg_emit_error("Invalid debug flag %s",
1050
ucl_object_tostring(cur));
1051
ret = EPKG_FATAL;
1052
continue;
1053
}
1054
ctx.debug_flags |= f->flag;
1055
}
1056
return (ret);
1057
}
1058
1059
static bool
1060
config_validate_shlib_provide_paths() {
1061
const char *config_options[] = {
1062
"SHLIB_PROVIDE_PATHS_NATIVE",
1063
"SHLIB_PROVIDE_PATHS_COMPAT_32",
1064
"SHLIB_PROVIDE_PATHS_COMPAT_LINUX",
1065
"SHLIB_PROVIDE_PATHS_COMPAT_LINUX_32",
1066
NULL,
1067
};
1068
bool valid = true;
1069
for (const char **option = config_options; *option != NULL; option++) {
1070
const ucl_object_t *paths = pkg_config_get(*option);
1071
const ucl_object_t *cur;
1072
ucl_object_iter_t it = NULL;
1073
while ((cur = ucl_object_iterate(paths, &it, true))) {
1074
const char *path = ucl_object_tostring(cur);
1075
if (path[0] != '/') {
1076
pkg_emit_error("Invalid value for config option %s, "
1077
"'%s' is not an absolute path.",
1078
*option, path);
1079
valid = false;
1080
}
1081
}
1082
}
1083
return valid;
1084
}
1085
1086
/* Parses ABI_FILE, ABI, ALTABI, and OSVERSION from the given ucl file and sets
1087
* the values in the environment. These values must be parsed separately from
1088
* the rest of the config because they are made available as variable expansions
1089
* when parsing the rest of the config (See config_parser_vars_register()). */
1090
static void
1091
config_parse_abi_options(int conffd)
1092
{
1093
if (conffd < 0) {
1094
return;
1095
}
1096
1097
struct ucl_parser *p = ucl_parser_new(0);
1098
1099
if (!ucl_parser_add_fd(p, conffd)) {
1100
pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
1101
}
1102
1103
ucl_object_t *obj = ucl_parser_get_object(p);
1104
1105
ucl_object_iter_t it = NULL;
1106
const ucl_object_t *cur;
1107
xstring *ukey = NULL;
1108
while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
1109
xstring_renew(ukey);
1110
const char *key = ucl_object_key(cur);
1111
for (size_t i = 0; key[i] != '\0'; i++)
1112
fputc(toupper(key[i]), ukey->fp);
1113
fflush(ukey->fp);
1114
1115
if (STREQ(ukey->buf, "ABI_FILE") ||
1116
STREQ(ukey->buf, "ABI") ||
1117
STREQ(ukey->buf, "ALTABI")) {
1118
if (cur->type == UCL_STRING) {
1119
/* Don't overwrite the value already set on the
1120
command line or in the environment */
1121
setenv(ukey->buf, ucl_object_tostring(cur), 0);
1122
} else {
1123
pkg_emit_error("Malformed key %s, got '%s' expecting "
1124
"'string', ignoring", key,
1125
type_to_string(cur->type));
1126
}
1127
} else if (STREQ(ukey->buf, "OSVERSION")) {
1128
if (cur->type == UCL_INT) {
1129
int64_t osversion = ucl_object_toint(cur);
1130
char *str_osversion;
1131
xasprintf(&str_osversion, "%" PRIi64, osversion);
1132
/* Don't overwrite the value already set on the
1133
command line or in the environment */
1134
setenv(ukey->buf, str_osversion, 0);
1135
free(str_osversion);
1136
} else {
1137
pkg_emit_error("Malformed key %s, got '%s' expecting "
1138
"'integer', ignoring", key,
1139
type_to_string(cur->type));
1140
}
1141
1142
1143
}
1144
}
1145
1146
ucl_object_unref(obj);
1147
ucl_parser_free(p);
1148
}
1149
1150
static bool
1151
config_init_abi(struct pkg_abi *abi)
1152
{
1153
if (getenv("ALTABI") != NULL) {
1154
pkg_emit_error("Setting ALTABI manually is no longer supported, "
1155
"set ABI and OSVERSION or ABI_FILE instead.");
1156
}
1157
1158
const char *env_abi_file = getenv("ABI_FILE");
1159
const char *env_abi_string = getenv("ABI");
1160
const char *env_osversion_string = getenv("OSVERSION");
1161
1162
if (env_abi_file != NULL && env_abi_string != NULL) {
1163
pkg_emit_error("Both ABI_FILE and ABI are set, ABI_FILE overrides ABI");
1164
}
1165
1166
if (env_abi_file != NULL && env_osversion_string != NULL) {
1167
pkg_emit_error("Both ABI_FILE and OSVERSION are set, ABI_FILE overrides OSVERSION");
1168
}
1169
1170
if (env_abi_string != NULL) {
1171
if (!pkg_abi_from_string(abi, env_abi_string)) {
1172
return (false);
1173
}
1174
1175
if (abi->os == PKG_OS_FREEBSD) {
1176
if (env_osversion_string == NULL) {
1177
pkg_emit_error("Setting ABI requires setting OSVERSION, guessing the OSVERSION as: %d",
1178
pkg_abi_get_freebsd_osversion(abi));
1179
return (true);
1180
}
1181
1182
const char *errstr = NULL;
1183
int env_osversion = strtonum(env_osversion_string, 1, INT_MAX, &errstr);
1184
if (errstr != NULL) {
1185
pkg_emit_error("Invalid OSVERSION %s, %s", env_osversion_string, errstr);
1186
return (false);
1187
}
1188
1189
pkg_abi_set_freebsd_osversion(abi, env_osversion);
1190
} else {
1191
if (env_osversion_string != NULL) {
1192
pkg_emit_notice("OSVERSION is ignored on %s",
1193
pkg_os_to_string(abi->os));
1194
}
1195
}
1196
} else {
1197
if (env_osversion_string != NULL) {
1198
dbg(1, "Setting OSVERSION requires setting ABI as well (ignoring)");
1199
unsetenv("OSVERSION");
1200
}
1201
if (pkg_abi_from_file(abi) != EPKG_OK) {
1202
return (false);
1203
}
1204
}
1205
1206
return (true);
1207
}
1208
1209
int
1210
pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
1211
{
1212
struct ucl_parser *p = NULL;
1213
size_t i;
1214
const char *val = NULL;
1215
const char *buf, *walk, *value, *key, *k;
1216
const char *evkey = NULL;
1217
const char *nsname = NULL;
1218
const char *useragent = NULL;
1219
const char *evpipe = NULL;
1220
const char *url;
1221
struct pkg_repo *repo = NULL;
1222
const ucl_object_t *cur, *object;
1223
ucl_object_t *obj = NULL, *o, *ncfg;
1224
ucl_object_iter_t it = NULL;
1225
xstring *ukey = NULL;
1226
bool fatal_errors = false;
1227
int conffd = -1;
1228
char *tmp = NULL;
1229
size_t ukeylen;
1230
int err = EPKG_OK;
1231
1232
k = NULL;
1233
o = NULL;
1234
if (ctx.rootfd == -1 && (ctx.rootfd = open("/", O_DIRECTORY|O_RDONLY|O_CLOEXEC)) < 0) {
1235
pkg_emit_error("Impossible to open /");
1236
return (EPKG_FATAL);
1237
}
1238
1239
if (parsed != false) {
1240
pkg_emit_error("pkg_init() must only be called once");
1241
return (EPKG_FATAL);
1242
}
1243
1244
if (path == NULL)
1245
conffd = openat(ctx.rootfd, &PREFIX"/etc/pkg.conf"[1], 0);
1246
else
1247
conffd = open(path, O_RDONLY);
1248
if (conffd == -1 && errno != ENOENT) {
1249
pkg_errno("Cannot open %s/%s",
1250
ctx.pkg_rootdir != NULL ? ctx.pkg_rootdir : "",
1251
path);
1252
}
1253
1254
config_parse_abi_options(conffd);
1255
if (!config_init_abi(&ctx.abi)) {
1256
return (EPKG_FATAL);
1257
}
1258
1259
if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
1260
((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
1261
pkg_emit_error("Invalid flags for pkg_init()");
1262
return (EPKG_FATAL);
1263
}
1264
if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
1265
ctx.ip = IPV4;
1266
if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
1267
ctx.ip = IPV6;
1268
1269
config = ucl_object_typed_new(UCL_OBJECT);
1270
1271
for (i = 0; i < c_size; i++) {
1272
switch (c[i].type) {
1273
case PKG_STRING:
1274
tmp = NULL;
1275
if (c[i].def != NULL && c[i].def[0] == '/' &&
1276
ctx.pkg_rootdir != NULL) {
1277
xasprintf(&tmp, "%s%s", ctx.pkg_rootdir, c[i].def);
1278
}
1279
obj = ucl_object_fromstring_common(
1280
c[i].def != NULL ? tmp != NULL ? tmp : c[i].def : "", 0, UCL_STRING_TRIM);
1281
free(tmp);
1282
ucl_object_insert_key(config, obj,
1283
c[i].key, strlen(c[i].key), false);
1284
break;
1285
case PKG_INT:
1286
ucl_object_insert_key(config,
1287
ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
1288
c[i].key, strlen(c[i].key), false);
1289
break;
1290
case PKG_BOOL:
1291
ucl_object_insert_key(config,
1292
ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
1293
c[i].key, strlen(c[i].key), false);
1294
break;
1295
case PKG_OBJECT:
1296
obj = ucl_object_typed_new(UCL_OBJECT);
1297
if (c[i].def != NULL) {
1298
walk = buf = c[i].def;
1299
while ((buf = strchr(buf, ',')) != NULL) {
1300
key = walk;
1301
value = walk;
1302
while (*value != ',') {
1303
if (*value == '=')
1304
break;
1305
value++;
1306
}
1307
ucl_object_insert_key(obj,
1308
ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
1309
key, value - key, false);
1310
buf++;
1311
walk = buf;
1312
}
1313
key = walk;
1314
value = walk;
1315
while (*value != ',') {
1316
if (*value == '=')
1317
break;
1318
value++;
1319
}
1320
if (o == NULL)
1321
o = ucl_object_typed_new(UCL_OBJECT);
1322
ucl_object_insert_key(o,
1323
ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
1324
key, value - key, false);
1325
}
1326
ucl_object_insert_key(config, obj,
1327
c[i].key, strlen(c[i].key), false);
1328
break;
1329
case PKG_ARRAY:
1330
obj = ucl_object_typed_new(UCL_ARRAY);
1331
if (c[i].def != NULL) {
1332
walk = buf = c[i].def;
1333
while ((buf = strchr(buf, ',')) != NULL) {
1334
ucl_array_append(obj,
1335
ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
1336
buf++;
1337
walk = buf;
1338
}
1339
ucl_array_append(obj,
1340
ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
1341
}
1342
ucl_object_insert_key(config, obj,
1343
c[i].key, strlen(c[i].key), false);
1344
break;
1345
}
1346
}
1347
1348
p = ucl_parser_new(0);
1349
1350
struct config_parser_vars *parser_vars = config_parser_vars_register(p);
1351
1352
errno = 0;
1353
obj = NULL;
1354
if (conffd != -1) {
1355
if (!ucl_parser_add_fd(p, conffd)) {
1356
pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
1357
}
1358
close(conffd);
1359
}
1360
1361
obj = ucl_parser_get_object(p);
1362
ncfg = NULL;
1363
ukey = NULL;
1364
while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
1365
xstring_renew(ukey);
1366
key = ucl_object_key(cur);
1367
for (i = 0; key[i] != '\0'; i++)
1368
fputc(toupper(key[i]), ukey->fp);
1369
fflush(ukey->fp);
1370
ukeylen = strlen(ukey->buf);
1371
object = ucl_object_find_keyl(config, ukey->buf, ukeylen);
1372
1373
if (STREQ(ukey->buf, "PACKAGESITE") ||
1374
STREQ(ukey->buf, "PUBKEY") ||
1375
STREQ(ukey->buf, "MIRROR_TYPE")) {
1376
pkg_emit_error("%s in pkg.conf is no longer "
1377
"supported. Convert to the new repository style."
1378
" See pkg.conf(5)", ukey->buf);
1379
fatal_errors = true;
1380
continue;
1381
}
1382
1383
if (STREQ(ukey->buf, "ABI_FILE") ||
1384
STREQ(ukey->buf, "ABI") ||
1385
STREQ(ukey->buf, "ALTABI") ||
1386
STREQ(ukey->buf, "OSVERSION")) {
1387
continue; /* Already parsed in config_parse_abi_options() */
1388
}
1389
1390
/* ignore unknown keys */
1391
if (object == NULL)
1392
continue;
1393
1394
if (object->type != cur->type) {
1395
pkg_emit_error("Malformed key %s, got '%s' expecting "
1396
"'%s', ignoring", key,
1397
type_to_string(cur->type),
1398
type_to_string(object->type));
1399
continue;
1400
}
1401
1402
if (ncfg == NULL)
1403
ncfg = ucl_object_typed_new(UCL_OBJECT);
1404
ucl_object_insert_key(ncfg, ucl_object_copy(cur), ukey->buf,
1405
ukeylen, true);
1406
}
1407
xstring_free(ukey);
1408
1409
if (fatal_errors) {
1410
ucl_object_unref(ncfg);
1411
ucl_parser_free(p);
1412
err = EPKG_FATAL;
1413
goto out;
1414
}
1415
1416
if (ncfg != NULL) {
1417
it = NULL;
1418
while (( cur = ucl_iterate_object(ncfg, &it, true))) {
1419
key = ucl_object_key(cur);
1420
ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
1421
}
1422
}
1423
ncfg = NULL;
1424
it = NULL;
1425
while ((cur = ucl_iterate_object(config, &it, true))) {
1426
o = NULL;
1427
key = ucl_object_key(cur);
1428
val = getenv(key);
1429
if (val == NULL)
1430
continue;
1431
switch (cur->type) {
1432
case UCL_STRING:
1433
o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
1434
break;
1435
case UCL_INT:
1436
o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
1437
if (o->type != UCL_INT) {
1438
pkg_emit_error("Invalid type for environment "
1439
"variable %s, got %s, while expecting an integer",
1440
key, val);
1441
ucl_object_unref(o);
1442
continue;
1443
}
1444
break;
1445
case UCL_BOOLEAN:
1446
o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
1447
if (o->type != UCL_BOOLEAN) {
1448
pkg_emit_error("Invalid type for environment "
1449
"variable %s, got %s, while expecting a boolean",
1450
key, val);
1451
ucl_object_unref(o);
1452
continue;
1453
}
1454
break;
1455
case UCL_OBJECT:
1456
o = ucl_object_typed_new(UCL_OBJECT);
1457
walk = buf = val;
1458
while ((buf = strchr(buf, ',')) != NULL) {
1459
k = walk;
1460
value = walk;
1461
while (*value != ',') {
1462
if (*value == '=')
1463
break;
1464
value++;
1465
}
1466
ucl_object_insert_key(o,
1467
ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
1468
k, value - k, false);
1469
buf++;
1470
walk = buf;
1471
}
1472
k = walk;
1473
value = walk;
1474
while (*value != '\0') {
1475
if (*value == '=')
1476
break;
1477
value++;
1478
}
1479
ucl_object_insert_key(o,
1480
ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
1481
k, value - k, false);
1482
break;
1483
case UCL_ARRAY:
1484
o = ucl_object_typed_new(UCL_ARRAY);
1485
walk = buf = val;
1486
while ((buf = strchr(buf, ',')) != NULL) {
1487
ucl_array_append(o,
1488
ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
1489
buf++;
1490
walk = buf;
1491
}
1492
ucl_array_append(o,
1493
ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
1494
break;
1495
default:
1496
/* ignore other types */
1497
break;
1498
}
1499
if (o != NULL) {
1500
if (ncfg == NULL)
1501
ncfg = ucl_object_typed_new(UCL_OBJECT);
1502
ucl_object_insert_key(ncfg, o, key, strlen(key), true);
1503
}
1504
}
1505
1506
if (ncfg != NULL) {
1507
it = NULL;
1508
while (( cur = ucl_iterate_object(ncfg, &it, true))) {
1509
key = ucl_object_key(cur);
1510
ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
1511
}
1512
ucl_object_unref(ncfg);
1513
}
1514
1515
disable_plugins_if_static();
1516
1517
parsed = true;
1518
ucl_object_unref(obj);
1519
ucl_parser_free(p);
1520
1521
if (!config_validate_shlib_provide_paths()) {
1522
err = EPKG_FATAL;
1523
goto out;
1524
}
1525
1526
{
1527
/* Even though we no longer support setting ABI/ALTABI/OSVERSION
1528
in the pkg.conf config file, we still need to expose these
1529
values through e.g. `pkg config ABI`. */
1530
char *abi_string = pkg_abi_to_string(&ctx.abi);
1531
char altabi_string[BUFSIZ];
1532
pkg_arch_to_legacy(abi_string, altabi_string, sizeof(altabi_string));
1533
1534
ucl_object_insert_key(config,
1535
ucl_object_fromstring(abi_string), "ABI", 0, true);
1536
ucl_object_insert_key(config,
1537
ucl_object_fromstring(altabi_string), "ALTABI", 0, true);
1538
1539
free(abi_string);
1540
1541
if (ctx.abi.os == PKG_OS_FREEBSD) {
1542
char *osversion;
1543
xasprintf(&osversion, "%d", pkg_abi_get_freebsd_osversion(&ctx.abi));
1544
ucl_object_insert_key(config,
1545
ucl_object_fromstring(osversion), "OSVERSION", 0, true);
1546
free(osversion);
1547
}
1548
}
1549
1550
dbg(1, "pkg initialized");
1551
1552
/* Start the event pipe */
1553
evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
1554
if (evpipe != NULL)
1555
connect_evpipe(evpipe);
1556
1557
ctx.debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));
1558
err = config_validate_debug_flags(ucl_object_find_key(config, "PKG_DEBUG_FLAGS"));
1559
if (err != EPKG_OK)
1560
goto out;
1561
ctx.developer_mode = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
1562
ctx.metalog = pkg_object_string(pkg_config_get("METALOG"));
1563
ctx.dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
1564
ctx.cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));
1565
ctx.backup_libraries = pkg_object_bool(pkg_config_get("BACKUP_LIBRARIES"));
1566
ctx.backup_library_path = pkg_object_string(pkg_config_get("BACKUP_LIBRARY_PATH"));
1567
ctx.triggers = pkg_object_bool(pkg_config_get("PKG_TRIGGERS_ENABLE"));
1568
ctx.triggers_path = pkg_object_string(pkg_config_get("PKG_TRIGGERS_DIR"));
1569
ctx.compression_format = pkg_object_string(pkg_config_get("COMPRESSION_FORMAT"));
1570
ctx.compression_level = pkg_object_int(pkg_config_get("COMPRESSION_LEVEL"));
1571
ctx.compression_threads = pkg_object_int(pkg_config_get("COMPRESSION_THREADS"));
1572
ctx.archive_symlink = pkg_object_bool(pkg_config_get("ARCHIVE_SYMLINK"));
1573
ctx.repo_accept_legacy_pkg = pkg_object_bool(pkg_config_get("REPO_ACCEPT_LEGACY_PKG"));
1574
ctx.no_version_for_deps = (getenv("PKG_NO_VERSION_FOR_DEPS") != NULL);
1575
ctx.track_linux_compat_shlibs = pkg_object_bool(pkg_config_get("TRACK_LINUX_COMPAT_SHLIBS"));
1576
1577
it = NULL;
1578
object = ucl_object_find_key(config, "PKG_ENV");
1579
while ((cur = ucl_iterate_object(object, &it, true))) {
1580
evkey = ucl_object_key(cur);
1581
dbg(1, "Setting env var: %s", evkey);
1582
if (evkey != NULL && evkey[0] != '\0')
1583
setenv(evkey, ucl_object_tostring_forced(cur), 1);
1584
}
1585
1586
/* Set user-agent */
1587
useragent = pkg_object_string(pkg_config_get("HTTP_USER_AGENT"));
1588
if (useragent != NULL)
1589
setenv("HTTP_USER_AGENT", useragent, 1);
1590
else
1591
setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);
1592
1593
/* load the repositories */
1594
load_repositories(reposdir, flags);
1595
1596
object = ucl_object_find_key(config, "REPOSITORIES");
1597
while ((cur = ucl_iterate_object(object, &it, true))) {
1598
add_repo_obj(cur, path, flags);
1599
}
1600
1601
/* validate the different scheme */
1602
while (pkg_repos(&repo) == EPKG_OK) {
1603
object = ucl_object_find_key(config, "VALID_URL_SCHEME");
1604
url = pkg_repo_url(repo);
1605
buf = strstr(url, ":/");
1606
if (buf == NULL) {
1607
pkg_emit_error("invalid url: %s", url);
1608
err = EPKG_FATAL;
1609
goto out;
1610
}
1611
fatal_errors = true;
1612
it = NULL;
1613
while ((cur = ucl_iterate_object(object, &it, true))) {
1614
if (strncmp(url, ucl_object_tostring_forced(cur),
1615
buf - url) == 0) {
1616
fatal_errors = false;
1617
break;
1618
}
1619
}
1620
1621
if (fatal_errors) {
1622
pkg_emit_error("invalid scheme %.*s", (int)(buf - url), url);
1623
err = EPKG_FATAL;
1624
goto out;
1625
}
1626
}
1627
1628
/* bypass resolv.conf with specified NAMESERVER if any */
1629
nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
1630
if (nsname != NULL && set_nameserver(nsname) != 0)
1631
pkg_emit_error("Unable to set nameserver, ignoring");
1632
1633
/* Open metalog */
1634
if (ctx.metalog != NULL && metalog_open(ctx.metalog) != EPKG_OK) {
1635
err = EPKG_FATAL;
1636
goto out;
1637
}
1638
1639
out:
1640
config_parser_vars_free(parser_vars);
1641
1642
return err;
1643
}
1644
1645
static struct pkg_repo_ops*
1646
pkg_repo_find_type(const char *type)
1647
{
1648
struct pkg_repo_ops *found = NULL, **cur;
1649
1650
/* Default repo type */
1651
if (type == NULL)
1652
return (pkg_repo_find_type("binary"));
1653
1654
cur = &repos_ops[0];
1655
while (*cur != NULL) {
1656
if (STRIEQ(type, (*cur)->type)) {
1657
found = *cur;
1658
}
1659
cur ++;
1660
}
1661
1662
if (found == NULL)
1663
return (pkg_repo_find_type("binary"));
1664
1665
return (found);
1666
}
1667
1668
static struct pkg_repo *
1669
pkg_repo_new(const char *name, const char *url, const char *type)
1670
{
1671
struct pkg_repo *r;
1672
1673
r = xcalloc(1, sizeof(struct pkg_repo));
1674
r->dfd = -1;
1675
r->ops = pkg_repo_find_type(type);
1676
r->url = xstrdup(url);
1677
r->signature_type = SIG_NONE;
1678
r->mirror_type = NOMIRROR;
1679
r->enable = true;
1680
r->meta = pkg_repo_meta_default();
1681
r->name = xstrdup(name);
1682
DL_APPEND(repos, r);
1683
1684
return (r);
1685
}
1686
1687
static void
1688
pkg_repo_overwrite(struct pkg_repo *r, const char *name, const char *url,
1689
const char *type)
1690
{
1691
1692
free(r->name);
1693
r->name = xstrdup(name);
1694
if (url != NULL) {
1695
free(r->url);
1696
r->url = xstrdup(url);
1697
}
1698
r->ops = pkg_repo_find_type(type);
1699
}
1700
1701
static void
1702
pkg_repo_free(struct pkg_repo *r)
1703
{
1704
free(r->url);
1705
free(r->name);
1706
free(r->pubkey);
1707
free(r->fingerprints);
1708
pkg_repo_meta_free(r->meta);
1709
if (r->fetcher != NULL && r->fetcher->cleanup != NULL)
1710
r->fetcher->cleanup(r);
1711
vec_free_and_free(&r->env, pkg_kv_free);
1712
free(r->dbpath);
1713
free(r);
1714
}
1715
1716
void
1717
pkg_shutdown(void)
1718
{
1719
if (!parsed) {
1720
pkg_emit_error("pkg_shutdown() must be called after pkg_init()");
1721
_exit(EXIT_FAILURE);
1722
/* NOTREACHED */
1723
}
1724
1725
metalog_close();
1726
ucl_object_unref(config);
1727
LL_FREE(repos, pkg_repo_free);
1728
1729
if (ctx.rootfd != -1) {
1730
close(ctx.rootfd);
1731
ctx.rootfd = -1;
1732
}
1733
if (ctx.cachedirfd != -1) {
1734
close(ctx.cachedirfd);
1735
ctx.cachedirfd = -1;
1736
}
1737
if (ctx.pkg_dbdirfd != -1) {
1738
close(ctx.pkg_dbdirfd);
1739
ctx.pkg_dbdirfd = -1;
1740
}
1741
1742
parsed = false;
1743
1744
return;
1745
}
1746
1747
int
1748
pkg_repos_total_count(void)
1749
{
1750
int cnt = 0;
1751
struct pkg_repo *r;
1752
1753
LL_COUNT(repos, r, cnt);
1754
return (cnt);
1755
}
1756
1757
int
1758
pkg_repos_activated_count(void)
1759
{
1760
struct pkg_repo *r = NULL;
1761
int count = 0;
1762
1763
LL_FOREACH(repos, r) {
1764
if (r->enable)
1765
count++;
1766
}
1767
1768
return (count);
1769
}
1770
1771
int
1772
pkg_repos(struct pkg_repo **r)
1773
{
1774
if (*r == NULL)
1775
*r = repos;
1776
else
1777
*r = (*r)->next;
1778
if (*r == NULL)
1779
return (EPKG_END);
1780
return (EPKG_OK);
1781
}
1782
1783
const char *
1784
pkg_repo_url(struct pkg_repo *r)
1785
{
1786
return (r->url);
1787
}
1788
1789
/* The basename of the sqlite DB file and the database name */
1790
const char *
1791
pkg_repo_name(struct pkg_repo *r)
1792
{
1793
return (r->name);
1794
}
1795
1796
const char *
1797
pkg_repo_key(struct pkg_repo *r)
1798
{
1799
return (r->pubkey);
1800
}
1801
1802
const char *
1803
pkg_repo_fingerprints(struct pkg_repo *r)
1804
{
1805
return (r->fingerprints);
1806
}
1807
1808
signature_t
1809
pkg_repo_signature_type(struct pkg_repo *r)
1810
{
1811
return (r->signature_type);
1812
}
1813
1814
bool
1815
pkg_repo_enabled(struct pkg_repo *r)
1816
{
1817
return (r->enable);
1818
}
1819
1820
mirror_t
1821
pkg_repo_mirror_type(struct pkg_repo *r)
1822
{
1823
return (r->mirror_type);
1824
}
1825
1826
int
1827
pkg_repo_priority(struct pkg_repo *r)
1828
{
1829
return (r->priority);
1830
}
1831
1832
unsigned int
1833
pkg_repo_ip_version(struct pkg_repo *r)
1834
{
1835
if (r->ip == IPV4)
1836
return 4;
1837
if (r->ip == IPV6)
1838
return 6;
1839
return 0;
1840
}
1841
1842
/* Locate the repo by the file basename / database name */
1843
struct pkg_repo *
1844
pkg_repo_find(const char *reponame)
1845
{
1846
struct pkg_repo *r;
1847
1848
LL_FOREACH(repos, r) {
1849
if (STREQ(r->name, reponame))
1850
return (r);
1851
}
1852
return (NULL);
1853
}
1854
1855
int64_t
1856
pkg_set_debug_level(int64_t new_debug_level) {
1857
int64_t old_debug_level = ctx.debug_level;
1858
1859
ctx.debug_level = new_debug_level;
1860
return old_debug_level;
1861
}
1862
1863
int
1864
pkg_set_ignore_osversion(bool ignore) {
1865
if (pkg_initialized())
1866
return (EPKG_FATAL);
1867
1868
ucl_object_insert_key(config,
1869
ucl_object_frombool(ignore),
1870
"IGNORE_OSVERSION", sizeof("IGNORE_OSVERSION"), false);
1871
1872
return (EPKG_OK);
1873
}
1874
1875
int
1876
pkg_set_rootdir(const char *rootdir) {
1877
if (pkg_initialized())
1878
return (EPKG_FATAL);
1879
1880
if (ctx.rootfd != -1)
1881
close(ctx.rootfd);
1882
1883
if ((ctx.rootfd = open(rootdir, O_DIRECTORY|O_RDONLY|O_CLOEXEC)) < 0) {
1884
pkg_emit_error("Impossible to open %s", rootdir);
1885
return (EPKG_FATAL);
1886
}
1887
ctx.pkg_rootdir = rootdir;
1888
ctx.defer_triggers = true;
1889
1890
return (EPKG_OK);
1891
}
1892
1893
int
1894
pkg_set_ischrooted(bool ischrooted) {
1895
if (pkg_initialized())
1896
return (EPKG_FATAL);
1897
1898
ctx.ischrooted = ischrooted;
1899
1900
return (EPKG_OK);
1901
}
1902
1903
const char *
1904
pkg_get_cachedir(void)
1905
{
1906
1907
return (ctx.cachedir);
1908
}
1909
1910
int
1911
pkg_get_cachedirfd(void)
1912
{
1913
1914
if (ctx.cachedirfd == -1) {
1915
/*
1916
* do not check the value as if we cannot open it means
1917
* it has not been created yet
1918
*/
1919
ctx.cachedirfd = open(ctx.cachedir, O_DIRECTORY|O_CLOEXEC);
1920
}
1921
1922
return (ctx.cachedirfd);
1923
}
1924
1925
int
1926
pkg_get_dbdirfd(void)
1927
{
1928
1929
if (ctx.pkg_dbdirfd == -1) {
1930
/*
1931
* do not check the value as if we cannot open it means
1932
* it has not been created yet
1933
*/
1934
ctx.pkg_dbdirfd = open(ctx.dbdir, O_DIRECTORY|O_CLOEXEC);
1935
}
1936
1937
return (ctx.pkg_dbdirfd);
1938
}
1939
1940
int
1941
pkg_get_reposdirfd(void)
1942
{
1943
int dbfd = pkg_get_dbdirfd();
1944
if (dbfd == -1)
1945
return (-1);
1946
if (ctx.pkg_reposdirfd == -1) {
1947
ctx.pkg_reposdirfd = openat(dbfd, "repos", O_DIRECTORY|O_CLOEXEC);
1948
if (ctx.pkg_reposdirfd == -1) {
1949
if (mkdirat(dbfd, "repos", 0755) == -1) {
1950
return (-1);
1951
}
1952
ctx.pkg_reposdirfd = openat(dbfd, "repos", O_DIRECTORY|O_CLOEXEC);
1953
}
1954
}
1955
return (ctx.pkg_reposdirfd);
1956
}
1957
1958
int
1959
pkg_open_devnull(void) {
1960
pkg_close_devnull();
1961
1962
if ((ctx.devnullfd = open("/dev/null", O_RDWR)) < 0) {
1963
pkg_emit_error("Cannot open /dev/null");
1964
return (EPKG_FATAL);
1965
}
1966
1967
return (EPKG_OK);
1968
}
1969
1970
void
1971
pkg_close_devnull(void) {
1972
if (ctx.devnullfd != 1) {
1973
close(ctx.devnullfd);
1974
}
1975
1976
return;
1977
}
1978
1979