LCOV - code coverage report
Current view: top level - src - version.c (source / functions) Hit Total Coverage
Test: plop Lines: 31 551 5.6 %
Date: 2024-12-28 18:40:32 Functions: 2 18 11.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 14 315 4.4 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2023 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
       5                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       6                 :            :  * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
       7                 :            :  * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org>
       8                 :            :  * All rights reserved.
       9                 :            :  *
      10                 :            :  * Redistribution and use in source and binary forms, with or without
      11                 :            :  * modification, are permitted provided that the following conditions
      12                 :            :  * are met:
      13                 :            :  * 1. Redistributions of source code must retain the above copyright
      14                 :            :  *    notice, this list of conditions and the following disclaimer
      15                 :            :  *    in this position and unchanged.
      16                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      17                 :            :  *    notice, this list of conditions and the following disclaimer in the
      18                 :            :  *    documentation and/or other materials provided with the distribution.
      19                 :            :  *
      20                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      21                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      22                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      23                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      24                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      25                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      29                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30                 :            :  */
      31                 :            : 
      32                 :            : #include <sys/param.h>
      33                 :            : #include <sys/utsname.h>
      34                 :            : #include <sys/wait.h>
      35                 :            : 
      36                 :            : #include <err.h>
      37                 :            : #include <errno.h>
      38                 :            : #include <getopt.h>
      39                 :            : #include <fcntl.h>
      40                 :            : #include <pkg.h>
      41                 :            : #include <stdbool.h>
      42                 :            : #include <stdio.h>
      43                 :            : #include <stdlib.h>
      44                 :            : #include <string.h>
      45                 :            : #include <unistd.h>
      46                 :            : #include <fnmatch.h>
      47                 :            : #include <spawn.h>
      48                 :            : #include <sys/types.h>
      49                 :            : #include <sys/stat.h>
      50                 :            : #include <pkghash.h>
      51                 :            : #include <xmalloc.h>
      52                 :            : 
      53                 :            : #include "pkgcli.h"
      54                 :            : 
      55                 :            : extern char **environ;
      56                 :            : 
      57                 :            : struct index_entry {
      58                 :            :         char *name;
      59                 :            :         char *version;
      60                 :            : };
      61                 :            : 
      62                 :            : struct category {
      63                 :            :         char *name;
      64                 :            :         pkghash *ports;
      65                 :            : };
      66                 :            : 
      67                 :            : pkghash *categories = NULL;
      68                 :            : 
      69                 :            : void
      70                 :          0 : usage_version(void)
      71                 :            : {
      72                 :          0 :         fprintf(stderr, "Usage: pkg version [-IPR] [-hoqvU] [-l limchar] [-L limchar] [-Cegix pattern]\n");
      73                 :          0 :         fprintf(stderr, "              [-r reponame] [-O origin|-n pkgname] [index]\n");
      74                 :          0 :         fprintf(stderr, "  pkg version -t <version1> <version2>\n");
      75                 :          0 :         fprintf(stderr, "  pkg version -T <pkgname> <pattern>\n\n");
      76                 :          0 :         fprintf(stderr, "For more information see 'pkg help version'.\n");
      77                 :          0 : }
      78                 :            : 
      79                 :            : static void
      80                 :          0 : print_version(struct pkg *pkg, const char *source, const char *ver,
      81                 :            :               char limchar, unsigned int opt)
      82                 :            : {
      83                 :            :         char             key;
      84                 :          0 :         const char      *version = NULL;
      85                 :            :         int              cout;
      86                 :            : 
      87                 :          0 :         pkg_get(pkg, PKG_ATTR_VERSION, &version);
      88         [ #  # ]:          0 :         if (ver == NULL) {
      89         [ #  # ]:          0 :                 if (source == NULL)
      90                 :          0 :                         key = '!';
      91                 :            :                 else
      92                 :          0 :                         key = '?';
      93                 :          0 :         } else {
      94   [ #  #  #  # ]:          0 :                 switch (pkg_version_cmp(version, ver)) {
      95                 :            :                 case -1:
      96                 :          0 :                         key = '<';
      97                 :          0 :                         break;
      98                 :            :                 case 0:
      99                 :          0 :                         key = '=';
     100                 :          0 :                         break;
     101                 :            :                 case 1:
     102                 :          0 :                         key = '>';
     103                 :          0 :                         break;
     104                 :            :                 default:
     105                 :          0 :                         key = '!';
     106                 :          0 :                         break;
     107                 :            :                 }
     108                 :            :         }
     109                 :            : 
     110   [ #  #  #  # ]:          0 :         if ((opt & VERSION_STATUS) && limchar != key)
     111                 :          0 :                 return;
     112                 :            : 
     113   [ #  #  #  # ]:          0 :         if ((opt & VERSION_NOSTATUS) && limchar == key)
     114                 :          0 :                 return;
     115                 :            : 
     116         [ #  # ]:          0 :         if (opt & VERSION_ORIGIN)
     117                 :          0 :                 pkg_printf("%-34o %c", pkg, key);
     118                 :            :         else {
     119                 :          0 :                 cout = pkg_printf("%n-%v", pkg, pkg);
     120                 :          0 :                 cout = 35 - cout;
     121         [ #  # ]:          0 :                 if (cout < 1)
     122                 :          0 :                         cout = 1;
     123                 :          0 :                 printf("%*s%c", cout, " ", key);
     124                 :            :         }
     125                 :            : 
     126         [ #  # ]:          0 :         if (opt & VERSION_VERBOSE) {
     127   [ #  #  #  #  :          0 :                 switch (key) {
                   #  # ]
     128                 :            :                 case '<':
     129                 :          0 :                         printf("   needs updating (%s has %s)", source, ver);
     130                 :          0 :                         break;
     131                 :            :                 case '=':
     132                 :          0 :                         printf("   up-to-date with %s", source);
     133                 :          0 :                         break;
     134                 :            :                 case '>':
     135                 :          0 :                         printf("   succeeds %s (%s has %s)", source, source, ver);
     136                 :          0 :                         break;
     137                 :            :                 case '?':
     138                 :          0 :                         pkg_printf("   orphaned: %o", pkg);
     139                 :          0 :                         break;
     140                 :          0 :                 case '!':
     141                 :            :                 default:
     142                 :          0 :                         printf("   Comparison failed");
     143                 :          0 :                         break;
     144                 :            :                 }
     145                 :          0 :         }
     146                 :            : 
     147         [ #  # ]:          0 :         putchar('\n');
     148                 :          0 : }
     149                 :            : 
     150                 :            : static int
     151                 :         11 : do_testversion(unsigned int opt, int argc, char ** restrict argv)
     152                 :            : {
     153                 :            :         /* -t must be unique and takes two arguments */
     154   [ +  -  -  + ]:         11 :         if ( opt != VERSION_TESTVERSION || argc < 2 ) {
     155                 :          0 :                 usage_version();
     156                 :          0 :                 return (EXIT_FAILURE);
     157                 :            :         }
     158                 :            : 
     159   [ +  -  +  + ]:         11 :         switch (pkg_version_cmp(argv[0], argv[1])) {
     160                 :            :         case -1:
     161                 :          8 :                 printf("<\n");
     162                 :          8 :                 break;
     163                 :            :         case 0:
     164                 :          1 :                 printf("=\n");
     165                 :          1 :                 break;
     166                 :            :         case 1:
     167                 :          2 :                 printf(">\n");
     168                 :          2 :                 break;
     169                 :            :         }
     170                 :            : 
     171                 :         11 :         return (EXIT_SUCCESS);
     172                 :         11 : }
     173                 :            : 
     174                 :            : static int
     175                 :          0 : do_testpattern(unsigned int opt, int argc, char ** restrict argv)
     176                 :            : {
     177                 :          0 :         bool     pattern_from_stdin = false;
     178                 :          0 :         bool     pkgname_from_stdin = false;
     179                 :          0 :         char    *line = NULL;
     180                 :          0 :         size_t   linecap = 0;
     181                 :            :         ssize_t  linelen;
     182                 :          0 :         int      retval = FNM_NOMATCH;
     183                 :            : 
     184                 :            :         /* -T must be unique and takes two arguments */
     185   [ #  #  #  # ]:          0 :         if ( opt != VERSION_TESTPATTERN || argc < 2 ) {
     186                 :          0 :                 usage_version();
     187                 :          0 :                 return (EXIT_FAILURE);
     188                 :            :         }
     189                 :            : 
     190         [ #  # ]:          0 :         if (strncmp(argv[0], "-", 1) == 0)
     191                 :          0 :                 pattern_from_stdin = true;
     192                 :            : 
     193         [ #  # ]:          0 :         if (strncmp(argv[1], "-", 1) == 0)
     194                 :          0 :                 pkgname_from_stdin = true;
     195                 :            : 
     196   [ #  #  #  # ]:          0 :         if (pattern_from_stdin && pkgname_from_stdin) {
     197                 :          0 :                 usage_version();
     198                 :          0 :                 return (EXIT_FAILURE);
     199                 :            :         }
     200                 :            : 
     201   [ #  #  #  # ]:          0 :         if (!pattern_from_stdin && !pkgname_from_stdin)
     202                 :          0 :                 return (fnmatch(argv[1], argv[0], 0));
     203                 :            : 
     204         [ #  # ]:          0 :         while ((linelen = getline(&line, &linecap, stdin)) > 0) {
     205                 :          0 :                 line[linelen - 1] = '\0'; /* Strip trailing newline */
     206                 :            : 
     207   [ #  #  #  #  :          0 :                 if ((pattern_from_stdin && (fnmatch(argv[1], line, 0) == 0)) ||
                   #  # ]
     208         [ #  # ]:          0 :                     (pkgname_from_stdin && (fnmatch(line, argv[0], 0) == 0))) {
     209                 :          0 :                         retval = EPKG_OK;
     210                 :          0 :                         printf("%.*s\n", (int)linelen, line);
     211                 :          0 :                 }
     212                 :            :         }
     213                 :            : 
     214                 :          0 :         free(line);
     215                 :            : 
     216                 :          0 :         return (retval);
     217                 :          0 : }
     218                 :            : 
     219                 :            : static bool
     220                 :          0 : have_ports(const char **portsdir, bool show_error)
     221                 :            : {
     222                 :            :         char             portsdirmakefile[MAXPATHLEN];
     223                 :            :         struct stat      sb;
     224                 :            :         bool             have_ports;
     225                 :            : 
     226                 :            :         /* Look for Makefile within $PORTSDIR as indicative of
     227                 :            :          * installed ports tree. */
     228                 :            : 
     229                 :          0 :         *portsdir = pkg_object_string(pkg_config_get("PORTSDIR"));
     230         [ #  # ]:          0 :         if (*portsdir == NULL)
     231                 :          0 :                 err(1, "Cannot get portsdir config entry!");
     232                 :            : 
     233                 :          0 :         snprintf(portsdirmakefile, sizeof(portsdirmakefile),
     234                 :          0 :                  "%s/Makefile", *portsdir);
     235                 :            : 
     236   [ #  #  #  # ]:          0 :         have_ports = (stat(portsdirmakefile, &sb) == 0 && S_ISREG(sb.st_mode));
     237                 :            : 
     238   [ #  #  #  # ]:          0 :         if (show_error && !have_ports)
     239                 :          0 :                 warnx("Cannot find ports tree: unable to open %s",
     240                 :          0 :                       portsdirmakefile);
     241                 :            : 
     242                 :          0 :         return (have_ports);
     243                 :            : }
     244                 :            : 
     245                 :            : static const char*
     246                 :          0 : indexfilename(char *filebuf, size_t filebuflen)
     247                 :            : {
     248                 :            :         const char      *indexdir;
     249                 :            :         const char      *indexfile;
     250                 :            : 
     251                 :            :         /* Construct the canonical name of the indexfile from the
     252                 :            :          * ports directory and the major version number of the OS.
     253                 :            :          * Overridden by INDEXDIR and INDEXFILE if defined. (Mimics
     254                 :            :          * the behaviour of ${PORTSDIR}/Makefile) */
     255                 :            : 
     256                 :          0 :         indexdir = pkg_object_string(pkg_config_get("INDEXDIR"));
     257         [ #  # ]:          0 :         if (indexdir == NULL) {
     258                 :          0 :                 indexdir = pkg_object_string(pkg_config_get("PORTSDIR"));
     259                 :            : 
     260         [ #  # ]:          0 :                 if (indexdir == NULL)
     261                 :          0 :                         err(EXIT_FAILURE, "Cannot get either INDEXDIR or "
     262                 :            :                             "PORTSDIR config entry!");
     263                 :          0 :         }
     264                 :            : 
     265                 :          0 :         indexfile = pkg_object_string(pkg_config_get("INDEXFILE"));
     266         [ #  # ]:          0 :         if (indexfile == NULL)
     267                 :          0 :                 err(EXIT_FAILURE, "Cannot get INDEXFILE config entry!");
     268                 :            : 
     269                 :          0 :         strlcpy(filebuf, indexdir, filebuflen);
     270                 :            : 
     271   [ #  #  #  # ]:          0 :         if (filebuf[0] != '\0' && filebuf[strlen(filebuf) - 1] != '/')
     272                 :          0 :                 strlcat(filebuf, "/", filebuflen);
     273                 :            : 
     274                 :          0 :         strlcat(filebuf, indexfile, filebuflen);
     275                 :            : 
     276                 :          0 :         return (filebuf);
     277                 :            : }
     278                 :            : 
     279                 :            : static pkghash *
     280                 :          0 : hash_indexfile(const char *indexfilename)
     281                 :            : {
     282                 :            :         FILE                    *indexfile;
     283                 :          0 :         pkghash                 *index = NULL;
     284                 :            :         struct index_entry      *entry;
     285                 :            :         char                    *version, *name;
     286                 :          0 :         char                    *line = NULL, *l;
     287                 :          0 :         size_t                   linecap = 0;
     288                 :            : 
     289                 :            : 
     290                 :            :         /* Create a hash table of all the package names and port
     291                 :            :          * directories from the index file. */
     292                 :            : 
     293                 :          0 :         indexfile = fopen(indexfilename, "re");
     294         [ #  # ]:          0 :         if (!indexfile)
     295                 :          0 :                 err(EXIT_FAILURE, "Unable to open %s", indexfilename);
     296                 :            : 
     297         [ #  # ]:          0 :         while (getline(&line, &linecap, indexfile) > 0) {
     298                 :            :                 /* line is pkgname|portdir|... */
     299                 :            : 
     300                 :          0 :                 l = line;
     301                 :            : 
     302                 :          0 :                 version = strsep(&l, "|");
     303                 :          0 :                 name = version;
     304                 :          0 :                 version = strrchr(version, '-');
     305         [ #  # ]:          0 :                 if (version == NULL)
     306                 :          0 :                         errx(EXIT_FAILURE, "Invalid INDEX file format: %s",
     307                 :          0 :                             indexfilename);
     308                 :          0 :                 version[0] = '\0';
     309                 :          0 :                 version++;
     310                 :            : 
     311                 :          0 :                 entry = xmalloc(sizeof(struct index_entry));
     312                 :          0 :                 entry->name = xstrdup(name);
     313                 :          0 :                 entry->version = xstrdup(version);
     314                 :            : 
     315         [ #  # ]:          0 :                 if (index == NULL)
     316                 :          0 :                         index = pkghash_new();
     317                 :            : 
     318         [ #  # ]:          0 :                 if (!pkghash_add(index, entry->name, entry, NULL)) {
     319                 :          0 :                         free(entry->version);
     320                 :          0 :                         free(entry->name);
     321                 :          0 :                         free(entry);
     322                 :          0 :                 }
     323                 :            :         }
     324                 :            : 
     325                 :          0 :         free(line);
     326                 :          0 :         fclose(indexfile);
     327                 :            : 
     328         [ #  # ]:          0 :         if (index == NULL)
     329                 :          0 :                 errx(EXIT_FAILURE, "No valid entries found in '%s'",
     330                 :          0 :                     indexfilename);
     331                 :            : 
     332                 :          0 :         return (index);
     333                 :            : }
     334                 :            : 
     335                 :            : static void
     336                 :          0 : free_categories(void)
     337                 :            : {
     338                 :            :         struct category *cat;
     339                 :            :         pkghash_it it;
     340                 :            : 
     341                 :          0 :         it = pkghash_iterator(categories);
     342         [ #  # ]:          0 :         while (pkghash_next(&it)) {
     343                 :          0 :                 cat = (struct category *) it.value;
     344                 :          0 :                 free(cat->name);
     345                 :          0 :                 pkghash_destroy(cat->ports);
     346                 :          0 :                 free(cat);
     347                 :            :         }
     348                 :          0 :         pkghash_destroy(categories);
     349                 :          0 : }
     350                 :            : 
     351                 :            : static void
     352                 :          0 : free_index(pkghash *index)
     353                 :            : {
     354                 :            :         pkghash_it it;
     355                 :            :         struct index_entry *entry;
     356                 :            : 
     357                 :          0 :         it = pkghash_iterator(index);
     358         [ #  # ]:          0 :         while (pkghash_next(&it)) {
     359                 :          0 :                 entry = (struct index_entry *)it.value;
     360                 :          0 :                 free(entry->version);
     361                 :          0 :                 free(entry->name);
     362                 :          0 :                 free(entry);
     363                 :            :         }
     364                 :          0 :         pkghash_destroy(index);
     365                 :          0 : }
     366                 :            : 
     367                 :            : static bool
     368                 :          0 : have_indexfile(const char **indexfile, char *filebuf, size_t filebuflen,
     369                 :            :                int argc, char ** restrict argv, bool show_error)
     370                 :            : {
     371                 :          0 :         bool            have_indexfile = true;
     372                 :            :         struct stat     sb;
     373                 :            : 
     374                 :            :         /* If there is a remaining command line argument, take
     375                 :            :            that as the name of the INDEX file to use.  Otherwise,
     376                 :            :            search for INDEX-N within the ports tree */
     377                 :            : 
     378         [ #  # ]:          0 :         if (argc == 0)
     379                 :          0 :                 *indexfile = indexfilename(filebuf, filebuflen);
     380                 :            :         else
     381                 :          0 :                 *indexfile = argv[0];
     382                 :            : 
     383         [ #  # ]:          0 :         if (stat(*indexfile, &sb) == -1) {
     384         [ #  # ]:          0 :                 if (errno == ENOENT)
     385                 :          0 :                         have_indexfile = false;
     386                 :            :                 else
     387                 :          0 :                         warn("Failed to get stat for the INDEX file!");
     388                 :          0 :         }
     389                 :            : 
     390   [ #  #  #  # ]:          0 :         if (show_error && !have_indexfile)
     391                 :          0 :                 warn("Can't access %s", *indexfile);
     392                 :            : 
     393                 :          0 :         return (have_indexfile);
     394                 :            : }
     395                 :            : 
     396                 :            : static int
     397                 :          0 : do_source_index(unsigned int opt, char limchar, char *pattern, match_t match,
     398                 :            :     const char *matchorigin, const char *matchname, const char *indexfile)
     399                 :            : {
     400                 :            :         pkghash         *index;
     401                 :            :         struct index_entry *ie;
     402                 :          0 :         struct pkgdb    *db = NULL;
     403                 :          0 :         struct pkgdb_it *it = NULL;
     404                 :          0 :         struct pkg      *pkg = NULL;
     405                 :          0 :         const char      *name = NULL;
     406                 :          0 :         const char      *origin = NULL;
     407                 :          0 :         bool            gotnone = true;
     408                 :            : 
     409         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCES) != VERSION_SOURCE_INDEX) {
     410                 :          0 :                 usage_version();
     411                 :          0 :                 return (EXIT_FAILURE);
     412                 :            :         }
     413                 :            : 
     414         [ #  # ]:          0 :         if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
     415                 :          0 :                 return (EXIT_FAILURE);
     416                 :            : 
     417                 :          0 :         index = hash_indexfile(indexfile);
     418                 :            : 
     419         [ #  # ]:          0 :         if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
     420                 :          0 :                 pkgdb_close(db);
     421                 :          0 :                 free_index(index);
     422                 :          0 :                 warnx("Cannot get a read lock on the database. "
     423                 :            :                       "It is locked by another process");
     424                 :          0 :                 return (EXIT_FAILURE);
     425                 :            :         }
     426                 :            : 
     427                 :          0 :         it = pkgdb_query(db, pattern, match);
     428         [ #  # ]:          0 :         if (it == NULL)
     429                 :          0 :                 goto cleanup;
     430                 :            : 
     431         [ #  # ]:          0 :         while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
     432                 :          0 :                 pkg_get(pkg, PKG_ATTR_NAME, &name);
     433                 :          0 :                 pkg_get(pkg, PKG_ATTR_ORIGIN, &origin);
     434                 :            : 
     435                 :            :                 /* If -O was specified, check if this origin matches */
     436   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHORIGIN) &&
     437                 :          0 :                     !STREQ(origin, matchorigin))
     438                 :          0 :                         continue;
     439                 :            : 
     440                 :            :                 /* If -n was specified, check if this name matches */
     441   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHNAME) &&
     442                 :          0 :                     !STREQ(name, matchname))
     443                 :          0 :                         continue;
     444                 :            : 
     445                 :          0 :                 ie = pkghash_get_value(index, name);
     446         [ #  # ]:          0 :                 print_version(pkg, "index", ie != NULL ? ie->version : NULL,
     447                 :          0 :                     limchar, opt);
     448                 :            : 
     449                 :            :                 /* If we reach here, it means at least one package
     450                 :            :                    has matched with our query. */
     451                 :          0 :                 gotnone = false;
     452                 :            :         }
     453                 :            : 
     454                 :            : cleanup:
     455                 :          0 :         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
     456                 :          0 :         free_index(index);
     457                 :          0 :         pkg_free(pkg);
     458                 :          0 :         pkgdb_it_free(it);
     459                 :          0 :         pkgdb_close(db);
     460                 :            : 
     461                 :          0 :         return (gotnone);
     462                 :          0 : }
     463                 :            : 
     464                 :            : static int
     465                 :          0 : do_source_remote(unsigned int opt, char limchar, char *pattern, match_t match,
     466                 :            :     bool auto_update, c_charv_t *reponames, const char *matchorigin,
     467                 :            :     const char *matchname)
     468                 :            : {
     469                 :          0 :         struct pkgdb    *db = NULL;
     470                 :          0 :         struct pkgdb_it *it = NULL;
     471                 :          0 :         struct pkgdb_it *it_remote = NULL;
     472                 :          0 :         struct pkg      *pkg = NULL;
     473                 :          0 :         struct pkg      *pkg_remote = NULL;
     474                 :          0 :         const char      *name = NULL;
     475                 :          0 :         const char      *origin = NULL;
     476                 :          0 :         const char      *version_remote = NULL;
     477                 :          0 :         bool            is_origin = false;
     478                 :          0 :         int             retcode = EXIT_FAILURE;
     479                 :            : 
     480         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCES) != VERSION_SOURCE_REMOTE ) {
     481                 :          0 :                 usage_version();
     482                 :          0 :                 return (EXIT_FAILURE);
     483                 :            :         }
     484                 :            : 
     485                 :            :         /* Only force remote mode if looking up remote, otherwise
     486                 :            :            user is forced to have a repo.sqlite */
     487                 :            : 
     488         [ #  # ]:          0 :         if (auto_update) {
     489                 :          0 :                 retcode = pkgcli_update(false, false, reponames);
     490         [ #  # ]:          0 :                 if (retcode != EPKG_OK)
     491                 :          0 :                         return (retcode);
     492                 :            :                 else
     493                 :          0 :                         retcode = EXIT_FAILURE;
     494                 :          0 :         }
     495                 :            : 
     496         [ #  # ]:          0 :         if (pkgdb_open_all2(&db, PKGDB_REMOTE, reponames) != EPKG_OK)
     497                 :          0 :                 return (EXIT_FAILURE);
     498                 :            : 
     499         [ #  # ]:          0 :         if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
     500                 :          0 :                 pkgdb_close(db);
     501                 :          0 :                 warnx("Cannot get a read lock on a database. "
     502                 :            :                       "It is locked by another process");
     503                 :          0 :                 return (EXIT_FAILURE);
     504                 :            :         }
     505                 :            : 
     506                 :          0 :         it = pkgdb_query(db, pattern, match);
     507         [ #  # ]:          0 :         if (it == NULL)
     508                 :          0 :                 goto cleanup;
     509                 :            : 
     510         [ #  # ]:          0 :         while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
     511                 :          0 :                 pkg_get(pkg, PKG_ATTR_NAME, &name);
     512                 :          0 :                 pkg_get(pkg, PKG_ATTR_ORIGIN, &origin);
     513                 :            : 
     514                 :            :                 /* If -O was specified, check if this origin matches */
     515   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHORIGIN) &&
     516                 :          0 :                     !STREQ(origin, matchorigin)) {
     517                 :          0 :                         is_origin = true;
     518                 :          0 :                         continue;
     519                 :            :                 }
     520                 :            : 
     521                 :            :                 /* If -n was specified, check if this name matches */
     522   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHNAME) &&
     523                 :          0 :                     !STREQ(name, matchname)) {
     524                 :          0 :                         is_origin = false;
     525                 :          0 :                         continue;
     526                 :            :                 }
     527                 :            : 
     528         [ #  # ]:          0 :                 it_remote = pkgdb_repo_query2(db, is_origin ? origin : name, MATCH_EXACT, reponames);
     529         [ #  # ]:          0 :                 if (it_remote == NULL) {
     530                 :          0 :                         retcode = EXIT_FAILURE;
     531                 :          0 :                         goto cleanup;
     532                 :            :                 }
     533                 :            : 
     534   [ #  #  #  # ]:          0 :                 if (pkgdb_it_next(it_remote, &pkg_remote, PKG_LOAD_BASIC)
     535                 :          0 :                     == EPKG_OK) {
     536                 :          0 :                         pkg_get(pkg_remote, PKG_ATTR_VERSION, &version_remote);
     537                 :          0 :                         print_version(pkg, "remote", version_remote, limchar,
     538                 :          0 :                             opt);
     539                 :          0 :                 } else {
     540                 :          0 :                         print_version(pkg, "remote", NULL, limchar, opt);
     541                 :            :                 }
     542                 :          0 :                 pkgdb_it_free(it_remote);
     543                 :            : 
     544                 :            :                 /* If we reach here, it means at least one package
     545                 :            :                    has matched with our query. */
     546                 :          0 :                 retcode = EXIT_SUCCESS;
     547                 :            :         }
     548                 :            : 
     549                 :            : cleanup:
     550                 :          0 :         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
     551                 :            : 
     552                 :          0 :         pkg_free(pkg);
     553                 :          0 :         pkg_free(pkg_remote);
     554                 :          0 :         pkgdb_it_free(it);
     555                 :          0 :         pkgdb_close(db);
     556                 :            : 
     557                 :          0 :         return (retcode);
     558                 :          0 : }
     559                 :            : 
     560                 :            : static int
     561                 :          0 : exec_buf(xstring *res, char **argv) {
     562                 :            :         char buf[BUFSIZ];
     563                 :            :         int spawn_err;
     564                 :            :         pid_t pid;
     565                 :            :         int pfd[2];
     566                 :            :         int r, pstat;
     567                 :            :         posix_spawn_file_actions_t actions;
     568                 :            : 
     569         [ #  # ]:          0 :         if (pipe(pfd) < 0) {
     570                 :          0 :                 warn("pipe()");
     571                 :          0 :                 return (0);
     572                 :            :         }
     573                 :            : 
     574         [ #  # ]:          0 :         if ((spawn_err = posix_spawn_file_actions_init(&actions)) != 0) {
     575                 :          0 :                 warnx("%s:%s", argv[0], strerror(spawn_err));
     576                 :          0 :                 return (0);
     577                 :            :         }
     578                 :            : 
     579         [ #  # ]:          0 :         if ((spawn_err = posix_spawn_file_actions_addopen(&actions,
     580         [ #  # ]:          0 :             STDERR_FILENO, "/dev/null", O_RDWR, 0)) != 0 ||
     581                 :          0 :             (spawn_err = posix_spawn_file_actions_addopen(&actions,
     582         [ #  # ]:          0 :             STDIN_FILENO, "/dev/null", O_RDONLY, 0)) != 0 ||
     583                 :          0 :             (spawn_err = posix_spawn_file_actions_adddup2(&actions,
     584   [ #  #  #  #  :          0 :             pfd[1], STDOUT_FILENO)!= 0) ||
                   #  # ]
     585                 :          0 :             (spawn_err = posix_spawnp(&pid, argv[0], &actions, NULL,
     586                 :          0 :             argv, environ)) != 0) {
     587                 :          0 :                 posix_spawn_file_actions_destroy(&actions);
     588                 :          0 :                 warnx("%s:%s", argv[0], strerror(spawn_err));
     589                 :          0 :                 return (0);
     590                 :            :         }
     591                 :          0 :         posix_spawn_file_actions_destroy(&actions);
     592                 :            : 
     593                 :          0 :         close(pfd[1]);
     594                 :            : 
     595                 :          0 :         xstring_reset(res);
     596         [ #  # ]:          0 :         while ((r = read(pfd[0], buf, BUFSIZ)) > 0)
     597                 :          0 :                 fwrite(buf, sizeof(char), r, res->fp);
     598                 :            : 
     599                 :          0 :         close(pfd[0]);
     600         [ #  # ]:          0 :         while (waitpid(pid, &pstat, 0) == -1) {
     601         [ #  # ]:          0 :                 if (errno != EINTR)
     602                 :          0 :                         return (-1);
     603                 :            :         }
     604         [ #  # ]:          0 :         if (WEXITSTATUS(pstat) != 0)
     605                 :          0 :                 return (-1);
     606                 :            : 
     607                 :          0 :         fflush(res->fp);
     608                 :          0 :         return (strlen(res->buf));
     609                 :          0 : }
     610                 :            : 
     611                 :            : static struct category *
     612                 :          0 : category_new(int portsfd, const char *category)
     613                 :            : {
     614                 :          0 :         struct category *cat = NULL;
     615                 :            :         xstring         *makecmd;
     616                 :            :         char            *results, *d;
     617                 :            :         char            *argv[5];
     618                 :            : 
     619                 :          0 :         makecmd = xstring_new();
     620                 :          0 :         fchdir(portsfd);
     621                 :            : 
     622                 :          0 :         argv[0] = "make";
     623                 :          0 :         argv[1] = "-C";
     624                 :          0 :         argv[2] = (char *)category;
     625                 :          0 :         argv[3] = "-VSUBDIR";
     626                 :          0 :         argv[4] = NULL;
     627                 :            : 
     628         [ #  # ]:          0 :         if (exec_buf(makecmd, argv) <= 0)
     629                 :          0 :                 goto cleanup;
     630                 :            : 
     631                 :          0 :         fflush(makecmd->fp);
     632                 :          0 :         results = makecmd->buf;
     633                 :            : 
     634         [ #  # ]:          0 :         if (categories == NULL)
     635                 :          0 :                 categories = pkghash_new();
     636                 :            : 
     637                 :          0 :         cat = xcalloc(1, sizeof(*cat));
     638                 :          0 :         cat->name = xstrdup(category);
     639                 :            : 
     640                 :          0 :         pkghash_add(categories, cat->name, cat, NULL);
     641         [ #  # ]:          0 :         while ((d = strsep(&results, " \n")) != NULL)
     642   [ #  #  #  # ]:          0 :                 pkghash_safe_add(cat->ports, d, NULL, NULL);
     643                 :            : 
     644                 :            : cleanup:
     645                 :          0 :         xstring_free(makecmd);
     646                 :            : 
     647                 :          0 :         return (cat);
     648                 :            : }
     649                 :            : 
     650                 :            : static bool
     651                 :          0 : validate_origin(int portsfd, const char *origin)
     652                 :            : {
     653                 :            :         struct category *cat;
     654                 :            :         char            *category, *buf;
     655                 :            : 
     656                 :            :         /* If the origin does not contain a / ignore it like for
     657                 :            :          * "base"
     658                 :            :          */
     659         [ #  # ]:          0 :         if (strchr(origin, '/') == NULL)
     660                 :          0 :                 return (false);
     661                 :            : 
     662                 :          0 :         category = xstrdup(origin);
     663                 :          0 :         buf = strrchr(category, '/');
     664                 :          0 :         buf[0] = '\0';
     665                 :            : 
     666                 :          0 :         cat = pkghash_get_value(categories, category);
     667         [ #  # ]:          0 :         if (cat == NULL)
     668                 :          0 :                 cat = category_new(portsfd, category);
     669         [ #  # ]:          0 :         if (cat == NULL)
     670                 :          0 :                 return (false);
     671                 :            : 
     672                 :          0 :         buf = strrchr(origin, '/');
     673                 :          0 :         buf++;
     674                 :            : 
     675         [ #  # ]:          0 :         if (STREQ(origin, "base"))
     676                 :          0 :                 return (false);
     677                 :            : 
     678                 :          0 :         return (pkghash_get(cat->ports, buf) != NULL);
     679                 :          0 : }
     680                 :            : 
     681                 :            : static const char *
     682                 :          0 : port_version(xstring *cmd, int portsfd, const char *origin, const char *pkgname)
     683                 :            : {
     684                 :            :         char    *output, *walk, *name;
     685                 :          0 :         char    *version = NULL;
     686                 :            :         char    *argv[5];
     687                 :            : 
     688                 :            :         /* Validate the port origin -- check the SUBDIR settings
     689                 :            :            in the ports and category Makefiles, then extract the
     690                 :            :            version from the port itself. */
     691                 :            : 
     692         [ #  # ]:          0 :         if (validate_origin(portsfd, origin)) {
     693                 :          0 :                 argv[0] = "make";
     694                 :          0 :                 argv[1] = "-C";
     695                 :          0 :                 argv[2] = (char *)origin;
     696                 :          0 :                 argv[3] = "flavors-package-names";
     697                 :          0 :                 argv[4] = NULL;
     698                 :            : 
     699         [ #  # ]:          0 :                 if (exec_buf(cmd, argv) > 0) {
     700                 :          0 :                         fflush(cmd->fp);
     701                 :          0 :                         output = cmd->buf;
     702         [ #  # ]:          0 :                         while ((walk = strsep(&output, "\n")) != NULL) {
     703                 :          0 :                                 name = walk;
     704                 :          0 :                                 walk = strrchr(walk, '-');
     705         [ #  # ]:          0 :                                 if (walk == NULL)
     706                 :          0 :                                         continue;
     707                 :          0 :                                 walk[0] = '\0';
     708                 :          0 :                                 walk++;
     709         [ #  # ]:          0 :                                 if (STREQ(name, pkgname)) {
     710                 :          0 :                                         version = walk;
     711                 :          0 :                                         break;
     712                 :            :                                 }
     713                 :            :                         }
     714                 :          0 :                 }
     715                 :          0 :         }
     716                 :            : 
     717                 :          0 :         return (version);
     718                 :            : }
     719                 :            : 
     720                 :            : static int
     721                 :          0 : do_source_ports(unsigned int opt, char limchar, char *pattern, match_t match,
     722                 :            :     const char *matchorigin, const char *matchname, const char *portsdir)
     723                 :            : {
     724                 :          0 :         struct pkgdb    *db = NULL;
     725                 :          0 :         struct pkgdb_it *it = NULL;
     726                 :          0 :         struct pkg      *pkg = NULL;
     727                 :            :         xstring         *cmd;
     728                 :          0 :         const char      *name = NULL;
     729                 :          0 :         const char      *origin = NULL;
     730                 :          0 :         const char      *version = NULL;
     731                 :            :         int             portsfd;
     732                 :          0 :         bool            gotnone = true;
     733                 :            : 
     734         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCES) != VERSION_SOURCE_PORTS ) {
     735                 :          0 :                 usage_version();
     736                 :          0 :                 return (EXIT_FAILURE);
     737                 :            :         }
     738                 :            : 
     739                 :          0 :         portsfd = open(portsdir, O_DIRECTORY);
     740         [ #  # ]:          0 :         if (portsfd == -1)
     741                 :          0 :                 err(EXIT_FAILURE, "Cannot open '%s'", portsdir);
     742                 :            : 
     743         [ #  # ]:          0 :         if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
     744                 :          0 :                 return (EXIT_FAILURE);
     745                 :            : 
     746         [ #  # ]:          0 :         if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
     747                 :          0 :                 pkgdb_close(db);
     748                 :          0 :                 warnx("Cannot get a read lock on a database. "
     749                 :            :                       "It is locked by another process");
     750                 :          0 :                 return (EXIT_FAILURE);
     751                 :            :         }
     752                 :            : 
     753         [ #  # ]:          0 :         if ((it = pkgdb_query(db, pattern, match)) == NULL)
     754                 :          0 :                 goto cleanup;
     755                 :            : 
     756                 :          0 :         cmd = xstring_new();
     757                 :            : 
     758         [ #  # ]:          0 :         while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
     759                 :          0 :                 pkg_get(pkg, PKG_ATTR_NAME, &name);
     760                 :          0 :                 pkg_get(pkg, PKG_ATTR_ORIGIN, &origin);
     761                 :            : 
     762                 :            :                 /* If -O was specified, check if this origin matches */
     763   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHORIGIN) &&
     764                 :          0 :                     !STREQ(origin, matchorigin))
     765                 :          0 :                         continue;
     766                 :            : 
     767                 :            :                 /* If -n was specified, check if this name matches */
     768   [ #  #  #  # ]:          0 :                 if ((opt & VERSION_WITHNAME) &&
     769                 :          0 :                     !STREQ(name, matchname))
     770                 :          0 :                         continue;
     771                 :            : 
     772                 :          0 :                 version = port_version(cmd, portsfd, origin, name);
     773                 :          0 :                 print_version(pkg, "port", version, limchar, opt);
     774                 :          0 :                 xstring_reset(cmd);
     775                 :            : 
     776                 :            :                 /* If we reach here, it means at least one package
     777                 :            :                    has matched with our query. */
     778                 :          0 :                 gotnone = false;
     779                 :            :         }
     780                 :            : 
     781                 :          0 :         xstring_free(cmd);
     782                 :            : 
     783                 :            : cleanup:
     784                 :          0 :         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
     785                 :            : 
     786                 :          0 :         free_categories();
     787                 :          0 :         pkg_free(pkg);
     788                 :          0 :         pkgdb_it_free(it);
     789                 :          0 :         pkgdb_close(db);
     790                 :            : 
     791                 :          0 :         return (gotnone);
     792                 :          0 : }
     793                 :            : 
     794                 :            : int
     795                 :         11 : exec_version(int argc, char **argv)
     796                 :            : {
     797                 :         11 :         unsigned int     opt = 0;
     798                 :         11 :         char             limchar = '-';
     799                 :         11 :         const char      *matchorigin = NULL;
     800                 :         11 :         const char      *matchname = NULL;
     801                 :            :         const char      *portsdir;
     802                 :            :         const char      *indexfile;
     803                 :            :         const char      *versionsource;
     804                 :            :         char             filebuf[MAXPATHLEN];
     805                 :         11 :         match_t          match = MATCH_ALL;
     806                 :         11 :         char            *pattern = NULL;
     807                 :            :         int              ch;
     808                 :            :         c_charv_t       reponames;
     809                 :            : 
     810                 :         11 :         struct option longopts[] = {
     811                 :            :                 { "case-sensitive",   no_argument,            NULL,   'C' },
     812                 :            :                 { "exact",            required_argument,      NULL,   'e' },
     813                 :            :                 { "glob",             required_argument,      NULL,   'g' },
     814                 :            :                 { "help",             no_argument,            NULL,   'h' },
     815                 :            :                 { "index",            no_argument,            NULL,   'I' },
     816                 :            :                 { "case-insensitive", no_argument,            NULL,   'i' },
     817                 :            :                 { "not-like",         required_argument,      NULL,   'L' },
     818                 :            :                 { "like",             required_argument,      NULL,   'l' },
     819                 :            :                 { "match-name",               required_argument,      NULL,   'n' },
     820                 :            :                 { "match-origin",     required_argument,      NULL,   'O' },
     821                 :            :                 { "origin",           no_argument,            NULL,   'o' },
     822                 :            :                 { "ports",            no_argument,            NULL,   'P' },
     823                 :            :                 { "quiet",            no_argument,            NULL,   'q' },
     824                 :            :                 { "remote",           no_argument,            NULL,   'R' },
     825                 :            :                 { "repository",               required_argument,      NULL,   'r' },
     826                 :            :                 { "test-pattern",     no_argument,            NULL,   'T' },
     827                 :            :                 { "test-version",     no_argument,            NULL,   't' },
     828                 :            :                 { "no-repo-update",   no_argument,            NULL,   'U' },
     829                 :            :                 { "verbose",          no_argument,            NULL,   'v' },
     830                 :            :                 { "regex",            required_argument,      NULL,   'x' },
     831                 :            :                 { NULL,                 0,                      NULL,   0   },
     832                 :            :         };
     833                 :            : 
     834                 :         11 :         pkgvec_init(&reponames);
     835   [ +  +  +  +  :         22 :         while ((ch = getopt_long(argc, argv, "+Ce:g:hIiL:l:n:O:oPqRr:TtUvx:",
                   +  + ]
     836                 :         44 :                                  longopts, NULL)) != -1) {
     837   [ -  -  -  -  :         11 :                 switch (ch) {
          -  -  -  -  -  
          -  -  -  -  -  
          -  +  -  -  -  
                   -  - ]
     838                 :            :                 case 'C':
     839                 :          0 :                         pkgdb_set_case_sensitivity(true);
     840                 :          0 :                         break;
     841                 :            :                 case 'e':
     842                 :          0 :                         match = MATCH_EXACT;
     843                 :          0 :                         pattern = optarg;
     844                 :          0 :                         break;
     845                 :            :                 case 'g':
     846                 :          0 :                         match = MATCH_GLOB;
     847                 :          0 :                         pattern = optarg;
     848                 :          0 :                         break;
     849                 :            :                 case 'h':
     850                 :          0 :                         usage_version();
     851                 :          0 :                         return (EXIT_SUCCESS);
     852                 :            :                 case 'I':
     853                 :          0 :                         opt |= VERSION_SOURCE_INDEX;
     854                 :          0 :                         break;
     855                 :            :                 case 'i':
     856                 :          0 :                         pkgdb_set_case_sensitivity(false);
     857                 :          0 :                         break;
     858                 :            :                 case 'L':
     859                 :          0 :                         opt |= VERSION_NOSTATUS;
     860                 :          0 :                         limchar = *optarg;
     861                 :          0 :                         break;
     862                 :            :                 case 'l':
     863                 :          0 :                         opt |= VERSION_STATUS;
     864                 :          0 :                         limchar = *optarg;
     865                 :          0 :                         break;
     866                 :            :                 case 'n':
     867                 :          0 :                         opt |= VERSION_WITHNAME;
     868                 :          0 :                         matchname = optarg;
     869                 :          0 :                         break;
     870                 :            :                 case 'O':
     871                 :          0 :                         opt |= VERSION_WITHORIGIN;
     872                 :          0 :                         matchorigin = optarg;
     873                 :          0 :                         break;
     874                 :            :                 case 'o':
     875                 :          0 :                         opt |= VERSION_ORIGIN;
     876                 :          0 :                         break;
     877                 :            :                 case 'P':
     878                 :          0 :                         opt |= VERSION_SOURCE_PORTS;
     879                 :          0 :                         break;
     880                 :            :                 case 'q':
     881                 :          0 :                         opt |= VERSION_QUIET;
     882                 :          0 :                         break;
     883                 :            :                 case 'R':
     884                 :          0 :                         opt |= VERSION_SOURCE_REMOTE;
     885                 :          0 :                         break;
     886                 :            :                 case 'r':
     887                 :          0 :                         opt |= VERSION_SOURCE_REMOTE;
     888   [ #  #  #  #  :          0 :                         pkgvec_push(&reponames, optarg);
                   #  # ]
     889                 :          0 :                         break;
     890                 :            :                 case 'T':
     891                 :          0 :                         opt |= VERSION_TESTPATTERN;
     892                 :          0 :                         break;
     893                 :            :                 case 't':
     894                 :         11 :                         opt |= VERSION_TESTVERSION;
     895                 :         11 :                         break;
     896                 :            :                 case 'U':
     897                 :          0 :                         auto_update = false;
     898                 :          0 :                         break;
     899                 :            :                 case 'v':
     900                 :          0 :                         opt |= VERSION_VERBOSE;
     901                 :          0 :                         break;
     902                 :            :                 case 'x':
     903                 :          0 :                         match = MATCH_REGEX;
     904                 :          0 :                         pattern = optarg;
     905                 :          0 :                         break;
     906                 :            :                 default:
     907                 :          0 :                         usage_version();
     908                 :          0 :                         return (EXIT_FAILURE);
     909                 :            :                 }
     910                 :            :         }
     911                 :         11 :         argc -= optind;
     912                 :         11 :         argv += optind;
     913                 :            : 
     914                 :            :         /*
     915                 :            :          * Allowed option combinations:
     916                 :            :          *   -t ver1 ver2        -- only
     917                 :            :          *   -T pkgname pattern  -- only
     918                 :            :          *   Only one of -I -P -R can be given
     919                 :            :          */
     920                 :            : 
     921   [ -  +  #  # ]:         11 :         if (matchorigin != NULL && matchname != NULL) {
     922                 :          0 :                 usage_version();
     923                 :          0 :                 return (EXIT_FAILURE);
     924                 :            :         }
     925                 :            : 
     926         [ +  - ]:         11 :         if ( (opt & VERSION_TESTVERSION) == VERSION_TESTVERSION )
     927                 :         11 :                 return (do_testversion(opt, argc, argv));
     928                 :            : 
     929         [ #  # ]:          0 :         if ( (opt & VERSION_TESTPATTERN) == VERSION_TESTPATTERN )
     930                 :          0 :                 return (do_testpattern(opt, argc, argv));
     931                 :            : 
     932         [ #  # ]:          0 :         if (opt & (VERSION_STATUS|VERSION_NOSTATUS)) {
     933   [ #  #  #  # ]:          0 :                 if (limchar != '<' &&
     934         [ #  # ]:          0 :                     limchar != '>' &&
     935         [ #  # ]:          0 :                     limchar != '=' &&
     936         [ #  # ]:          0 :                     limchar != '?' &&
     937                 :          0 :                     limchar != '!') {
     938                 :          0 :                         usage_version();
     939                 :          0 :                         return (EXIT_FAILURE);
     940                 :            :                 }
     941                 :          0 :         }
     942                 :            : 
     943         [ #  # ]:          0 :         if (opt & VERSION_QUIET)
     944                 :          0 :                 quiet = true;
     945                 :            : 
     946         [ #  # ]:          0 :         if (argc > 1) {
     947                 :          0 :                 usage_version();
     948                 :          0 :                 return (EXIT_FAILURE);
     949                 :            :         }
     950                 :            : 
     951         [ #  # ]:          0 :         if ( !(opt & VERSION_SOURCES ) ) {
     952                 :          0 :                 versionsource = pkg_object_string(
     953                 :          0 :                     pkg_config_get("VERSION_SOURCE"));
     954         [ #  # ]:          0 :                 if (versionsource != NULL) {
     955   [ #  #  #  # ]:          0 :                         switch (versionsource[0]) {
     956                 :            :                         case 'I':
     957                 :          0 :                                 opt |= VERSION_SOURCE_INDEX;
     958                 :          0 :                                 break;
     959                 :            :                         case 'P':
     960                 :          0 :                                 opt |= VERSION_SOURCE_PORTS;
     961                 :          0 :                                 break;
     962                 :            :                         case 'R':
     963                 :          0 :                                 opt |= VERSION_SOURCE_REMOTE;
     964                 :          0 :                                 break;
     965                 :            :                         default:
     966                 :          0 :                                 warnx("Invalid VERSION_SOURCE"
     967                 :            :                                     " in configuration.");
     968                 :          0 :                         }
     969                 :          0 :                 }
     970                 :          0 :         }
     971                 :            : 
     972         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCE_INDEX) == VERSION_SOURCE_INDEX ) {
     973   [ #  #  #  # ]:          0 :                 if (!have_indexfile(&indexfile, filebuf, sizeof(filebuf),
     974                 :          0 :                      argc, argv, true))
     975                 :          0 :                         return (EXIT_FAILURE);
     976                 :            :                 else
     977                 :          0 :                         return (do_source_index(opt, limchar, pattern, match,
     978                 :          0 :                                     matchorigin, matchname, indexfile));
     979                 :            :         }
     980                 :            : 
     981         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCE_REMOTE) == VERSION_SOURCE_REMOTE )
     982                 :          0 :                 return (do_source_remote(opt, limchar, pattern, match,
     983                 :          0 :                             auto_update, &reponames, matchorigin, matchname));
     984                 :            : 
     985         [ #  # ]:          0 :         if ( (opt & VERSION_SOURCE_PORTS) == VERSION_SOURCE_PORTS ) {
     986         [ #  # ]:          0 :                 if (!have_ports(&portsdir, true))
     987                 :          0 :                         return (EXIT_FAILURE);
     988                 :            :                 else
     989                 :          0 :                         return (do_source_ports(opt, limchar, pattern,
     990                 :          0 :                                     match, matchorigin, matchname, portsdir));
     991                 :            :         }
     992                 :            : 
     993                 :            :         /* If none of -IPR were specified, and INDEX exists use that.
     994                 :            :            Failing that, if portsdir exists and is valid, use that
     995                 :            :            (slow) otherwise fallback to remote. */
     996                 :            : 
     997         [ #  # ]:          0 :         if (have_indexfile(&indexfile, filebuf, sizeof(filebuf), argc, argv,
     998                 :            :             false)) {
     999                 :          0 :                 opt |= VERSION_SOURCE_INDEX;
    1000                 :          0 :                 return (do_source_index(opt, limchar, pattern, match,
    1001                 :          0 :                             matchorigin, matchname, indexfile));
    1002         [ #  # ]:          0 :         } else if (have_ports(&portsdir, false)) {
    1003         [ #  # ]:          0 :                 if (argc == 1) {
    1004                 :          0 :                         warnx("No such INDEX file: '%s'", argv[0]);
    1005                 :          0 :                         return (EXIT_FAILURE);
    1006                 :            :                 }
    1007                 :          0 :                 opt |= VERSION_SOURCE_PORTS;
    1008                 :          0 :                 return (do_source_ports(opt, limchar, pattern, match,
    1009                 :          0 :                             matchorigin, matchname, portsdir));
    1010                 :            :         } else {
    1011                 :          0 :                 opt |= VERSION_SOURCE_REMOTE;
    1012                 :          0 :                 return (do_source_remote(opt, limchar, pattern, match,
    1013                 :          0 :                             auto_update, &reponames, matchorigin, matchname));
    1014                 :            :         }
    1015                 :            : 
    1016                 :            :         /* NOTREACHED */
    1017                 :            :         return (EXIT_FAILURE);
    1018                 :         11 : }
    1019                 :            : /*
    1020                 :            :  * That's All Folks!
    1021                 :            :  */

Generated by: LCOV version 1.15