Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2024 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
5 : : * Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
6 : : * Copyright (c) 2017 Vsevolod Stakhov <vsevolod@FreeBSD.org>
7 : : * Copyright (c) 2023, Serenity Cyber Security, LLC
8 : : * Author: Gleb Popov <arrowd@FreeBSD.org>
9 : : *
10 : : * SPDX-License-Identifier: BSD-2-Clause
11 : : */
12 : :
13 : : #include <archive.h>
14 : : #include <archive_entry.h>
15 : : #include <assert.h>
16 : : #include <errno.h>
17 : : #include <fcntl.h>
18 : : #include <string.h>
19 : :
20 : : #include "pkg.h"
21 : : #include "private/event.h"
22 : : #include "private/pkg.h"
23 : : #include "private/pkgdb.h"
24 : : #include "private/utils.h"
25 : : #include "xmalloc.h"
26 : :
27 : : #define dbg(x, ...) pkg_dbg(PKG_DBG_PACKAGE, x, __VA_ARGS__)
28 : :
29 : : int
30 : 2088 : pkg_new(struct pkg **pkg, pkg_t type)
31 : : {
32 : 2088 : *pkg = xcalloc(1, sizeof(struct pkg));
33 : 2088 : (*pkg)->type = type;
34 : 2088 : (*pkg)->rootfd = -1;
35 : :
36 : 2088 : return (EPKG_OK);
37 : : }
38 : :
39 : : static void
40 : 143 : pkg_message_free(struct pkg_message *m)
41 : : {
42 : 143 : free(m->str);
43 : 143 : free(m->maximum_version);
44 : 143 : free(m->minimum_version);
45 : 143 : free(m);
46 : 143 : }
47 : :
48 : : void
49 : 3128 : pkg_free(struct pkg *pkg)
50 : : {
51 [ + + ]: 3128 : if (pkg == NULL)
52 : 1090 : return;
53 : :
54 : 2038 : free(pkg->name);
55 : 2038 : free(pkg->origin);
56 : 2038 : free(pkg->old_version);
57 : 2038 : free(pkg->version);
58 : 2038 : free(pkg->maintainer);
59 : 2038 : free(pkg->www);
60 : 2038 : free(pkg->altabi);
61 : 2038 : free(pkg->abi);
62 : 2038 : free(pkg->uid);
63 : 2038 : free(pkg->digest);
64 : 2038 : free(pkg->old_digest);
65 : 2038 : free(pkg->prefix);
66 : 2038 : free(pkg->oprefix);
67 : 2038 : free(pkg->comment);
68 : 2038 : free(pkg->desc);
69 : 2038 : free(pkg->sum);
70 : 2038 : free(pkg->repopath);
71 : 2038 : free(pkg->reponame);
72 : 2038 : free(pkg->repourl);
73 : 2038 : free(pkg->reason);
74 : 2038 : free(pkg->dep_formula);
75 : :
76 [ + + ]: 20380 : for (int i = 0; i < PKG_NUM_SCRIPTS; i++)
77 : 18342 : xstring_free(pkg->scripts[i]);
78 [ + + ]: 12228 : for (int i = 0; i < PKG_NUM_LUA_SCRIPTS; i++)
79 [ + + + + : 10267 : tll_free_and_free(pkg->lua_scripts[i], free);
+ + ]
80 : :
81 : 2038 : pkg_list_free(pkg, PKG_DEPS);
82 : 2038 : pkg_list_free(pkg, PKG_RDEPS);
83 : 2038 : pkg_list_free(pkg, PKG_FILES);
84 : 2038 : pkg_list_free(pkg, PKG_DIRS);
85 : 2038 : pkg_list_free(pkg, PKG_OPTIONS);
86 : :
87 [ - + - + : 2038 : tll_free_and_free(pkg->users, free);
# # ]
88 : 2038 : pkg->flags &= ~PKG_LOAD_USERS;
89 [ - + - + : 2038 : tll_free_and_free(pkg->groups, free);
# # ]
90 : 2038 : pkg->flags &= ~PKG_LOAD_GROUPS;
91 [ + + + + : 2160 : tll_free_and_free(pkg->shlibs_required, free);
+ + ]
92 : 2038 : pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
93 [ + + + + : 2080 : tll_free_and_free(pkg->shlibs_provided, free);
+ + ]
94 : 2038 : pkg->flags &= ~PKG_LOAD_SHLIBS_REQUIRED;
95 [ + + + + : 2071 : tll_free_and_free(pkg->provides, free);
- + ]
96 : 2038 : pkg->flags &= ~PKG_LOAD_PROVIDES;
97 [ + + + + : 2101 : tll_free_and_free(pkg->requires, free);
- + ]
98 : 2038 : pkg->flags &= ~PKG_LOAD_REQUIRES;
99 [ + + + + : 3099 : tll_free_and_free(pkg->categories, free);
- + ]
100 : 2038 : pkg->flags &= ~PKG_LOAD_CATEGORIES;
101 [ + + + + : 2048 : tll_free_and_free(pkg->licenses, free);
- + ]
102 : 2038 : pkg->flags &= ~PKG_LOAD_LICENSES;
103 : :
104 [ + + + + : 2181 : tll_free_and_free(pkg->message, pkg_message_free);
+ + ]
105 [ + + + + : 3526 : tll_free_and_free(pkg->annotations, pkg_kv_free);
+ + ]
106 : :
107 [ + + + + : 2040 : tll_free_and_free(pkg->dir_to_del, free);
+ + ]
108 : :
109 [ + + ]: 2038 : if (pkg->rootfd != -1)
110 : 244 : close(pkg->rootfd);
111 : :
112 : 2038 : free(pkg);
113 : 3128 : }
114 : :
115 : : pkg_t
116 : 806 : pkg_type(const struct pkg * restrict pkg)
117 : : {
118 [ + - ]: 806 : assert(pkg != NULL);
119 : :
120 : 806 : return (pkg->type);
121 : : }
122 : :
123 : : int
124 : 709 : pkg_is_valid(const struct pkg * restrict pkg)
125 : : {
126 [ + - ]: 709 : if (pkg == NULL) {
127 : 0 : pkg_emit_error("Invalid package: not allocated");
128 : 0 : return (EPKG_FATAL);
129 : : }
130 : :
131 [ + + ]: 709 : if (pkg->origin == NULL) {
132 : 3 : pkg_emit_error("Invalid package: object has missing property origin");
133 : 3 : return (EPKG_FATAL);
134 : : }
135 : :
136 [ + + ]: 706 : if (pkg->name == NULL) {
137 : 3 : pkg_emit_error("Invalid package: object has missing property name");
138 : 3 : return (EPKG_FATAL);
139 : : }
140 : :
141 [ + + ]: 703 : if (pkg->comment == NULL) {
142 : 3 : pkg_emit_error("Invalid package: object has missing property comment");
143 : 3 : return (EPKG_FATAL);
144 : : }
145 : :
146 [ + + ]: 700 : if (pkg->version == NULL) {
147 : 3 : pkg_emit_error("Invalid package: object has missing property version");
148 : 3 : return (EPKG_FATAL);
149 : : }
150 : :
151 [ + + ]: 697 : if (pkg->desc == NULL) {
152 : 3 : pkg_emit_error("Invalid package: object has missing property desc");
153 : 3 : return (EPKG_FATAL);
154 : : }
155 : :
156 [ + + ]: 694 : if (pkg->maintainer == NULL) {
157 : 3 : pkg_emit_error("Invalid package: object has missing property maintainer");
158 : 3 : return (EPKG_FATAL);
159 : : }
160 : :
161 [ + + ]: 691 : if (pkg->www == NULL) {
162 : 3 : pkg_emit_error("Invalid package: object has missing property www");
163 : 3 : return (EPKG_FATAL);
164 : : }
165 : :
166 [ + + ]: 688 : if (pkg->prefix == NULL) {
167 : 3 : pkg_emit_error("Invalid package: object has missing property prefix");
168 : 3 : return (EPKG_FATAL);
169 : : }
170 : :
171 : 685 : return (EPKG_OK);
172 : 709 : }
173 : :
174 : : int
175 : 0 : pkg_set_i(struct pkg *pkg, pkg_attr attr, int64_t val)
176 : : {
177 [ # # # # : 0 : switch (attr) {
# ]
178 : : case PKG_ATTR_FLATSIZE:
179 : 0 : pkg->flatsize = val;
180 : 0 : break;
181 : : case PKG_ATTR_OLD_FLATSIZE:
182 : 0 : pkg->old_flatsize = val;
183 : 0 : break;
184 : : case PKG_ATTR_PKGSIZE:
185 : 0 : pkg->pkgsize = val;
186 : 0 : break;
187 : : case PKG_ATTR_TIME:
188 : 0 : pkg->timestamp = val;
189 : 0 : break;
190 : : default:
191 : 0 : pkg_emit_error("%d does not accept int64_t values", attr);
192 : 0 : return (EPKG_FATAL);
193 : : }
194 : 0 : return (EPKG_OK);
195 : 0 : }
196 : :
197 : : int
198 : 3 : pkg_set_b(struct pkg *pkg, pkg_attr attr, bool boolean)
199 : : {
200 [ - - + - ]: 3 : switch (attr) {
201 : : case PKG_ATTR_AUTOMATIC:
202 : 3 : pkg->automatic = boolean;
203 : 3 : break;
204 : : case PKG_ATTR_LOCKED:
205 : 0 : pkg->locked = boolean;
206 : 0 : break;
207 : : case PKG_ATTR_VITAL:
208 : 0 : pkg->vital = boolean;
209 : 0 : break;
210 : : default:
211 : 0 : pkg_emit_error("%d does not accept bool values", attr);
212 : 0 : return (EPKG_FATAL);
213 : : }
214 : 3 : return (EPKG_OK);
215 : 3 : }
216 : :
217 : : int
218 : 33 : pkg_set_s(struct pkg *pkg, pkg_attr attr, const char *str)
219 : : {
220 : : char *endptr;
221 : : ucl_object_t *obj;
222 : : int64_t i;
223 : :
224 [ + + + + : 33 : switch (attr) {
+ + - + +
+ - - - -
- - - - -
- - - -
- ]
225 : : case PKG_ATTR_NAME:
226 : 4 : free(pkg->name);
227 : 4 : pkg->name = xstrdup(str);
228 : 4 : free(pkg->uid);
229 : 4 : pkg->uid = xstrdup(str);
230 : 4 : break;
231 : : case PKG_ATTR_ORIGIN:
232 : 4 : free(pkg->origin);
233 : 4 : pkg->origin = xstrdup(str);
234 : 4 : break;
235 : : case PKG_ATTR_VERSION:
236 : 3 : free(pkg->version);
237 : 3 : pkg->version = xstrdup(str);
238 : 3 : break;
239 : : case PKG_ATTR_DESC:
240 : 3 : free(pkg->desc);
241 : 3 : pkg->desc = xstrdup(str);
242 : 3 : break;
243 : : case PKG_ATTR_COMMENT:
244 : 3 : free(pkg->comment);
245 : 3 : pkg->comment = xstrdup(str);
246 : 3 : break;
247 : : case PKG_ATTR_MESSAGE:
248 [ # # # # : 0 : tll_free_and_free(pkg->message, pkg_message_free);
# # ]
249 [ # # ]: 0 : if (*str == '[') {
250 : 0 : pkg_message_from_str(pkg, str, strlen(str));
251 : 0 : } else {
252 : 0 : obj = ucl_object_fromstring_common(str, strlen(str),
253 : : UCL_STRING_RAW|UCL_STRING_TRIM);
254 : 0 : pkg_message_from_ucl(pkg, obj);
255 : 0 : ucl_object_unref(obj);
256 : : }
257 : 0 : break;
258 : : case PKG_ATTR_ARCH:
259 : 1 : free(pkg->altabi);
260 : 1 : pkg->altabi = xstrdup(str);
261 : 1 : break;
262 : : case PKG_ATTR_ABI:
263 : 0 : free(pkg->abi);
264 : 0 : pkg->abi = xstrdup(str);
265 : 0 : break;
266 : : case PKG_ATTR_MAINTAINER:
267 : 3 : free(pkg->maintainer);
268 : 3 : pkg->maintainer = xstrdup(str);
269 : 3 : break;
270 : : case PKG_ATTR_WWW:
271 : 3 : free(pkg->www);
272 : 3 : pkg->www = xstrdup(str);
273 : 3 : break;
274 : : case PKG_ATTR_PREFIX:
275 : 9 : free(pkg->prefix);
276 : 9 : pkg->prefix = xstrdup(str);
277 : 9 : break;
278 : : case PKG_ATTR_REPOPATH:
279 : 0 : free(pkg->repopath);
280 : 0 : pkg->repopath = xstrdup(str);
281 : 0 : break;
282 : : case PKG_ATTR_CKSUM:
283 : 0 : free(pkg->sum);
284 : 0 : pkg->sum = xstrdup(str);
285 : 0 : break;
286 : : case PKG_ATTR_OLD_VERSION:
287 : 0 : free(pkg->old_version);
288 : 0 : pkg->old_version = xstrdup(str);
289 : 0 : break;
290 : : case PKG_ATTR_REPONAME:
291 : 0 : free(pkg->reponame);
292 : 0 : pkg->reponame = xstrdup(str);
293 : 0 : break;
294 : : case PKG_ATTR_REPOURL:
295 : 0 : free(pkg->repourl);
296 : 0 : pkg->repourl = xstrdup(str);
297 : 0 : break;
298 : : case PKG_ATTR_DIGEST:
299 : 0 : free(pkg->digest);
300 : 0 : pkg->digest = xstrdup(str);
301 : 0 : break;
302 : : case PKG_ATTR_REASON:
303 : 0 : free(pkg->reason);
304 : 0 : pkg->reason = xstrdup(str);
305 : 0 : break;
306 : : case PKG_ATTR_DEP_FORMULA:
307 : 0 : free(pkg->dep_formula);
308 : 0 : pkg->dep_formula = xstrdup(str);
309 : 0 : break;
310 : : case PKG_ATTR_FLATSIZE:
311 : 0 : i = strtoimax(str, &endptr, 10);
312 [ # # ]: 0 : if (endptr != NULL) {
313 : 0 : pkg_emit_error("Impossible to convert '%s' to int64_t",
314 : 0 : str);
315 : 0 : return (EPKG_FATAL);
316 : : }
317 : 0 : pkg->flatsize = i;
318 : 0 : break;
319 : : case PKG_ATTR_OLD_FLATSIZE:
320 : 0 : i = strtoimax(str, &endptr, 10);
321 [ # # ]: 0 : if (endptr != NULL) {
322 : 0 : pkg_emit_error("Impossible to convert '%s' to int64_t",
323 : 0 : str);
324 : 0 : return (EPKG_FATAL);
325 : : }
326 : 0 : pkg->old_flatsize = i;
327 : 0 : break;
328 : : case PKG_ATTR_PKGSIZE:
329 : 0 : i = strtoimax(str, &endptr, 10);
330 [ # # ]: 0 : if (endptr != NULL) {
331 : 0 : pkg_emit_error("Impossible to convert '%s' to int64_t",
332 : 0 : str);
333 : 0 : return (EPKG_FATAL);
334 : : }
335 : 0 : pkg->pkgsize = i;
336 : 0 : break;
337 : : case PKG_ATTR_TIME:
338 : 0 : i = strtoimax(str, &endptr, 10);
339 [ # # ]: 0 : if (endptr != NULL) {
340 : 0 : pkg_emit_error("Impossible to convert '%s' to int64_t",
341 : 0 : str);
342 : 0 : return (EPKG_FATAL);
343 : : }
344 : 0 : pkg->timestamp = i;
345 : 0 : break;
346 : : default:
347 : 0 : pkg_emit_error("%d does not accept string values", attr);
348 : 0 : return (EPKG_FATAL);
349 : : }
350 : 33 : return (EPKG_OK);
351 : 33 : }
352 : :
353 : : int
354 : 0 : pkg_set_from_fileat(int fd, struct pkg *pkg, pkg_attr attr, const char *path,
355 : : bool trimcr)
356 : : {
357 : 0 : char *buf = NULL;
358 : : char *cp;
359 : 0 : off_t size = 0;
360 : 0 : int ret = EPKG_OK;
361 : :
362 [ # # ]: 0 : assert(pkg != NULL);
363 [ # # ]: 0 : assert(path != NULL);
364 : :
365 [ # # ]: 0 : if ((ret = file_to_bufferat(fd, path, &buf, &size)) != EPKG_OK)
366 : 0 : return (ret);
367 : :
368 [ # # ]: 0 : if (trimcr) {
369 : 0 : cp = buf + strlen(buf) - 1;
370 [ # # # # : 0 : while (cp > buf && *cp == '\n') {
# # ]
371 : 0 : *cp = 0;
372 : 0 : cp--;
373 : : }
374 : 0 : }
375 : :
376 : 0 : ret = pkg_set(pkg, attr, buf);
377 : :
378 : 0 : free(buf);
379 : :
380 : 0 : return (ret);
381 : 0 : }
382 : :
383 : : #define pkg_each(name, type, field) \
384 : : int \
385 : : pkg_##name(const struct pkg *p, type **t) { \
386 : : assert(p != NULL); \
387 : : if ((*t) == NULL) \
388 : : (*t) = p->field; \
389 : : else \
390 : : (*t) = (*t)->next; \
391 : : if ((*t) == NULL) \
392 : : return (EPKG_END); \
393 : : return (EPKG_OK); \
394 : : }
395 : :
396 [ + - + + : 1251 : pkg_each(dirs, struct pkg_dir, dirs);
+ + ]
397 [ + - + + : 3957 : pkg_each(files, struct pkg_file, files);
+ + ]
398 [ + - + + : 2724 : pkg_each(deps, struct pkg_dep, depends);
+ + ]
399 [ + - + + : 269 : pkg_each(rdeps, struct pkg_dep, rdepends);
+ + ]
400 [ + - + + : 1573 : pkg_each(options, struct pkg_option, options);
+ + ]
401 [ + - + + : 1138 : pkg_each(conflicts, struct pkg_conflict, conflicts);
+ + ]
402 [ + - + + : 895 : pkg_each(config_files, struct pkg_config_file, config_files);
+ + ]
403 : :
404 : : int
405 : 0 : pkg_adduser(struct pkg *pkg, const char *name)
406 : : {
407 [ # # ]: 0 : assert(pkg != NULL);
408 [ # # ]: 0 : assert(name != NULL && name[0] != '\0');
409 : :
410 [ # # # # : 0 : tll_foreach(pkg->users, u) {
# # ]
411 [ # # ]: 0 : if (!STREQ(u->item, name))
412 : 0 : continue;
413 [ # # ]: 0 : if (ctx.developer_mode) {
414 : 0 : pkg_emit_error("duplicate user listing: %s, fatal (developer mode)", name);
415 : 0 : return (EPKG_FATAL);
416 : : }
417 : 0 : pkg_emit_error("duplicate user listing: %s, ignoring", name);
418 : 0 : return (EPKG_OK);
419 : : }
420 : :
421 [ # # # # : 0 : tll_push_back(pkg->users, xstrdup(name));
# # # # #
# ]
422 : :
423 : 0 : return (EPKG_OK);
424 : 0 : }
425 : :
426 : : int
427 : 0 : pkg_addgroup(struct pkg *pkg, const char *name)
428 : : {
429 [ # # ]: 0 : assert(pkg != NULL);
430 [ # # ]: 0 : assert(name != NULL && name[0] != '\0');
431 : :
432 [ # # # # : 0 : tll_foreach(pkg->groups, g) {
# # ]
433 [ # # ]: 0 : if (!STREQ(g->item, name))
434 : 0 : continue;
435 [ # # ]: 0 : if (ctx.developer_mode) {
436 : 0 : pkg_emit_error("duplicate group listing: %s, fatal (developer mode)", name);
437 : 0 : return (EPKG_FATAL);
438 : : }
439 : 0 : pkg_emit_error("duplicate group listing: %s, ignoring", name);
440 : 0 : return (EPKG_OK);
441 : : }
442 : :
443 [ # # # # : 0 : tll_push_back(pkg->groups, xstrdup(name));
# # # # #
# ]
444 : :
445 : 0 : return (EPKG_OK);
446 : 0 : }
447 : :
448 : : int
449 : 479 : pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked)
450 : : {
451 [ + - ]: 479 : if (pkg_adddep_chain(NULL, pkg, name, origin, version, locked) == NULL) {
452 : 0 : return (EPKG_FATAL);
453 : : }
454 : :
455 : 479 : return (EPKG_OK);
456 : 479 : }
457 : :
458 : : struct pkg_dep *
459 : 479 : pkg_adddep_chain(struct pkg_dep *chain,
460 : : struct pkg *pkg,
461 : : const char *name,
462 : : const char *origin,
463 : : const char *version, bool locked)
464 : : {
465 : 479 : struct pkg_dep *d = NULL;
466 : :
467 [ + - ]: 479 : assert(pkg != NULL);
468 [ + - ]: 479 : assert(name != NULL && name[0] != '\0');
469 : :
470 [ + - ]: 479 : dbg(3, "add a new dependency origin: %s, name: %s", origin ? origin : "", name);
471 [ - + ]: 479 : if (pkghash_get(pkg->depshash, name) != NULL) {
472 : 0 : pkg_emit_error("%s: duplicate dependency listing: %s",
473 : 0 : pkg->name, name);
474 : 0 : return (NULL);
475 : : }
476 : :
477 : 479 : d = xcalloc(1, sizeof(*d));
478 [ + + - + ]: 479 : if (origin != NULL && origin[0] != '\0')
479 : 478 : d->origin = xstrdup(origin);
480 : 479 : d->name = xstrdup(name);
481 [ + + - + ]: 479 : if (version != NULL && version[0] != '\0')
482 : 410 : d->version = xstrdup(version);
483 : 479 : d->uid = xstrdup(name);
484 : 479 : d->locked = locked;
485 : :
486 [ + + - + ]: 566 : pkghash_safe_add(pkg->depshash, d->name, d, NULL);
487 [ - + ]: 479 : if (chain == NULL) {
488 [ + + ]: 479 : DL_APPEND(pkg->depends, d);
489 : 479 : chain = pkg->depends;
490 : 479 : }
491 : : else {
492 [ # # ]: 0 : DL_APPEND2(chain, d, alt_prev, alt_next);
493 : : }
494 : :
495 : 479 : return (chain);
496 : 479 : }
497 : :
498 : : int
499 : 34 : pkg_addrdep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked)
500 : : {
501 : : struct pkg_dep *d;
502 : :
503 [ + - ]: 34 : assert(pkg != NULL);
504 [ + - ]: 34 : assert(name != NULL && name[0] != '\0');
505 : :
506 [ + - ]: 34 : dbg(3, "add a new reverse dependency origin: %s, name: %s", origin ? origin : "", name);
507 : :
508 : 34 : d = xcalloc(1, sizeof(*d));
509 [ + - - + ]: 34 : if (origin != NULL && origin[0] != '\0')
510 : 34 : d->origin = xstrdup(origin);
511 : 34 : d->name = xstrdup(name);
512 [ + - - + ]: 34 : if (version != NULL && version[0] != '\0')
513 : 34 : d->version = xstrdup(version);
514 : 34 : d->uid = xstrdup(name);
515 : 34 : d->locked = locked;
516 : :
517 [ + + - + ]: 40 : pkghash_safe_add(pkg->rdepshash, d->name, d, NULL);
518 : 34 : LL_PREPEND(pkg->rdepends, d);
519 : :
520 : 34 : return (EPKG_OK);
521 : : }
522 : :
523 : : int
524 : 721 : pkg_addfile(struct pkg *pkg, const char *path, const char *sum, bool check_duplicates)
525 : : {
526 : 721 : return (pkg_addfile_attr(pkg, path, sum, NULL, NULL, 0, 0, check_duplicates));
527 : : }
528 : :
529 : : int
530 : 830 : pkg_addfile_attr(struct pkg *pkg, const char *path, const char *sum,
531 : : const char *uname, const char *gname, mode_t perm, u_long fflags,
532 : : bool check_duplicates)
533 : : {
534 : 830 : struct pkg_file *f = NULL;
535 : : char abspath[MAXPATHLEN];
536 : :
537 [ + - ]: 830 : assert(pkg != NULL);
538 [ + - ]: 830 : assert(path != NULL && path[0] != '\0');
539 : :
540 : 830 : path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
541 : 830 : dbg(3, "add new file '%s'", path);
542 : :
543 [ + + + - ]: 830 : if (check_duplicates && pkghash_get(pkg->filehash, path) != NULL) {
544 [ # # ]: 0 : if (ctx.developer_mode) {
545 : 0 : pkg_emit_error("duplicate file listing: %s, fatal (developer mode)", path);
546 : 0 : return (EPKG_FATAL);
547 : : } else {
548 : 0 : pkg_emit_error("duplicate file listing: %s, ignoring", path);
549 : 0 : return (EPKG_OK);
550 : : }
551 : : }
552 : :
553 : 830 : f = xcalloc(1, sizeof(*f));
554 : 830 : strlcpy(f->path, path, sizeof(f->path));
555 : :
556 [ + + ]: 830 : if (sum != NULL)
557 : 607 : f->sum = xstrdup(sum);
558 : :
559 [ + + ]: 830 : if (uname != NULL)
560 : 86 : strlcpy(f->uname, uname, sizeof(f->uname));
561 : :
562 [ + + ]: 830 : if (gname != NULL)
563 : 86 : strlcpy(f->gname, gname, sizeof(f->gname));
564 : :
565 [ + + ]: 830 : if (perm != 0)
566 : 28 : f->perm = perm;
567 : :
568 [ + + ]: 830 : if (fflags != 0)
569 : 1 : f->fflags = fflags;
570 : :
571 [ + + - + ]: 1107 : pkghash_safe_add(pkg->filehash, f->path, f, NULL);
572 [ + + ]: 830 : DL_APPEND(pkg->files, f);
573 : :
574 : 830 : return (EPKG_OK);
575 : 830 : }
576 : :
577 : : int
578 : 48 : pkg_addconfig_file(struct pkg *pkg, const char *path, const char *content)
579 : : {
580 : 48 : struct pkg_config_file *f = NULL;
581 : : char abspath[MAXPATHLEN];
582 : :
583 : 48 : path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
584 : 48 : dbg(3, "add new config file '%s'", path);
585 : :
586 [ + + ]: 48 : if (pkghash_get(pkg->config_files_hash, path) != NULL) {
587 : 2 : pkg_emit_error("duplicate file listing: %s", path);
588 : 2 : return (EPKG_FATAL);
589 : : }
590 : 46 : f = xcalloc(1, sizeof(*f));
591 : 46 : strlcpy(f->path, path, sizeof(f->path));
592 : :
593 [ + + ]: 46 : if (content != NULL)
594 : 16 : f->content = xstrdup(content);
595 : :
596 [ - + # # ]: 46 : pkghash_safe_add(pkg->config_files_hash, f->path, f, NULL);
597 [ - + ]: 46 : DL_APPEND(pkg->config_files, f);
598 : :
599 : 46 : return (EPKG_OK);
600 : 48 : }
601 : :
602 : : int
603 : 1068 : pkg_addstring(stringlist_t *list, const char *val, const char *title)
604 : : {
605 [ + - ]: 1068 : assert(val != NULL);
606 [ + - ]: 1068 : assert(title != NULL);
607 : :
608 [ + + - + : 1068 : tll_foreach(*list, v) {
# # ]
609 [ # # ]: 0 : if (!STREQ(v->item, val))
610 : 0 : continue;
611 [ # # ]: 0 : if (ctx.developer_mode) {
612 : 0 : pkg_emit_error("duplicate %s listing: %s, fatal"
613 : 0 : " (developer mode)", title, val);
614 : 0 : return (EPKG_FATAL);
615 : : }
616 : 0 : pkg_emit_error("duplicate %s listing: %s, "
617 : 0 : "ignoring", title, val);
618 : 0 : return (EPKG_OK);
619 : : }
620 : :
621 [ - + + - : 1068 : tll_push_back(*list, xstrdup(val));
# # + + +
+ ]
622 : :
623 : 1068 : return (EPKG_OK);
624 : 1068 : }
625 : :
626 : : int
627 : 33 : pkg_adddir(struct pkg *pkg, const char *path, bool check_duplicates)
628 : : {
629 : 33 : return(pkg_adddir_attr(pkg, path, NULL, NULL, 0, 0, check_duplicates));
630 : : }
631 : :
632 : : int
633 : 38 : pkg_adddir_attr(struct pkg *pkg, const char *path, const char *uname,
634 : : const char *gname, mode_t perm, u_long fflags, bool check_duplicates)
635 : : {
636 : 38 : struct pkg_dir *d = NULL;
637 : : char abspath[MAXPATHLEN];
638 : :
639 [ + - ]: 38 : assert(pkg != NULL);
640 [ + - ]: 38 : assert(path != NULL && path[0] != '\0');
641 : :
642 [ + - ]: 38 : if (STREQ(path, "/")) {
643 : 0 : pkg_emit_error("skipping useless directory: '%s'\n", path);
644 : 0 : return (EPKG_OK);
645 : : }
646 : 38 : path = pkg_absolutepath(path, abspath, sizeof(abspath), false);
647 : 38 : dbg(3, "add new directory '%s'", path);
648 [ + + + - ]: 38 : if (check_duplicates && pkghash_get(pkg->dirhash, path) != NULL) {
649 [ # # ]: 0 : if (ctx.developer_mode) {
650 : 0 : pkg_emit_error("duplicate directory listing: %s, fatal (developer mode)", path);
651 : 0 : return (EPKG_FATAL);
652 : : } else {
653 : 0 : pkg_emit_error("duplicate directory listing: %s, ignoring", path);
654 : 0 : return (EPKG_OK);
655 : : }
656 : : }
657 : :
658 : 38 : d = xcalloc(1, sizeof(*d));
659 : 38 : strlcpy(d->path, path, sizeof(d->path));
660 : :
661 [ + + ]: 38 : if (uname != NULL)
662 : 5 : strlcpy(d->uname, uname, sizeof(d->uname));
663 : :
664 [ + + ]: 38 : if (gname != NULL)
665 : 5 : strlcpy(d->gname, gname, sizeof(d->gname));
666 : :
667 [ + - ]: 38 : if (perm != 0)
668 : 0 : d->perm = perm;
669 : :
670 [ + - ]: 38 : if (fflags != 0)
671 : 0 : d->fflags = fflags;
672 : :
673 [ + + - + ]: 49 : pkghash_safe_add(pkg->dirhash, d->path, d, NULL);
674 [ + + ]: 38 : DL_APPEND(pkg->dirs, d);
675 : :
676 : 38 : return (EPKG_OK);
677 : 38 : }
678 : :
679 : : int
680 : 83 : pkg_addscript(struct pkg *pkg, const char *data, pkg_script type)
681 : : {
682 : :
683 [ + - ]: 83 : assert(pkg != NULL);
684 [ - + ]: 83 : xstring_renew(pkg->scripts[type]);
685 : 83 : fprintf(pkg->scripts[type]->fp, "%s", data);
686 : :
687 : 83 : return (EPKG_OK);
688 : : }
689 : :
690 : : int
691 : 5 : pkg_add_lua_script(struct pkg *pkg, const char *data, pkg_lua_script type)
692 : : {
693 [ + - ]: 5 : assert(pkg != NULL);
694 : :
695 [ - + ]: 5 : if (type >= PKG_LUA_UNKNOWN)
696 : 0 : return (EPKG_FATAL);
697 : :
698 [ + + + + : 5 : tll_push_back(pkg->lua_scripts[type], xstrdup(data));
+ - - + +
+ ]
699 : :
700 : 5 : return (EPKG_OK);
701 : 5 : }
702 : :
703 : : int
704 : 0 : pkg_addluascript_fileat(int fd, struct pkg *pkg, const char *filename)
705 : : {
706 : : char *data;
707 : : pkg_lua_script type;
708 : 0 : int ret = EPKG_OK;
709 : 0 : off_t sz = 0;
710 : :
711 [ # # ]: 0 : assert(pkg != NULL);
712 [ # # ]: 0 : assert(filename != NULL);
713 : :
714 : 0 : dbg(1, "Adding script from: '%s'", filename);
715 : :
716 [ # # ]: 0 : if ((ret = file_to_bufferat(fd, filename, &data, &sz)) != EPKG_OK)
717 : 0 : return (ret);
718 : :
719 [ # # ]: 0 : if (STREQ(filename, "pkg-pre-install.lua")) {
720 : 0 : type = PKG_LUA_PRE_INSTALL;
721 [ # # ]: 0 : } else if (STREQ(filename, "pkg-post-install.lua")) {
722 : 0 : type = PKG_LUA_POST_INSTALL;
723 [ # # ]: 0 : } else if (STREQ(filename, "pkg-pre-deinstall.lua")) {
724 : 0 : type = PKG_LUA_PRE_DEINSTALL;
725 [ # # ]: 0 : } else if (STREQ(filename, "pkg-post-deinstall.lua")) {
726 : 0 : type = PKG_LUA_POST_DEINSTALL;
727 : 0 : } else {
728 : 0 : pkg_emit_error("unknown lua script '%s'", filename);
729 : 0 : ret = EPKG_FATAL;
730 : 0 : goto cleanup;
731 : : }
732 : :
733 : 0 : ret = pkg_add_lua_script(pkg, data, type);
734 : : cleanup:
735 : 0 : free(data);
736 : 0 : return (ret);
737 : 0 : }
738 : :
739 : : int
740 : 0 : pkg_addscript_fileat(int fd, struct pkg *pkg, const char *filename)
741 : : {
742 : : char *data;
743 : : pkg_script type;
744 : 0 : int ret = EPKG_OK;
745 : 0 : off_t sz = 0;
746 : :
747 [ # # ]: 0 : assert(pkg != NULL);
748 [ # # ]: 0 : assert(filename != NULL);
749 : :
750 : 0 : dbg(1, "Adding script from: '%s'", filename);
751 : :
752 [ # # ]: 0 : if ((ret = file_to_bufferat(fd, filename, &data, &sz)) != EPKG_OK)
753 : 0 : return (ret);
754 : :
755 [ # # # # ]: 0 : if (STREQ(filename, "pkg-pre-install") ||
756 : 0 : STREQ(filename, "+PRE_INSTALL")) {
757 : 0 : type = PKG_SCRIPT_PRE_INSTALL;
758 [ # # # # ]: 0 : } else if (STREQ(filename, "pkg-post-install") ||
759 : 0 : STREQ(filename, "+POST_INSTALL")) {
760 : 0 : type = PKG_SCRIPT_POST_INSTALL;
761 [ # # # # ]: 0 : } else if (STREQ(filename, "pkg-install") ||
762 : 0 : STREQ(filename, "+INSTALL")) {
763 : 0 : type = PKG_SCRIPT_INSTALL;
764 [ # # # # ]: 0 : } else if (STREQ(filename, "pkg-pre-deinstall") ||
765 : 0 : STREQ(filename, "+PRE_DEINSTALL")) {
766 : 0 : type = PKG_SCRIPT_PRE_DEINSTALL;
767 [ # # # # ]: 0 : } else if (STREQ(filename, "pkg-post-deinstall") ||
768 : 0 : STREQ(filename, "+POST_DEINSTALL")) {
769 : 0 : type = PKG_SCRIPT_POST_DEINSTALL;
770 [ # # # # ]: 0 : } else if (STREQ(filename, "pkg-deinstall") ||
771 : 0 : STREQ(filename, "+DEINSTALL")) {
772 : 0 : type = PKG_SCRIPT_DEINSTALL;
773 : 0 : } else {
774 : 0 : pkg_emit_error("unknown script '%s'", filename);
775 : 0 : ret = EPKG_FATAL;
776 : 0 : goto cleanup;
777 : : }
778 : :
779 : 0 : ret = pkg_addscript(pkg, data, type);
780 : : cleanup:
781 : 0 : free(data);
782 : 0 : return (ret);
783 : 0 : }
784 : :
785 : : int
786 : 3 : pkg_appendscript(struct pkg *pkg, const char *cmd, pkg_script type)
787 : : {
788 : :
789 [ + - ]: 3 : assert(pkg != NULL);
790 [ + - ]: 3 : assert(cmd != NULL && cmd[0] != '\0');
791 : :
792 [ - + ]: 3 : if (pkg->scripts[type] == NULL)
793 : 3 : pkg->scripts[type] = xstring_new();
794 : :
795 : 3 : fprintf(pkg->scripts[type]->fp, "%s", cmd);
796 : :
797 : 3 : return (EPKG_OK);
798 : : }
799 : :
800 : : int
801 : 184 : pkg_addoption(struct pkg *pkg, const char *key, const char *value)
802 : : {
803 : 184 : struct pkg_option *o = NULL;
804 : :
805 [ + - ]: 184 : assert(pkg != NULL);
806 [ + - ]: 184 : assert(key != NULL && key[0] != '\0');
807 [ + - ]: 184 : assert(value != NULL && value[0] != '\0');
808 : :
809 : : /* There might be a default or description for the option
810 : : already, so we only count it as a duplicate if the value
811 : : field is already set. Which implies there could be a
812 : : default value or description for an option but no actual
813 : : value. */
814 : :
815 : 184 : dbg(2,"adding options: %s = %s", key, value);
816 [ - + ]: 184 : if (pkghash_get(pkg->optionshash, key) != NULL) {
817 [ # # ]: 0 : if (ctx.developer_mode) {
818 : 0 : pkg_emit_error("duplicate options listing: %s, fatal (developer mode)", key);
819 : 0 : return (EPKG_FATAL);
820 : : } else {
821 : 0 : pkg_emit_error("duplicate options listing: %s, ignoring", key);
822 : 0 : return (EPKG_OK);
823 : : }
824 : : }
825 : 184 : o = xcalloc(1, sizeof(*o));
826 : 184 : o->key = xstrdup(key);
827 : 184 : o->value = xstrdup(value);
828 [ + + - + ]: 326 : pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
829 [ + + ]: 184 : DL_APPEND(pkg->options, o);
830 : :
831 : 184 : return (EPKG_OK);
832 : 184 : }
833 : :
834 : : int
835 : 0 : pkg_addoption_default(struct pkg *pkg, const char *key,
836 : : const char *default_value)
837 : : {
838 : 0 : struct pkg_option *o = NULL;
839 : :
840 [ # # ]: 0 : assert(pkg != NULL);
841 [ # # ]: 0 : assert(key != NULL && key[0] != '\0');
842 [ # # ]: 0 : assert(default_value != NULL && default_value[0] != '\0');
843 : :
844 : : /* There might be a value or description for the option
845 : : already, so we only count it as a duplicate if the
846 : : default_value field is already set. Which implies there
847 : : could be a default value or description for an option but
848 : : no actual value. */
849 : :
850 [ # # ]: 0 : if (pkghash_get(pkg->optionshash, key) != NULL) {
851 [ # # ]: 0 : if (ctx.developer_mode) {
852 : 0 : pkg_emit_error("duplicate default value for option: %s, fatal (developer mode)", key);
853 : 0 : return (EPKG_FATAL);
854 : : } else {
855 : 0 : pkg_emit_error("duplicate default value for option: %s, ignoring", key);
856 : 0 : return (EPKG_OK);
857 : : }
858 : : }
859 : 0 : o = xcalloc(1, sizeof(*o));
860 : 0 : o->key = xstrdup(key);
861 : 0 : o->default_value = xstrdup(default_value);
862 [ # # # # ]: 0 : pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
863 [ # # ]: 0 : DL_APPEND(pkg->options, o);
864 : :
865 : 0 : return (EPKG_OK);
866 : 0 : }
867 : :
868 : : int
869 : 0 : pkg_addoption_description(struct pkg *pkg, const char *key,
870 : : const char *description)
871 : : {
872 : 0 : struct pkg_option *o = NULL;
873 : :
874 [ # # ]: 0 : assert(pkg != NULL);
875 [ # # ]: 0 : assert(key != NULL && key[0] != '\0');
876 [ # # ]: 0 : assert(description != NULL && description[0] != '\0');
877 : :
878 : : /* There might be a value or default for the option already,
879 : : so we only count it as a duplicate if the description field
880 : : is already set. Which implies there could be a default
881 : : value or description for an option but no actual value. */
882 : :
883 [ # # ]: 0 : if (pkghash_get(pkg->optionshash, key) != NULL) {
884 [ # # ]: 0 : if (ctx.developer_mode) {
885 : 0 : pkg_emit_error("duplicate description for option: %s, fatal (developer mode)", key);
886 : 0 : return (EPKG_FATAL);
887 : : } else {
888 : 0 : pkg_emit_error("duplicate description for option: %s, ignoring", key);
889 : 0 : return (EPKG_OK);
890 : : }
891 : : }
892 : :
893 : 0 : o = xcalloc(1, sizeof(*o));
894 : 0 : o->key = xstrdup(key);
895 : 0 : o->description = xstrdup(description);
896 [ # # # # ]: 0 : pkghash_safe_add(pkg->optionshash, o->key, o, NULL);
897 [ # # ]: 0 : DL_APPEND(pkg->options, o);
898 : :
899 : 0 : return (EPKG_OK);
900 : 0 : }
901 : :
902 : : enum pkg_shlib_flags
903 : 25 : pkg_shlib_flags_from_abi(const struct pkg_abi *shlib_abi)
904 : : {
905 : 25 : enum pkg_shlib_flags flags = PKG_SHLIB_FLAGS_NONE;
906 : :
907 [ + + ]: 25 : if (ctx.abi.os == PKG_OS_FREEBSD) {
908 [ - + # # ]: 23 : if (shlib_abi->os == PKG_OS_LINUX &&
909 : 0 : pkg_object_bool(pkg_config_get("TRACK_LINUX_COMPAT_SHLIBS"))) {
910 : 0 : flags |= PKG_SHLIB_FLAGS_COMPAT_LINUX;
911 : 0 : }
912 : :
913 [ + + + + ]: 23 : switch (ctx.abi.arch) {
914 : : case PKG_ARCH_AMD64:
915 [ + - ]: 15 : if (shlib_abi->arch == PKG_ARCH_I386) {
916 : 0 : flags |= PKG_SHLIB_FLAGS_COMPAT_32;
917 : 0 : }
918 : 15 : break;
919 : : case PKG_ARCH_AARCH64:
920 [ + - ]: 1 : if (shlib_abi->arch == PKG_ARCH_ARMV7) {
921 : 0 : flags |= PKG_SHLIB_FLAGS_COMPAT_32;
922 : 0 : }
923 : 1 : break;
924 : : case PKG_ARCH_POWERPC64:
925 [ + - ]: 1 : if (shlib_abi->arch == PKG_ARCH_POWERPC) {
926 : 0 : flags |= PKG_SHLIB_FLAGS_COMPAT_32;
927 : 0 : }
928 : 1 : break;
929 : : }
930 : 23 : }
931 : :
932 : 25 : return (flags);
933 : : }
934 : :
935 : : /*
936 : : * Format examples:
937 : : *
938 : : * libfoo.so.1.0.0 - native
939 : : * libfoo.so.1.0.0:32 - compat 32
940 : : * libfoo.so.1.0.0:Linux - compat Linux
941 : : * libfoo.so.1.0.0:Linux:32 - compat Linux 32
942 : : */
943 : : char *
944 : 27730 : pkg_shlib_name_with_flags(const char *name, enum pkg_shlib_flags flags)
945 : : {
946 : 27730 : const char *compat_os = "";
947 [ + - ]: 27730 : if ((flags & PKG_SHLIB_FLAGS_COMPAT_LINUX) != 0) {
948 : 0 : compat_os = ":Linux";
949 : 0 : }
950 : :
951 : 27730 : const char *compat_arch = "";
952 [ + - ]: 27730 : if ((flags & PKG_SHLIB_FLAGS_COMPAT_32) != 0) {
953 : 0 : compat_arch = ":32";
954 : 0 : }
955 : :
956 : : char *ret;
957 : 27730 : xasprintf(&ret, "%s%s%s", name, compat_os, compat_arch);
958 : 27730 : return (ret);
959 : : }
960 : :
961 : : int
962 : 99 : pkg_addshlib_required(struct pkg *pkg, const char *name,
963 : : enum pkg_shlib_flags flags)
964 : : {
965 [ + - ]: 99 : assert(pkg != NULL);
966 [ + - ]: 99 : assert(name != NULL && name[0] != '\0');
967 : :
968 : 99 : char *full_name = pkg_shlib_name_with_flags(name, flags);
969 : :
970 [ - + - + ]: 198 : if (match_ucl_lists(full_name,
971 : 99 : pkg_config_get("SHLIB_REQUIRE_IGNORE_GLOB"),
972 : 99 : pkg_config_get("SHLIB_REQUIRE_IGNORE_REGEX"))) {
973 : 0 : dbg(3, "ignoring shlib %s required by package %s", full_name, pkg->name);
974 : 0 : free(full_name);
975 : 0 : return (EPKG_OK);
976 : : }
977 : :
978 : : /* silently ignore duplicates in case of shlibs */
979 [ + + + + : 122 : tll_foreach(pkg->shlibs_required, s) {
- + ]
980 [ + + ]: 25 : if (STREQ(s->item, full_name)) {
981 : 2 : free(full_name);
982 : 2 : return (EPKG_OK);
983 : : }
984 : 23 : }
985 : :
986 [ + + + + : 97 : tll_push_back(pkg->shlibs_required, full_name);
+ - - + +
+ ]
987 : :
988 : 97 : dbg(3, "added shlib deps for %s on %s", pkg->name, full_name);
989 : :
990 : 97 : return (EPKG_OK);
991 : 99 : }
992 : :
993 : : int
994 : 41 : pkg_addshlib_provided(struct pkg *pkg, const char *name,
995 : : enum pkg_shlib_flags flags)
996 : : {
997 [ + - ]: 41 : assert(pkg != NULL);
998 [ + - ]: 41 : assert(name != NULL && name[0] != '\0');
999 : :
1000 : : /* ignore files which are not starting with lib */
1001 [ - + ]: 41 : if (strncmp(name, "lib", 3) != 0)
1002 : 0 : return (EPKG_OK);
1003 : :
1004 : 41 : char *full_name = pkg_shlib_name_with_flags(name, flags);
1005 : :
1006 : : /* silently ignore duplicates in case of shlibs */
1007 [ + + + + : 43 : tll_foreach(pkg->shlibs_provided, s) {
- + ]
1008 [ - + ]: 2 : if (STREQ(s->item, full_name)) {
1009 : 0 : free(full_name);
1010 : 0 : return (EPKG_OK);
1011 : : }
1012 : 2 : }
1013 : :
1014 [ + + + + : 41 : tll_push_back(pkg->shlibs_provided, full_name);
+ - + - +
+ ]
1015 : :
1016 : 41 : dbg(3, "added shlib provide %s for %s", full_name, pkg->name);
1017 : :
1018 : 41 : return (EPKG_OK);
1019 : 41 : }
1020 : :
1021 : : int
1022 : 0 : pkg_addconflict(struct pkg *pkg, const char *uniqueid)
1023 : : {
1024 : 0 : struct pkg_conflict *c = NULL;
1025 : :
1026 [ # # ]: 0 : assert(pkg != NULL);
1027 [ # # ]: 0 : assert(uniqueid != NULL && uniqueid[0] != '\0');
1028 : :
1029 [ # # ]: 0 : if (pkghash_get(pkg->conflictshash, uniqueid) != NULL) {
1030 : : /* silently ignore duplicates in case of conflicts */
1031 : 0 : return (EPKG_OK);
1032 : : }
1033 : :
1034 : 0 : c = xcalloc(1, sizeof(*c));
1035 : 0 : c->uid = xstrdup(uniqueid);
1036 : 0 : dbg(3, "add a new conflict origin: %s, with %s", pkg->uid, uniqueid);
1037 : :
1038 [ # # # # ]: 0 : pkghash_safe_add(pkg->conflictshash, c->uid, c, NULL);
1039 [ # # ]: 0 : DL_APPEND(pkg->conflicts, c);
1040 : :
1041 : 0 : return (EPKG_OK);
1042 : 0 : }
1043 : :
1044 : : int
1045 : 63 : pkg_addrequire(struct pkg *pkg, const char *name)
1046 : : {
1047 [ + - ]: 63 : assert(pkg != NULL);
1048 [ + - ]: 63 : assert(name != NULL && name[0] != '\0');
1049 : :
1050 : : /* silently ignore duplicates in case of conflicts */
1051 [ + + - + : 63 : tll_foreach(pkg->requires, p) {
# # ]
1052 [ # # ]: 0 : if (STREQ(p->item, name))
1053 : 0 : return (EPKG_OK);
1054 : 0 : }
1055 : :
1056 [ - + + - : 63 : tll_push_back(pkg->requires, xstrdup(name));
# # - + -
+ ]
1057 : :
1058 : 63 : return (EPKG_OK);
1059 : 63 : }
1060 : :
1061 : : int
1062 : 38 : pkg_addprovide(struct pkg *pkg, const char *name)
1063 : : {
1064 [ + - ]: 38 : assert(pkg != NULL);
1065 [ + - ]: 38 : assert(name != NULL && name[0] != '\0');
1066 : :
1067 : : /* silently ignore duplicates in case of conflicts */
1068 [ + - - + : 38 : tll_foreach(pkg->provides, p) {
# # ]
1069 [ # # ]: 0 : if (STREQ(p->item, name))
1070 : 0 : return (EPKG_OK);
1071 : 0 : }
1072 : :
1073 [ - + + - : 38 : tll_push_back(pkg->provides, xstrdup(name));
# # - + -
+ ]
1074 : :
1075 : 38 : return (EPKG_OK);
1076 : 38 : }
1077 : :
1078 : : const char *
1079 : 1071 : pkg_kv_get(const kvlist_t *kv, const char *tag)
1080 : : {
1081 [ + - ]: 1071 : assert(tag != NULL);
1082 : :
1083 [ + + + + : 1889 : tll_foreach(*kv, k) {
+ + ]
1084 [ + + ]: 966 : if (STREQ(k->item->key, tag))
1085 : 148 : return (k->item->value);
1086 : 818 : }
1087 : :
1088 : 923 : return (NULL);
1089 : 1071 : }
1090 : :
1091 : : int
1092 : 1540 : pkg_kv_add(kvlist_t *list, const char *key, const char *val, const char *title)
1093 : : {
1094 : : struct pkg_kv *kv;
1095 : :
1096 [ + - ]: 1540 : assert(val != NULL);
1097 [ + - ]: 1540 : assert(title != NULL);
1098 : :
1099 [ + + + + : 2059 : tll_foreach(*list, k) {
+ + ]
1100 [ + - ]: 519 : if (!STREQ(k->item->key, key))
1101 : 519 : continue;
1102 [ # # ]: 0 : if (ctx.developer_mode) {
1103 : 0 : pkg_emit_error("duplicate %s: %s, fatal"
1104 : 0 : " (developer mode)", title, key);
1105 : 0 : return (EPKG_FATAL);
1106 : : }
1107 : 0 : pkg_emit_error("duplicate %s: %s, "
1108 : 0 : "ignoring", title, val);
1109 : 0 : return (EPKG_OK);
1110 : : }
1111 : :
1112 : 1540 : kv = pkg_kv_new(key, val);
1113 [ + + + + : 1540 : tll_push_back(*list, kv);
+ - - + +
+ ]
1114 : :
1115 : 1540 : return (EPKG_OK);
1116 : 1540 : }
1117 : :
1118 : : int
1119 : 23 : pkg_list_count(const struct pkg *pkg, pkg_list list)
1120 : : {
1121 [ - - + + : 23 : switch (list) {
- - - + +
- - - +
+ ]
1122 : : case PKG_DEPS:
1123 : 0 : return (pkghash_count(pkg->depshash));
1124 : : case PKG_RDEPS:
1125 : 0 : return (pkghash_count(pkg->rdepshash));
1126 : : case PKG_OPTIONS:
1127 : 5 : return (pkghash_count(pkg->optionshash));
1128 : : case PKG_FILES:
1129 : 6 : return (pkghash_count(pkg->filehash));
1130 : : case PKG_DIRS:
1131 : 0 : return (pkghash_count(pkg->dirhash));
1132 : : case PKG_CONFLICTS:
1133 : 0 : return (pkghash_count(pkg->conflictshash));
1134 : : case PKG_CONFIG_FILES:
1135 : 0 : return (pkghash_count(pkg->config_files_hash));
1136 : : case PKG_USERS:
1137 : 0 : return (tll_length(pkg->users));
1138 : : case PKG_GROUPS:
1139 : 0 : return (tll_length(pkg->groups));
1140 : : case PKG_SHLIBS_REQUIRED:
1141 : 3 : return (tll_length(pkg->shlibs_required));
1142 : : case PKG_SHLIBS_PROVIDED:
1143 : 3 : return (tll_length(pkg->shlibs_provided));
1144 : : case PKG_REQUIRES:
1145 : 3 : return (tll_length(pkg->requires));
1146 : : case PKG_PROVIDES:
1147 : 3 : return (tll_length(pkg->provides));
1148 : : }
1149 : :
1150 : 0 : return (0);
1151 : 23 : }
1152 : :
1153 : : void
1154 : 10601 : pkg_list_free(struct pkg *pkg, pkg_list list) {
1155 : : struct pkg_dep *cur;
1156 : :
1157 [ + + - + : 10601 : switch (list) {
+ + + - ]
1158 : : case PKG_DEPS:
1159 [ + + ]: 2503 : DL_FOREACH (pkg->depends, cur) {
1160 [ + - ]: 465 : if (cur->alt_next) {
1161 [ # # # # : 0 : DL_FREE2(cur->alt_next, pkg_dep_free, alt_prev, alt_next);
# # # # #
# # # #
# ]
1162 : 0 : }
1163 : 465 : }
1164 [ + + - + : 2503 : DL_FREE(pkg->depends, pkg_dep_free);
+ + + - +
+ - + #
# ]
1165 : 2038 : pkghash_destroy(pkg->depshash);
1166 : 2038 : pkg->depshash = NULL;
1167 : 2038 : pkg->flags &= ~PKG_LOAD_DEPS;
1168 : 2038 : break;
1169 : : case PKG_RDEPS:
1170 [ + + - + : 2072 : LL_FREE(pkg->rdepends, pkg_dep_free);
+ + - + #
# # # # #
# # ]
1171 : 2038 : pkghash_destroy(pkg->rdepshash);
1172 : 2038 : pkg->depshash = NULL;
1173 : 2038 : pkg->flags &= ~PKG_LOAD_RDEPS;
1174 : 2038 : break;
1175 : : case PKG_OPTIONS:
1176 [ + + - + : 2222 : DL_FREE(pkg->options, pkg_option_free);
+ + + - +
+ - + #
# ]
1177 : 2038 : pkghash_destroy(pkg->optionshash);
1178 : 2038 : pkg->optionshash = NULL;
1179 : 2038 : pkg->flags &= ~PKG_LOAD_OPTIONS;
1180 : 4350 : break;
1181 : : case PKG_FILES:
1182 : : case PKG_CONFIG_FILES:
1183 [ + + - + : 3139 : DL_FREE(pkg->files, pkg_file_free);
+ + + - +
+ - + #
# ]
1184 : 2312 : pkghash_destroy(pkg->filehash);
1185 : 2312 : pkg->filehash = NULL;
1186 [ + + - + : 2358 : DL_FREE(pkg->config_files, pkg_config_file_free);
+ + + - -
+ # # #
# ]
1187 : 2312 : pkghash_destroy(pkg->config_files_hash);
1188 : 2312 : pkg->config_files_hash = NULL;
1189 : 2312 : pkg->flags &= ~PKG_LOAD_FILES;
1190 : 2312 : break;
1191 : : case PKG_DIRS:
1192 [ + + - + : 2213 : DL_FREE(pkg->dirs, free);
+ + + - +
+ - + #
# ]
1193 : 2175 : pkghash_destroy(pkg->dirhash);
1194 : 2175 : pkg->dirhash = NULL;
1195 : 2175 : pkg->flags &= ~PKG_LOAD_DIRS;
1196 : 2175 : break;
1197 : : case PKG_CONFLICTS:
1198 [ # # # # : 0 : DL_FREE(pkg->conflicts, pkg_conflict_free);
# # # # #
# # # #
# ]
1199 : 0 : pkghash_destroy(pkg->conflictshash);
1200 : 0 : pkg->conflictshash = NULL;
1201 : 0 : pkg->flags &= ~PKG_LOAD_CONFLICTS;
1202 : 0 : break;
1203 : : }
1204 : 10601 : }
1205 : :
1206 : : int
1207 : 361 : pkg_open(struct pkg **pkg_p, const char *path, int flags)
1208 : : {
1209 : : struct archive *a;
1210 : : struct archive_entry *ae;
1211 : : int ret;
1212 : :
1213 : 361 : ret = pkg_open2(pkg_p, &a, &ae, path, flags, -1);
1214 : :
1215 [ + + + + ]: 361 : if (ret != EPKG_OK && ret != EPKG_END)
1216 : 2 : return (EPKG_FATAL);
1217 : :
1218 : 359 : archive_read_close(a);
1219 : 359 : archive_read_free(a);
1220 : :
1221 : 359 : return (EPKG_OK);
1222 : 361 : }
1223 : :
1224 : : int
1225 : 36 : pkg_open_fd(struct pkg **pkg_p, int fd, int flags)
1226 : : {
1227 : : struct archive *a;
1228 : : struct archive_entry *ae;
1229 : : int ret;
1230 : :
1231 : 36 : ret = pkg_open2(pkg_p, &a, &ae, NULL, flags, fd);
1232 : :
1233 [ + + + - ]: 36 : if (ret != EPKG_OK && ret != EPKG_END)
1234 : 0 : return (EPKG_FATAL);
1235 : :
1236 : 36 : archive_read_close(a);
1237 : 36 : archive_read_free(a);
1238 : :
1239 : 36 : return (EPKG_OK);
1240 : 36 : }
1241 : :
1242 : : static int
1243 : 558 : pkg_parse_archive(struct pkg *pkg, struct archive *a, size_t len)
1244 : : {
1245 : : void *buffer;
1246 : : int rc;
1247 : :
1248 : 558 : buffer = xmalloc(len);
1249 : :
1250 : 558 : archive_read_data(a, buffer, len);
1251 : 558 : rc = pkg_parse_manifest(pkg, buffer, len);
1252 : 558 : free(buffer);
1253 : 558 : return (rc);
1254 : : }
1255 : :
1256 : : int
1257 : 573 : pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
1258 : : const char *path, int flags, int fd)
1259 : : {
1260 : 573 : struct pkg *pkg = NULL;
1261 : 573 : pkg_error_t retcode = EPKG_OK;
1262 : : int ret;
1263 : : const char *fpath;
1264 : 573 : bool manifest = false;
1265 : 573 : bool read_from_stdin = 0;
1266 : :
1267 : 573 : *a = archive_read_new();
1268 : 573 : archive_read_support_filter_all(*a);
1269 : 573 : archive_read_support_format_tar(*a);
1270 : :
1271 : : /* archive_read_open_filename() treats a path of NULL as
1272 : : * meaning "read from stdin," but we want this behaviour if
1273 : : * path is exactly "-". In the unlikely event of wanting to
1274 : : * read an on-disk file called "-", just say "./-" or some
1275 : : * other leading path. */
1276 : :
1277 [ + + ]: 573 : if (fd == -1) {
1278 [ + - ]: 533 : if (path == NULL) {
1279 : 0 : pkg_emit_error("bad usage of pkg_open2");
1280 : 0 : retcode = EPKG_FATAL;
1281 : 0 : goto cleanup;
1282 : : }
1283 : 533 : read_from_stdin = (strncmp(path, "-", 2) == 0);
1284 : :
1285 [ + + + + ]: 1599 : if (archive_read_open_filename(*a,
1286 [ + + ]: 533 : read_from_stdin ? NULL : path, 4096) != ARCHIVE_OK) {
1287 [ + - ]: 3 : if ((flags & PKG_OPEN_TRY) == 0)
1288 : 0 : pkg_emit_error("archive_read_open_filename(%s): %s", path,
1289 : 0 : archive_error_string(*a));
1290 : :
1291 : 3 : retcode = EPKG_FATAL;
1292 : 3 : goto cleanup;
1293 : : }
1294 : 530 : } else {
1295 [ - + ]: 40 : if (archive_read_open_fd(*a, fd, 4096) != ARCHIVE_OK) {
1296 [ # # ]: 0 : if ((flags & PKG_OPEN_TRY) == 0)
1297 : 0 : pkg_emit_error("archive_read_open_fd: %s",
1298 : 0 : archive_error_string(*a));
1299 : :
1300 : 0 : retcode = EPKG_FATAL;
1301 : 0 : goto cleanup;
1302 : : }
1303 : : }
1304 : :
1305 : 570 : retcode = pkg_new(pkg_p, PKG_FILE);
1306 [ - + ]: 570 : if (retcode != EPKG_OK)
1307 : 0 : goto cleanup;
1308 : :
1309 : 570 : pkg = *pkg_p;
1310 : :
1311 [ + + ]: 1328 : while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
1312 : 1218 : fpath = archive_entry_pathname(*ae);
1313 [ + + ]: 1218 : if (fpath[0] != '+')
1314 : 236 : break;
1315 : :
1316 [ + + - + ]: 1136 : if (!manifest &&
1317 [ + + ]: 981 : (flags & PKG_OPEN_MANIFEST_COMPACT) &&
1318 : 154 : STREQ(fpath, "+COMPACT_MANIFEST")) {
1319 : 154 : manifest = true;
1320 : :
1321 : 154 : ret = pkg_parse_archive(pkg, *a, archive_entry_size(*ae));
1322 [ - + ]: 154 : if (ret != EPKG_OK) {
1323 : 0 : retcode = EPKG_FATAL;
1324 : 0 : goto cleanup;
1325 : : }
1326 : : /* Do not read anything more */
1327 : 154 : break;
1328 : : }
1329 [ + - + + ]: 828 : if (!manifest && STREQ(fpath, "+MANIFEST")) {
1330 : 413 : manifest = true;
1331 : :
1332 : 413 : ret = pkg_parse_archive(pkg, *a, archive_entry_size(*ae));
1333 [ + - ]: 413 : if (ret != EPKG_OK) {
1334 [ # # ]: 0 : if ((flags & PKG_OPEN_TRY) == 0)
1335 : 0 : pkg_emit_error("%s is not a valid package: "
1336 : 0 : "Invalid manifest", path);
1337 : :
1338 : 0 : retcode = EPKG_FATAL;
1339 : 0 : goto cleanup;
1340 : : }
1341 : :
1342 [ + + ]: 413 : if (flags & PKG_OPEN_MANIFEST_ONLY)
1343 : 68 : break;
1344 : 345 : }
1345 : : }
1346 : :
1347 [ + + + - ]: 568 : if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) {
1348 [ # # ]: 0 : if ((flags & PKG_OPEN_TRY) == 0)
1349 : 0 : pkg_emit_error("archive_read_next_header(): %s",
1350 : 0 : archive_error_string(*a));
1351 : :
1352 : 0 : retcode = EPKG_FATAL;
1353 : 0 : }
1354 : :
1355 [ + + ]: 568 : if (ret == ARCHIVE_EOF)
1356 : 109 : retcode = EPKG_END;
1357 : :
1358 [ + - ]: 568 : if (!manifest) {
1359 : 0 : retcode = EPKG_FATAL;
1360 [ # # ]: 0 : if ((flags & PKG_OPEN_TRY) == 0)
1361 : 0 : pkg_emit_error("%s is not a valid package: no manifest found", path);
1362 : 0 : }
1363 : :
1364 : : cleanup:
1365 [ + + + + ]: 571 : if (retcode != EPKG_OK && retcode != EPKG_END) {
1366 [ + - ]: 2 : if (*a != NULL) {
1367 : 2 : archive_read_close(*a);
1368 : 2 : archive_read_free(*a);
1369 : 2 : }
1370 : 2 : free(pkg);
1371 : 2 : *pkg_p = NULL;
1372 : 2 : *a = NULL;
1373 : 2 : *ae = NULL;
1374 : 2 : }
1375 : :
1376 : 571 : return (retcode);
1377 : : }
1378 : :
1379 : : int
1380 : 557 : pkg_validate(struct pkg *pkg, struct pkgdb *db)
1381 : : {
1382 [ + - ]: 557 : assert(pkg != NULL);
1383 : 557 : unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
1384 : : PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
1385 : : PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
1386 : : PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
1387 : :
1388 [ + + ]: 557 : if (pkg->uid == NULL) {
1389 : : /* Keep that part for the day we have to change it */
1390 : : /* Generate uid from name*/
1391 [ + - ]: 62 : if (pkg->name == NULL)
1392 : 0 : return (EPKG_FATAL);
1393 : :
1394 : 62 : pkg->uid = xstrdup(pkg->name);
1395 : 62 : }
1396 : :
1397 [ + + - + : 557 : if (pkg->digest == NULL || !pkg_checksum_is_valid(pkg->digest,
- + ]
1398 : 494 : strlen(pkg->digest))) {
1399 : : /* Calculate new digest */
1400 [ + + ]: 63 : if (pkgdb_ensure_loaded(db, pkg, flags)) {
1401 : 62 : return (pkg_checksum_calculate(pkg, db, false, true, false));
1402 : : }
1403 : 1 : return (EPKG_FATAL);
1404 : : }
1405 : :
1406 : 494 : return (EPKG_OK);
1407 : 557 : }
1408 : :
1409 : : int
1410 : 0 : pkg_test_filesum(struct pkg *pkg)
1411 : : {
1412 : 0 : struct pkg_file *f = NULL;
1413 : 0 : int rc = EPKG_OK;
1414 : : int ret;
1415 : :
1416 [ # # ]: 0 : assert(pkg != NULL);
1417 : :
1418 [ # # ]: 0 : while (pkg_files(pkg, &f) == EPKG_OK) {
1419 [ # # # # ]: 0 : if (f->sum != NULL &&
1420 : : /* skip config files as they can be modified */
1421 : 0 : pkghash_get_value(pkg->config_files_hash, f->path) == NULL) {
1422 : 0 : ret = pkg_checksum_validate_file(f->path, f->sum);
1423 [ # # ]: 0 : if (ret != 0) {
1424 [ # # ]: 0 : if (ret == ENOENT)
1425 : 0 : pkg_emit_file_missing(pkg, f);
1426 : : else
1427 : 0 : pkg_emit_file_mismatch(pkg, f, f->sum);
1428 : 0 : rc = EPKG_FATAL;
1429 : 0 : }
1430 : 0 : }
1431 : : }
1432 : :
1433 : 0 : return (rc);
1434 : : }
1435 : :
1436 : : int
1437 : 102 : pkg_try_installed(struct pkgdb *db, const char *name,
1438 : : struct pkg **pkg, unsigned flags) {
1439 : 102 : struct pkgdb_it *it = NULL;
1440 : 102 : int ret = EPKG_FATAL;
1441 : :
1442 [ + - ]: 102 : if ((it = pkgdb_query(db, name, MATCH_INTERNAL)) == NULL)
1443 : 0 : return (EPKG_FATAL);
1444 : :
1445 : 102 : ret = pkgdb_it_next(it, pkg, flags);
1446 : 102 : pkgdb_it_free(it);
1447 : :
1448 : 102 : return (ret);
1449 : 102 : }
1450 : :
1451 : : int
1452 : 85 : pkg_is_installed(struct pkgdb *db, const char *name)
1453 : : {
1454 : 85 : struct pkg *pkg = NULL;
1455 : 85 : int ret = EPKG_FATAL;
1456 : :
1457 : 85 : ret = pkg_try_installed(db, name, &pkg, PKG_LOAD_BASIC);
1458 : 85 : pkg_free(pkg);
1459 : :
1460 : 85 : return (ret);
1461 : : }
1462 : :
1463 : : bool
1464 : 1067 : pkg_has_message(struct pkg *p)
1465 : : {
1466 : 1067 : return (tll_length(p->message) > 0);
1467 : : }
1468 : :
1469 : : bool
1470 : 373 : pkg_is_locked(const struct pkg * restrict p)
1471 : : {
1472 [ + - ]: 373 : assert(p != NULL);
1473 : :
1474 : 373 : return (p->locked);
1475 : : }
1476 : :
1477 : : bool
1478 : 6 : pkg_is_config_file(struct pkg *p, const char *path,
1479 : : const struct pkg_file **file,
1480 : : struct pkg_config_file **cfile)
1481 : : {
1482 : 6 : *file = NULL;
1483 : 6 : *cfile = NULL;
1484 : :
1485 [ + + ]: 6 : if (pkghash_count(p->config_files_hash) == 0)
1486 : 2 : return (false);
1487 : :
1488 : 4 : *file = pkghash_get_value(p->filehash, path);
1489 [ + - ]: 4 : if (*file == NULL)
1490 : 0 : return (false);
1491 : 4 : *cfile = pkghash_get_value(p->config_files_hash, path);
1492 [ + - ]: 4 : if (*cfile == NULL) {
1493 : 0 : *file = NULL;
1494 : 0 : return (false);
1495 : : }
1496 : :
1497 : 4 : return (true);
1498 : 6 : }
1499 : :
1500 : : struct pkg_dir *
1501 : 6 : pkg_get_dir(struct pkg *p, const char *path)
1502 : : {
1503 : 6 : return (pkghash_get_value(p->dirhash, path));
1504 : : }
1505 : :
1506 : : struct pkg_file *
1507 : 136 : pkg_get_file(struct pkg *p, const char *path)
1508 : : {
1509 : 136 : return (pkghash_get_value(p->filehash, path));
1510 : : }
1511 : :
1512 : : bool
1513 : 167 : pkg_has_file(struct pkg *p, const char *path)
1514 : : {
1515 : 167 : return (pkghash_get(p->filehash, path) != NULL);
1516 : : }
1517 : :
1518 : : bool
1519 : 34 : pkg_has_dir(struct pkg *p, const char *path)
1520 : : {
1521 : 34 : return (pkghash_get(p->dirhash, path) != NULL);
1522 : : }
1523 : :
1524 : : int
1525 : 289 : pkg_open_root_fd(struct pkg *pkg)
1526 : : {
1527 : : const char *path;
1528 : :
1529 [ + + ]: 289 : if (pkg->rootfd != -1)
1530 : 43 : return (EPKG_OK);
1531 : :
1532 : 246 : path = pkg_kv_get(&pkg->annotations, "relocated");
1533 [ - + ]: 246 : if (path == NULL) {
1534 [ + - ]: 246 : if ((pkg->rootfd = dup(ctx.rootfd)) == -1) {
1535 : 0 : pkg_emit_errno("dup", "rootfd");
1536 : 0 : return (EPKG_FATAL);
1537 : : }
1538 : 246 : return (EPKG_OK);
1539 : : }
1540 : :
1541 : 0 : pkg_absolutepath(path, pkg->rootpath, sizeof(pkg->rootpath), false);
1542 : :
1543 [ # # ]: 0 : if ((pkg->rootfd = openat(ctx.rootfd, pkg->rootpath + 1, O_DIRECTORY)) >= 0 )
1544 : 0 : return (EPKG_OK);
1545 : :
1546 : 0 : pkg->rootpath[0] = '\0';
1547 : 0 : pkg_emit_errno("open", path);
1548 : :
1549 : 0 : return (EPKG_FATAL);
1550 : 289 : }
1551 : :
1552 : : int
1553 : 41 : pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj)
1554 : : {
1555 : 41 : struct pkg_message *msg = NULL;
1556 : : const ucl_object_t *elt, *cur;
1557 : 41 : ucl_object_iter_t it = NULL;
1558 : :
1559 [ + + ]: 41 : if (ucl_object_type(obj) == UCL_STRING) {
1560 : 3 : msg = xcalloc(1, sizeof(*msg));
1561 : 3 : msg->str = xstrdup(ucl_object_tostring(obj));
1562 : 3 : msg->type = PKG_MESSAGE_ALWAYS;
1563 [ - + + - : 3 : tll_push_back(pkg->message, msg);
# # - + -
+ ]
1564 : 3 : return (EPKG_OK);
1565 : : }
1566 : :
1567 : : /* New format of pkg message */
1568 [ + - ]: 38 : if (ucl_object_type(obj) != UCL_ARRAY)
1569 : 0 : pkg_emit_error("package message badly formatted, an array was"
1570 : : " expected");
1571 : :
1572 [ + + ]: 175 : while ((cur = ucl_iterate_object(obj, &it, true))) {
1573 : 137 : elt = ucl_object_find_key(cur, "message");
1574 : :
1575 [ + - - + ]: 137 : if (elt == NULL || ucl_object_type(elt) != UCL_STRING) {
1576 : 0 : pkg_emit_error("package message lacks 'message' key"
1577 : : " that is required");
1578 : :
1579 : 0 : return (EPKG_FATAL);
1580 : : }
1581 : :
1582 : 137 : msg = xcalloc(1, sizeof(*msg));
1583 : :
1584 : 137 : msg->str = xstrdup(ucl_object_tostring(elt));
1585 : 137 : msg->type = PKG_MESSAGE_ALWAYS;
1586 : 137 : elt = ucl_object_find_key(cur, "type");
1587 [ + + - + ]: 137 : if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1588 [ + + ]: 98 : if (STRIEQ(ucl_object_tostring(elt), "install"))
1589 : 18 : msg->type = PKG_MESSAGE_INSTALL;
1590 [ + + ]: 80 : else if (STRIEQ(ucl_object_tostring(elt), "remove"))
1591 : 17 : msg->type = PKG_MESSAGE_REMOVE;
1592 [ - + ]: 63 : else if (STRIEQ(ucl_object_tostring(elt), "upgrade"))
1593 : 63 : msg->type = PKG_MESSAGE_UPGRADE;
1594 : : else
1595 : 0 : pkg_emit_error("Unknown message type,"
1596 : : " message will always be printed");
1597 : 98 : }
1598 [ + + ]: 137 : if (msg->type != PKG_MESSAGE_UPGRADE) {
1599 [ + + + + : 74 : tll_push_back(pkg->message, msg);
+ - - + +
+ ]
1600 : 74 : continue;
1601 : : }
1602 : :
1603 : 63 : elt = ucl_object_find_key(cur, "minimum_version");
1604 [ + + - + ]: 63 : if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1605 : 30 : msg->minimum_version = xstrdup(ucl_object_tostring(elt));
1606 : 30 : }
1607 : :
1608 : 63 : elt = ucl_object_find_key(cur, "maximum_version");
1609 [ + + - + ]: 63 : if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
1610 : 30 : msg->maximum_version = xstrdup(ucl_object_tostring(elt));
1611 : 30 : }
1612 : :
1613 [ + - - + : 63 : tll_push_back(pkg->message, msg);
+ - - + +
- ]
1614 : : }
1615 : :
1616 : 38 : return (EPKG_OK);
1617 : 41 : }
1618 : :
1619 : : int
1620 : 17 : pkg_message_from_str(struct pkg *pkg, const char *str, size_t len)
1621 : : {
1622 : : struct ucl_parser *parser;
1623 : : ucl_object_t *obj;
1624 : 17 : int ret = EPKG_FATAL;
1625 : :
1626 [ + - ]: 17 : assert(str != NULL);
1627 : :
1628 [ + + ]: 17 : if (len == 0) {
1629 : 15 : len = strlen(str);
1630 : 15 : }
1631 : :
1632 : 17 : parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
1633 [ + + ]: 17 : if (pkg->prefix != NULL) {
1634 : 2 : ucl_parser_register_variable(parser, "PREFIX", pkg->prefix);
1635 : 2 : }
1636 [ - + ]: 17 : if (pkg->name != NULL) {
1637 : 17 : ucl_parser_register_variable(parser, "PKGNAME", pkg->name);
1638 : 17 : }
1639 [ - + ]: 17 : if (pkg->origin != NULL) {
1640 : 17 : ucl_parser_register_variable(parser, "PKGORIGIN", pkg->origin);
1641 : 17 : }
1642 [ + + ]: 17 : if (pkg->maintainer != NULL) {
1643 : 2 : ucl_parser_register_variable(parser, "MAINTAINER", pkg->maintainer);
1644 : 2 : }
1645 : :
1646 [ + - ]: 17 : if (ucl_parser_add_chunk(parser, (const unsigned char*)str, len)) {
1647 : 17 : obj = ucl_parser_get_object(parser);
1648 : 17 : ucl_parser_free(parser);
1649 : :
1650 : 17 : ret = pkg_message_from_ucl(pkg, obj);
1651 : 17 : ucl_object_unref(obj);
1652 : :
1653 : 17 : return (ret);
1654 : : }
1655 : :
1656 : 0 : ucl_parser_free (parser);
1657 : :
1658 : 0 : return (ret);
1659 : 17 : }
1660 : :
1661 : : ucl_object_t*
1662 : 23 : pkg_message_to_ucl(const struct pkg *pkg)
1663 : : {
1664 : : struct pkg_message *msg;
1665 : : ucl_object_t *array;
1666 : : ucl_object_t *obj;
1667 : :
1668 : 23 : array = ucl_object_typed_new(UCL_ARRAY);
1669 [ + - + + : 98 : tll_foreach(pkg->message, t) {
+ + ]
1670 : 75 : msg = t->item;
1671 : 75 : obj = ucl_object_typed_new (UCL_OBJECT);
1672 : :
1673 : 150 : ucl_object_insert_key(obj,
1674 : 75 : ucl_object_fromstring_common(msg->str, 0,
1675 : : UCL_STRING_RAW|UCL_STRING_TRIM),
1676 : : "message", 0, false);
1677 : :
1678 [ - + + + : 75 : switch (msg->type) {
+ ]
1679 : : case PKG_MESSAGE_ALWAYS:
1680 : 25 : break;
1681 : : case PKG_MESSAGE_INSTALL:
1682 : 20 : ucl_object_insert_key(obj,
1683 : 10 : ucl_object_fromstring("install"),
1684 : : "type", 0, false);
1685 : 10 : break;
1686 : : case PKG_MESSAGE_UPGRADE:
1687 : 64 : ucl_object_insert_key(obj,
1688 : 32 : ucl_object_fromstring("upgrade"),
1689 : : "type", 0, false);
1690 : 32 : break;
1691 : : case PKG_MESSAGE_REMOVE:
1692 : 16 : ucl_object_insert_key(obj,
1693 : 8 : ucl_object_fromstring("remove"),
1694 : : "type", 0, false);
1695 : 8 : break;
1696 : : }
1697 [ + + ]: 75 : if (msg->maximum_version) {
1698 : 28 : ucl_object_insert_key(obj,
1699 : 14 : ucl_object_fromstring(msg->maximum_version),
1700 : : "maximum_version", 0, false);
1701 : 14 : }
1702 [ + + ]: 75 : if (msg->minimum_version) {
1703 : 28 : ucl_object_insert_key(obj,
1704 : 14 : ucl_object_fromstring(msg->minimum_version),
1705 : : "minimum_version", 0, false);
1706 : 14 : }
1707 : 75 : ucl_array_append(array, obj);
1708 : 75 : }
1709 : :
1710 : 23 : return (array);
1711 : : }
1712 : :
1713 : : char*
1714 : 246 : pkg_message_to_str(struct pkg *pkg)
1715 : : {
1716 : : ucl_object_t *obj;
1717 : 246 : char *ret = NULL;
1718 : :
1719 [ + + ]: 246 : if (tll_length(pkg->message) <= 0)
1720 : 232 : return (NULL);
1721 : :
1722 : 14 : obj = pkg_message_to_ucl(pkg);
1723 : 14 : ret = ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
1724 : 14 : ucl_object_unref(obj);
1725 : :
1726 : 14 : return (ret);
1727 : 246 : }
|