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