Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2023 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2013-2014 Vsevolod Stakhov <vsevolod@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 <sys/types.h>
30 : : #include <stddef.h>
31 : :
32 : : #include <assert.h>
33 : : #include <ctype.h>
34 : : #include <errno.h>
35 : : #include <stdbool.h>
36 : : #include <stdlib.h>
37 : : #include <string.h>
38 : : #include <fcntl.h>
39 : : #include <ucl.h>
40 : :
41 : : #include "pkg.h"
42 : : #include "private/event.h"
43 : : #include "private/pkg.h"
44 : : #include "private/utils.h"
45 : :
46 : : #define dbg(x, ...) pkg_dbg(PKG_DBG_MANIFEST, x, __VA_ARGS__)
47 : :
48 : : enum {
49 : : MANIFEST_ANNOTATIONS,
50 : : MANIFEST_CATEGORIES,
51 : : MANIFEST_CONFIG_FILES,
52 : : MANIFEST_CONFLICTS,
53 : : MANIFEST_DEPS,
54 : : MANIFEST_DIRECTORIES,
55 : : MANIFEST_DIRS,
56 : : MANIFEST_FILES,
57 : : MANIFEST_GROUPS,
58 : : MANIFEST_LICENSES,
59 : : MANIFEST_LUA_SCRIPTS,
60 : : MANIFEST_OPTIONS,
61 : : MANIFEST_OPTION_DEFAULTS,
62 : : MANIFEST_OPTION_DESCRIPTIONS,
63 : : MANIFEST_PROVIDES,
64 : : MANIFEST_REQUIRES,
65 : : MANIFEST_SCRIPTS,
66 : : MANIFEST_SHLIBS_PROVIDED,
67 : : MANIFEST_SHLIBS_REQUIRED,
68 : : MANIFEST_USERS,
69 : : };
70 : :
71 : : #define PKG_MESSAGE_LEGACY 1
72 : : #define PKG_MESSAGE_NEW 2
73 : :
74 : : static int pkg_string(struct pkg *, const ucl_object_t *, uint32_t);
75 : : static int pkg_obj(struct pkg *, const ucl_object_t *, uint32_t);
76 : : static int pkg_array(struct pkg *, const ucl_object_t *, uint32_t);
77 : : static int pkg_int(struct pkg *, const ucl_object_t *, uint32_t);
78 : : static int pkg_boolean(struct pkg *, const ucl_object_t *, uint32_t);
79 : : static int pkg_message(struct pkg *, const ucl_object_t *, uint32_t);
80 : : static int pkg_set_deps_from_object(struct pkg *, const ucl_object_t *);
81 : : static int pkg_set_files_from_object(struct pkg *, const ucl_object_t *);
82 : : static int pkg_set_dirs_from_object(struct pkg *, const ucl_object_t *);
83 : :
84 : : /*
85 : : * Keep sorted
86 : : */
87 : : #define TYPE_SHIFT(x) (1 << (x))
88 : : #define STRING_FLAG_LICENSE (1U << 31)
89 : : #define STRING_FLAG_URLDECODE (1U << 30)
90 : : #define STRING_FLAG_MASK ~(STRING_FLAG_LICENSE|STRING_FLAG_URLDECODE)
91 : :
92 : : static struct pkg_manifest_key {
93 : : const char *key;
94 : : uint32_t type;
95 : : uint16_t valid_type;
96 : : int (*parse_data)(struct pkg *, const ucl_object_t *, uint32_t);
97 : : } manifest_keys[] = {
98 : : { "annotations", MANIFEST_ANNOTATIONS,
99 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
100 : :
101 : : { "abi", offsetof(struct pkg, abi),
102 : : TYPE_SHIFT(UCL_STRING), pkg_string},
103 : :
104 : : { "arch", offsetof(struct pkg, altabi),
105 : : TYPE_SHIFT(UCL_STRING), pkg_string},
106 : :
107 : : { "categories", MANIFEST_CATEGORIES,
108 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
109 : :
110 : : { "comment", offsetof(struct pkg, comment),
111 : : TYPE_SHIFT(UCL_STRING), pkg_string},
112 : :
113 : : { "conflicts", MANIFEST_CONFLICTS,
114 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
115 : :
116 : : { "config", MANIFEST_CONFIG_FILES,
117 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
118 : :
119 : : { "dep_formula", offsetof(struct pkg, dep_formula),
120 : : TYPE_SHIFT(UCL_STRING), pkg_string},
121 : :
122 : : { "deps", MANIFEST_DEPS,
123 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
124 : :
125 : : { "desc", offsetof(struct pkg, desc) | STRING_FLAG_URLDECODE,
126 : : TYPE_SHIFT(UCL_STRING), pkg_string},
127 : :
128 : : { "directories", MANIFEST_DIRECTORIES,
129 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
130 : :
131 : : { "dirs", MANIFEST_DIRS,
132 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
133 : :
134 : : { "files", MANIFEST_FILES,
135 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
136 : :
137 : : { "flatsize", offsetof(struct pkg, flatsize),
138 : : TYPE_SHIFT(UCL_INT), pkg_int},
139 : :
140 : : { "groups", MANIFEST_GROUPS,
141 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
142 : :
143 : : { "licenselogic", offsetof(struct pkg, licenselogic) | STRING_FLAG_LICENSE,
144 : : TYPE_SHIFT(UCL_STRING), pkg_string},
145 : :
146 : : { "licenses", MANIFEST_LICENSES,
147 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
148 : :
149 : : { "lua_scripts", MANIFEST_LUA_SCRIPTS,
150 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
151 : :
152 : : { "maintainer", offsetof(struct pkg, maintainer),
153 : : TYPE_SHIFT(UCL_STRING), pkg_string},
154 : :
155 : : { "messages", PKG_MESSAGE_NEW,
156 : : TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_ARRAY), pkg_message},
157 : :
158 : : { "message", PKG_MESSAGE_LEGACY,
159 : : TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_ARRAY), pkg_message},
160 : :
161 : : { "name", offsetof(struct pkg, name),
162 : : TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_INT), pkg_string},
163 : :
164 : : { "options", MANIFEST_OPTIONS,
165 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
166 : :
167 : : { "option_defaults", MANIFEST_OPTION_DEFAULTS,
168 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
169 : :
170 : : { "option_descriptions", MANIFEST_OPTION_DESCRIPTIONS,
171 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
172 : :
173 : : { "origin", offsetof(struct pkg, origin),
174 : : TYPE_SHIFT(UCL_STRING), pkg_string},
175 : :
176 : : { "path", offsetof(struct pkg, repopath),
177 : : TYPE_SHIFT(UCL_STRING), pkg_string},
178 : :
179 : : { "repopath", offsetof(struct pkg, repopath),
180 : : TYPE_SHIFT(UCL_STRING), pkg_string},
181 : :
182 : : { "pkgsize", offsetof(struct pkg, pkgsize),
183 : : TYPE_SHIFT(UCL_INT), pkg_int},
184 : :
185 : : { "prefix", offsetof(struct pkg, prefix),
186 : : TYPE_SHIFT(UCL_STRING), pkg_string},
187 : :
188 : : { "provides", MANIFEST_PROVIDES,
189 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
190 : :
191 : : { "requires", MANIFEST_REQUIRES,
192 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
193 : :
194 : : { "scripts", MANIFEST_SCRIPTS,
195 : : TYPE_SHIFT(UCL_OBJECT), pkg_obj},
196 : :
197 : : { "shlibs", MANIFEST_SHLIBS_REQUIRED,
198 : : TYPE_SHIFT(UCL_ARRAY), pkg_array}, /* Backwards compat with 1.0.x packages */
199 : :
200 : : { "shlibs_provided", MANIFEST_SHLIBS_PROVIDED,
201 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
202 : :
203 : : { "shlibs_required", MANIFEST_SHLIBS_REQUIRED,
204 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
205 : :
206 : : { "sum", offsetof(struct pkg, sum),
207 : : TYPE_SHIFT(UCL_STRING), pkg_string},
208 : :
209 : : { "users", MANIFEST_USERS,
210 : : TYPE_SHIFT(UCL_ARRAY), pkg_array},
211 : :
212 : : { "version", offsetof(struct pkg, version),
213 : : TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_INT), pkg_string},
214 : :
215 : : { "vital", offsetof(struct pkg, vital),
216 : : TYPE_SHIFT(UCL_BOOLEAN), pkg_boolean},
217 : :
218 : : { "www", offsetof(struct pkg, www),
219 : : TYPE_SHIFT(UCL_STRING), pkg_string},
220 : :
221 : : };
222 : :
223 : : static int
224 : 1007 : urlencode(const char *src, xstring **dest)
225 : : {
226 : : size_t len;
227 : : size_t i;
228 : :
229 [ + + ]: 1007 : xstring_renew(*dest);
230 : :
231 : 1007 : len = strlen(src);
232 [ + + ]: 19257 : for (i = 0; i < len; i++) {
233 [ + - - + ]: 18250 : if (!isascii(src[i]) || src[i] == '%')
234 : 0 : fprintf((*dest)->fp, "%%%.2x", (unsigned char)src[i]);
235 : : else
236 : 18250 : fputc(src[i], (*dest)->fp);
237 : 18250 : }
238 : :
239 : 1007 : fflush((*dest)->fp);
240 : 1007 : return (EPKG_OK);
241 : : }
242 : :
243 : : static int
244 : 1847 : urldecode(const char *src, xstring **dest)
245 : : {
246 : : size_t len;
247 : : size_t i;
248 : : char c;
249 : 1847 : char hex[] = {'\0', '\0', '\0'};
250 : :
251 [ + + ]: 1847 : xstring_renew(*dest);
252 : :
253 : 1847 : len = strlen(src);
254 [ + + ]: 45197 : for (i = 0; i < len; i++) {
255 [ + - ]: 43350 : if (src[i] != '%') {
256 : 43350 : fputc(src[i], (*dest)->fp);
257 : 43350 : } else {
258 [ # # ]: 0 : if (i + 2 > len) {
259 : 0 : pkg_emit_error("unexpected end of string");
260 : 0 : return (EPKG_FATAL);
261 : : }
262 : :
263 : 0 : hex[0] = src[++i];
264 : 0 : hex[1] = src[++i];
265 : 0 : errno = 0;
266 : 0 : c = strtol(hex, NULL, 16);
267 [ # # ]: 0 : if (errno != 0) {
268 : : /*
269 : : * if it fails consider this is not a urlencoded
270 : : * information
271 : : */
272 : 0 : fprintf((*dest)->fp, "%%%s", hex);
273 : 0 : } else {
274 : 0 : fputc(c,(*dest)->fp);
275 : : }
276 : : }
277 : 43350 : }
278 : :
279 : 1847 : fflush((*dest)->fp);
280 : 1847 : return (EPKG_OK);
281 : 1847 : }
282 : :
283 : : static int
284 : 64 : lua_script_type_str(const char *str)
285 : : {
286 [ + - ]: 64 : if (STREQ(str, "pre-install"))
287 : 0 : return (PKG_LUA_PRE_INSTALL);
288 [ - + ]: 64 : if (STREQ(str, "post-install"))
289 : 64 : return (PKG_LUA_POST_INSTALL);
290 [ # # ]: 0 : if (STREQ(str, "pre-deinstall"))
291 : 0 : return (PKG_LUA_PRE_DEINSTALL);
292 [ # # ]: 0 : if (STREQ(str, "post-deinstall"))
293 : 0 : return (PKG_LUA_POST_DEINSTALL);
294 : 0 : return (PKG_LUA_UNKNOWN);
295 : 64 : }
296 : :
297 : : static int
298 : 80 : script_type_str(const char *str)
299 : : {
300 [ + + ]: 80 : if (STREQ(str, "pre-install"))
301 : 20 : return (PKG_SCRIPT_PRE_INSTALL);
302 [ + - ]: 60 : if (STREQ(str, "install"))
303 : 0 : return (PKG_SCRIPT_INSTALL);
304 [ + + ]: 60 : if (STREQ(str, "post-install"))
305 : 45 : return (PKG_SCRIPT_POST_INSTALL);
306 [ + + ]: 15 : if (STREQ(str, "pre-deinstall"))
307 : 4 : return (PKG_SCRIPT_PRE_DEINSTALL);
308 [ + - ]: 11 : if (STREQ(str, "deinstall"))
309 : 0 : return (PKG_SCRIPT_DEINSTALL);
310 [ - + ]: 11 : if (STREQ(str, "post-deinstall"))
311 : 11 : return (PKG_SCRIPT_POST_DEINSTALL);
312 : 0 : return (PKG_SCRIPT_UNKNOWN);
313 : 80 : }
314 : :
315 : : static int
316 : 10595 : pkg_string(struct pkg *pkg, const ucl_object_t *obj, uint32_t offset)
317 : : {
318 : : const char *str;
319 : : char **dest;
320 : 10595 : xstring *buf = NULL;
321 : :
322 : 10595 : str = ucl_object_tostring_forced(obj);
323 : :
324 [ + + ]: 10595 : if (offset & STRING_FLAG_LICENSE) {
325 [ - + ]: 8 : if (STREQ(str, "single"))
326 : 8 : pkg->licenselogic = LICENSE_SINGLE;
327 [ # # # # ]: 0 : else if (STREQ(str, "or") ||
328 : 0 : STREQ(str, "dual"))
329 : 0 : pkg->licenselogic = LICENSE_OR;
330 [ # # # # ]: 0 : else if (STREQ(str, "and") ||
331 : 0 : STREQ(str, "multi"))
332 : 0 : pkg->licenselogic = LICENSE_AND;
333 : : else {
334 : 0 : pkg_emit_error("Unknown license logic: %s", str);
335 : 0 : return (EPKG_FATAL);
336 : : }
337 : 8 : }
338 : : else {
339 : :
340 [ + + ]: 10587 : if (offset & STRING_FLAG_URLDECODE) {
341 : 1070 : urldecode(str, &buf);
342 : 1070 : str = buf->buf;
343 : 1070 : }
344 : :
345 : : /* Remove flags from the offset */
346 : 10587 : offset &= STRING_FLAG_MASK;
347 : 10587 : dest = (char **) ((unsigned char *)pkg + offset);
348 : 10587 : *dest = xstrdup(str);
349 : :
350 : 10587 : xstring_free(buf);
351 : : }
352 : :
353 : 10595 : return (EPKG_OK);
354 : 10595 : }
355 : :
356 : : static int
357 : 870 : pkg_int(struct pkg *pkg, const ucl_object_t *obj, uint32_t offset)
358 : : {
359 : : int64_t *dest;
360 : :
361 : 870 : dest = (int64_t *)((unsigned char *)pkg + offset);
362 : 870 : *dest = ucl_object_toint(obj);
363 : :
364 : 870 : return (EPKG_OK);
365 : : }
366 : :
367 : : static int
368 : 9 : pkg_boolean(struct pkg *pkg, const ucl_object_t *obj, uint32_t offset)
369 : : {
370 : : bool *dest;
371 : :
372 : 9 : dest = (bool *)((unsigned char *)pkg + offset);
373 : 9 : *dest = ucl_object_toboolean(obj);
374 : :
375 : 9 : return (EPKG_OK);
376 : : }
377 : :
378 : : static int
379 : 1216 : pkg_array(struct pkg *pkg, const ucl_object_t *obj, uint32_t attr)
380 : : {
381 : : const ucl_object_t *cur;
382 : 1216 : ucl_object_iter_t it = NULL;
383 : : int ret;
384 : :
385 : 1216 : dbg(3, "%s", "parsing array");
386 [ + + ]: 2446 : while ((cur = ucl_iterate_object(obj, &it, true))) {
387 [ + + + - : 1231 : switch (attr) {
- - + + -
+ + + ]
388 : : case MANIFEST_CATEGORIES:
389 [ - + ]: 1053 : if (cur->type != UCL_STRING)
390 : 0 : pkg_emit_error("Skipping malformed category");
391 : : else
392 : 2106 : pkg_addstring(&pkg->categories,
393 : 1053 : ucl_object_tostring(cur), "category");
394 : 1053 : break;
395 : : case MANIFEST_LICENSES:
396 [ - + ]: 4 : if (cur->type != UCL_STRING)
397 : 0 : pkg_emit_error("Skipping malformed license");
398 : : else
399 : 8 : pkg_addstring(&pkg->licenses,
400 : 4 : ucl_object_tostring(cur), "license");
401 : 4 : break;
402 : : case MANIFEST_USERS:
403 [ # # ]: 0 : if (cur->type == UCL_STRING)
404 : 0 : pkg_adduser(pkg, ucl_object_tostring(cur));
405 [ # # ]: 0 : else if (cur->type == UCL_OBJECT)
406 : 0 : pkg_obj(pkg, cur, attr);
407 : : else
408 : 0 : pkg_emit_error("Skipping malformed license");
409 : 0 : break;
410 : : case MANIFEST_GROUPS:
411 [ # # ]: 0 : if (cur->type == UCL_STRING)
412 : 0 : pkg_addgroup(pkg, ucl_object_tostring(cur));
413 [ # # ]: 0 : else if (cur->type == UCL_OBJECT)
414 : 0 : pkg_obj(pkg, cur, attr);
415 : : else
416 : 0 : pkg_emit_error("Skipping malformed license");
417 : 0 : break;
418 : : case MANIFEST_DIRS:
419 [ # # ]: 0 : if (cur->type == UCL_STRING)
420 : 0 : pkg_adddir(pkg, ucl_object_tostring(cur), false);
421 [ # # ]: 0 : else if (cur->type == UCL_OBJECT)
422 : 0 : pkg_obj(pkg, cur, attr);
423 : : else
424 : 0 : pkg_emit_error("Skipping malformed dirs");
425 : 0 : break;
426 : : case MANIFEST_SHLIBS_REQUIRED:
427 [ - + ]: 55 : if (cur->type != UCL_STRING)
428 : 0 : pkg_emit_error("Skipping malformed required shared library");
429 : : else
430 : 55 : pkg_addshlib_required(pkg, ucl_object_tostring(cur), PKG_SHLIB_FLAGS_NONE);
431 : 55 : break;
432 : : case MANIFEST_SHLIBS_PROVIDED:
433 [ - + ]: 28 : if (cur->type != UCL_STRING)
434 : 0 : pkg_emit_error("Skipping malformed provided shared library");
435 : : else
436 : 28 : pkg_addshlib_provided(pkg, ucl_object_tostring(cur), PKG_SHLIB_FLAGS_NONE);
437 : 28 : break;
438 : : case MANIFEST_CONFLICTS:
439 [ # # ]: 0 : if (cur->type != UCL_STRING)
440 : 0 : pkg_emit_error("Skipping malformed conflict name");
441 : : else
442 : 0 : pkg_addconflict(pkg, ucl_object_tostring(cur));
443 : 0 : break;
444 : : case MANIFEST_PROVIDES:
445 [ - + ]: 22 : if (cur->type != UCL_STRING)
446 : 0 : pkg_emit_error("Skipping malformed provide name");
447 : : else
448 : 22 : pkg_addprovide(pkg, ucl_object_tostring(cur));
449 : 22 : break;
450 : : case MANIFEST_CONFIG_FILES:
451 [ - + ]: 31 : if (cur->type != UCL_STRING)
452 : 0 : pkg_emit_error("Skipping malformed config file name");
453 : : else {
454 : 31 : ret = pkg_addconfig_file(pkg, ucl_object_tostring(cur), NULL);
455 [ + + ]: 31 : if (ret != EPKG_OK)
456 : 1 : return (ret);
457 : : }
458 : 30 : break;
459 : : case MANIFEST_REQUIRES:
460 [ - + ]: 36 : if (cur->type != UCL_STRING)
461 : 0 : pkg_emit_error("Skipping malformed require name");
462 : : else
463 : 36 : pkg_addrequire(pkg, ucl_object_tostring(cur));
464 : 36 : break;
465 : : }
466 : : }
467 : :
468 : 1211 : return (EPKG_OK);
469 : 1212 : }
470 : :
471 : : static int
472 : 1332 : pkg_obj(struct pkg *pkg, const ucl_object_t *obj, uint32_t attr)
473 : : {
474 : 1332 : xstring *tmp = NULL;
475 : : const ucl_object_t *cur;
476 : 1332 : ucl_object_iter_t it = NULL;
477 : : pkg_script script_type;
478 : : pkg_lua_script lua_script_type;
479 : : const char *key, *buf;
480 : : size_t len;
481 : :
482 : 1332 : dbg(3, "%s", "parsing object");
483 [ + + ]: 3098 : while ((cur = ucl_iterate_object(obj, &it, true))) {
484 : 1766 : key = ucl_object_key(cur);
485 [ + - ]: 1766 : if (key == NULL)
486 : 0 : continue;
487 [ + + - + : 1766 : switch (attr) {
+ + - - +
+ + ]
488 : : case MANIFEST_DEPS:
489 [ - + # # ]: 299 : if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY)
490 : 0 : pkg_emit_error("Skipping malformed dependency %s",
491 : 0 : key);
492 : : else
493 : 299 : pkg_set_deps_from_object(pkg, cur);
494 : 299 : break;
495 : : case MANIFEST_DIRS:
496 [ # # ]: 0 : if (cur->type != UCL_OBJECT)
497 : 0 : pkg_emit_error("Skipping malformed dirs %s",
498 : 0 : key);
499 : : else
500 : 0 : pkg_set_dirs_from_object(pkg, cur);
501 : 0 : break;
502 : : case MANIFEST_DIRECTORIES:
503 [ - + ]: 32 : if (cur->type == UCL_BOOLEAN) {
504 : 0 : urldecode(key, &tmp);
505 : 0 : pkg_adddir(pkg, tmp->buf, false);
506 [ + - ]: 32 : } else if (cur->type == UCL_OBJECT) {
507 : 0 : pkg_set_dirs_from_object(pkg, cur);
508 [ + - ]: 32 : } else if (cur->type == UCL_STRING) {
509 : 32 : urldecode(key, &tmp);
510 : 32 : pkg_adddir(pkg, tmp->buf, false);
511 : 32 : } else {
512 : 0 : pkg_emit_error("Skipping malformed directories %s",
513 : 0 : key);
514 : : }
515 : 32 : break;
516 : : case MANIFEST_FILES:
517 [ + + ]: 666 : if (cur->type == UCL_STRING) {
518 : 643 : buf = ucl_object_tolstring(cur, &len);
519 : 643 : urldecode(key, &tmp);
520 [ + + ]: 643 : pkg_addfile(pkg, tmp->buf, len >= 2 ? buf : NULL, false);
521 [ - + ]: 666 : } else if (cur->type == UCL_OBJECT)
522 : 23 : pkg_set_files_from_object(pkg, cur);
523 : : else
524 : 0 : pkg_emit_error("Skipping malformed files %s",
525 : 0 : key);
526 : 666 : break;
527 : : case MANIFEST_OPTIONS:
528 [ - + # # ]: 134 : if (cur->type != UCL_STRING && cur->type != UCL_BOOLEAN)
529 : 0 : pkg_emit_error("Skipping malformed option %s",
530 : 0 : key);
531 [ + - ]: 134 : else if (cur->type == UCL_STRING) {
532 : 134 : pkg_addoption(pkg, key, ucl_object_tostring(cur));
533 : 134 : } else {
534 : 0 : pkg_addoption(pkg, key, ucl_object_toboolean(cur) ? "on" : "off");
535 : : }
536 : 134 : break;
537 : : case MANIFEST_OPTION_DEFAULTS:
538 [ # # ]: 0 : if (cur->type != UCL_STRING)
539 : 0 : pkg_emit_error("Skipping malformed option default %s",
540 : 0 : key);
541 : : else
542 : 0 : pkg_addoption_default(pkg, key,
543 : 0 : ucl_object_tostring(cur));
544 : 0 : break;
545 : : case MANIFEST_OPTION_DESCRIPTIONS:
546 [ # # ]: 0 : if (cur->type != UCL_STRING)
547 : 0 : pkg_emit_error("Skipping malformed option description %s",
548 : 0 : key);
549 : : else
550 : 0 : pkg_addoption_description(pkg, key,
551 : 0 : ucl_object_tostring(cur));
552 : 0 : break;
553 : : case MANIFEST_SCRIPTS:
554 [ - + ]: 80 : if (cur->type != UCL_STRING)
555 : 0 : pkg_emit_error("Skipping malformed scripts %s",
556 : 0 : key);
557 : : else {
558 : 80 : script_type = script_type_str(key);
559 [ - + ]: 80 : if (script_type == PKG_SCRIPT_UNKNOWN) {
560 : 0 : pkg_emit_error("Skipping unknown script "
561 : 0 : "type: %s", key);
562 : 0 : break;
563 : : }
564 : :
565 : 80 : urldecode(ucl_object_tostring(cur), &tmp);
566 : 80 : pkg_addscript(pkg, tmp->buf, script_type);
567 : : }
568 : 80 : break;
569 : : case MANIFEST_LUA_SCRIPTS:
570 [ - + ]: 64 : if (cur->type != UCL_ARRAY) {
571 : 0 : pkg_emit_error("Skipping malformed dependency %s",
572 : 0 : key);
573 : 0 : break;
574 : : }
575 : 64 : lua_script_type = lua_script_type_str(key);
576 [ - + ]: 64 : if (lua_script_type == PKG_LUA_UNKNOWN) {
577 : 0 : pkg_emit_error("Skipping unknown script "
578 : 0 : "type: %s", key);
579 : 0 : break;
580 : : }
581 : 64 : pkg_lua_script_from_ucl(pkg, cur, lua_script_type);
582 : 64 : break;
583 : : case MANIFEST_ANNOTATIONS:
584 [ - + ]: 489 : if (cur->type != UCL_STRING)
585 : 0 : pkg_emit_error("Skipping malformed annotation %s",
586 : 0 : key);
587 : : else
588 : 489 : pkg_kv_add(&pkg->annotations, key, ucl_object_tostring(cur), "annotation");
589 : 489 : break;
590 : : }
591 : : }
592 : :
593 : 1332 : xstring_free(tmp);
594 : :
595 : 1332 : return (EPKG_OK);
596 : : }
597 : :
598 : : static int
599 : 21 : pkg_message(struct pkg *pkg, const ucl_object_t *obj, uint32_t attr __unused)
600 : : {
601 : 21 : return pkg_message_from_ucl(pkg, obj);
602 : : }
603 : :
604 : : static int
605 : 23 : pkg_set_files_from_object(struct pkg *pkg, const ucl_object_t *obj)
606 : : {
607 : : const ucl_object_t *cur;
608 : 23 : ucl_object_iter_t it = NULL;
609 : 23 : const char *sum = NULL;
610 : 23 : const char *uname = NULL;
611 : 23 : const char *gname = NULL;
612 : 23 : mode_t perm = 0;
613 : 23 : xstring *fname = NULL;
614 : : const char *key, *okey;
615 : :
616 : 23 : okey = ucl_object_key(obj);
617 [ + - ]: 23 : if (okey == NULL)
618 : 0 : return (EPKG_FATAL);
619 : 23 : urldecode(okey, &fname);
620 [ + + ]: 46 : while ((cur = ucl_iterate_object(obj, &it, true))) {
621 : 23 : key = ucl_object_key(cur);
622 [ + - ]: 23 : if (key == NULL)
623 : 0 : continue;
624 [ - + # # ]: 23 : if (STRIEQ(key, "uname") && cur->type == UCL_STRING)
625 : 0 : uname = ucl_object_tostring(cur);
626 [ - + # # ]: 23 : else if (STRIEQ(key, "gname") && cur->type == UCL_STRING)
627 : 0 : gname = ucl_object_tostring(cur);
628 [ - + # # : 23 : else if (STRIEQ(key, "sum") && cur->type == UCL_STRING &&
# # ]
629 : 0 : strlen(ucl_object_tostring(cur)) == 64)
630 : 0 : sum = ucl_object_tostring(cur);
631 [ - + + - ]: 46 : else if (STRIEQ(key, "perm") &&
632 [ + - ]: 23 : (cur->type == UCL_STRING || cur->type == UCL_INT)) {
633 : 23 : void *set = 0;
634 [ + - ]: 23 : if ((set = setmode(ucl_object_tostring_forced(cur))) == NULL)
635 : 0 : pkg_emit_error("Not a valid mode: %s",
636 : 0 : ucl_object_tostring(cur));
637 : : else
638 : 23 : perm = getmode(set, 0);
639 : 23 : free(set);
640 : 23 : } else {
641 : 0 : dbg(1, "Skipping unknown key for file(%s): %s",
642 : : fname->buf, key);
643 : : }
644 : : }
645 : :
646 : 23 : pkg_addfile_attr(pkg, fname->buf, sum, uname, gname, perm, 0,
647 : : false);
648 : 23 : xstring_free(fname);
649 : :
650 : 23 : return (EPKG_OK);
651 : 23 : }
652 : :
653 : : static int
654 : 0 : pkg_set_dirs_from_object(struct pkg *pkg, const ucl_object_t *obj)
655 : : {
656 : : const ucl_object_t *cur;
657 : 0 : ucl_object_iter_t it = NULL;
658 : 0 : const char *uname = NULL;
659 : 0 : const char *gname = NULL;
660 : 0 : mode_t perm = 0;
661 : 0 : xstring *dirname = NULL;
662 : : const char *key, *okey;
663 : :
664 : 0 : okey = ucl_object_key(obj);
665 [ # # ]: 0 : if (okey == NULL)
666 : 0 : return (EPKG_FATAL);
667 : 0 : urldecode(okey, &dirname);
668 [ # # ]: 0 : while ((cur = ucl_iterate_object(obj, &it, true))) {
669 : 0 : key = ucl_object_key(cur);
670 [ # # ]: 0 : if (key == NULL)
671 : 0 : continue;
672 [ # # # # ]: 0 : if (STRIEQ(key, "uname") && cur->type == UCL_STRING)
673 : 0 : uname = ucl_object_tostring(cur);
674 [ # # # # ]: 0 : else if (STRIEQ(key, "gname") && cur->type == UCL_STRING)
675 : 0 : gname = ucl_object_tostring(cur);
676 [ # # # # ]: 0 : else if (STRIEQ(key, "perm") &&
677 [ # # ]: 0 : (cur->type == UCL_STRING || cur->type == UCL_INT)) {
678 : 0 : void *set = 0;
679 [ # # ]: 0 : if ((set = setmode(ucl_object_tostring_forced(cur))) == NULL)
680 : 0 : pkg_emit_error("Not a valid mode: %s",
681 : 0 : ucl_object_tostring(cur));
682 : : else
683 : 0 : perm = getmode(set, 0);
684 : 0 : free(set);
685 [ # # # # ]: 0 : } else if (STRIEQ(key, "try") && cur->type == UCL_BOOLEAN) {
686 : : /* ignore on purpose : compatibility*/
687 : 0 : } else {
688 : 0 : dbg(1, "Skipping unknown key for dir(%s): %s",
689 : : dirname->buf, key);
690 : : }
691 : : }
692 : :
693 : 0 : pkg_adddir_attr(pkg, dirname->buf, uname, gname, perm, 0, false);
694 : 0 : xstring_free(dirname);
695 : :
696 : 0 : return (EPKG_OK);
697 : 0 : }
698 : :
699 : : static int
700 : 299 : pkg_set_deps_from_object(struct pkg *pkg, const ucl_object_t *obj)
701 : : {
702 : : const ucl_object_t *cur, *self;
703 : 299 : ucl_object_iter_t it = NULL, it2;
704 : 299 : const char *origin = NULL;
705 : 299 : const char *version = NULL;
706 : : const char *key, *okey;
707 : 299 : bool noversion = false;
708 : :
709 : 299 : noversion = (getenv("PKG_NO_VERSION_FOR_DEPS") != NULL);
710 : 299 : okey = ucl_object_key(obj);
711 [ + - ]: 299 : if (okey == NULL)
712 : 0 : return (EPKG_FATAL);
713 : 299 : dbg(2, "Found %s", okey);
714 [ + + ]: 598 : while ((self = ucl_iterate_object(obj, &it, (obj->type == UCL_ARRAY)))) {
715 : 299 : it2 = NULL;
716 [ + + ]: 891 : while ((cur = ucl_iterate_object(self, &it2, true))) {
717 : 592 : key = ucl_object_key(cur);
718 [ + - ]: 592 : if (key == NULL)
719 : 0 : continue;
720 [ + + ]: 592 : if (cur->type != UCL_STRING) {
721 : : /* accept version to be an integer */
722 [ + - - + ]: 13 : if (cur->type == UCL_INT && STRIEQ(key, "version")) {
723 [ - + ]: 13 : if (!noversion)
724 : 13 : version = ucl_object_tostring_forced(cur);
725 : 13 : continue;
726 : : }
727 : :
728 : 0 : pkg_emit_error("Skipping malformed dependency entry "
729 : 0 : "for %s", okey);
730 : 0 : continue;
731 : : }
732 [ + + ]: 579 : if (STRIEQ(key, "origin"))
733 : 299 : origin = ucl_object_tostring(cur);
734 [ + + - + ]: 579 : if (STRIEQ(key, "version") && !noversion)
735 : 280 : version = ucl_object_tostring(cur);
736 : : }
737 [ + - ]: 299 : if (origin != NULL)
738 : 299 : pkg_adddep(pkg, okey, origin, version, false);
739 : : else
740 : 0 : pkg_emit_error("Skipping malformed dependency %s", okey);
741 : : }
742 : :
743 : 299 : return (EPKG_OK);
744 : 299 : }
745 : :
746 : : static struct pkg_manifest_key *
747 : 28037 : select_manifest_key(const char *key)
748 : : {
749 [ + + ]: 517226 : for (int i = 0; i < NELEM(manifest_keys); i++)
750 [ + + ]: 517224 : if (STREQ(manifest_keys[i].key, key))
751 : 28035 : return (&(manifest_keys[i]));
752 : 2 : return (NULL);
753 : 28037 : }
754 : : static int
755 : 1076 : parse_manifest(struct pkg *pkg, ucl_object_t *obj)
756 : : {
757 : : const ucl_object_t *cur;
758 : 1076 : ucl_object_iter_t it = NULL;
759 : 1076 : struct pkg_manifest_key *selected_key = NULL;
760 : : const char *key;
761 : 1076 : int ret = EPKG_OK;
762 : :
763 [ + + ]: 15157 : while ((cur = ucl_iterate_object(obj, &it, true))) {
764 : 14082 : key = ucl_object_key(cur);
765 [ + - ]: 14082 : if (key == NULL)
766 : 0 : continue;
767 : 14082 : dbg(3, "found key: '%s'", key);
768 [ + + ]: 14082 : if ((selected_key = select_manifest_key(key)) == NULL) {
769 : 1 : dbg(1, "Skipping unknown key '%s'", key);
770 : 1 : continue;
771 : : }
772 [ + - ]: 14081 : if (TYPE_SHIFT(ucl_object_type(cur)) & selected_key->valid_type) {
773 : 14081 : ret = selected_key->parse_data(pkg, cur, selected_key->type);
774 [ + + ]: 14081 : if (ret != EPKG_OK)
775 : 1 : return (ret);
776 : 14080 : } else {
777 : 0 : pkg_emit_error("Skipping malformed key '%s'", key);
778 : : }
779 : : }
780 : :
781 : 1075 : return (EPKG_OK);
782 : 1076 : }
783 : :
784 : : int
785 : 1076 : pkg_parse_manifest_ucl(struct pkg *pkg, ucl_object_t *obj)
786 : : {
787 : : const ucl_object_t *cur;
788 : 1076 : ucl_object_iter_t it = NULL;
789 : 1076 : struct pkg_manifest_key *sk = NULL;
790 : : const char *key;
791 : :
792 : : /* do a minimal validation */
793 [ + + ]: 15127 : while ((cur = ucl_iterate_object(obj, &it, true))) {
794 : 14052 : key = ucl_object_key(cur);
795 [ + - ]: 14052 : if (key == NULL)
796 : 0 : continue;
797 [ + + ]: 14052 : if ((sk = select_manifest_key(key)) == NULL)
798 : 1 : continue;
799 [ + + ]: 14051 : if (!(sk->valid_type & TYPE_SHIFT(ucl_object_type(cur)))) {
800 : 1 : pkg_emit_error("Bad format in manifest for key:"
801 : 1 : " %s", key);
802 : 1 : UCL_FREE (sizeof (*it), it);
803 : 1 : return (EPKG_FATAL);
804 : : }
805 : : }
806 : :
807 : 1075 : return (parse_manifest(pkg, obj));
808 : 1076 : }
809 : :
810 : : int
811 : 567 : pkg_parse_manifest(struct pkg *pkg, const char *buf, size_t len)
812 : : {
813 : 567 : struct ucl_parser *p = NULL;
814 : 567 : ucl_object_t *obj = NULL;
815 : : int rc;
816 : :
817 [ + - ]: 567 : assert(pkg != NULL);
818 [ + - ]: 567 : assert(buf != NULL);
819 : :
820 : 567 : dbg(2, "%s", "Parsing from buffer");
821 : :
822 : 567 : p = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
823 [ + - ]: 567 : if (!ucl_parser_add_chunk(p, buf, len)) {
824 : 0 : pkg_emit_error("Error parsing manifest: %s",
825 : 0 : ucl_parser_get_error(p));
826 : 0 : ucl_parser_free(p);
827 : :
828 : 0 : return (EPKG_FATAL);
829 : : }
830 : :
831 [ + - ]: 567 : if ((obj = ucl_parser_get_object(p)) == NULL) {
832 : 0 : ucl_parser_free(p);
833 : 0 : return (EPKG_FATAL);
834 : : }
835 : :
836 : 567 : ucl_parser_free(p);
837 : 567 : rc = pkg_parse_manifest_ucl(pkg, obj);
838 : 567 : ucl_object_unref(obj);
839 : :
840 : 567 : return (rc);
841 : 567 : }
842 : :
843 : : int
844 : 359 : pkg_parse_manifest_fileat(int dfd, struct pkg *pkg, const char *file)
845 : : {
846 : 359 : struct ucl_parser *p = NULL;
847 : 359 : ucl_object_t *obj = NULL;
848 : : int rc;
849 : : char *data;
850 : 359 : off_t sz = 0;
851 : :
852 [ + - ]: 359 : assert(pkg != NULL);
853 [ + - ]: 359 : assert(file != NULL);
854 : :
855 : 359 : dbg(1, "Parsing from '%s'", file);
856 : :
857 : 359 : errno = 0;
858 : :
859 [ - + ]: 359 : if (file_to_bufferat(dfd, file, &data, &sz) != EPKG_OK)
860 : 0 : return (EPKG_FATAL);
861 : :
862 : 359 : p = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
863 [ + - ]: 359 : if (!ucl_parser_add_string(p, data, sz)) {
864 : 0 : pkg_emit_error("manifest parsing error: %s", ucl_parser_get_error(p));
865 : 0 : ucl_parser_free(p);
866 : 0 : free(data);
867 : 0 : return (EPKG_FATAL);
868 : : }
869 : :
870 [ + - ]: 359 : if ((obj = ucl_parser_get_object(p)) == NULL) {
871 : 0 : ucl_parser_free(p);
872 : 0 : free(data);
873 : 0 : return (EPKG_FATAL);
874 : : }
875 : 359 : ucl_parser_free(p);
876 : :
877 : 359 : rc = pkg_parse_manifest_ucl(pkg, obj);
878 : 359 : ucl_object_unref(obj);
879 : 359 : free(data);
880 : :
881 : 359 : return (rc);
882 : 359 : }
883 : :
884 : : int
885 : 322 : pkg_parse_manifest_file(struct pkg *pkg, const char *file)
886 : : {
887 : 322 : return pkg_parse_manifest_fileat(AT_FDCWD, pkg, file);
888 : : }
889 : :
890 : : #define MANIFEST_EXPORT_FIELD(result, o, field, type) do { \
891 : : ucl_object_insert_key((result), ucl_object_from ## type (o->field), #field, 0, false); \
892 : : } while (0)
893 : :
894 : : int
895 : 4 : pkg_emit_filelist(struct pkg *pkg, FILE *f)
896 : : {
897 : 4 : ucl_object_t *obj = NULL, *seq;
898 : 4 : struct pkg_file *file = NULL;
899 : 4 : xstring *b = NULL;
900 : :
901 : 4 : obj = ucl_object_typed_new(UCL_OBJECT);
902 : 4 : MANIFEST_EXPORT_FIELD(obj, pkg, origin, string);
903 : 4 : MANIFEST_EXPORT_FIELD(obj, pkg, name, string);
904 : 4 : MANIFEST_EXPORT_FIELD(obj, pkg, version, string);
905 : :
906 : 4 : seq = NULL;
907 [ + + ]: 8 : while (pkg_files(pkg, &file) == EPKG_OK) {
908 : : char dpath[MAXPATHLEN];
909 : 4 : const char *dp = file->path;
910 : :
911 [ + - ]: 4 : if (pkg->oprefix != NULL) {
912 : 0 : size_t l = strlen(pkg->prefix);
913 [ # # # # ]: 0 : if (strncmp(file->path, pkg->prefix, l) == 0 &&
914 [ # # ]: 0 : (file->path[l] == '/' || l == 1)) {
915 : 0 : snprintf(dpath, sizeof(dpath), "%s%s%s",
916 : 0 : pkg->oprefix, l == 1 ? "/" : "", file->path + l);
917 : 0 : dp = dpath;
918 : 0 : }
919 : 0 : }
920 : 4 : urlencode(dp, &b);
921 [ - + ]: 4 : if (seq == NULL)
922 : 4 : seq = ucl_object_typed_new(UCL_ARRAY);
923 : 4 : ucl_array_append(seq, ucl_object_fromlstring(b->buf, strlen(b->buf)));
924 : : }
925 [ - + ]: 4 : if (seq != NULL)
926 : 4 : ucl_object_insert_key(obj, seq, "files", 5, false);
927 : :
928 : 4 : ucl_object_emit_file(obj, UCL_EMIT_JSON_COMPACT, f);
929 : :
930 : 4 : xstring_free(b);
931 : 4 : ucl_object_unref(obj);
932 : :
933 : 4 : return (EPKG_OK);
934 : : }
935 : :
936 : : pkg_object*
937 : 708 : pkg_emit_object(struct pkg *pkg, short flags)
938 : : {
939 : : struct pkg_kv *kv;
940 : 708 : struct pkg_dep *dep = NULL;
941 : 708 : struct pkg_option *option = NULL;
942 : 708 : struct pkg_file *file = NULL;
943 : 708 : struct pkg_dir *dir = NULL;
944 : 708 : struct pkg_conflict *conflict = NULL;
945 : 708 : struct pkg_config_file *cf = NULL;
946 : 708 : xstring *tmpsbuf = NULL;
947 : : int i;
948 : 708 : const char *script_types = NULL;
949 : : char legacyarch[BUFSIZ];
950 : : ucl_object_t *map, *seq, *submap;
951 : 708 : ucl_object_t *top = ucl_object_typed_new(UCL_OBJECT);
952 : :
953 [ - + # # ]: 708 : if (pkg->abi == NULL && pkg->altabi != NULL)
954 : 0 : pkg->abi = xstrdup(pkg->altabi);
955 : 708 : pkg_arch_to_legacy(pkg->abi, legacyarch, BUFSIZ);
956 : 708 : free(pkg->altabi);
957 : 708 : pkg->altabi = xstrdup(legacyarch);
958 : 708 : dbg(4, "Emitting basic metadata");
959 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, name, string);
960 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, origin, string);
961 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, version, string);
962 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, comment, string);
963 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, maintainer, string);
964 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, www, string);
965 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, abi, string);
966 : : /* We need to keep altabi named arch in the manifest */
967 : 708 : ucl_object_insert_key(top, ucl_object_fromstring(pkg->altabi), "arch", 0, false);
968 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, prefix, string);
969 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, sum, string);
970 : 708 : MANIFEST_EXPORT_FIELD(top, pkg, flatsize, int);
971 [ + - ]: 708 : if (pkg->dep_formula != NULL)
972 : 0 : MANIFEST_EXPORT_FIELD(top, pkg, dep_formula, string);
973 [ - + # # ]: 708 : if (pkg->type == PKG_INSTALLED &&
974 : 0 : (flags & PKG_MANIFEST_EMIT_LOCAL_METADATA) == PKG_MANIFEST_EMIT_LOCAL_METADATA) {
975 : 0 : MANIFEST_EXPORT_FIELD(top, pkg, timestamp, int);
976 : 0 : }
977 : :
978 : : /*
979 : : * XXX: dirty hack to be compatible with pkg 1.2
980 : : */
981 [ + + ]: 708 : if (pkg->repopath) {
982 : 306 : ucl_object_insert_key(top,
983 : 153 : ucl_object_fromstring(pkg->repopath), "path", 4, false);
984 : 153 : MANIFEST_EXPORT_FIELD(top, pkg, repopath, string);
985 : 153 : }
986 : :
987 [ - + - - ]: 708 : switch (pkg->licenselogic) {
988 : : case LICENSE_SINGLE:
989 : 0 : ucl_object_insert_key(top, ucl_object_fromlstring("single", 6), "licenselogic", 12, false);
990 : 0 : break;
991 : : case LICENSE_AND:
992 : 0 : ucl_object_insert_key(top, ucl_object_fromlstring("and", 3), "licenselogic", 12, false);
993 : 0 : break;
994 : : case LICENSE_OR:
995 : 0 : ucl_object_insert_key(top, ucl_object_fromlstring("or", 2), "licenselogic", 12, false);
996 : 0 : break;
997 : : }
998 : :
999 : 708 : dbg(4, "Emitting licenses");
1000 : 708 : seq = NULL;
1001 [ - + - + : 708 : tll_foreach(pkg->licenses, l) {
# # ]
1002 [ # # ]: 0 : if (seq == NULL)
1003 : 0 : seq = ucl_object_typed_new(UCL_ARRAY);
1004 : 0 : ucl_array_append(seq, ucl_object_fromstring(l->item));
1005 : 0 : }
1006 [ + - ]: 708 : if (seq)
1007 : 0 : ucl_object_insert_key(top, seq, "licenses", 8, false);
1008 : :
1009 [ + + ]: 708 : if (pkg->pkgsize > 0)
1010 : 153 : MANIFEST_EXPORT_FIELD(top, pkg, pkgsize, int);
1011 [ + + ]: 708 : if (pkg->vital)
1012 : 6 : MANIFEST_EXPORT_FIELD(top, pkg, vital, bool);
1013 : :
1014 [ - + ]: 708 : if (pkg->desc != NULL) {
1015 : 708 : urlencode(pkg->desc, &tmpsbuf);
1016 : 1416 : ucl_object_insert_key(top,
1017 : 708 : ucl_object_fromstring_common(tmpsbuf->buf, strlen(tmpsbuf->buf), UCL_STRING_TRIM),
1018 : : "desc", 4, false);
1019 : 708 : }
1020 : :
1021 : 708 : dbg(4, "Emitting deps");
1022 : 708 : map = NULL;
1023 [ + + ]: 901 : while (pkg_deps(pkg, &dep) == EPKG_OK) {
1024 : 193 : submap = ucl_object_typed_new(UCL_OBJECT);
1025 : 193 : MANIFEST_EXPORT_FIELD(submap, dep, origin, string);
1026 : 193 : MANIFEST_EXPORT_FIELD(submap, dep, version, string);
1027 [ + + ]: 193 : if (map == NULL)
1028 : 158 : map = ucl_object_typed_new(UCL_OBJECT);
1029 : 193 : ucl_object_insert_key(map, submap, dep->name, 0, false);
1030 : : }
1031 [ + + ]: 708 : if (map)
1032 : 158 : ucl_object_insert_key(top, map, "deps", 4, false);
1033 : :
1034 : 708 : dbg(4, "Emitting categories");
1035 : 708 : seq = NULL;
1036 [ + + + + : 1410 : tll_foreach(pkg->categories, c) {
- + ]
1037 [ - + ]: 702 : if (seq == NULL)
1038 : 702 : seq = ucl_object_typed_new(UCL_ARRAY);
1039 : 702 : ucl_array_append(seq, ucl_object_fromstring(c->item));
1040 : 702 : }
1041 [ + + ]: 708 : if (seq)
1042 : 702 : ucl_object_insert_key(top, seq, "categories", 10, false);
1043 : :
1044 : 708 : dbg(4, "Emitting users");
1045 : 708 : seq = NULL;
1046 [ - + - + : 708 : tll_foreach(pkg->users, u) {
# # ]
1047 [ # # ]: 0 : if (seq == NULL)
1048 : 0 : seq = ucl_object_typed_new(UCL_ARRAY);
1049 : 0 : ucl_array_append(seq, ucl_object_fromstring(u->item));
1050 : 0 : }
1051 [ + - ]: 708 : if (seq)
1052 : 0 : ucl_object_insert_key(top, seq, "users", 5, false);
1053 : :
1054 : 708 : dbg(4, "Emitting groups");
1055 : 708 : seq = NULL;
1056 [ - + - + : 708 : tll_foreach(pkg->groups, g) {
# # ]
1057 [ # # ]: 0 : if (seq == NULL)
1058 : 0 : seq = ucl_object_typed_new(UCL_ARRAY);
1059 : 0 : ucl_array_append(seq, ucl_object_fromstring(g->item));
1060 : 0 : }
1061 [ + - ]: 708 : if (seq)
1062 : 0 : ucl_object_insert_key(top, seq, "groups", 6, false);
1063 : :
1064 : 708 : dbg(4, "Emitting shibs_required");
1065 : 708 : seq = NULL;
1066 [ + + + + : 806 : tll_foreach(pkg->shlibs_required, s) {
+ + ]
1067 [ + + ]: 98 : if (seq == NULL)
1068 : 77 : seq = ucl_object_typed_new(UCL_ARRAY);
1069 : 98 : ucl_array_append(seq, ucl_object_fromstring(s->item));
1070 : 98 : }
1071 [ + + ]: 708 : if (seq)
1072 : 77 : ucl_object_insert_key(top, seq, "shlibs_required", 15, false);
1073 : :
1074 : 708 : dbg(4, "Emitting shlibs_provided");
1075 : 708 : seq = NULL;
1076 [ + + + + : 728 : tll_foreach(pkg->shlibs_provided, s) {
- + ]
1077 [ - + ]: 20 : if (seq == NULL)
1078 : 20 : seq = ucl_object_typed_new(UCL_ARRAY);
1079 : 20 : ucl_array_append(seq, ucl_object_fromstring(s->item));
1080 : 20 : }
1081 [ + + ]: 708 : if (seq)
1082 : 20 : ucl_object_insert_key(top, seq, "shlibs_provided", 15, false);
1083 : :
1084 : 708 : dbg(4, "Emitting conflicts");
1085 : 708 : seq = NULL;
1086 [ - + ]: 708 : while (pkg_conflicts(pkg, &conflict) == EPKG_OK) {
1087 [ # # ]: 0 : if (seq == NULL)
1088 : 0 : seq = ucl_object_typed_new(UCL_ARRAY);
1089 : 0 : ucl_array_append(seq, ucl_object_fromstring(conflict->uid));
1090 : : }
1091 [ + - ]: 708 : if (seq)
1092 : 0 : ucl_object_insert_key(top, seq, "conflicts", 9, false);
1093 : :
1094 : 708 : dbg(4, "Emitting provides");
1095 : 708 : seq = NULL;
1096 [ + + + + : 720 : tll_foreach(pkg->provides, p) {
- + ]
1097 [ - + ]: 12 : if (seq == NULL)
1098 : 12 : seq = ucl_object_typed_new(UCL_ARRAY);
1099 : 12 : ucl_array_append(seq, ucl_object_fromstring(p->item));
1100 : 12 : }
1101 [ + + ]: 708 : if (seq)
1102 : 12 : ucl_object_insert_key(top, seq, "provides", 8, false);
1103 : :
1104 : 708 : dbg(4, "Emitting requires");
1105 : 708 : seq = NULL;
1106 [ + + + + : 729 : tll_foreach(pkg->requires, r) {
- + ]
1107 [ - + ]: 21 : if (seq == NULL)
1108 : 21 : seq = ucl_object_typed_new(UCL_ARRAY);
1109 : 21 : ucl_array_append(seq, ucl_object_fromstring(r->item));
1110 : 21 : }
1111 [ + + ]: 708 : if (seq)
1112 : 21 : ucl_object_insert_key(top, seq, "requires", 8, false);
1113 : :
1114 : 708 : dbg(4, "Emitting options");
1115 : 708 : map = NULL;
1116 [ + + ]: 728 : while (pkg_options(pkg, &option) == EPKG_OK) {
1117 : 20 : dbg(4, "Emitting option: %s", option->value);
1118 [ + + ]: 20 : if (map == NULL)
1119 : 10 : map = ucl_object_typed_new(UCL_OBJECT);
1120 : 40 : ucl_object_insert_key(map,
1121 : 20 : ucl_object_fromstring(option->value),
1122 : 20 : option->key, 0, false);
1123 : : }
1124 [ + + ]: 708 : if (map)
1125 : 10 : ucl_object_insert_key(top, map, "options", 7, false);
1126 : :
1127 : 708 : map = NULL;
1128 [ + + + + : 1140 : tll_foreach(pkg->annotations, k) {
- + ]
1129 : 432 : kv = k->item;
1130 [ - + ]: 432 : if (map == NULL)
1131 : 432 : map = ucl_object_typed_new(UCL_OBJECT);
1132 : : /* Add annotations except for internal ones. */
1133 [ + - # # ]: 432 : if ((STREQ(kv->key, "repository") ||
1134 [ - + ]: 432 : STREQ(kv->key, "relocated")) &&
1135 : 0 : (flags & PKG_MANIFEST_EMIT_LOCAL_METADATA) == 0)
1136 : 0 : continue;
1137 : 864 : ucl_object_insert_key(map, ucl_object_fromstring(kv->value),
1138 : 432 : kv->key, strlen(kv->key), true);
1139 : 432 : }
1140 [ + + ]: 708 : if (map)
1141 : 432 : ucl_object_insert_key(top, map, "annotations", 11, false);
1142 : :
1143 [ + + ]: 708 : if ((flags & PKG_MANIFEST_EMIT_COMPACT) == 0) {
1144 [ - + ]: 445 : if ((flags & PKG_MANIFEST_EMIT_NOFILES) == 0) {
1145 : 445 : dbg(4, "Emitting files");
1146 : 445 : map = NULL;
1147 [ + + ]: 689 : while (pkg_files(pkg, &file) == EPKG_OK) {
1148 : : char dpath[MAXPATHLEN];
1149 : 244 : const char *dp = file->path;
1150 : :
1151 [ + + ]: 244 : if (pkg->oprefix != NULL) {
1152 : 2 : size_t l = strlen(pkg->prefix);
1153 [ - + + - ]: 4 : if (strncmp(file->path, pkg->prefix, l) == 0 &&
1154 [ + - ]: 2 : (file->path[l] == '/' || l == 1)) {
1155 : 4 : snprintf(dpath, sizeof(dpath), "%s%s%s",
1156 : 2 : pkg->oprefix, l == 1 ? "/" : "", file->path + l);
1157 : 2 : dp = dpath;
1158 : 2 : }
1159 : 2 : }
1160 [ + - ]: 244 : if (file->sum == NULL)
1161 : 0 : file->sum = xstrdup("-");
1162 : :
1163 : 244 : urlencode(dp, &tmpsbuf);
1164 [ + + ]: 244 : if (map == NULL)
1165 : 204 : map = ucl_object_typed_new(UCL_OBJECT);
1166 : 488 : ucl_object_insert_key(map,
1167 : 244 : ucl_object_fromstring(file->sum),
1168 : 244 : tmpsbuf->buf, strlen(tmpsbuf->buf), true);
1169 : : }
1170 [ + + ]: 445 : if (map)
1171 : 204 : ucl_object_insert_key(top, map, "files", 5, false);
1172 : :
1173 : 445 : dbg(4, "Emitting config files");
1174 : 445 : seq = NULL;
1175 [ + + ]: 460 : while (pkg_config_files(pkg, &cf) == EPKG_OK) {
1176 : 15 : urlencode(cf->path, &tmpsbuf);
1177 [ - + ]: 15 : if (seq == NULL)
1178 : 15 : seq = ucl_object_typed_new(UCL_ARRAY);
1179 : 15 : ucl_array_append(seq, ucl_object_fromstring(tmpsbuf->buf));
1180 : : }
1181 [ + + ]: 445 : if (seq)
1182 : 15 : ucl_object_insert_key(top, seq, "config", 6, false);
1183 : :
1184 : 445 : dbg(4, "Emitting directories");
1185 : 445 : map = NULL;
1186 [ + + ]: 454 : while (pkg_dirs(pkg, &dir) == EPKG_OK) {
1187 : 9 : urlencode(dir->path, &tmpsbuf);
1188 [ + + ]: 9 : if (map == NULL)
1189 : 8 : map = ucl_object_typed_new(UCL_OBJECT);
1190 : 18 : ucl_object_insert_key(map,
1191 : 9 : ucl_object_fromstring("y"),
1192 : 9 : tmpsbuf->buf, strlen(tmpsbuf->buf), true);
1193 : : }
1194 [ + + ]: 445 : if (map)
1195 : 8 : ucl_object_insert_key(top, map, "directories", 11, false);
1196 : 445 : }
1197 : :
1198 : 445 : dbg(4, "Emitting scripts");
1199 : 445 : map = NULL;
1200 [ + + ]: 4450 : for (i = 0; i < PKG_NUM_SCRIPTS; i++) {
1201 [ + + ]: 4005 : if (pkg_script_get(pkg, i) == NULL)
1202 : 3978 : continue;
1203 : :
1204 [ + - + - : 27 : switch (i) {
- - - ]
1205 : : case PKG_SCRIPT_PRE_INSTALL:
1206 : 9 : script_types = "pre-install";
1207 : 9 : break;
1208 : : case PKG_SCRIPT_INSTALL:
1209 : 0 : script_types = "install";
1210 : 0 : break;
1211 : : case PKG_SCRIPT_POST_INSTALL:
1212 : 18 : script_types = "post-install";
1213 : 18 : break;
1214 : : case PKG_SCRIPT_PRE_DEINSTALL:
1215 : 0 : script_types = "pre-deinstall";
1216 : 0 : break;
1217 : : case PKG_SCRIPT_DEINSTALL:
1218 : 0 : script_types = "deinstall";
1219 : 0 : break;
1220 : : case PKG_SCRIPT_POST_DEINSTALL:
1221 : 0 : script_types = "post-deinstall";
1222 : 0 : break;
1223 : : }
1224 : 27 : urlencode(pkg_script_get(pkg, i), &tmpsbuf);
1225 [ + + ]: 27 : if (map == NULL)
1226 : 19 : map = ucl_object_typed_new(UCL_OBJECT);
1227 : 54 : ucl_object_insert_key(map,
1228 : 54 : ucl_object_fromstring_common(tmpsbuf->buf,
1229 : 27 : strlen(tmpsbuf->buf), UCL_STRING_TRIM),
1230 : 27 : script_types, 0, true);
1231 : 27 : }
1232 [ + + ]: 445 : if (map)
1233 : 19 : ucl_object_insert_key(top, map, "scripts", 7, false);
1234 : :
1235 : 445 : dbg(4, "Emitting lua scripts");
1236 : 445 : map = NULL;
1237 [ + + ]: 2670 : for (i = 0; i < PKG_NUM_LUA_SCRIPTS; i++) {
1238 [ + + ]: 2225 : if (tll_length(pkg->lua_scripts[i]) == 0)
1239 : 2204 : continue;
1240 [ - - + - : 21 : switch(i) {
- ]
1241 : : case PKG_LUA_PRE_INSTALL:
1242 : 0 : script_types = "pre-install";
1243 : 0 : break;
1244 : : case PKG_LUA_POST_INSTALL:
1245 : 21 : script_types = "post-install";
1246 : 21 : break;
1247 : : case PKG_LUA_PRE_DEINSTALL:
1248 : 0 : script_types = "pre-deinstall";
1249 : 0 : break;
1250 : : case PKG_LUA_POST_DEINSTALL:
1251 : 0 : script_types = "post-deinstall";
1252 : 0 : break;
1253 : : }
1254 [ - + ]: 21 : if (map == NULL)
1255 : 21 : map = ucl_object_typed_new(UCL_OBJECT);
1256 : 42 : ucl_object_insert_key(map,
1257 : 21 : pkg_lua_script_to_ucl(&pkg->lua_scripts[i]),
1258 : 21 : script_types, 0, true);
1259 : 21 : }
1260 [ + + ]: 445 : if (map)
1261 : 21 : ucl_object_insert_key(top, map, "lua_scripts", 11, false);
1262 : 445 : }
1263 : :
1264 : 708 : dbg(4, "Emitting message");
1265 [ + + ]: 708 : if (pkg_has_message(pkg)) {
1266 : 18 : ucl_object_insert_key(top,
1267 : 9 : pkg_message_to_ucl(pkg),
1268 : : "messages", sizeof("messages") - 1, false);
1269 : 9 : }
1270 : :
1271 : 708 : xstring_free(tmpsbuf);
1272 : :
1273 : 708 : return (top);
1274 : : }
1275 : :
1276 : : int
1277 : 29 : pkg_emit_manifest_file(struct pkg *pkg, FILE *out, short flags)
1278 : : {
1279 : : ucl_object_t *top;
1280 : :
1281 : 29 : top = pkg_emit_object(pkg, flags);
1282 : :
1283 [ + + ]: 29 : if ((flags & PKG_MANIFEST_EMIT_PRETTY) == PKG_MANIFEST_EMIT_PRETTY)
1284 : 1 : ucl_object_emit_file(top, UCL_EMIT_YAML, out);
1285 [ + - ]: 28 : else if ((flags & PKG_MANIFEST_EMIT_UCL) == PKG_MANIFEST_EMIT_UCL)
1286 : 28 : ucl_object_emit_file(top, UCL_EMIT_CONFIG, out);
1287 [ # # ]: 0 : else if ((flags & PKG_MANIFEST_EMIT_JSON) == PKG_MANIFEST_EMIT_JSON)
1288 : 0 : ucl_object_emit_file(top, UCL_EMIT_JSON, out);
1289 : : else
1290 : 0 : ucl_object_emit_file(top, UCL_EMIT_JSON_COMPACT, out);
1291 : :
1292 : 29 : ucl_object_unref(top);
1293 : :
1294 : 29 : return (EPKG_OK);
1295 : : }
|