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