LCOV - code coverage report
Current view: top level - libpkg - pkg_config.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 358 519 69.0 %
Date: 2015-08-15 Functions: 30 33 90.9 %

          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) 2014 Matthew Seaman <matthew@FreeBSD.org>
       5             :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       6             :  * All rights reserved.
       7             :  * 
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer
      13             :  *    in this position and unchanged.
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer in the
      16             :  *    documentation and/or other materials provided with the distribution.
      17             :  * 
      18             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      19             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      20             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      21             :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      22             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      23             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      24             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      25             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      27             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             :  */
      29             : 
      30             : #include "pkg_config.h"
      31             : 
      32             : #include <assert.h>
      33             : #include <sys/socket.h>
      34             : #include <sys/un.h>
      35             : #include <ctype.h>
      36             : #include <dirent.h>
      37             : #include <dlfcn.h>
      38             : #include <errno.h>
      39             : #include <fcntl.h>
      40             : #ifdef HAVE_OSRELDATE_H
      41             : #include <osreldate.h>
      42             : #endif
      43             : #include <ucl.h>
      44             : 
      45             : #include "pkg.h"
      46             : #include "private/pkg.h"
      47             : #include "private/event.h"
      48             : #include "pkg_repos.h"
      49             : 
      50             : #ifndef PORTSDIR
      51             : #define PORTSDIR "/usr/ports"
      52             : #endif
      53             : #ifndef DEFAULT_VULNXML_URL
      54             : #define DEFAULT_VULNXML_URL "http://vuxml.freebsd.org/freebsd/vuln.xml.bz2"
      55             : #endif
      56             : 
      57             : #ifdef  OSMAJOR
      58             : #define STRINGIFY(X)    TEXT(X)
      59             : #define TEXT(X)         #X
      60             : #define INDEXFILE       "INDEX-" STRINGIFY(OSMAJOR)
      61             : #else
      62             : #define INDEXFILE       "INDEX"
      63             : #endif
      64             : 
      65             : int eventpipe = -1;
      66             : int64_t debug_level = 0;
      67             : bool developer_mode = false;
      68             : const char *pkg_rootdir = NULL;
      69             : 
      70             : struct config_entry {
      71             :         uint8_t type;
      72             :         const char *key;
      73             :         const char *def;
      74             :         const char *desc;
      75             : };
      76             : 
      77             : static char myabi[BUFSIZ], myabi_legacy[BUFSIZ];
      78             : static struct pkg_repo *repos = NULL;
      79             : ucl_object_t *config = NULL;
      80             : 
      81             : static struct config_entry c[] = {
      82             :         {
      83             :                 PKG_STRING,
      84             :                 "PKG_DBDIR",
      85             :                 "/var/db/pkg",
      86             :                 "Where the package databases are stored",
      87             :         },
      88             :         {
      89             :                 PKG_STRING,
      90             :                 "PKG_CACHEDIR",
      91             :                 "/var/cache/pkg",
      92             :                 "Directory containing cache of downloaded packages",
      93             :         },
      94             :         {
      95             :                 PKG_STRING,
      96             :                 "PORTSDIR",
      97             :                 "/usr/ports",
      98             :                 "Location of the ports collection",
      99             :         },
     100             :         {
     101             :                 PKG_STRING,
     102             :                 "INDEXDIR",
     103             :                 NULL,           /* Default to PORTSDIR unless defined */
     104             :                 "Location of the ports INDEX",
     105             :         },
     106             :         {
     107             :                 PKG_STRING,
     108             :                 "INDEXFILE",
     109             :                 INDEXFILE,
     110             :                 "Filename of the ports INDEX",
     111             :         },
     112             :         {
     113             :                 PKG_BOOL,
     114             :                 "HANDLE_RC_SCRIPTS",
     115             :                 "NO",
     116             :                 "Automatically handle restarting services",
     117             :         },
     118             :         {
     119             :                 PKG_BOOL,
     120             :                 "DEFAULT_ALWAYS_YES",
     121             :                 "NO",
     122             :                 "Default to 'yes' for all pkg(8) questions",
     123             :         },
     124             :         {
     125             :                 PKG_BOOL,
     126             :                 "ASSUME_ALWAYS_YES",
     127             :                 "NO",
     128             :                 "Answer 'yes' to all pkg(8) questions",
     129             :         },
     130             :         {
     131             :                 PKG_ARRAY,
     132             :                 "REPOS_DIR",
     133             :                 "/etc/pkg/,"PREFIX"/etc/pkg/repos/",
     134             :                 "Location of the repository configuration files"
     135             :         },
     136             :         {
     137             :                 PKG_STRING,
     138             :                 "PLIST_KEYWORDS_DIR",
     139             :                 NULL,
     140             :                 "Directory containing definitions of plist keywords",
     141             :         },
     142             :         {
     143             :                 PKG_BOOL,
     144             :                 "SYSLOG",
     145             :                 "YES",
     146             :                 "Log pkg(8) operations via syslog(3)",
     147             :         },
     148             :         {
     149             :                 PKG_STRING,
     150             :                 "ABI",
     151             :                 myabi,
     152             :                 "Override the automatically detected ABI",
     153             :         },
     154             :         {
     155             :                 PKG_STRING,
     156             :                 "ALTABI",
     157             :                 myabi_legacy,
     158             :                 "Override the automatically detected old-form ABI",
     159             :         },
     160             :         {
     161             :                 PKG_BOOL,
     162             :                 "DEVELOPER_MODE",
     163             :                 "NO",
     164             :                 "Add extra strict, pedantic warnings as an aid to package maintainers",
     165             :         },
     166             :         {
     167             :                 PKG_STRING,
     168             :                 "VULNXML_SITE",
     169             :                 DEFAULT_VULNXML_URL,
     170             :                 "URL giving location of the vulnxml database",
     171             :         },
     172             :         {
     173             :                 PKG_INT,
     174             :                 "FETCH_RETRY",
     175             :                 "3",
     176             :                 "How many times to retry fetching files",
     177             :         },
     178             :         {
     179             :                 PKG_STRING,
     180             :                 "PKG_PLUGINS_DIR",
     181             :                 PREFIX"/lib/pkg/",
     182             :                 "Directory which pkg(8) will load plugins from",
     183             :         },
     184             :         {
     185             :                 PKG_BOOL,
     186             :                 "PKG_ENABLE_PLUGINS",
     187             :                 "YES",
     188             :                 "Activate plugin support",
     189             :         },
     190             :         {
     191             :                 PKG_ARRAY,
     192             :                 "PLUGINS",
     193             :                 NULL,
     194             :                 "List of plugins that pkg(8) should load",
     195             :         },
     196             :         {
     197             :                 PKG_BOOL,
     198             :                 "DEBUG_SCRIPTS",
     199             :                 "NO",
     200             :                 "Run shell scripts in verbose mode to facilitate debugging",
     201             :         },
     202             :         {
     203             :                 PKG_STRING,
     204             :                 "PLUGINS_CONF_DIR",
     205             :                 PREFIX"/etc/pkg/",
     206             :                 "Directory containing plugin configuration data",
     207             :         },
     208             :         {
     209             :                 PKG_BOOL,
     210             :                 "PERMISSIVE",
     211             :                 "NO",
     212             :                 "Permit package installation despite presence of conflicting packages",
     213             :         },
     214             :         {
     215             :                 PKG_BOOL,
     216             :                 "REPO_AUTOUPDATE",
     217             :                 "YES",
     218             :                 "Automatically update repository catalogues prior to package updates",
     219             :         },
     220             :         {
     221             :                 PKG_STRING,
     222             :                 "NAMESERVER",
     223             :                 NULL,
     224             :                 "Use this nameserver when looking up addresses",
     225             :         },
     226             :         {
     227             :                 PKG_STRING,
     228             :                 "HTTP_USER_AGENT",
     229             :                 "pkg/"PKGVERSION,
     230             :                 "HTTP User-Agent",
     231             :         },
     232             :         {
     233             :                 PKG_STRING,
     234             :                 "EVENT_PIPE",
     235             :                 NULL,
     236             :                 "Send all events to the specified fifo or Unix socket",
     237             :         },
     238             :         {
     239             :                 PKG_INT,
     240             :                 "FETCH_TIMEOUT",
     241             :                 "30",
     242             :                 "Number of seconds before fetch(3) times out",
     243             :         },
     244             :         {
     245             :                 PKG_BOOL,
     246             :                 "UNSET_TIMESTAMP",
     247             :                 "NO",
     248             :                 "Do not include timestamps in the package",
     249             :         },
     250             :         {
     251             :                 PKG_STRING,
     252             :                 "SSH_RESTRICT_DIR",
     253             :                 NULL,
     254             :                 "Directory the ssh subsystem will be restricted to",
     255             :         },
     256             :         {
     257             :                 PKG_OBJECT,
     258             :                 "PKG_ENV",
     259             :                 NULL,
     260             :                 "Environment variables pkg will use",
     261             :         },
     262             :         {
     263             :                 PKG_STRING,
     264             :                 "PKG_SSH_ARGS",
     265             :                 NULL,
     266             :                 "Extras arguments to pass to ssh(1)",
     267             :         },
     268             :         {
     269             :                 PKG_INT,
     270             :                 "DEBUG_LEVEL",
     271             :                 "0",
     272             :                 "Level for debug messages",
     273             :         },
     274             :         {
     275             :                 PKG_OBJECT,
     276             :                 "ALIAS",
     277             :                 NULL,
     278             :                 "Command aliases",
     279             :         },
     280             :         {
     281             :                 PKG_STRING,
     282             :                 "CUDF_SOLVER",
     283             :                 NULL,
     284             :                 "Experimental: tells pkg to use an external CUDF solver",
     285             :         },
     286             :         {
     287             :                 PKG_STRING,
     288             :                 "SAT_SOLVER",
     289             :                 NULL,
     290             :                 "Experimental: tells pkg to use an external SAT solver",
     291             :         },
     292             :         {
     293             :                 PKG_BOOL,
     294             :                 "RUN_SCRIPTS",
     295             :                 "YES",
     296             :                 "Run post/pre actions scripts",
     297             :         },
     298             :         {
     299             :                 PKG_BOOL,
     300             :                 "CASE_SENSITIVE_MATCH",
     301             :                 "NO",
     302             :                 "Match package names case sensitively",
     303             :         },
     304             :         {
     305             :                 PKG_INT,
     306             :                 "LOCK_WAIT",
     307             :                 "1",
     308             :                 "Wait time to regain a lock if it is not available"
     309             :         },
     310             :         {
     311             :                 PKG_INT,
     312             :                 "LOCK_RETRIES",
     313             :                 "5",
     314             :                 "Retries performed to obtain a lock"
     315             :         },
     316             :         {
     317             :                 PKG_BOOL,
     318             :                 "SQLITE_PROFILE",
     319             :                 "NO",
     320             :                 "Profile sqlite queries"
     321             :         },
     322             :         {
     323             :                 PKG_INT,
     324             :                 "WORKERS_COUNT",
     325             :                 "0",
     326             :                 "How many workers are used for pkg-repo (hw.ncpu if 0)"
     327             :         },
     328             :         {
     329             :                 PKG_BOOL,
     330             :                 "READ_LOCK",
     331             :                 "NO",
     332             :                 "Use read locking for query database"
     333             :         },
     334             :         {
     335             :                 PKG_BOOL,
     336             :                 "PLIST_ACCEPT_DIRECTORIES",
     337             :                 "NO",
     338             :                 "Accept directories listed like plain files in plist"
     339             :         },
     340             :         {
     341             :                 PKG_INT,
     342             :                 "IP_VERSION",
     343             :                 "0",
     344             :                 "Restrict network access to IPv4 or IPv6 only"
     345             :         },
     346             :         {
     347             :                 PKG_BOOL,
     348             :                 "AUTOMERGE",
     349             :                 "YES",
     350             :                 "Automatically merge configuration files"
     351             :         },
     352             :         {
     353             :                 PKG_STRING,
     354             :                 "VERSION_SOURCE",
     355             :                 NULL,
     356             :                 "Version source for pkg-version (I, P, R), default is auto detect"
     357             :         },
     358             :         {
     359             :                 PKG_BOOL,
     360             :                 "CONSERVATIVE_UPGRADE",
     361             :                 "YES",
     362             :                 "Prefer repos with higher priority during upgrade"
     363             :         },
     364             :         {
     365             :                 PKG_BOOL,
     366             :                 "PKG_CREATE_VERBOSE",
     367             :                 "NO",
     368             :                 "Enable verbose mode for 'pkg create'",
     369             :         },
     370             :         {
     371             :                 PKG_BOOL,
     372             :                 "AUTOCLEAN",
     373             :                 "NO",
     374             :                 "Always cleanup the cache directory after install/upgrade",
     375             :         },
     376             : };
     377             : 
     378             : static bool parsed = false;
     379             : static size_t c_size = NELEM(c);
     380             : 
     381             : static struct pkg_repo* pkg_repo_new(const char *name,
     382             :         const char *url, const char *type);
     383             : static void pkg_repo_overwrite(struct pkg_repo*, const char *name,
     384             :         const char *url, const char *type);
     385             : static void pkg_repo_free(struct pkg_repo *r);
     386             : 
     387             : static void
     388           0 : connect_evpipe(const char *evpipe) {
     389             :         struct stat st;
     390             :         struct sockaddr_un sock;
     391           0 :         int flag = O_WRONLY;
     392             : 
     393           0 :         if (stat(evpipe, &st) != 0) {
     394           0 :                 pkg_emit_error("No such event pipe: %s", evpipe);
     395           0 :                 return;
     396             :         }
     397             : 
     398           0 :         if (!S_ISFIFO(st.st_mode) && !S_ISSOCK(st.st_mode)) {
     399           0 :                 pkg_emit_error("%s is not a fifo or socket", evpipe);
     400           0 :                 return;
     401             :         }
     402             : 
     403           0 :         if (S_ISFIFO(st.st_mode)) {
     404           0 :                 flag |= O_NONBLOCK;
     405           0 :                 if ((eventpipe = open(evpipe, flag)) == -1)
     406           0 :                         pkg_emit_errno("open event pipe", evpipe);
     407           0 :                 return;
     408             :         }
     409             : 
     410           0 :         if (S_ISSOCK(st.st_mode)) {
     411           0 :                 if ((eventpipe = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
     412           0 :                         pkg_emit_errno("Open event pipe", evpipe);
     413           0 :                         return;
     414             :                 }
     415           0 :                 memset(&sock, 0, sizeof(struct sockaddr_un));
     416           0 :                 sock.sun_family = AF_UNIX;
     417           0 :                 if (strlcpy(sock.sun_path, evpipe, sizeof(sock.sun_path)) >=
     418             :                     sizeof(sock.sun_path)) {
     419           0 :                         pkg_emit_error("Socket path too long: %s", evpipe);
     420           0 :                         close(eventpipe);
     421           0 :                         eventpipe = -1;
     422           0 :                         return;
     423             :                 }
     424             : 
     425           0 :                 if (connect(eventpipe, (struct sockaddr *)&sock, SUN_LEN(&sock)) == -1) {
     426           0 :                         pkg_emit_errno("Connect event pipe", evpipe);
     427           0 :                         close(eventpipe);
     428           0 :                         eventpipe = -1;
     429           0 :                         return;
     430             :                 }
     431             :         }
     432             : 
     433             : }
     434             : 
     435             : int
     436           1 : pkg_initialized(void)
     437             : {
     438           1 :         return (parsed);
     439             : }
     440             : 
     441             : const pkg_object *
     442        5237 : pkg_config_get(const char *key) {
     443        5237 :         return (ucl_object_find_key(config, key));
     444             : }
     445             : 
     446             : const char *
     447           2 : pkg_config_dump(void)
     448             : {
     449           2 :         return (pkg_object_dump(config));
     450             : }
     451             : 
     452             : static void
     453         200 : disable_plugins_if_static(void)
     454             : {
     455             :         void *dlh;
     456             : 
     457         200 :         dlh = dlopen(0, 0);
     458             : 
     459             :         /* if dlh is NULL then we are in static binary */
     460         200 :         if (dlh == NULL)
     461           0 :                 ucl_object_replace_key(config, ucl_object_frombool(false), "PKG_ENABLE_PLUGINS", 18, false);
     462             :         else
     463         200 :                 dlclose(dlh);
     464             : 
     465         200 :         return;
     466             : }
     467             : 
     468             : static void
     469         200 : add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags)
     470             : {
     471             :         const ucl_object_t *cur, *enabled;
     472         200 :         ucl_object_iter_t it = NULL;
     473         200 :         bool enable = true;
     474         200 :         const char *url = NULL, *pubkey = NULL, *mirror_type = NULL;
     475         200 :         const char *signature_type = NULL, *fingerprints = NULL;
     476             :         const char *key;
     477         200 :         const char *type = NULL;
     478         200 :         int use_ipvx = 0;
     479         200 :         int priority = 0;
     480             : 
     481         200 :         pkg_debug(1, "PkgConfig: parsing repository object %s", rname);
     482             : 
     483         200 :         enabled = ucl_object_find_key(obj, "enabled");
     484         200 :         if (enabled == NULL)
     485           3 :                 enabled = ucl_object_find_key(obj, "ENABLED");
     486         200 :         if (enabled != NULL) {
     487         197 :                 enable = ucl_object_toboolean(enabled);
     488         197 :                 if (!enable && r == NULL) {
     489           0 :                         pkg_debug(1, "PkgConfig: skipping disabled repo %s", rname);
     490           0 :                         return;
     491             :                 }
     492         197 :                 else if (!enable && r != NULL) {
     493             :                         /*
     494             :                          * We basically want to remove the existing repo r and
     495             :                          * forget all stuff parsed
     496             :                          */
     497           0 :                         pkg_debug(1, "PkgConfig: disabling repo %s", rname);
     498           0 :                         HASH_DEL(repos, r);
     499           0 :                         pkg_repo_free(r);
     500           0 :                         return;
     501             :                 }
     502             :         }
     503             : 
     504        1364 :         while ((cur = ucl_iterate_object(obj, &it, true))) {
     505         964 :                 key = ucl_object_key(cur);
     506         964 :                 if (key == NULL)
     507           0 :                         continue;
     508             : 
     509         964 :                 if (strcasecmp(key, "url") == 0) {
     510         200 :                         if (cur->type != UCL_STRING) {
     511           0 :                                 pkg_emit_error("Expecting a string for the "
     512             :                                     "'%s' key of the '%s' repo",
     513             :                                     key, rname);
     514           0 :                                 return;
     515             :                         }
     516         200 :                         url = ucl_object_tostring(cur);
     517         764 :                 } else if (strcasecmp(key, "pubkey") == 0) {
     518           0 :                         if (cur->type != UCL_STRING) {
     519           0 :                                 pkg_emit_error("Expecting a string for the "
     520             :                                     "'%s' key of the '%s' repo",
     521             :                                     key, rname);
     522           0 :                                 return;
     523             :                         }
     524           0 :                         pubkey = ucl_object_tostring(cur);
     525         764 :                 } else if (strcasecmp(key, "mirror_type") == 0) {
     526         189 :                         if (cur->type != UCL_STRING) {
     527           0 :                                 pkg_emit_error("Expecting a string for the "
     528             :                                     "'%s' key of the '%s' repo",
     529             :                                     key, rname);
     530           0 :                                 return;
     531             :                         }
     532         189 :                         mirror_type = ucl_object_tostring(cur);
     533         575 :                 } else if (strcasecmp(key, "signature_type") == 0) {
     534         189 :                         if (cur->type != UCL_STRING) {
     535           0 :                                 pkg_emit_error("Expecting a string for the "
     536             :                                     "'%s' key of the '%s' repo",
     537             :                                     key, rname);
     538           0 :                                 return;
     539             :                         }
     540         189 :                         signature_type = ucl_object_tostring(cur);
     541         386 :                 } else if (strcasecmp(key, "fingerprints") == 0) {
     542         189 :                         if (cur->type != UCL_STRING) {
     543           0 :                                 pkg_emit_error("Expecting a string for the "
     544             :                                     "'%s' key of the '%s' repo",
     545             :                                     key, rname);
     546           0 :                                 return;
     547             :                         }
     548         189 :                         fingerprints = ucl_object_tostring(cur);
     549         197 :                 } else if (strcasecmp(key, "type") == 0) {
     550           0 :                         if (cur->type != UCL_STRING) {
     551           0 :                                 pkg_emit_error("Expecting a string for the "
     552             :                                         "'%s' key of the '%s' repo",
     553             :                                         key, rname);
     554           0 :                                 return;
     555             :                         }
     556           0 :                         type = ucl_object_tostring(cur);
     557         197 :                 } else if (strcasecmp(key, "ip_version") == 0) {
     558           0 :                         if (cur->type != UCL_INT) {
     559           0 :                                 pkg_emit_error("Expecting a integer for the "
     560             :                                         "'%s' key of the '%s' repo",
     561             :                                         key, rname);
     562           0 :                                 return;
     563             :                         }
     564           0 :                         use_ipvx = ucl_object_toint(cur);
     565           0 :                         if (use_ipvx != 4 && use_ipvx != 6)
     566           0 :                                 use_ipvx = 0;
     567         197 :                 } else if (strcasecmp(key, "priority") == 0) {
     568           0 :                         if (cur->type != UCL_INT) {
     569           0 :                                 pkg_emit_error("Expecting a integer for the "
     570             :                                         "'%s' key of the '%s' repo",
     571             :                                         key, rname);
     572           0 :                                 return;
     573             :                         }
     574           0 :                         priority = ucl_object_toint(cur);
     575             :                 }
     576             :         }
     577             : 
     578         200 :         if (r == NULL && url == NULL) {
     579           0 :                 pkg_debug(1, "No repo and no url for %s", rname);
     580           0 :                 return;
     581             :         }
     582             : 
     583         200 :         if (r == NULL)
     584         200 :                 r = pkg_repo_new(rname, url, type);
     585             :         else
     586           0 :                 pkg_repo_overwrite(r, rname, url, type);
     587             : 
     588         200 :         if (signature_type != NULL) {
     589         189 :                 if (strcasecmp(signature_type, "pubkey") == 0)
     590           0 :                         r->signature_type = SIG_PUBKEY;
     591         189 :                 else if (strcasecmp(signature_type, "fingerprints") == 0)
     592         189 :                         r->signature_type = SIG_FINGERPRINT;
     593             :                 else
     594           0 :                         r->signature_type = SIG_NONE;
     595             :         }
     596             : 
     597             : 
     598         200 :         if (fingerprints != NULL) {
     599         189 :                 free(r->fingerprints);
     600         189 :                 r->fingerprints = strdup(fingerprints);
     601             :         }
     602             : 
     603         200 :         if (pubkey != NULL) {
     604           0 :                 free(r->pubkey);
     605           0 :                 r->pubkey = strdup(pubkey);
     606             :         }
     607             : 
     608         200 :         r->enable = enable;
     609         200 :         r->priority = priority;
     610             : 
     611         200 :         if (mirror_type != NULL) {
     612         189 :                 if (strcasecmp(mirror_type, "srv") == 0)
     613         189 :                         r->mirror_type = SRV;
     614           0 :                 else if (strcasecmp(mirror_type, "http") == 0)
     615           0 :                         r->mirror_type = HTTP;
     616             :                 else
     617           0 :                         r->mirror_type = NOMIRROR;
     618             :         }
     619             : 
     620         200 :         if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
     621           0 :                 use_ipvx = 4;
     622         200 :         else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)
     623           0 :                 use_ipvx = 6;
     624             : 
     625         200 :         if (use_ipvx != 4 && use_ipvx != 6)
     626         200 :                 use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION"));
     627             : 
     628         200 :         if (use_ipvx == 4)
     629           0 :                 r->flags = REPO_FLAGS_USE_IPV4;
     630         200 :         else if (use_ipvx == 6)
     631           0 :                 r->flags = REPO_FLAGS_USE_IPV6;
     632             : }
     633             : 
     634             : static void
     635         200 : walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
     636             : {
     637             :         const ucl_object_t *cur;
     638         200 :         ucl_object_iter_t it = NULL;
     639             :         struct pkg_repo *r;
     640             :         const char *key;
     641             : 
     642         600 :         while ((cur = ucl_iterate_object(obj, &it, true))) {
     643         200 :                 key = ucl_object_key(cur);
     644         200 :                 pkg_debug(1, "PkgConfig: parsing key '%s'", key);
     645         200 :                 r = pkg_repo_find(key);
     646         200 :                 if (r != NULL)
     647           0 :                         pkg_debug(1, "PkgConfig: overwriting repository %s", key);
     648         200 :                 if (cur->type == UCL_OBJECT)
     649         200 :                         add_repo(cur, r, key, flags);
     650             :                 else
     651           0 :                         pkg_emit_error("Ignoring bad configuration entry in %s: %s",
     652             :                             file, ucl_object_emit(cur, UCL_EMIT_YAML));
     653             :         }
     654         200 : }
     655             : 
     656             : static void
     657         200 : load_repo_file(const char *repofile, pkg_init_flags flags)
     658             : {
     659             :         struct ucl_parser *p;
     660         200 :         ucl_object_t *obj = NULL;
     661         200 :         const char *myarch = NULL;
     662         200 :         const char *myarch_legacy = NULL;
     663             : 
     664         200 :         p = ucl_parser_new(0);
     665             : 
     666         200 :         myarch = pkg_object_string(pkg_config_get("ABI"));
     667         200 :         ucl_parser_register_variable (p, "ABI", myarch);
     668             : 
     669         200 :         myarch_legacy = pkg_object_string(pkg_config_get("ALTABI"));
     670         200 :         ucl_parser_register_variable (p, "ALTABI", myarch_legacy);
     671             : 
     672         200 :         pkg_debug(1, "PKgConfig: loading %s", repofile);
     673         200 :         if (!ucl_parser_add_file(p, repofile)) {
     674           0 :                 pkg_emit_error("Error parsing: %s: %s", repofile,
     675             :                     ucl_parser_get_error(p));
     676           0 :                 ucl_parser_free(p);
     677           0 :                 return;
     678             :         }
     679             : 
     680         200 :         obj = ucl_parser_get_object(p);
     681         200 :         if (obj == NULL)
     682           0 :                 return;
     683             : 
     684         200 :         if (obj->type == UCL_OBJECT)
     685         200 :                 walk_repo_obj(obj, repofile, flags);
     686             : 
     687         200 :         ucl_object_unref(obj);
     688             : }
     689             : 
     690             : static int
     691        1102 : nodots(const struct dirent *dp)
     692             : {
     693        1102 :         return (dp->d_name[0] != '.');
     694             : }
     695             : 
     696             : static void
     697         389 : load_repo_files(const char *repodir, pkg_init_flags flags)
     698             : {
     699             :         struct dirent **ent;
     700             :         char *p;
     701             :         size_t n;
     702             :         int nents, i;
     703             :         char path[MAXPATHLEN];
     704             : 
     705         389 :         pkg_debug(1, "PkgConfig: loading repositories in %s", repodir);
     706             : 
     707         389 :         nents = scandir(repodir, &ent, nodots, alphasort);
     708         717 :         for (i = 0; i < nents; i++) {
     709         328 :                 if ((n = strlen(ent[i]->d_name)) <= 5)
     710           5 :                         continue;
     711         323 :                 p = &ent[i]->d_name[n - 5];
     712         323 :                 if (strcmp(p, ".conf") == 0) {
     713         200 :                         snprintf(path, sizeof(path), "%s%s%s",
     714             :                             repodir,
     715         200 :                             repodir[strlen(repodir) - 1] == '/' ? "" : "/",
     716         200 :                             ent[i]->d_name);
     717         200 :                         load_repo_file(path, flags);
     718             :                 }
     719         323 :                 free(ent[i]);
     720             :         }
     721         389 :         if (nents >= 0)
     722         387 :                 free(ent);
     723         389 : }
     724             : 
     725             : static void
     726         200 : load_repositories(const char *repodir, pkg_init_flags flags)
     727             : {
     728             :         const pkg_object *reposlist, *cur;
     729         200 :         pkg_iter it = NULL;
     730             : 
     731         200 :         if (repodir != NULL) {
     732           2 :                 load_repo_files(repodir, flags);
     733         202 :                 return;
     734             :         }
     735             : 
     736         198 :         reposlist = pkg_config_get( "REPOS_DIR");
     737         783 :         while ((cur = pkg_object_iterate(reposlist, &it)))
     738         387 :                 load_repo_files(pkg_object_string(cur), flags);
     739             : }
     740             : 
     741             : bool
     742         200 : pkg_compiled_for_same_os_major(void)
     743             : {
     744             : #ifdef OSMAJOR
     745             :         const char      *myabi;
     746             :         int              osmajor;
     747             : 
     748         200 :         myabi = pkg_object_string(pkg_config_get("ABI"));
     749         200 :         myabi = strchr(myabi,':');
     750         200 :         myabi++;
     751             : 
     752         200 :         osmajor = (int) strtol(myabi, NULL, 10);
     753             : 
     754         200 :         return (osmajor == OSMAJOR);
     755             : #else
     756             :         return (true);          /* Can't tell, so assume yes  */
     757             : #endif
     758             : }
     759             : 
     760             : 
     761             : int
     762           0 : pkg_init(const char *path, const char *reposdir)
     763             : {
     764           0 :         return (pkg_ini(path, reposdir, 0));
     765             : }
     766             : 
     767             : int
     768         200 : pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
     769             : {
     770         200 :         struct ucl_parser *p = NULL;
     771             :         size_t i;
     772         200 :         const char *val = NULL;
     773             :         const char *buf, *walk, *value, *key, *k;
     774         200 :         const char *evkey = NULL;
     775         200 :         const char *nsname = NULL;
     776         200 :         const char *useragent = NULL;
     777         200 :         const char *evpipe = NULL;
     778             :         const ucl_object_t *cur, *object;
     779         200 :         ucl_object_t *obj = NULL, *o, *ncfg;
     780         200 :         ucl_object_iter_t it = NULL;
     781         200 :         struct sbuf *ukey = NULL;
     782         200 :         bool fatal_errors = false;
     783         200 :         char *rootedpath = NULL;
     784         200 :         char *tmp = NULL;
     785             : 
     786         200 :         k = NULL;
     787         200 :         o = NULL;
     788             : 
     789         200 :         pkg_get_myarch(myabi, BUFSIZ);
     790         200 :         pkg_get_myarch_legacy(myabi_legacy, BUFSIZ);
     791         200 :         if (parsed != false) {
     792           0 :                 pkg_emit_error("pkg_init() must only be called once");
     793           0 :                 return (EPKG_FATAL);
     794             :         }
     795             : 
     796         200 :         if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
     797           0 :             ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
     798           0 :                 pkg_emit_error("Invalid flags for pkg_init()");
     799           0 :                 return (EPKG_FATAL);
     800             :         }
     801             : 
     802         200 :         config = ucl_object_typed_new(UCL_OBJECT);
     803             : 
     804       10000 :         for (i = 0; i < c_size; i++) {
     805        9800 :                 switch (c[i].type) {
     806             :                 case PKG_STRING:
     807        3800 :                         tmp = NULL;
     808        4800 :                         if (c[i].def != NULL && c[i].def[0] == '/' &&
     809        1000 :                             pkg_rootdir != NULL) {
     810           5 :                                 asprintf(&tmp, "%s%s", pkg_rootdir, c[i].def);
     811             :                         }
     812        5800 :                         obj = ucl_object_fromstring_common(
     813        5800 :                             c[i].def != NULL ? tmp != NULL ? tmp : c[i].def : "", 0, UCL_STRING_TRIM);
     814        3800 :                         free(tmp);
     815        3800 :                         ucl_object_insert_key(config, obj,
     816             :                             c[i].key, strlen(c[i].key), false);
     817        3800 :                         break;
     818             :                 case PKG_INT:
     819        1400 :                         ucl_object_insert_key(config,
     820             :                             ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
     821             :                             c[i].key, strlen(c[i].key), false);
     822        1400 :                         break;
     823             :                 case PKG_BOOL:
     824        3800 :                         ucl_object_insert_key(config,
     825             :                             ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
     826             :                             c[i].key, strlen(c[i].key), false);
     827        3800 :                         break;
     828             :                 case PKG_OBJECT:
     829         400 :                         obj = ucl_object_typed_new(UCL_OBJECT);
     830         400 :                         if (c[i].def != NULL) {
     831           0 :                                 walk = buf = c[i].def;
     832           0 :                                 while ((buf = strchr(buf, ',')) != NULL) {
     833           0 :                                         key = walk;
     834           0 :                                         value = walk;
     835           0 :                                         while (*value != ',') {
     836           0 :                                                 if (*value == '=')
     837           0 :                                                         break;
     838           0 :                                                 value++;
     839             :                                         }
     840           0 :                                         ucl_object_insert_key(obj,
     841           0 :                                             ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
     842           0 :                                             key, value - key, false);
     843           0 :                                         buf++;
     844           0 :                                         walk = buf;
     845             :                                 }
     846           0 :                                 key = walk;
     847           0 :                                 value = walk;
     848           0 :                                 while (*value != ',') {
     849           0 :                                         if (*value == '=')
     850           0 :                                                 break;
     851           0 :                                         value++;
     852             :                                 }
     853           0 :                                 if (o == NULL)
     854           0 :                                         o = ucl_object_typed_new(UCL_OBJECT);
     855           0 :                                 ucl_object_insert_key(o,
     856             :                                     ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
     857           0 :                                     key, value - key, false);
     858             :                         }
     859         400 :                         ucl_object_insert_key(config, obj,
     860             :                             c[i].key, strlen(c[i].key), false);
     861         400 :                         break;
     862             :                 case PKG_ARRAY:
     863         400 :                         obj = ucl_object_typed_new(UCL_ARRAY);
     864         400 :                         if (c[i].def != NULL) {
     865         200 :                                 walk = buf = c[i].def;
     866         600 :                                 while ((buf = strchr(buf, ',')) != NULL) {
     867         200 :                                         ucl_array_append(obj,
     868         200 :                                             ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
     869         200 :                                         buf++;
     870         200 :                                         walk = buf;
     871             :                                 }
     872         200 :                                 ucl_array_append(obj,
     873             :                                     ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
     874             :                         }
     875         400 :                         ucl_object_insert_key(config, obj,
     876             :                             c[i].key, strlen(c[i].key), false);
     877         400 :                         break;
     878             :                 }
     879             :         }
     880             : 
     881         200 :         if (path == NULL)
     882         187 :                 path = PREFIX"/etc/pkg.conf";
     883             : 
     884         200 :         if (pkg_rootdir != NULL)
     885           1 :                 asprintf(&rootedpath, "%s/%s", pkg_rootdir, path);
     886             : 
     887         200 :         p = ucl_parser_new(0);
     888         200 :         ucl_parser_register_variable (p, "ABI", myabi);
     889         200 :         ucl_parser_register_variable (p, "ALTABI", myabi_legacy);
     890             : 
     891         200 :         errno = 0;
     892         200 :         obj = NULL;
     893         200 :         if (!ucl_parser_add_file(p, rootedpath != NULL ? rootedpath : path)) {
     894          10 :                 if (errno != ENOENT)
     895           0 :                         pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
     896             :         } else {
     897         190 :                 obj = ucl_parser_get_object(p);
     898             : 
     899             :         }
     900             : 
     901         200 :         ncfg = NULL;
     902         590 :         while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
     903         190 :                 sbuf_init(&ukey);
     904         190 :                 key = ucl_object_key(cur);
     905        1140 :                 for (i = 0; key[i] != '\0'; i++)
     906         950 :                         sbuf_putc(ukey, toupper(key[i]));
     907         190 :                 sbuf_finish(ukey);
     908         190 :                 object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey));
     909             : 
     910         190 :                 if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey))
     911         190 :                     == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY",
     912         380 :                     sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey),
     913         190 :                     "MIRROR_TYPE", sbuf_len(ukey)) == 0) {
     914           0 :                         pkg_emit_error("%s in pkg.conf is no longer "
     915             :                             "supported.  Convert to the new repository style."
     916             :                             "  See pkg.conf(5)", sbuf_data(ukey));
     917           0 :                         fatal_errors = true;
     918           0 :                         continue;
     919             :                 }
     920             : 
     921             :                 /* ignore unknown keys */
     922         190 :                 if (object == NULL)
     923           0 :                         continue;
     924             : 
     925         190 :                 if (object->type != cur->type) {
     926           0 :                         pkg_emit_error("Malformed key %s, ignoring", key);
     927           0 :                         continue;
     928             :                 }
     929             : 
     930         190 :                 if (ncfg == NULL)
     931         190 :                         ncfg = ucl_object_typed_new(UCL_OBJECT);
     932         190 :                 ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true);
     933             :         }
     934             : 
     935         200 :         if (fatal_errors) {
     936           0 :                 ucl_object_unref(ncfg);
     937           0 :                 ucl_parser_free(p);
     938           0 :                 free(rootedpath);
     939           0 :                 return (EPKG_FATAL);
     940             :         }
     941             : 
     942         200 :         if (ncfg != NULL) {
     943         190 :                 it = NULL;
     944         570 :                 while (( cur = ucl_iterate_object(ncfg, &it, true))) {
     945         190 :                         key = ucl_object_key(cur);
     946         190 :                         ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
     947             :                 }
     948         190 :                 ucl_object_unref(ncfg);
     949             :         }
     950             : 
     951         200 :         ncfg = NULL;
     952         200 :         it = NULL;
     953       10200 :         while ((cur = ucl_iterate_object(config, &it, true))) {
     954        9800 :                 o = NULL;
     955        9800 :                 key = ucl_object_key(cur);
     956        9800 :                 val = getenv(key);
     957        9800 :                 if (val == NULL)
     958        9568 :                         continue;
     959         232 :                 switch (cur->type) {
     960             :                 case UCL_STRING:
     961         215 :                         o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
     962         215 :                         break;
     963             :                 case UCL_INT:
     964           0 :                         o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
     965           0 :                         if (o->type != UCL_INT) {
     966           0 :                                 pkg_emit_error("Invalid type for environment "
     967             :                                     "variable %s, got %s, while expecting an integer",
     968             :                                     key, val);
     969           0 :                                 ucl_object_unref(o);
     970           0 :                                 continue;
     971             :                         }
     972           0 :                         break;
     973             :                 case UCL_BOOLEAN:
     974           3 :                         o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
     975           3 :                         if (o->type != UCL_BOOLEAN) {
     976           0 :                                 pkg_emit_error("Invalid type for environment "
     977             :                                     "variable %s, got %s, while expecting a boolean",
     978             :                                     key, val);
     979           0 :                                 ucl_object_unref(o);
     980           0 :                                 continue;
     981             :                         }
     982           3 :                         break;
     983             :                 case UCL_OBJECT:
     984           4 :                         o = ucl_object_typed_new(UCL_OBJECT);
     985           4 :                         walk = buf = val;
     986          12 :                         while ((buf = strchr(buf, ',')) != NULL) {
     987           4 :                                 k = walk;
     988           4 :                                 value = walk;
     989          52 :                                 while (*value != ',') {
     990          48 :                                         if (*value == '=')
     991           4 :                                                 break;
     992          44 :                                         value++;
     993             :                                 }
     994           8 :                                 ucl_object_insert_key(o,
     995           4 :                                     ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
     996           4 :                                     k, value - k, false);
     997           4 :                                 buf++;
     998           4 :                                 walk = buf;
     999             :                         }
    1000           4 :                         k = walk;
    1001           4 :                         value = walk;
    1002          24 :                         while (*value != '\0') {
    1003          20 :                                 if (*value == '=')
    1004           4 :                                         break;
    1005          16 :                                 value++;
    1006             :                         }
    1007           4 :                         ucl_object_insert_key(o,
    1008             :                             ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
    1009           4 :                             k, value - k, false);
    1010           4 :                         break;
    1011             :                 case UCL_ARRAY:
    1012          10 :                         o = ucl_object_typed_new(UCL_ARRAY);
    1013          10 :                         walk = buf = val;
    1014          20 :                         while ((buf = strchr(buf, ',')) != NULL) {
    1015           0 :                                 ucl_array_append(o,
    1016           0 :                                     ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
    1017           0 :                                 buf++;
    1018           0 :                                 walk = buf;
    1019             :                         }
    1020          10 :                         ucl_array_append(o,
    1021             :                             ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
    1022          10 :                         break;
    1023             :                 default:
    1024             :                         /* ignore other types */
    1025           0 :                         break;
    1026             :                 }
    1027         232 :                 if (o != NULL) {
    1028         232 :                         if (ncfg == NULL)
    1029         198 :                                 ncfg = ucl_object_typed_new(UCL_OBJECT);
    1030         232 :                         ucl_object_insert_key(ncfg, o, key, strlen(key), true);
    1031             :                 }
    1032             :         }
    1033             : 
    1034         200 :         if (ncfg != NULL) {
    1035         198 :                 it = NULL;
    1036         628 :                 while (( cur = ucl_iterate_object(ncfg, &it, true))) {
    1037         232 :                         key = ucl_object_key(cur);
    1038         232 :                         ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
    1039             :                 }
    1040         198 :                 ucl_object_unref(ncfg);
    1041             :         }
    1042             : 
    1043         200 :         disable_plugins_if_static();
    1044             : 
    1045         200 :         parsed = true;
    1046         200 :         ucl_object_unref(obj);
    1047         200 :         ucl_parser_free(p);
    1048         200 :         free(rootedpath);
    1049             : 
    1050         200 :         if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) {
    1051           0 :                 pkg_emit_error("Unable to determine ABI");
    1052           0 :                 return (EPKG_FATAL);
    1053             :         }
    1054             : 
    1055         200 :         pkg_debug(1, "%s", "pkg initialized");
    1056             : 
    1057             :         /* Start the event pipe */
    1058         200 :         evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
    1059         200 :         if (evpipe != NULL)
    1060           0 :                 connect_evpipe(evpipe);
    1061             : 
    1062         200 :         debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));
    1063         200 :         developer_mode = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
    1064             : 
    1065         200 :         it = NULL;
    1066         200 :         object = ucl_object_find_key(config, "PKG_ENV");
    1067         400 :         while ((cur = ucl_iterate_object(object, &it, true))) {
    1068           0 :                 evkey = ucl_object_key(cur);
    1069           0 :                 pkg_debug(1, "Setting env var: %s", evkey);
    1070           0 :                 if (evkey != NULL && evkey[0] != '\0')
    1071           0 :                         setenv(evkey, ucl_object_tostring_forced(cur), 1);
    1072             :         }
    1073             : 
    1074             :         /* Set user-agent */
    1075         200 :         useragent = pkg_object_string(pkg_config_get("HTTP_USER_AGENT"));
    1076         200 :         setenv("HTTP_USER_AGENT", useragent, 1);
    1077             : 
    1078             :         /* load the repositories */
    1079         200 :         load_repositories(reposdir, flags);
    1080             : 
    1081             :         /* bypass resolv.conf with specified NAMESERVER if any */
    1082         200 :         nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
    1083         200 :         if (nsname != NULL)
    1084           0 :                 set_nameserver(ucl_object_tostring_forced(o));
    1085             : 
    1086         200 :         return (EPKG_OK);
    1087             : }
    1088             : 
    1089             : static struct pkg_repo_ops*
    1090         400 : pkg_repo_find_type(const char *type)
    1091             : {
    1092         400 :         struct pkg_repo_ops *found = NULL, **cur;
    1093             : 
    1094             :         /* Default repo type */
    1095         400 :         if (type == NULL)
    1096         200 :                 return (pkg_repo_find_type("binary"));
    1097             : 
    1098         200 :         cur = &repos_ops[0];
    1099         600 :         while (*cur != NULL) {
    1100         200 :                 if (strcasecmp(type, (*cur)->type) == 0) {
    1101         200 :                         found = *cur;
    1102             :                 }
    1103         200 :                 cur ++;
    1104             :         }
    1105             : 
    1106         200 :         if (found == NULL)
    1107           0 :                 return (pkg_repo_find_type("binary"));
    1108             : 
    1109         200 :         return (found);
    1110             : }
    1111             : 
    1112             : static struct pkg_repo *
    1113         200 : pkg_repo_new(const char *name, const char *url, const char *type)
    1114             : {
    1115             :         struct pkg_repo *r;
    1116             : 
    1117         200 :         r = calloc(1, sizeof(struct pkg_repo));
    1118         200 :         r->ops = pkg_repo_find_type(type);
    1119         200 :         r->url = strdup(url);
    1120         200 :         r->signature_type = SIG_NONE;
    1121         200 :         r->mirror_type = NOMIRROR;
    1122         200 :         r->enable = true;
    1123         200 :         r->meta = pkg_repo_meta_default();
    1124         200 :         r->name = strdup(name);
    1125         200 :         HASH_ADD_KEYPTR(hh, repos, r->name, strlen(r->name), r);
    1126             : 
    1127         200 :         return (r);
    1128             : }
    1129             : 
    1130             : static void
    1131           0 : pkg_repo_overwrite(struct pkg_repo *r, const char *name, const char *url,
    1132             :     const char *type)
    1133             : {
    1134             : 
    1135           0 :         free(r->name);
    1136           0 :         r->name = strdup(name);
    1137           0 :         if (url != NULL) {
    1138           0 :                 free(r->url);
    1139           0 :                 r->url = strdup(url);
    1140             :         }
    1141           0 :         r->ops = pkg_repo_find_type(type);
    1142           0 :         HASH_DEL(repos, r);
    1143           0 :         HASH_ADD_KEYPTR(hh, repos, r->name, strlen(r->name), r);
    1144           0 : }
    1145             : 
    1146             : static void
    1147         200 : pkg_repo_free(struct pkg_repo *r)
    1148             : {
    1149         200 :         free(r->url);
    1150         200 :         free(r->name);
    1151         200 :         free(r->pubkey);
    1152         200 :         free(r->meta);
    1153         200 :         if (r->ssh != NULL) {
    1154           0 :                 fprintf(r->ssh, "quit\n");
    1155           0 :                 pclose(r->ssh);
    1156             :         }
    1157         200 :         free(r);
    1158         200 : }
    1159             : 
    1160             : void
    1161         200 : pkg_shutdown(void)
    1162             : {
    1163         200 :         if (!parsed) {
    1164           0 :                 pkg_emit_error("pkg_shutdown() must be called after pkg_init()");
    1165           0 :                 _exit(EX_SOFTWARE);
    1166             :                 /* NOTREACHED */
    1167             :         }
    1168             : 
    1169         200 :         ucl_object_unref(config);
    1170         200 :         HASH_FREE(repos, pkg_repo_free);
    1171             : 
    1172         200 :         parsed = false;
    1173             : 
    1174         200 :         return;
    1175             : }
    1176             : 
    1177             : int
    1178          35 : pkg_repos_total_count(void)
    1179             : {
    1180             : 
    1181          35 :         return (HASH_COUNT(repos));
    1182             : }
    1183             : 
    1184             : int
    1185           8 : pkg_repos_activated_count(void)
    1186             : {
    1187           8 :         struct pkg_repo *r = NULL;
    1188           8 :         int count = 0;
    1189             : 
    1190          16 :         for (r = repos; r != NULL; r = r->hh.next) {
    1191           8 :                 if (r->enable)
    1192           8 :                         count++;
    1193             :         }
    1194             : 
    1195           8 :         return (count);
    1196             : }
    1197             : 
    1198             : int
    1199          71 : pkg_repos(struct pkg_repo **r)
    1200             : {
    1201          71 :         HASH_NEXT(repos, (*r));
    1202             : }
    1203             : 
    1204             : const char *
    1205         106 : pkg_repo_url(struct pkg_repo *r)
    1206             : {
    1207         106 :         return (r->url);
    1208             : }
    1209             : 
    1210             : /* The basename of the sqlite DB file and the database name */
    1211             : const char *
    1212         126 : pkg_repo_name(struct pkg_repo *r)
    1213             : {
    1214         126 :         return (r->name);
    1215             : }
    1216             : 
    1217             : const char *
    1218           3 : pkg_repo_key(struct pkg_repo *r)
    1219             : {
    1220           3 :         return (r->pubkey);
    1221             : }
    1222             : 
    1223             : const char *
    1224           3 : pkg_repo_fingerprints(struct pkg_repo *r)
    1225             : {
    1226           3 :         return (r->fingerprints);
    1227             : }
    1228             : 
    1229             : signature_t
    1230          55 : pkg_repo_signature_type(struct pkg_repo *r)
    1231             : {
    1232          55 :         return (r->signature_type);
    1233             : }
    1234             : 
    1235             : bool
    1236          35 : pkg_repo_enabled(struct pkg_repo *r)
    1237             : {
    1238          35 :         return (r->enable);
    1239             : }
    1240             : 
    1241             : mirror_t
    1242           6 : pkg_repo_mirror_type(struct pkg_repo *r)
    1243             : {
    1244           6 :         return (r->mirror_type);
    1245             : }
    1246             : 
    1247             : unsigned int
    1248           3 : pkg_repo_priority(struct pkg_repo *r)
    1249             : {
    1250           3 :         return (r->priority);
    1251             : }
    1252             : 
    1253             : /* Locate the repo by the file basename / database name */
    1254             : struct pkg_repo *
    1255         218 : pkg_repo_find(const char *reponame)
    1256             : {
    1257             :         struct pkg_repo *r;
    1258             : 
    1259         218 :         HASH_FIND_STR(repos, reponame, r);
    1260         218 :         return (r);
    1261             : }
    1262             : 
    1263             : int64_t
    1264         381 : pkg_set_debug_level(int64_t new_debug_level) {
    1265         381 :         int64_t old_debug_level = debug_level;
    1266             : 
    1267         381 :         debug_level = new_debug_level;
    1268         381 :         return old_debug_level;
    1269             : }
    1270             : 
    1271             : void
    1272           1 : pkg_set_rootdir(const char *rootdir) {
    1273           1 :         if (pkg_initialized())
    1274           1 :                 return;
    1275             : 
    1276           1 :         pkg_rootdir = rootdir;
    1277             : }

Generated by: LCOV version 1.10