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