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