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