pkg_ports.c
1 /*- 2 * Copyright (c) 2011-2020 Baptiste Daroussin <bapt@FreeBSD.org> 3 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org> 4 * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "pkg_config.h" 30 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 35 #include <assert.h> 36 #include <ctype.h> 37 #include <errno.h> 38 #include <regex.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <stdbool.h> 42 #include <string.h> 43 #include <fcntl.h> 44 #include <unistd.h> 45 #include <err.h> 46 47 #include "pkg.h" 48 #include "private/utils.h" 49 #include "private/event.h" 50 #include "private/pkg.h" 51 #include "private/lua.h" 52 53 static ucl_object_t *keyword_schema = NULL; 54 55 static int override_prefix(struct plist *, char *, struct file_attr *); 56 static int setprefix(struct plist *, char *, struct file_attr *); 57 static int dir(struct plist *, char *, struct file_attr *); 58 static int file(struct plist *, char *, struct file_attr *); 59 static int setmod(struct plist *, char *, struct file_attr *); 60 static int setowner(struct plist *, char *, struct file_attr *); 61 static int setgroup(struct plist *, char *, struct file_attr *); 62 static int comment_key(struct plist *, char *, struct file_attr *); 63 static int config(struct plist *, char *, struct file_attr *); 64 /* compat with old packages */ 65 static int name_key(struct plist *, char *, struct file_attr *); 66 static int include_plist(struct plist *, char *, struct file_attr *); 67 static int add_variable(struct plist *, char *, struct file_attr *); 68 69 static struct action_cmd { 70 const char *name; 71 int (*perform)(struct plist *, char *, struct file_attr *); 72 size_t namelen; 73 } list_actions[] = { 74 { "setprefix", setprefix, 9}, 75 { "dir", dir, 3 }, 76 { "file", file, 4 }, 77 { "setmode", setmod, 6 }, 78 { "setowner", setowner, 8 }, 79 { "setgroup", setgroup, 8 }, 80 { "comment", comment_key, 7 }, 81 { "config", config, 6 }, 82 { "override_prefix", override_prefix, 15 }, 83 /* compat with old packages */ 84 { "name", name_key, 4 }, 85 { NULL, NULL, 0 } 86 }; 87 88 static ucl_object_t * 89 keyword_open_schema(void) 90 { 91 struct ucl_parser *parser; 92 static const char keyword_schema_str[] = "" 93 "{" 94 " type = object;" 95 " properties {" 96 " actions = { " 97 " type = array; " 98 " items = { type = string }; " 99 " uniqueItems: true " 100 " }; " 101 " actions_script = { type = string }; " 102 " arguments = { type = boolean }; " 103 " preformat_arguments { type = boolean }; " 104 " prepackaging = { type = string }; " 105 " deprecated = { type = boolean }; " 106 " deprecation_message = { type = string }; " 107 " attributes = { " 108 " type = object; " 109 " properties { " 110 " owner = { type = string }; " 111 " group = { type = string }; " 112 " mode = { oneOf: [ { type = integer }, { type = string } ] }; " 113 " }" 114 " }; " 115 " pre-install = { type = string }; " 116 " post-install = { type = string }; " 117 " pre-deinstall = { type = string }; " 118 " post-deinstall = { type = string }; " 119 " pre-install-lua = { type = string }; " 120 " post-install-lua = { type = string }; " 121 " pre-deinstall-lua = { type = string }; " 122 " post-deinstall-lua = { type = string }; " 123 " messages: {" 124 " type = array; " 125 " items = {" 126 " type = object;" 127 " properties {" 128 " message = { type = string };" 129 " type = { enum = [ upgrade, remove, install ] };" 130 " };" 131 " required [ message ];" 132 " };" 133 " };" 134 " }" 135 "}"; 136 137 if (keyword_schema != NULL) 138 return (keyword_schema); 139 140 parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS); 141 if (!ucl_parser_add_chunk(parser, keyword_schema_str, 142 sizeof(keyword_schema_str) -1)) { 143 pkg_emit_error("Cannot parse schema for keywords: %s", 144 ucl_parser_get_error(parser)); 145 ucl_parser_free(parser); 146 return (NULL); 147 } 148 149 keyword_schema = ucl_parser_get_object(parser); 150 ucl_parser_free(parser); 151 152 return (keyword_schema); 153 } 154 155 void * 156 parse_mode(const char *str) 157 { 158 if (str == NULL || *str == '\0') 159 return (NULL); 160 161 if (strstr(str, "u+") || strstr(str, "o+") || strstr(str, "g+") || 162 strstr(str, "u-") || strstr(str, "o-") || strstr(str, "g-") || 163 strstr(str, "a+") || strstr(str, "a-")) 164 return (NULL); 165 166 return (setmode(str)); 167 } 168 169 void 170 free_file_attr(struct file_attr *a) 171 { 172 if (a == NULL) 173 return; 174 free(a->owner); 175 free(a->group); 176 free(a); 177 } 178 179 static int 180 override_prefix(struct plist *p, char *line, struct file_attr *a __unused) 181 { 182 char *np = NULL; 183 184 if (line[0] != '\0') 185 np = xstrdup(line); 186 free(p->pkg->oprefix); 187 p->pkg->oprefix = np; 188 return (EPKG_OK); 189 } 190 191 static int 192 setprefix(struct plist *p, char *line, struct file_attr *a __unused) 193 { 194 /* if no arguments then set default prefix */ 195 if (line[0] == '\0') { 196 strlcpy(p->prefix, p->pkg->prefix, sizeof(p->prefix)); 197 } 198 else 199 strlcpy(p->prefix, line, sizeof(p->prefix)); 200 201 if (p->pkg->prefix == NULL) 202 p->pkg->prefix = xstrdup(line); 203 204 p->slash = p->prefix[strlen(p->prefix) -1] == '/' ? "" : "/"; 205 206 fprintf(p->post_install_buf->fp, "cd %s\n", p->prefix); 207 fprintf(p->pre_deinstall_buf->fp, "cd %s\n", p->prefix); 208 fprintf(p->post_deinstall_buf->fp, "cd %s\n", p->prefix); 209 210 return (EPKG_OK); 211 } 212 213 static int 214 name_key(struct plist *p, char *line, struct file_attr *a __unused) 215 { 216 char *tmp; 217 218 if (p->pkg->name != NULL) { 219 return (EPKG_OK); 220 } 221 tmp = strrchr(line, '-'); 222 if (tmp == NULL) { 223 pkg_emit_error("Invalid @name key: '%s' expecting <name>-<version>", line); 224 return (EPKG_FATAL); 225 } 226 tmp[0] = '\0'; 227 tmp++; 228 p->pkg->name = xstrdup(line); 229 free(p->pkg->uid); 230 p->pkg->uid = xstrdup(line); 231 p->pkg->version = xstrdup(tmp); 232 233 return (EPKG_OK); 234 } 235 236 static int 237 lua_meta(lua_State *L, 238 int (*perform)(struct plist *, char *, struct file_attr *)) 239 { 240 int n = lua_gettop(L); 241 int ret; 242 luaL_argcheck(L, n == 1, n > 1 ? 2 : n, 243 "takes exactly one argument"); 244 char *str = xstrdup(luaL_checkstring(L, 1)); 245 lua_getglobal(L, "plist"); 246 struct plist *p = lua_touserdata(L, -1); 247 lua_getglobal(L, "attrs"); 248 struct file_attr *a = lua_touserdata(L, -1); 249 250 ret = perform(p, str, a); 251 free(str); 252 lua_pushboolean(L, ret == EPKG_OK); 253 return (1); 254 } 255 256 static int 257 lua_dir(lua_State *L) 258 { 259 return (lua_meta(L, dir)); 260 } 261 262 static int 263 lua_config(lua_State *L) { 264 return (lua_meta(L, config)); 265 } 266 267 static int 268 lua_file(lua_State *L) { 269 return (lua_meta(L, file)); 270 } 271 272 273 static int 274 dir(struct plist *p, char *line, struct file_attr *a) 275 { 276 char path[MAXPATHLEN+1]; 277 char *cp; 278 struct stat st; 279 int ret = EPKG_OK; 280 281 cp = line + strlen(line) -1; 282 while (cp > line && isspace(*cp)) { 283 *cp = 0; 284 cp--; 285 } 286 287 if (line[0] == '/') 288 snprintf(path, sizeof(path), "%s/", line); 289 else 290 snprintf(path, sizeof(path), "%s%s%s/", p->prefix, p->slash, 291 line); 292 293 if (fstatat(p->stagefd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW) 294 == -1) { 295 pkg_errno("Unable to access file %s%s", 296 p->stage ? p->stage: "", path); 297 if (p->stage != NULL) 298 ret = EPKG_FATAL; 299 if (ctx.developer_mode) { 300 pkg_emit_developer_mode("Plist error: @dir %s", line); 301 ret = EPKG_FATAL; 302 } 303 } else { 304 mode_t m = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 305 if (a != NULL) 306 ret = pkg_adddir_attr(p->pkg, path, 307 a->owner ? a->owner : p->uname, 308 a->group ? a->group : p->gname, 309 a->mode ? a->mode : p->perm, 310 a->fflags, true); 311 else { 312 ret = pkg_adddir_attr(p->pkg, path, p->uname, p->gname, 313 p->perm == 0 ? m : p->perm, 0, true); 314 } 315 } 316 317 return (ret); 318 } 319 320 static int 321 meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config) 322 { 323 size_t len; 324 char path[MAXPATHLEN]; 325 ssize_t linklen = 0; 326 char symlink_target[MAXPATHLEN]; 327 struct stat st; 328 char *buf = NULL; 329 bool regular = false; 330 int ret = EPKG_OK; 331 332 len = strlen(line); 333 334 while (isspace(line[len - 1])) 335 line[--len] = '\0'; 336 337 if (line[0] == '/') 338 snprintf(path, sizeof(path), "%s", line); 339 else 340 snprintf(path, sizeof(path), "%s%s%s", p->prefix, 341 p->slash, line); 342 343 if (fstatat(p->stagefd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW) 344 == -1) { 345 pkg_errno("Unable to access file %s%s", 346 p->stage ? p->stage : "", path); 347 if (p->stage != NULL) 348 ret = EPKG_FATAL; 349 if (ctx.developer_mode) { 350 pkg_emit_developer_mode("Plist error, missing file: %s", 351 line); 352 ret = EPKG_FATAL; 353 } 354 return (ret); 355 } 356 buf = NULL; 357 regular = false; 358 359 if (S_ISREG(st.st_mode)) { 360 if (st.st_nlink > 1) 361 regular = !check_for_hardlink(&p->hardlinks, &st); 362 else 363 regular = true; 364 } else if (S_ISLNK(st.st_mode)) { 365 regular = false; 366 linklen = readlinkat(p->stagefd, RELATIVE_PATH(path), 367 symlink_target, sizeof(symlink_target) - 1); 368 if (linklen == -1) { 369 pkg_emit_errno("meta_file", "readlink failed"); 370 return (EPKG_FATAL); 371 } 372 symlink_target[linklen] = '\0'; 373 } 374 375 buf = pkg_checksum_generate_fileat(p->stagefd, RELATIVE_PATH(path), 376 PKG_HASH_TYPE_SHA256_HEX); 377 if (buf == NULL) { 378 return (EPKG_FATAL); 379 } 380 381 if (regular) { 382 p->flatsize += st.st_size; 383 if (is_config) { 384 off_t sz; 385 char *content; 386 file_to_bufferat(p->stagefd, RELATIVE_PATH(path), 387 &content, &sz); 388 ret = pkg_addconfig_file(p->pkg, path, content); 389 if (ret != EPKG_OK) { 390 return (ret); 391 } 392 free(content); 393 } 394 } 395 396 if (S_ISDIR(st.st_mode)) { 397 pkg_emit_error("Plist error, directory listed as a file: %s", 398 line); 399 free(buf); 400 return (EPKG_FATAL); 401 } 402 403 if (a != NULL) { 404 ret = pkg_addfile_attr(p->pkg, path, buf, 405 a->owner ? a->owner : p->uname, 406 a->group ? a->group : p->gname, 407 a->mode ? a->mode : p->perm, 408 a->fflags, st.st_mtim.tv_sec, 409 linklen > 0 ? symlink_target : NULL, 410 true); 411 } else { 412 ret = pkg_addfile_attr(p->pkg, path, buf, p->uname, 413 p->gname, p->perm, 0, st.st_mtim.tv_sec, 414 linklen > 0 ? symlink_target : NULL, 415 true); 416 } 417 418 free(buf); 419 420 return (ret); 421 } 422 423 static int 424 config(struct plist *p, char *line, struct file_attr *a) 425 { 426 return (meta_file(p, line, a, true)); 427 } 428 429 static int 430 file(struct plist *p, char *line, struct file_attr *a) 431 { 432 return (meta_file(p, line, a, false)); 433 } 434 435 static int 436 setmod(struct plist *p, char *line, struct file_attr *a __unused) 437 { 438 void *set; 439 440 p->perm = 0; 441 442 if (line[0] == '\0') 443 return (EPKG_OK); 444 445 if ((set = parse_mode(line)) == NULL) { 446 pkg_emit_error("%s wrong mode value", line); 447 return (EPKG_FATAL); 448 } 449 p->perm = getmode(set, 0); 450 return (EPKG_OK); 451 } 452 453 static int 454 setowner(struct plist *p, char *line, struct file_attr *a __unused) 455 { 456 free(p->uname); 457 if (line[0] == '\0') 458 p->uname = xstrdup("root"); 459 else 460 p->uname = xstrdup(line); 461 return (EPKG_OK); 462 } 463 464 static int 465 setgroup(struct plist *p, char *line, struct file_attr *a __unused) 466 { 467 free(p->gname); 468 if (line[0] == '\0') 469 p->gname = xstrdup("wheel"); 470 else 471 p->gname = xstrdup(line); 472 return (EPKG_OK); 473 } 474 475 static int 476 comment_key(struct plist *p __unused, char *line __unused , struct file_attr *a __unused) 477 { 478 /* ignore md5 will be recomputed anyway */ 479 return (EPKG_OK); 480 } 481 482 static struct keyact { 483 const char *key; 484 int (*action)(struct plist *, char *, struct file_attr *); 485 } keyacts[] = { 486 { "cwd", setprefix }, 487 { "comment", comment_key }, 488 { "config", config }, 489 { "dir", dir }, 490 { "include", include_plist }, 491 { "mode", setmod }, 492 { "owner", setowner }, 493 { "group", setgroup }, 494 { "override_prefix", override_prefix }, 495 { "var", add_variable }, 496 /* old pkg compat */ 497 { "name", name_key }, 498 { NULL, NULL }, 499 }; 500 501 static struct lua_map { 502 const char *key; 503 pkg_lua_script type; 504 } lua_mapping[] = { 505 { "pre-install-lua", PKG_LUA_PRE_INSTALL }, 506 { "post-install-lua", PKG_LUA_POST_INSTALL }, 507 { "pre-deinstall-lua", PKG_LUA_PRE_DEINSTALL }, 508 { "post-deinstall-lua", PKG_LUA_POST_DEINSTALL }, 509 }; 510 511 static struct script_map { 512 const char *key; 513 pkg_script type; 514 } script_mapping[] = { 515 { "pre-install", PKG_SCRIPT_PRE_INSTALL }, 516 { "post-install", PKG_SCRIPT_POST_INSTALL }, 517 { "pre-deinstall", PKG_SCRIPT_PRE_DEINSTALL }, 518 { "post-deinstall", PKG_SCRIPT_POST_DEINSTALL }, 519 }; 520 521 static void 522 populate_keywords(struct plist *p) 523 { 524 struct keyword *k; 525 struct action *a; 526 int i; 527 528 for (i = 0; keyacts[i].key != NULL; i++) { 529 k = xcalloc(1, sizeof(struct keyword)); 530 a = xmalloc(sizeof(struct action)); 531 k->keyword = xstrdup(keyacts[i].key); 532 a->perform = keyacts[i].action; 533 vec_push(&k->actions, a); 534 pkghash_safe_add(p->keywords, k->keyword, k, NULL); 535 } 536 } 537 538 static void 539 keyword_free(struct keyword *k) 540 { 541 free(k->keyword); 542 vec_free_and_free(&k->actions, free); 543 free(k); 544 } 545 546 static int 547 parse_actions(const ucl_object_t *o, struct plist *p, 548 char *line, struct file_attr *a, int argc, char **argv) 549 { 550 const ucl_object_t *cur; 551 const char *actname; 552 ucl_object_iter_t it = NULL; 553 int i, j = 0; 554 int r, rc = EPKG_OK; 555 556 while ((cur = ucl_iterate_object(o, &it, true))) { 557 actname = ucl_object_tostring(cur); 558 for (i = 0; list_actions[i].name != NULL; i++) { 559 if (!strncasecmp(actname, list_actions[i].name, 560 list_actions[i].namelen) && 561 (actname[list_actions[i].namelen ] == '\0' || 562 actname[list_actions[i].namelen ] == '(' )) { 563 actname += list_actions[i].namelen; 564 if (*actname == '(') { 565 if (strspn(actname + 1, "1234567890") 566 != strlen(actname + 1) - 1) { 567 pkg_emit_error( 568 "Invalid argument: " 569 "expecting a number " 570 "got %s", actname); 571 return (EPKG_FATAL); 572 } 573 j = strtol(actname+1, NULL, 10); 574 if (j > argc) { 575 pkg_emit_error( 576 "Invalid argument requested %d" 577 " available: %d", j, argc); 578 return (EPKG_FATAL); 579 } 580 } 581 r = list_actions[i].perform(p, j > 0 ? argv[j - 1] : line, a); 582 if (r != EPKG_OK && rc == EPKG_OK) 583 rc = r; 584 break; 585 } 586 } 587 } 588 589 return (rc); 590 } 591 592 static void 593 parse_attributes(const ucl_object_t *o, struct file_attr **a) 594 { 595 const ucl_object_t *cur; 596 ucl_object_iter_t it = NULL; 597 const char *key; 598 599 if (*a == NULL) 600 *a = xcalloc(1, sizeof(struct file_attr)); 601 602 while ((cur = ucl_iterate_object(o, &it, true))) { 603 key = ucl_object_key(cur); 604 if (key == NULL) 605 continue; 606 if (STRIEQ(key, "owner") && cur->type == UCL_STRING) { 607 free((*a)->owner); 608 (*a)->owner = xstrdup(ucl_object_tostring(cur)); 609 continue; 610 } 611 if (STRIEQ(key, "group") && cur->type == UCL_STRING) { 612 free((*a)->group); 613 (*a)->group = xstrdup(ucl_object_tostring(cur)); 614 continue; 615 } 616 if (STRIEQ(key, "mode")) { 617 if (cur->type == UCL_STRING) { 618 void *set; 619 if ((set = parse_mode(ucl_object_tostring(cur))) == NULL) { 620 pkg_emit_error("Bad format for the mode attribute: %s", ucl_object_tostring(cur)); 621 return; 622 } 623 (*a)->mode = getmode(set, 0); 624 free(set); 625 } else { 626 pkg_emit_error("Expecting a string for the mode attribute, ignored"); 627 } 628 } 629 } 630 } 631 632 static void 633 append_script(struct plist *p, pkg_script t, const char *cmd) 634 { 635 switch (t) { 636 case PKG_SCRIPT_PRE_INSTALL: 637 fprintf(p->pre_install_buf->fp, "%s\n", cmd); 638 break; 639 case PKG_SCRIPT_POST_INSTALL: 640 fprintf(p->post_install_buf->fp, "%s\n", cmd); 641 break; 642 case PKG_SCRIPT_PRE_DEINSTALL: 643 fprintf(p->pre_deinstall_buf->fp, "%s\n", cmd); 644 break; 645 case PKG_SCRIPT_POST_DEINSTALL: 646 fprintf(p->post_deinstall_buf->fp, "%s\n", cmd); 647 break; 648 } 649 } 650 651 static int 652 apply_keyword_file(ucl_object_t *obj, struct plist *p, char *line, struct file_attr *attr) 653 { 654 const ucl_object_t *o, *cur, *elt; 655 ucl_object_iter_t it = NULL; 656 struct pkg_message *msg; 657 char *cmd; 658 const char *l = line; 659 char *formated_line = NULL; 660 char **args = NULL; 661 char *buf, *tofree = NULL; 662 struct file_attr *freeattr = NULL; 663 int spaces, argc = 0; 664 int ret = EPKG_FATAL; 665 666 if ((o = ucl_object_find_key(obj, "arguments")) && ucl_object_toboolean(o)) { 667 spaces = pkg_utils_count_spaces(line); 668 args = xmalloc((spaces + 1)* sizeof(char *)); 669 tofree = buf = xstrdup(line); 670 while (buf != NULL) { 671 args[argc++] = pkg_utils_tokenize(&buf); 672 } 673 } 674 675 if ((o = ucl_object_find_key(obj, "attributes"))) 676 parse_attributes(o, attr != NULL ? &attr : &freeattr); 677 678 if ((o = ucl_object_find_key(obj, "preformat_arguments")) && 679 ucl_object_toboolean(o)) { 680 format_exec_cmd(&formated_line, line, p->prefix, p->last_file, NULL, 0, 681 NULL, false); 682 l = formated_line; 683 } 684 /* add all shell scripts */ 685 for (int i = 0; i < NELEM(script_mapping); i++) { 686 if ((o = ucl_object_find_key(obj, script_mapping[i].key))) { 687 if (format_exec_cmd(&cmd, ucl_object_tostring(o), p->prefix, 688 p->last_file, l, argc, args, false) != EPKG_OK) 689 goto keywords_cleanup; 690 append_script(p, script_mapping[i].type, cmd); 691 free(cmd); 692 } 693 } 694 695 /* add all lua scripts */ 696 for (int i = 0; i < NELEM(lua_mapping); i++) { 697 if ((o = ucl_object_find_key(obj, lua_mapping[i].key))) { 698 if (format_exec_cmd(&cmd, ucl_object_tostring(o), p->prefix, 699 p->last_file, l, argc, args, true) != EPKG_OK) 700 goto keywords_cleanup; 701 pkg_add_lua_script(p->pkg, cmd, lua_mapping[i].type); 702 free(cmd); 703 } 704 } 705 free(formated_line); 706 707 if ((o = ucl_object_find_key(obj, "messages"))) { 708 while ((cur = ucl_iterate_object(o, &it, true))) { 709 elt = ucl_object_find_key(cur, "message"); 710 msg = xcalloc(1, sizeof(*msg)); 711 msg->str = xstrdup(ucl_object_tostring(elt)); 712 msg->type = PKG_MESSAGE_ALWAYS; 713 elt = ucl_object_find_key(cur, "type"); 714 if (elt != NULL) { 715 if (STRIEQ(ucl_object_tostring(elt), "install")) 716 msg->type = PKG_MESSAGE_INSTALL; 717 else if (STRIEQ(ucl_object_tostring(elt), "remove")) 718 msg->type = PKG_MESSAGE_REMOVE; 719 else if (STRIEQ(ucl_object_tostring(elt), "upgrade")) 720 msg->type = PKG_MESSAGE_UPGRADE; 721 } 722 vec_push(&p->pkg->message, msg); 723 } 724 } 725 726 ret = EPKG_OK; 727 if ((o = ucl_object_find_key(obj, "actions"))) 728 ret = parse_actions(o, p, line, attr, argc, args); 729 730 if (ret == EPKG_OK && (o = ucl_object_find_key(obj, "prepackaging"))) { 731 lua_State *L = luaL_newstate(); 732 static const luaL_Reg plist_lib[] = { 733 { "config", lua_config }, 734 { "dir", lua_dir }, 735 { "file", lua_file }, 736 { NULL, NULL }, 737 }; 738 luaL_openlibs(L); 739 lua_pushlightuserdata(L, p); 740 lua_setglobal(L, "plist"); 741 lua_pushlightuserdata(L, attr); 742 lua_setglobal(L, "attrs"); 743 lua_pushstring(L, line); 744 lua_setglobal(L, "line"); 745 lua_args_table(L, args, argc); 746 luaL_newlib(L, plist_lib); 747 lua_setglobal(L, "pkg"); 748 lua_override_ios(L, false); 749 pkg_debug(3, "Scripts: executing lua\n--- BEGIN ---" 750 "\n%s\nScripts: --- END ---", ucl_object_tostring(o)); 751 if (luaL_dostring(L, ucl_object_tostring(o))) { 752 pkg_emit_error("Failed to execute lua script: " 753 "%s", lua_tostring(L, -1)); 754 ret = EPKG_FATAL; 755 } 756 if (lua_tonumber(L, -1) != 0) { 757 ret = EPKG_FATAL; 758 } 759 lua_close(L); 760 } 761 762 keywords_cleanup: 763 free(args); 764 free(tofree); 765 return (ret); 766 } 767 768 static int 769 external_keyword(struct plist *plist, char *keyword, char *line, struct file_attr *attr) 770 { 771 struct ucl_parser *parser; 772 const char *keyword_dir = NULL; 773 char keyfile_path[MAXPATHLEN]; 774 int ret = EPKG_UNKNOWN, fd; 775 ucl_object_t *o, *schema; 776 const ucl_object_t *obj; 777 struct ucl_schema_error err; 778 779 keyword_dir = pkg_object_string(pkg_config_get("PLIST_KEYWORDS_DIR")); 780 if (keyword_dir == NULL) { 781 keyword_dir = pkg_object_string(pkg_config_get("PORTSDIR")); 782 snprintf(keyfile_path, sizeof(keyfile_path), 783 "%s/Keywords/%s.ucl", keyword_dir, keyword); 784 } else { 785 snprintf(keyfile_path, sizeof(keyfile_path), 786 "%s/%s.ucl", keyword_dir, keyword); 787 } 788 789 fd = open(keyfile_path, O_RDONLY); 790 if (fd == -1) { 791 pkg_emit_error("cannot load keyword from %s: %s", 792 keyfile_path, strerror(errno)); 793 return (EPKG_UNKNOWN); 794 } 795 796 parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS); 797 if (!ucl_parser_add_fd(parser, fd)) { 798 pkg_emit_error("cannot parse keyword: %s", 799 ucl_parser_get_error(parser)); 800 ucl_parser_free(parser); 801 close(fd); 802 return (EPKG_UNKNOWN); 803 } 804 805 close(fd); 806 o = ucl_parser_get_object(parser); 807 ucl_parser_free(parser); 808 809 schema = keyword_open_schema(); 810 811 if (schema != NULL) { 812 if (!ucl_object_validate(schema, o, &err)) { 813 pkg_emit_error("Keyword definition %s cannot be validated: %s", keyfile_path, err.msg); 814 ucl_object_unref(o); 815 return (EPKG_FATAL); 816 } 817 } 818 819 if ((obj = ucl_object_find_key(o, "deprecated")) && 820 ucl_object_toboolean(obj)) { 821 obj = ucl_object_find_key(o, "deprecation_message"); 822 pkg_emit_error("Use of '@%s' is deprecated%s%s", keyword, 823 obj != NULL ? ": " : "", 824 obj != NULL ? ucl_object_tostring(obj) : ""); 825 if (ctx.developer_mode) { 826 ucl_object_unref(o); 827 return (EPKG_FATAL); 828 } 829 } 830 ret = apply_keyword_file(o, plist, line, attr); 831 if (ret != EPKG_OK) { 832 pkg_emit_error("Failed to apply keyword '%s'", keyword); 833 } 834 835 return (ret); 836 } 837 838 struct file_attr * 839 parse_keyword_args(char *args, char *keyword) 840 { 841 struct file_attr *attr; 842 char *owner, *group, *permstr, *fflags; 843 void *set = NULL; 844 u_long fset = 0; 845 846 owner = group = permstr = fflags = NULL; 847 848 /* remove last ')' */ 849 args[strlen(args) -1] = '\0'; 850 851 do { 852 args[0] = '\0'; 853 args++; 854 while (isspace(*args)) 855 args++; 856 if (*args == '\0') 857 break; 858 if (owner == NULL) { 859 owner = args; 860 } else if (group == NULL) { 861 group = args; 862 } else if (permstr == NULL) { 863 permstr = args; 864 } else if (fflags == NULL) { 865 fflags = args; 866 break; 867 } else { 868 return (NULL); 869 } 870 } while ((args = strchr(args, ',')) != NULL); 871 872 if (fflags != NULL && *fflags != '\0') { 873 #ifdef HAVE_STRTOFFLAGS 874 if (strtofflags(&fflags, &fset, NULL) != 0) { 875 pkg_emit_error("Malformed keyword '%s', wrong fflags", 876 keyword); 877 return (NULL); 878 } 879 #else 880 pkg_emit_error("Malformed keyword '%s', maximum 3 arguments " 881 "are accepted", keyword); 882 #endif 883 } 884 885 if (permstr != NULL && *permstr != '\0') { 886 if ((set = parse_mode(permstr)) == NULL) { 887 pkg_emit_error("Malformed keyword '%s', wrong mode " 888 "section", keyword); 889 return (NULL); 890 } 891 } 892 if (owner == NULL && group == NULL && set == NULL) 893 return (NULL); 894 895 attr = xcalloc(1, sizeof(struct file_attr)); 896 if (owner != NULL && *owner != '\0') 897 attr->owner = xstrdup(rtrimspace(owner)); 898 if (group != NULL && *group != '\0') 899 attr->group = xstrdup(rtrimspace(group)); 900 if (set != NULL) { 901 attr->mode = getmode(set, 0); 902 free(set); 903 } 904 attr->fflags = fset; 905 906 return (attr); 907 } 908 909 static int 910 parse_keywords(struct plist *plist, char *keyword, 911 char *line, struct file_attr *attr) 912 { 913 struct keyword *k = NULL; 914 int ret = EPKG_FATAL; 915 916 /* if keyword is empty consider it as a file */ 917 if (*keyword == '\0') 918 return (file(plist, line, attr)); 919 920 k = pkghash_get_value(plist->keywords, keyword); 921 if (k != NULL) { 922 vec_foreach(k->actions, i) { 923 ret = k->actions.d[i]->perform(plist, line, attr); 924 if (ret != EPKG_OK) 925 break; 926 } 927 return (ret); 928 } 929 930 /* 931 * if we are here it means the keyword has not been found 932 * maybe it is defined externally 933 * let's try to find it 934 */ 935 return (external_keyword(plist, keyword, line, attr)); 936 } 937 938 char * 939 extract_keywords(char *line, char **keyword, struct file_attr **attr) 940 { 941 char *k, *buf, *tmp; 942 struct file_attr *a = NULL; 943 944 buf = k = line; 945 while (!(isspace(buf[0]) || buf[0] == '\0')) { 946 if (buf[0] == '(' && (buf = strchr(buf, ')')) == NULL) 947 return (NULL); 948 buf++; 949 } 950 if (buf[0] != '\0') { 951 buf[0] = '\0'; 952 buf++; 953 } 954 955 /* trim spaces after the keyword */ 956 while (isspace(buf[0])) 957 buf++; 958 959 pkg_debug(1, "Parsing plist, found keyword: '%s", k); 960 961 if ((tmp = strchr(k, '(')) != NULL && k[strlen(k) -1] != ')') 962 return (NULL); 963 964 if (tmp != NULL) { 965 a = parse_keyword_args(tmp, k); 966 if (a == NULL) 967 return (NULL); 968 } 969 970 *attr = a; 971 *keyword = k; 972 973 return (buf); 974 } 975 976 static void 977 flush_script_buffer(xstring *buf, struct pkg *p, int type) 978 { 979 fflush(buf->fp); 980 if (buf->buf[0] != '\0') { 981 pkg_appendscript(p, buf->buf, type); 982 } 983 } 984 985 int 986 plist_parse_line(struct plist *plist, char *line) 987 { 988 char *buf, *bkpline; 989 990 if (line[0] == '\0') 991 return (EPKG_OK); 992 993 pkg_debug(1, "Parsing plist line: '%s'", line); 994 bkpline = xstrdup(line); 995 996 if (line[0] == '@') { 997 char *keyword = 0; 998 struct file_attr *a = 0; 999 buf = extract_keywords(line + 1, &keyword, &a); 1000 if (buf == NULL) { 1001 pkg_emit_error("Malformed keyword %s, expecting @keyword " 1002 "or @keyword(owner,group,mode)", bkpline); 1003 free_file_attr(a); 1004 free(bkpline); 1005 return (EPKG_FATAL); 1006 } 1007 1008 switch (parse_keywords(plist, keyword, buf, a)) { 1009 case EPKG_UNKNOWN: 1010 pkg_emit_error("unknown keyword %s: %s", 1011 keyword, line); 1012 /* FALLTHRU */ 1013 case EPKG_FATAL: 1014 free_file_attr(a); 1015 free(bkpline); 1016 return (EPKG_FATAL); 1017 } 1018 free_file_attr(a); 1019 } else { 1020 buf = line; 1021 strlcpy(plist->last_file, buf, sizeof(plist->last_file)); 1022 1023 /* remove spaces at the begining and at the end */ 1024 while (isspace(buf[0])) 1025 buf++; 1026 1027 if (file(plist, buf, NULL) != EPKG_OK) { 1028 free(bkpline); 1029 return (EPKG_FATAL); 1030 } 1031 } 1032 1033 free(bkpline); 1034 return (EPKG_OK); 1035 } 1036 1037 struct plist * 1038 plist_new(struct pkg *pkg, const char *stage) 1039 { 1040 struct plist *p; 1041 1042 p = xcalloc(1, sizeof(struct plist)); 1043 p->plistdirfd = -1; 1044 p->stagefd = open(stage ? stage : "/", O_DIRECTORY | O_CLOEXEC); 1045 if (p->stagefd == -1) { 1046 free(p); 1047 return (NULL); 1048 } 1049 1050 p->pkg = pkg; 1051 if (pkg->prefix != NULL) 1052 strlcpy(p->prefix, pkg->prefix, sizeof(p->prefix)); 1053 p->slash = *p->prefix != '\0' && p->prefix[strlen(p->prefix) - 1] == '/' ? "" : "/"; 1054 p->stage = stage; 1055 1056 p->uname = xstrdup("root"); 1057 p->gname = xstrdup("wheel"); 1058 1059 p->pre_install_buf = xstring_new(); 1060 p->post_install_buf = xstring_new(); 1061 p->pre_deinstall_buf = xstring_new(); 1062 p->post_deinstall_buf = xstring_new(); 1063 1064 populate_keywords(p); 1065 1066 return (p); 1067 } 1068 1069 void 1070 plist_free(struct plist *p) 1071 { 1072 if (p == NULL) 1073 return; 1074 1075 if (p->stagefd != -1) 1076 close(p->stagefd); 1077 if (p->plistdirfd != -1) 1078 close(p->plistdirfd); 1079 1080 pkghash_it it = pkghash_iterator(p->keywords); 1081 while (pkghash_next(&it)) 1082 keyword_free((struct keyword *)it.value); 1083 pkghash_destroy(p->keywords); 1084 p->keywords = NULL; 1085 1086 free(p->uname); 1087 free(p->gname); 1088 vec_free_and_free(&p->hardlinks, free); 1089 1090 xstring_free(p->post_deinstall_buf); 1091 xstring_free(p->post_install_buf); 1092 xstring_free(p->pre_deinstall_buf); 1093 xstring_free(p->pre_install_buf); 1094 1095 free(p); 1096 } 1097 1098 char * 1099 expand_plist_variables(const char *in, kvlist_t *vars) 1100 { 1101 xstring *buf; 1102 const char *cp; 1103 size_t len; 1104 1105 if (vec_len(vars) == 0) 1106 return (xstrdup(in)); 1107 1108 buf = xstring_new(); 1109 cp = NULL; 1110 while (in[0] != '\0') { 1111 if (in[0] != '%') { 1112 fputc(in[0], buf->fp); 1113 in++; 1114 continue; 1115 } 1116 in++; 1117 if (in[0] == '\0') { 1118 fputc('%', buf->fp); 1119 break; 1120 } 1121 if (in[0] != '%') { 1122 fputc('%', buf->fp); 1123 fputc(in[0], buf->fp); 1124 in++; 1125 continue; 1126 } 1127 in++; 1128 cp = in; 1129 while (in[0] != '\0' && !isspace(in[0])) { 1130 if (in[0] == '%' && in[1] == '%') { 1131 in++; 1132 break; 1133 } 1134 in++; 1135 } 1136 if (in[0] != '%') { 1137 fprintf(buf->fp, "%%%%%.*s", (int)(in - cp), cp); 1138 continue; 1139 } 1140 len = in - cp -1; 1141 /* we have a variable */ 1142 bool found = false; 1143 vec_foreach(*vars, i) { 1144 if (strncmp(cp, vars->d[i]->key, len) != 0) 1145 continue; 1146 fputs(vars->d[i]->value, buf->fp); 1147 found = true; 1148 in++; 1149 break; 1150 } 1151 if (found) 1152 continue; 1153 fprintf(buf->fp, "%%%%%.*s%%", (int)(in - cp), cp); 1154 in++; 1155 } 1156 return (xstring_get(buf)); 1157 } 1158 1159 static int 1160 plist_parse(struct plist *pplist, FILE *f) 1161 { 1162 int ret, rc = EPKG_OK; 1163 size_t linecap = 0; 1164 ssize_t linelen; 1165 char *line = NULL; 1166 char *l; 1167 1168 while ((linelen = getline(&line, &linecap, f)) > 0) { 1169 if (line[linelen - 1] == '\n') 1170 line[linelen - 1] = '\0'; 1171 l = expand_plist_variables(line, &pplist->variables); 1172 ret = plist_parse_line(pplist, l); 1173 free(l); 1174 if (ret != EPKG_OK && rc == EPKG_OK) 1175 rc = ret; 1176 } 1177 free(line); 1178 1179 return (rc); 1180 } 1181 1182 static int 1183 open_directory_of(const char *file) 1184 { 1185 char path[MAXPATHLEN]; 1186 char *walk; 1187 1188 if (strchr(file, '/') == NULL) { 1189 if (getcwd(path, MAXPATHLEN) == NULL) { 1190 pkg_emit_error("Unable to determine current location"); 1191 return (-1); 1192 } 1193 return (open(path, O_DIRECTORY)); 1194 } 1195 strlcpy(path, file, sizeof(path)); 1196 walk = strrchr(path, '/'); 1197 *walk = '\0'; 1198 return (open(path, O_DIRECTORY)); 1199 } 1200 1201 int 1202 add_variable(struct plist *p, char *line, struct file_attr *a __unused) 1203 { 1204 const char *key; 1205 char *val; 1206 1207 key = val = line; 1208 while (*val != '\0' && !isspace(*val)) 1209 val++; 1210 if (*val != '\0') { 1211 *val = '\0'; 1212 val++; 1213 } 1214 1215 if (*key == '\0') { 1216 pkg_emit_error("Inside in @include it is not allowed to reuse @include"); 1217 return (EPKG_FATAL); 1218 } 1219 1220 while (*val != '\0' && isspace(*val)) 1221 val++; 1222 1223 vec_foreach(p->variables, i) { 1224 if (STREQ(p->variables.d[i]->key, key)) { 1225 free(p->variables.d[i]->value); 1226 p->variables.d[i]->value = xstrdup(val); 1227 return (EPKG_OK); 1228 } 1229 } 1230 struct pkg_kv *kv = pkg_kv_new(key, val); 1231 vec_push(&p->variables, kv); 1232 return (EPKG_OK); 1233 } 1234 1235 int 1236 include_plist(struct plist *p, char *name, struct file_attr *a __unused) 1237 { 1238 FILE *f; 1239 int fd; 1240 int rc; 1241 1242 if (p->in_include) { 1243 pkg_emit_error("Inside in @include it is not allowed to reuse @include"); 1244 return (EPKG_FATAL); 1245 } 1246 p->in_include = true; 1247 1248 fd = openat(p->plistdirfd, name, O_RDONLY); 1249 if (fd == -1) { 1250 pkg_emit_errno("Unable to include", name); 1251 return (EPKG_FATAL); 1252 } 1253 f = fdopen(fd, "r"); 1254 if (f == NULL) { 1255 pkg_emit_errno("Unable to include", name); 1256 close(fd); 1257 return (EPKG_FATAL); 1258 } 1259 1260 rc = plist_parse(p, f); 1261 1262 fclose(f); 1263 return (rc); 1264 } 1265 1266 int 1267 ports_parse_plist(struct pkg *pkg, const char *plist, const char *stage) 1268 { 1269 int rc = EPKG_OK; 1270 struct plist *pplist; 1271 FILE *plist_f; 1272 1273 assert(pkg != NULL); 1274 assert(plist != NULL); 1275 1276 if ((pplist = plist_new(pkg, stage)) == NULL) 1277 return (EPKG_FATAL); 1278 1279 pplist->plistdirfd = open_directory_of(plist); 1280 if (pplist->plistdirfd == -1) { 1281 pkg_emit_error("Unable to open the directory where the plist is: %s", plist); 1282 plist_free(pplist); 1283 return (EPKG_FATAL); 1284 } 1285 if ((plist_f = fopen(plist, "re")) == NULL) { 1286 pkg_emit_error("Unable to open plist file: %s", plist); 1287 plist_free(pplist); 1288 return (EPKG_FATAL); 1289 } 1290 1291 rc = plist_parse(pplist, plist_f); 1292 1293 pkg->flatsize = pplist->flatsize; 1294 1295 flush_script_buffer(pplist->pre_install_buf, pkg, 1296 PKG_SCRIPT_PRE_INSTALL); 1297 flush_script_buffer(pplist->post_install_buf, pkg, 1298 PKG_SCRIPT_POST_INSTALL); 1299 flush_script_buffer(pplist->pre_deinstall_buf, pkg, 1300 PKG_SCRIPT_PRE_DEINSTALL); 1301 flush_script_buffer(pplist->post_deinstall_buf, pkg, 1302 PKG_SCRIPT_POST_DEINSTALL); 1303 1304 fclose(plist_f); 1305 1306 plist_free(pplist); 1307 1308 return (rc); 1309 } 1310 1311 /* 1312 * if the provided database is NULL then we don't want to register the package 1313 * in the database aka NO_PKG_REGISTER 1314 */ 1315 int 1316 pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path, 1317 const char *reloc, bool testing) 1318 { 1319 const char *location; 1320 int rc = EPKG_OK; 1321 xstring *message; 1322 1323 if (db != NULL && pkg_is_installed(db, pkg->name) != EPKG_END) { 1324 return(EPKG_INSTALLED); 1325 } 1326 1327 location = reloc; 1328 if (ctx.pkg_rootdir != NULL) 1329 location = ctx.pkg_rootdir; 1330 1331 if (ctx.pkg_rootdir == NULL && location != NULL) 1332 pkg_kv_add(&pkg->annotations, "relocated", location, "annotation"); 1333 1334 pkg_emit_install_begin(pkg); 1335 1336 if (db != NULL) { 1337 rc = pkgdb_register_pkg(db, pkg, 0, NULL); 1338 if (rc != EPKG_OK) { 1339 db = NULL; 1340 goto cleanup; 1341 } 1342 } 1343 1344 if (!testing) { 1345 /* Execute pre-install scripts */ 1346 pkg_lua_script_run(pkg, PKG_LUA_PRE_INSTALL, false); 1347 pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, false, false); 1348 1349 if (input_path != NULL) { 1350 pkg_register_cleanup_callback(pkg_rollback_cb, pkg); 1351 rc = pkg_add_fromdir(pkg, input_path, db); 1352 pkg_unregister_cleanup_callback(pkg_rollback_cb, pkg); 1353 if (rc != EPKG_OK) { 1354 pkg_rollback_pkg(pkg); 1355 if (db != NULL) 1356 pkg_delete_dirs(db, pkg, NULL); 1357 } 1358 } 1359 1360 /* Execute post-install scripts */ 1361 pkg_lua_script_run(pkg, PKG_LUA_POST_INSTALL, false); 1362 pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, false, false); 1363 } 1364 1365 if (rc == EPKG_OK) { 1366 pkg_emit_install_finished(pkg, NULL); 1367 if (pkg_has_message(pkg)) 1368 message = xstring_new(); 1369 vec_foreach(pkg->message, i) { 1370 if (pkg->message.d[i]->type == PKG_MESSAGE_ALWAYS || 1371 pkg->message.d[i]->type == PKG_MESSAGE_INSTALL) { 1372 fprintf(message->fp, "%s\n", pkg->message.d[i]->str); 1373 } 1374 } 1375 if (pkg_has_message(pkg)) { 1376 fflush(message->fp); 1377 if (message->buf[0] != '\0') { 1378 pkg_emit_message(message->buf); 1379 } 1380 xstring_free(message); 1381 } 1382 } 1383 /* it is impossible at this point to get any cleanup triggers to run */ 1384 triggers_execute(NULL); 1385 1386 cleanup: 1387 if (db != NULL) 1388 pkgdb_register_finale(db, rc, NULL); 1389 1390 return (rc); 1391 }