LCOV - code coverage report
Current view: top level - libpkg - pkg_manifest.c (source / functions) Hit Total Coverage
Test: rapport Lines: 554 821 67.5 %
Date: 2021-12-10 16:22:55 Functions: 25 29 86.2 %
Branches: 263 479 54.9 %

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

Generated by: LCOV version 1.15