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