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