/ libpkg / pkg_ports.c
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  }