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