LCOV - code coverage report
Current view: top level - src - query.c (source / functions) Hit Total Coverage
Test: plop Lines: 324 701 46.2 %
Date: 2024-12-28 18:40:32 Functions: 5 6 83.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 191 430 44.4 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       4                 :            :  * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
       5                 :            :  * Copyright (c) 2013-2014 Matthew Seaman <matthew@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 <sys/types.h>
      31                 :            : 
      32                 :            : #include <ctype.h>
      33                 :            : #include <err.h>
      34                 :            : #include <getopt.h>
      35                 :            : #include <inttypes.h>
      36                 :            : #include <stdio.h>
      37                 :            : #include <stdlib.h>
      38                 :            : #include <string.h>
      39                 :            : #include <unistd.h>
      40                 :            : 
      41                 :            : #include <pkg.h>
      42                 :            : #include "pkgcli.h"
      43                 :            : 
      44                 :            : static struct query_flags accepted_query_flags[] = {
      45                 :            :         { 'd', "nov",         1, PKG_LOAD_DEPS },
      46                 :            :         { 'r', "nov",         1, PKG_LOAD_RDEPS },
      47                 :            :         { 'C', "",            1, PKG_LOAD_CATEGORIES },
      48                 :            :         { 'F', "ps",          1, PKG_LOAD_FILES },
      49                 :            :         { 'O', "kvdD",                1, PKG_LOAD_OPTIONS },
      50                 :            :         { 'D', "",            1, PKG_LOAD_DIRS },
      51                 :            :         { 'L', "",            1, PKG_LOAD_LICENSES },
      52                 :            :         { 'U', "",            1, PKG_LOAD_USERS },
      53                 :            :         { 'G', "",            1, PKG_LOAD_GROUPS },
      54                 :            :         { 'B', "",            1, PKG_LOAD_SHLIBS_REQUIRED },
      55                 :            :         { 'b', "",            1, PKG_LOAD_SHLIBS_PROVIDED },
      56                 :            :         { 'A', "tv",            1, PKG_LOAD_ANNOTATIONS },
      57                 :            :         { '?', "drCFODLUGBbA",        1, PKG_LOAD_BASIC },    /* dbflags handled in analyse_query_string() */
      58                 :            :         { '#', "drCFODLUGBbA",        1, PKG_LOAD_BASIC },    /* dbflags handled in analyse_query_string() */
      59                 :            :         { 's', "hb",          0, PKG_LOAD_BASIC },
      60                 :            :         { 'Q', "",            0, PKG_LOAD_BASIC },
      61                 :            :         { 'n', "",            0, PKG_LOAD_BASIC },
      62                 :            :         { 'v', "",            0, PKG_LOAD_BASIC },
      63                 :            :         { 'o', "",            0, PKG_LOAD_BASIC },
      64                 :            :         { 'p', "",            0, PKG_LOAD_BASIC },
      65                 :            :         { 'm', "",            0, PKG_LOAD_BASIC },
      66                 :            :         { 'c', "",            0, PKG_LOAD_BASIC },
      67                 :            :         { 'e', "",            0, PKG_LOAD_BASIC },
      68                 :            :         { 'w', "",            0, PKG_LOAD_BASIC },
      69                 :            :         { 'l', "",            0, PKG_LOAD_BASIC },
      70                 :            :         { 'q', "",            0, PKG_LOAD_BASIC },
      71                 :            :         { 'a', "",            0, PKG_LOAD_BASIC },
      72                 :            :         { 'k', "",            0, PKG_LOAD_BASIC },
      73                 :            :         { 'M', "",            0, PKG_LOAD_BASIC },
      74                 :            :         { 't', "",            0, PKG_LOAD_BASIC },
      75                 :            :         { 'R', "",              0, PKG_LOAD_ANNOTATIONS },
      76                 :            :         { 'V', "",            0, PKG_LOAD_BASIC },
      77                 :            :         { 'X', "",            0, PKG_LOAD_BASIC | PKG_LOAD_SCRIPTS | PKG_LOAD_LUA_SCRIPTS },
      78                 :            : };
      79                 :            : 
      80                 :            : static void
      81                 :         44 : format_str(struct pkg *pkg, xstring *dest, const char *qstr, const void *data)
      82                 :            : {
      83                 :         44 :         bool automatic = false;
      84                 :         44 :         bool locked = false;
      85                 :         44 :         bool vital = false;
      86                 :            : 
      87                 :         44 :         xstring_reset(dest);
      88                 :            : 
      89         [ +  + ]:        143 :         while (qstr[0] != '\0') {
      90         [ +  + ]:         99 :                 if (qstr[0] == '%') {
      91                 :         68 :                         qstr++;
      92   [ -  -  +  +  :         68 :                         switch (qstr[0]) {
          -  -  -  -  +  
          -  +  -  -  -  
          -  +  +  -  -  
          -  +  +  -  +  
          -  -  -  -  -  
          -  -  -  +  +  
                      - ]
      93                 :            :                         case 'n':
      94                 :         18 :                                 pkg_fprintf(dest->fp, "%n", pkg);
      95                 :         18 :                                 break;
      96                 :            :                         case 'v':
      97                 :          7 :                                 pkg_fprintf(dest->fp, "%v", pkg);
      98                 :          7 :                                 break;
      99                 :            :                         case 'o':
     100                 :          0 :                                 pkg_fprintf(dest->fp, "%o", pkg);
     101                 :          0 :                                 break;
     102                 :            :                         case 'R':
     103                 :          0 :                                 pkg_fprintf(dest->fp, "%N", pkg);
     104                 :          0 :                                 break;
     105                 :            :                         case 'p':
     106                 :          0 :                                 pkg_fprintf(dest->fp, "%p", pkg);
     107                 :          0 :                                 break;
     108                 :            :                         case 'm':
     109                 :          0 :                                 pkg_fprintf(dest->fp, "%m", pkg);
     110                 :          0 :                                 break;
     111                 :            :                         case 'c':
     112                 :          2 :                                 pkg_fprintf(dest->fp, "%c", pkg);
     113                 :          2 :                                 break;
     114                 :            :                         case 'w':
     115                 :          0 :                                 pkg_fprintf(dest->fp, "%w", pkg);
     116                 :          0 :                                 break;
     117                 :            :                         case 'a':
     118                 :          5 :                                 pkg_get(pkg, PKG_ATTR_AUTOMATIC, &automatic);
     119                 :          5 :                                 fprintf(dest->fp, "%d", automatic);
     120                 :          5 :                                 break;
     121                 :            :                         case 'k':
     122                 :          0 :                                 pkg_get(pkg, PKG_ATTR_LOCKED, &locked);
     123                 :          0 :                                 fprintf(dest->fp, "%d", locked);
     124                 :          0 :                                 break;
     125                 :            :                         case 't':
     126                 :          0 :                                 pkg_fprintf(dest->fp, "%t", pkg);
     127                 :          0 :                                 break;
     128                 :            :                         case 's':
     129                 :          0 :                                 qstr++;
     130         [ #  # ]:          0 :                                 if (qstr[0] == 'h')
     131                 :          0 :                                         pkg_fprintf(dest->fp, "%#sB", pkg);
     132         [ #  # ]:          0 :                                 else if (qstr[0] == 'b')
     133                 :          0 :                                         pkg_fprintf(dest->fp, "%s", pkg);
     134                 :          0 :                                 break;
     135                 :            :                         case 'e':
     136                 :          0 :                                 pkg_fprintf(dest->fp, "%e", pkg);
     137                 :          0 :                                 break;
     138                 :            :                         case '?':
     139                 :          2 :                                 qstr++;
     140   [ +  -  -  -  :          2 :                                 switch (qstr[0]) {
          -  -  +  -  -  
             -  -  -  - ]
     141                 :            :                                 case 'd':
     142                 :          0 :                                         pkg_fprintf(dest->fp, "%?d", pkg);
     143                 :          0 :                                         break;
     144                 :            :                                 case 'r':
     145                 :          0 :                                         pkg_fprintf(dest->fp, "%?r", pkg);
     146                 :          0 :                                         break;
     147                 :            :                                 case 'C':
     148                 :          0 :                                         pkg_fprintf(dest->fp, "%?C", pkg);
     149                 :          0 :                                         break;
     150                 :            :                                 case 'F':
     151                 :          1 :                                         pkg_fprintf(dest->fp, "%?F", pkg);
     152                 :          1 :                                         break;
     153                 :            :                                 case 'O':
     154                 :          1 :                                         pkg_fprintf(dest->fp, "%?O", pkg);
     155                 :          1 :                                         break;
     156                 :            :                                 case 'D':
     157                 :          0 :                                         pkg_fprintf(dest->fp, "%?D", pkg);
     158                 :          0 :                                         break;
     159                 :            :                                 case 'L':
     160                 :          0 :                                         pkg_fprintf(dest->fp, "%?L", pkg);
     161                 :          0 :                                         break;
     162                 :            :                                 case 'U':
     163                 :          0 :                                         pkg_fprintf(dest->fp, "%?U", pkg);
     164                 :          0 :                                         break;
     165                 :            :                                 case 'G':
     166                 :          0 :                                         pkg_fprintf(dest->fp, "%?G", pkg);
     167                 :          0 :                                         break;
     168                 :            :                                 case 'B':
     169                 :          0 :                                         pkg_fprintf(dest->fp, "%?B", pkg);
     170                 :          0 :                                         break;
     171                 :            :                                 case 'b':
     172                 :          0 :                                         pkg_fprintf(dest->fp, "%?b", pkg);
     173                 :          0 :                                         break;
     174                 :            :                                 case 'A':
     175                 :          0 :                                         pkg_fprintf(dest->fp, "%?A", pkg);
     176                 :          0 :                                         break;
     177                 :            :                                 }
     178                 :          2 :                                 break;
     179                 :            :                         case '#':
     180                 :          2 :                                 qstr++;
     181   [ +  -  -  -  :          2 :                                 switch (qstr[0]) {
          -  -  +  -  -  
             -  -  -  - ]
     182                 :            :                                 case 'd':
     183                 :          0 :                                         pkg_fprintf(dest->fp, "%#d", pkg);
     184                 :          0 :                                         break;
     185                 :            :                                 case 'r':
     186                 :          0 :                                         pkg_fprintf(dest->fp, "%#r", pkg);
     187                 :          0 :                                         break;
     188                 :            :                                 case 'C':
     189                 :          0 :                                         pkg_fprintf(dest->fp, "%#C", pkg);
     190                 :          0 :                                         break;
     191                 :            :                                 case 'F':
     192                 :          1 :                                         pkg_fprintf(dest->fp, "%#F", pkg);
     193                 :          1 :                                         break;
     194                 :            :                                 case 'O':
     195                 :          1 :                                         pkg_fprintf(dest->fp, "%#O", pkg);
     196                 :          1 :                                         break;
     197                 :            :                                 case 'D':
     198                 :          0 :                                         pkg_fprintf(dest->fp, "%#D", pkg);
     199                 :          0 :                                         break;
     200                 :            :                                 case 'L':
     201                 :          0 :                                         pkg_fprintf(dest->fp, "%#L", pkg);
     202                 :          0 :                                         break;
     203                 :            :                                 case 'U':
     204                 :          0 :                                         pkg_fprintf(dest->fp, "%#U", pkg);
     205                 :          0 :                                         break;
     206                 :            :                                 case 'G':
     207                 :          0 :                                         pkg_fprintf(dest->fp, "%#G", pkg);
     208                 :          0 :                                         break;
     209                 :            :                                 case 'B':
     210                 :          0 :                                         pkg_fprintf(dest->fp, "%#B", pkg);
     211                 :          0 :                                         break;
     212                 :            :                                 case 'b':
     213                 :          0 :                                         pkg_fprintf(dest->fp, "%#b", pkg);
     214                 :          0 :                                         break;
     215                 :            :                                 case 'A':
     216                 :          0 :                                         pkg_fprintf(dest->fp, "%#A", pkg);
     217                 :          0 :                                         break;
     218                 :            :                                 }
     219                 :          2 :                                 break;
     220                 :            :                         case 'Q':
     221                 :          0 :                                 pkg_fprintf(dest->fp, "%Q", pkg);
     222                 :          0 :                                 break;
     223                 :            :                         case 'q':
     224                 :          0 :                                 pkg_fprintf(dest->fp, "%q", pkg);
     225                 :          0 :                                 break;
     226                 :            :                         case 'l':
     227                 :          0 :                                 pkg_fprintf(dest->fp, "%l", pkg);
     228                 :          0 :                                 break;
     229                 :            :                         case 'd':
     230                 :          6 :                                 qstr++;
     231         [ +  + ]:          6 :                                 if (qstr[0] == 'n')
     232                 :          2 :                                         pkg_fprintf(dest->fp, "%dn", data);
     233         [ +  + ]:          4 :                                 else if (qstr[0] == 'o')
     234                 :          2 :                                         pkg_fprintf(dest->fp, "%do", data);
     235         [ -  + ]:          2 :                                 else if (qstr[0] == 'v')
     236                 :          2 :                                         pkg_fprintf(dest->fp, "%dv", data);
     237                 :          6 :                                 break;
     238                 :            :                         case 'r':
     239                 :         15 :                                 qstr++;
     240         [ +  + ]:         15 :                                 if (qstr[0] == 'n')
     241                 :          5 :                                         pkg_fprintf(dest->fp, "%rn", data);
     242         [ +  + ]:         10 :                                 else if (qstr[0] == 'o')
     243                 :          5 :                                         pkg_fprintf(dest->fp, "%ro", data);
     244         [ -  + ]:          5 :                                 else if (qstr[0] == 'v')
     245                 :          5 :                                         pkg_fprintf(dest->fp, "%rv", data);
     246                 :         15 :                                 break;
     247                 :            :                         case 'C':
     248                 :          0 :                                 pkg_fprintf(dest->fp, "%Cn", data);
     249                 :          0 :                                 break;
     250                 :            :                         case 'F':
     251                 :          5 :                                 qstr++;
     252         [ +  - ]:          5 :                                 if (qstr[0] == 'p')
     253                 :          5 :                                         pkg_fprintf(dest->fp, "%Fn", data);
     254         [ #  # ]:          0 :                                 else if (qstr[0] == 's')
     255                 :          0 :                                         pkg_fprintf(dest->fp, "%Fs", data);
     256                 :          5 :                                 break;
     257                 :            :                         case 'O':
     258                 :          0 :                                 qstr++;
     259         [ #  # ]:          0 :                                 if (qstr[0] == 'k')
     260                 :          0 :                                         pkg_fprintf(dest->fp, "%On", data);
     261         [ #  # ]:          0 :                                 else if (qstr[0] == 'v')
     262                 :          0 :                                         pkg_fprintf(dest->fp, "%Ov", data);
     263         [ #  # ]:          0 :                                 else if (qstr[0] == 'd') /* default value */
     264                 :          0 :                                         pkg_fprintf(dest->fp, "%Od", data);
     265         [ #  # ]:          0 :                                 else if (qstr[0] == 'D') /* description */
     266                 :          0 :                                         pkg_fprintf(dest->fp, "%OD", data);
     267                 :          0 :                                 break;
     268                 :            :                         case 'D':
     269                 :          0 :                                 pkg_fprintf(dest->fp, "%Dn", data);
     270                 :          0 :                                 break;
     271                 :            :                         case 'L':
     272                 :          0 :                                 pkg_fprintf(dest->fp, "%Ln", data);
     273                 :          0 :                                 break;
     274                 :            :                         case 'U':
     275                 :          0 :                                 pkg_fprintf(dest->fp, "%Un", data);
     276                 :          0 :                                 break;
     277                 :            :                         case 'G':
     278                 :          0 :                                 pkg_fprintf(dest->fp, "%Gn", data);
     279                 :          0 :                                 break;
     280                 :            :                         case 'B':
     281                 :          0 :                                 pkg_fprintf(dest->fp, "%Bn", data);
     282                 :          0 :                                 break;
     283                 :            :                         case 'b':
     284                 :          0 :                                 pkg_fprintf(dest->fp, "%bn", data);
     285                 :          0 :                                 break;
     286                 :            :                         case 'A':
     287                 :          0 :                                 qstr++;
     288         [ #  # ]:          0 :                                 if (qstr[0] == 't')
     289                 :          0 :                                         pkg_fprintf(dest->fp, "%An", data);
     290         [ #  # ]:          0 :                                 else if (qstr[0] == 'v')
     291                 :          0 :                                         pkg_fprintf(dest->fp, "%Av", data);
     292                 :          0 :                                 break;
     293                 :            :                         case 'M':
     294         [ #  # ]:          0 :                                 if (pkg_has_message(pkg))
     295                 :          0 :                                         pkg_fprintf(dest->fp, "%M", pkg);
     296                 :          0 :                                 break;
     297                 :            :                         case 'V':
     298                 :          4 :                                 pkg_get(pkg, PKG_ATTR_VITAL, &vital);
     299                 :          4 :                                 fprintf(dest->fp, "%d", vital);
     300                 :          4 :                                 break;
     301                 :            :                         case 'X':
     302                 :          2 :                                 pkg_fprintf(dest->fp, "%X", pkg);
     303                 :          2 :                                 break;
     304                 :            :                         case '%':
     305                 :          0 :                                 fprintf(dest->fp, "%c", '%');
     306                 :          0 :                                 break;
     307                 :            :                         }
     308         [ -  + ]:         99 :                 } else  if (qstr[0] == '\\') {
     309                 :          0 :                         qstr++;
     310   [ #  #  #  #  :          0 :                         switch (qstr[0]) {
             #  #  #  # ]
     311                 :            :                         case 'n':
     312                 :          0 :                                 fprintf(dest->fp, "%c", '\n');
     313                 :          0 :                                 break;
     314                 :            :                         case 'a':
     315                 :          0 :                                 fprintf(dest->fp, "%c", '\a');
     316                 :          0 :                                 break;
     317                 :            :                         case 'b':
     318                 :          0 :                                 fprintf(dest->fp, "%c", '\b');
     319                 :          0 :                                 break;
     320                 :            :                         case 'f':
     321                 :          0 :                                 fprintf(dest->fp, "%c", '\f');
     322                 :          0 :                                 break;
     323                 :            :                         case 'r':
     324                 :          0 :                                 fprintf(dest->fp, "%c", '\r');
     325                 :          0 :                                 break;
     326                 :            :                         case '\\':
     327                 :          0 :                                 fprintf(dest->fp, "%c", '\\');
     328                 :          0 :                                 break;
     329                 :            :                         case 't':
     330                 :          0 :                                 fprintf(dest->fp, "%c", '\t');
     331                 :          0 :                                 break;
     332                 :            :                         }
     333                 :          0 :                 } else {
     334                 :         31 :                         fprintf(dest->fp, "%c", qstr[0]);
     335                 :            :                 }
     336                 :         99 :                 qstr++;
     337                 :            :         }
     338                 :         44 :         fflush(dest->fp);
     339                 :         44 : }
     340                 :            : 
     341                 :            : void
     342                 :         42 : print_query(struct pkg *pkg, char *qstr, char multiline)
     343                 :            : {
     344                 :            :         xstring                 *output;
     345                 :         42 :         struct pkg_dep          *dep    = NULL;
     346                 :         42 :         struct pkg_option       *option = NULL;
     347                 :         42 :         struct pkg_file         *file   = NULL;
     348                 :         42 :         struct pkg_dir          *dir    = NULL;
     349                 :         42 :         const char              *str = NULL;
     350                 :         42 :         struct pkg_kv           *kv = NULL;
     351                 :         42 :         struct pkg_stringlist   *sl = NULL;
     352                 :            :         struct pkg_stringlist_iterator  *slit;
     353                 :         42 :         struct pkg_kvlist       *kl = NULL;
     354                 :            :         struct pkg_kvlist_iterator      *kit;
     355                 :            : 
     356                 :         42 :         output = xstring_new();
     357                 :            : 
     358   [ -  -  +  +  :         42 :         switch (multiline) {
          +  -  +  -  -  
             -  -  -  - ]
     359                 :            :         case 'd':
     360         [ +  + ]:          4 :                 while (pkg_deps(pkg, &dep) == EPKG_OK) {
     361                 :          2 :                         format_str(pkg, output, qstr, dep);
     362                 :          2 :                         printf("%s\n", output->buf);
     363                 :            :                 }
     364                 :          2 :                 break;
     365                 :            :         case 'r':
     366         [ +  + ]:         10 :                 while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
     367                 :          5 :                         format_str(pkg, output, qstr, dep);
     368                 :          5 :                         printf("%s\n", output->buf);
     369                 :            :                 }
     370                 :          5 :                 break;
     371                 :            :         case 'C':
     372                 :          0 :                 pkg_get(pkg, PKG_ATTR_CATEGORIES, &sl);
     373                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     374         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     375                 :          0 :                         format_str(pkg, output, qstr, str);
     376                 :          0 :                         printf("%s\n", output->buf);
     377                 :            :                 }
     378                 :          0 :                 free(slit);
     379                 :          0 :                 free(sl);
     380                 :          0 :                 break;
     381                 :            :         case 'O':
     382         [ #  # ]:          0 :                 while (pkg_options(pkg, &option) == EPKG_OK) {
     383                 :          0 :                         format_str(pkg, output, qstr, option);
     384                 :          0 :                         printf("%s\n", output->buf);
     385                 :            :                 }
     386                 :          0 :                 break;
     387                 :            :         case 'F':
     388         [ +  + ]:          8 :                 while (pkg_files(pkg, &file) == EPKG_OK) {
     389                 :          5 :                         format_str(pkg, output, qstr, file);
     390                 :          5 :                         printf("%s\n", output->buf);
     391                 :            :                 }
     392                 :          3 :                 break;
     393                 :            :         case 'D':
     394         [ #  # ]:          0 :                 while (pkg_dirs(pkg, &dir) == EPKG_OK) {
     395                 :          0 :                         format_str(pkg, output, qstr, dir);
     396                 :          0 :                         printf("%s\n", output->buf);
     397                 :            :                 }
     398                 :          0 :                 break;
     399                 :            :         case 'L':
     400                 :          0 :                 pkg_get(pkg, PKG_ATTR_LICENSES, &sl);
     401                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     402         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     403                 :          0 :                         format_str(pkg, output, qstr, str);
     404                 :          0 :                         printf("%s\n", output->buf);
     405                 :            :                 }
     406                 :          0 :                 free(slit);
     407                 :          0 :                 free(sl);
     408                 :          0 :                 break;
     409                 :            :         case 'U':
     410                 :          0 :                 pkg_get(pkg, PKG_ATTR_USERS, &sl);
     411                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     412         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     413                 :          0 :                         format_str(pkg, output, qstr, str);
     414                 :          0 :                         printf("%s\n", output->buf);
     415                 :            :                 }
     416                 :          0 :                 break;
     417                 :            :         case 'G':
     418                 :          0 :                 pkg_get(pkg, PKG_ATTR_GROUPS, &sl);
     419                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     420         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     421                 :          0 :                         format_str(pkg, output, qstr, str);
     422                 :          0 :                         printf("%s\n", output->buf);
     423                 :            :                 }
     424                 :          0 :                 break;
     425                 :            :         case 'B':
     426                 :          0 :                 pkg_get(pkg, PKG_ATTR_SHLIBS_REQUIRED, &sl);
     427                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     428         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     429                 :          0 :                         format_str(pkg, output, qstr, str);
     430                 :          0 :                         printf("%s\n", output->buf);
     431                 :            :                 }
     432                 :          0 :                 break;
     433                 :            :         case 'b':
     434                 :          0 :                 pkg_get(pkg, PKG_ATTR_SHLIBS_PROVIDED, &sl);
     435                 :          0 :                 slit = pkg_stringlist_iterator(sl);
     436         [ #  # ]:          0 :                 while ((str = pkg_stringlist_next(slit))) {
     437                 :          0 :                         format_str(pkg, output, qstr, str);
     438                 :          0 :                         printf("%s\n", output->buf);
     439                 :            :                 }
     440                 :          0 :                 break;
     441                 :            :         case 'A':
     442                 :          0 :                 pkg_get(pkg, PKG_ATTR_ANNOTATIONS, &kl);
     443                 :          0 :                 kit = pkg_kvlist_iterator(kl);
     444         [ #  # ]:          0 :                 while ((kv = pkg_kvlist_next(kit))) {
     445                 :          0 :                         format_str(pkg, output, qstr, kv);
     446                 :          0 :                         printf("%s\n", output->buf);
     447                 :            :                 }
     448                 :          0 :                 free(kit);
     449                 :          0 :                 free(kl);
     450                 :          0 :                 break;
     451                 :            :         default:
     452                 :         32 :                 format_str(pkg, output, qstr, dep);
     453                 :         32 :                 printf("%s\n", output->buf);
     454                 :         32 :                 break;
     455                 :            :         }
     456                 :         42 :         xstring_free(output);
     457                 :         42 : }
     458                 :            : 
     459                 :            : typedef enum {
     460                 :            :         NONE,
     461                 :            :         NEXT_IS_INT,
     462                 :            :         OPERATOR_INT,
     463                 :            :         INT,
     464                 :            :         NEXT_IS_STRING,
     465                 :            :         OPERATOR_STRING,
     466                 :            :         STRING,
     467                 :            :         QUOTEDSTRING,
     468                 :            :         SQUOTEDSTRING,
     469                 :            :         POST_EXPR,
     470                 :            : } state_t;
     471                 :            : 
     472                 :            : int
     473                 :         18 : format_sql_condition(const char *str, xstring *sqlcond, bool for_remote)
     474                 :            : {
     475                 :         18 :         state_t state = NONE;
     476                 :         18 :         unsigned int bracket_level = 0;
     477                 :            :         const char *sqlop;
     478                 :         18 :         bool collate_nocase = false;
     479                 :            : 
     480                 :         18 :         fprintf(sqlcond->fp, " WHERE ");
     481         [ +  + ]:        126 :         while (str[0] != '\0') {
     482         [ +  + ]:        108 :                 if (state == NONE) {
     483         [ +  + ]:         22 :                         if (str[0] == '%') {
     484                 :         20 :                                 str++;
     485   [ +  -  -  -  :         20 :                                 switch (str[0]) {
          -  -  -  -  -  
          +  -  -  -  -  
                +  -  - ]
     486                 :            :                                 case 'n':
     487                 :          5 :                                         fprintf(sqlcond->fp, "p.name");
     488                 :          5 :                                         state = OPERATOR_STRING;
     489                 :          5 :                                         break;
     490                 :            :                                 case 'o':
     491                 :          0 :                                         fprintf(sqlcond->fp, "origin");
     492                 :          0 :                                         state = OPERATOR_STRING;
     493                 :          0 :                                         break;
     494                 :            :                                 case 'p':
     495                 :          0 :                                         fprintf(sqlcond->fp, "prefix");
     496                 :          0 :                                         state = OPERATOR_STRING;
     497                 :          0 :                                         break;
     498                 :            :                                 case 'm':
     499                 :          0 :                                         fprintf(sqlcond->fp, "maintainer");
     500                 :          0 :                                         state = OPERATOR_STRING;
     501                 :          0 :                                         break;
     502                 :            :                                 case 'c':
     503                 :          0 :                                         fprintf(sqlcond->fp, "comment");
     504                 :          0 :                                         state = OPERATOR_STRING;
     505                 :          0 :                                         break;
     506                 :            :                                 case 'w':
     507                 :          0 :                                         fprintf(sqlcond->fp, "www");
     508                 :          0 :                                         state = OPERATOR_STRING;
     509                 :          0 :                                         break;
     510                 :            :                                 case 's':
     511                 :          0 :                                         fprintf(sqlcond->fp, "flatsize");
     512                 :          0 :                                         state = OPERATOR_INT;
     513                 :          0 :                                         break;
     514                 :            :                                 case 'a':
     515         [ +  - ]:          1 :                                         if (for_remote)
     516                 :          0 :                                                 goto bad_option;
     517                 :          1 :                                         fprintf(sqlcond->fp, "automatic");
     518                 :          1 :                                         state = OPERATOR_INT;
     519                 :          1 :                                         break;
     520                 :            :                                 case 'q':
     521                 :          0 :                                         fprintf(sqlcond->fp, "arch");
     522                 :          0 :                                         state = OPERATOR_STRING;
     523                 :          0 :                                         break;
     524                 :            :                                 case 'k':
     525         [ #  # ]:          0 :                                         if (for_remote)
     526                 :          0 :                                                 goto bad_option;
     527                 :          0 :                                         fprintf(sqlcond->fp, "locked");
     528                 :          0 :                                         state = OPERATOR_INT;
     529                 :          0 :                                         break;
     530                 :            :                                 case 'M':
     531         [ #  # ]:          0 :                                         if (for_remote)
     532                 :          0 :                                                 goto bad_option;
     533                 :          0 :                                         fprintf(sqlcond->fp, "message");
     534                 :          0 :                                         state = OPERATOR_STRING;
     535                 :          0 :                                         break;
     536                 :            :                                 case 't':
     537         [ #  # ]:          0 :                                         if (for_remote)
     538                 :          0 :                                                 goto bad_option;
     539                 :          0 :                                         fprintf(sqlcond->fp, "time");
     540                 :          0 :                                         state = OPERATOR_INT;
     541                 :          0 :                                         break;
     542                 :            :                                 case 'e':
     543                 :          0 :                                         fprintf(sqlcond->fp, "desc");
     544                 :          0 :                                         state = OPERATOR_STRING;
     545                 :          0 :                                         break;
     546                 :            :                                 case 'V':
     547         [ #  # ]:          0 :                                         if (for_remote)
     548                 :          0 :                                                 goto bad_option;
     549                 :          0 :                                         fprintf(sqlcond->fp, "vital");
     550                 :          0 :                                         state = OPERATOR_INT;
     551                 :         14 :                                         break;
     552                 :            :                                 case '#': /* FALLTHROUGH */
     553                 :            :                                 case '?':
     554                 :         14 :                                         sqlop = (str[0] == '#' ? "COUNT(*)" : "COUNT(*) > 0");
     555                 :         14 :                                         str++;
     556   [ +  +  -  +  :         14 :                                         switch (str[0]) {
          -  -  -  -  +  
             -  -  -  - ]
     557                 :            :                                                 case 'd':
     558                 :          3 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM deps AS d WHERE d.package_id=p.id)", sqlop);
     559                 :          3 :                                                         break;
     560                 :            :                                                 case 'r':
     561                 :          7 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM deps AS d WHERE d.name=p.name)", sqlop);
     562                 :          7 :                                                         break;
     563                 :            :                                                 case 'C':
     564                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_categories AS d WHERE d.package_id=p.id)", sqlop);
     565                 :          0 :                                                         break;
     566                 :            :                                                 case 'F':
     567         [ #  # ]:          0 :                                                         if (for_remote)
     568                 :          0 :                                                                 goto bad_option;
     569                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM files AS d WHERE d.package_id=p.id)", sqlop);
     570                 :          0 :                                                         break;
     571                 :            :                                                 case 'O':
     572                 :          3 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_option AS d WHERE d.package_id=p.id)", sqlop);
     573                 :          3 :                                                         break;
     574                 :            :                                                 case 'D':
     575         [ -  + ]:          1 :                                                         if (for_remote)
     576                 :          0 :                                                                 goto bad_option;
     577                 :          1 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_directories AS d WHERE d.package_id=p.id)", sqlop);
     578                 :          1 :                                                         break;
     579                 :            :                                                 case 'L':
     580                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_licenses AS d WHERE d.package_id=p.id)", sqlop);
     581                 :          0 :                                                         break;
     582                 :            :                                                 case 'U':
     583         [ #  # ]:          0 :                                                         if (for_remote)
     584                 :          0 :                                                                 goto bad_option;
     585                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_users AS d WHERE d.package_id=p.id)", sqlop);
     586                 :          0 :                                                         break;
     587                 :            :                                                 case 'G':
     588         [ #  # ]:          0 :                                                         if (for_remote)
     589                 :          0 :                                                                 goto bad_option;
     590                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_groups AS d WHERE d.package_id=p.id)", sqlop);
     591                 :          0 :                                                         break;
     592                 :            :                                                 case 'B':
     593                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_shlibs_required AS d WHERE d.package_id=p.id)", sqlop);
     594                 :          0 :                                                         break;
     595                 :            :                                                 case 'b':
     596                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_shlibs_provided AS d WHERE d.package_id=p.id)", sqlop);
     597                 :          0 :                                                         break;
     598                 :            :                                                 case 'A':
     599                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_annotation AS d WHERE d.package_id=p.id)", sqlop);
     600                 :          0 :                                                         break;
     601                 :            :                                                 default:
     602                 :          0 :                                                         goto bad_option;
     603                 :            :                                         }
     604                 :         14 :                                         state = OPERATOR_INT;
     605                 :         14 :                                         break;
     606                 :            :                                 default:
     607                 :            : bad_option:
     608                 :          0 :                                         fprintf(stderr, "malformed evaluation string\n");
     609                 :          0 :                                         return (EPKG_FATAL);
     610                 :            :                                 }
     611                 :         20 :                         } else {
     612   [ -  +  -  - ]:          2 :                                 switch (str[0]) {
     613                 :            :                                 case '(':
     614                 :          0 :                                         bracket_level++;
     615                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     616                 :          2 :                                         break;
     617                 :            :                                 case ' ':
     618                 :            :                                 case '\t':
     619                 :          2 :                                         break;
     620                 :            :                                 default:
     621                 :          0 :                                         fprintf(stderr, "unexpected character: %c\n", str[0]);
     622                 :          0 :                                         return (EPKG_FATAL);
     623                 :            :                                 }
     624                 :            :                         }
     625         [ +  + ]:        108 :                 } else if (state == POST_EXPR) {
     626   [ +  -  -  -  :          4 :                         switch (str[0]) {
                   -  + ]
     627                 :            :                         case ')':
     628         [ #  # ]:          0 :                                 if (bracket_level == 0) {
     629                 :          0 :                                         fprintf(stderr, "too many closing brackets.\n");
     630                 :          0 :                                         return (EPKG_FATAL);
     631                 :            :                                 }
     632                 :          0 :                                 bracket_level--;
     633                 :          0 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     634                 :          2 :                                 break;
     635                 :            :                         case ' ':
     636                 :            :                         case '\t':
     637                 :          2 :                                 break;
     638                 :            :                         case '|':
     639         [ #  # ]:          0 :                                 if (str[1] == '|') {
     640                 :          0 :                                         str++;
     641                 :          0 :                                         state = NONE;
     642                 :          0 :                                         fprintf(sqlcond->fp, " OR ");
     643                 :          0 :                                         break;
     644                 :            :                                 } else {
     645                 :          0 :                                         fprintf(stderr, "unexpected character %c\n", str[1]);
     646                 :          0 :                                         return (EPKG_FATAL);
     647                 :            :                                 }
     648                 :            :                         case '&':
     649         [ +  - ]:          2 :                                 if (str[1] == '&') {
     650                 :          2 :                                         str++;
     651                 :          2 :                                         state = NONE;
     652                 :          2 :                                         fprintf(sqlcond->fp, " AND ");
     653                 :          2 :                                         break;
     654                 :            :                                 } else {
     655                 :          0 :                                         fprintf(stderr, "unexpected character %c\n", str[1]);
     656                 :          0 :                                         return (EPKG_FATAL);
     657                 :            :                                 }
     658                 :            :                         default:
     659                 :          0 :                                 fprintf(stderr, "unexpected character %c\n", str[0]);
     660                 :          0 :                                 return (EPKG_FATAL);
     661                 :            :                         }
     662   [ +  +  +  + ]:         86 :                 } else if (state == OPERATOR_STRING || state == OPERATOR_INT) {
     663                 :            :                         /* only operators or space are allowed here */
     664         [ +  + ]:         30 :                         if (isspace(str[0])) {
     665                 :            :                                 /* do nothing */
     666         [ -  + ]:         30 :                         } else if (str[0] == '~' ) {
     667         [ #  # ]:          0 :                                 if (state != OPERATOR_STRING) {
     668                 :          0 :                                         fprintf(stderr, "~ expected only for string testing\n");
     669                 :          0 :                                         return (EPKG_FATAL);
     670                 :            :                                 }
     671                 :          0 :                                 state = NEXT_IS_STRING;
     672                 :          0 :                                 fprintf(sqlcond->fp, " GLOB ");
     673   [ +  +  -  + ]:         20 :                         } else if (str[0] == '>' || str[0] == '<') {
     674         [ +  - ]:         13 :                                 if (state != OPERATOR_INT) {
     675                 :          0 :                                         fprintf(stderr, "> expected only for integers\n");
     676                 :          0 :                                         return (EPKG_FATAL);
     677                 :            :                                 }
     678                 :         13 :                                 state = NEXT_IS_INT;
     679                 :         13 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     680         [ +  - ]:         13 :                                 if (str[1] == '=') {
     681                 :          0 :                                         str++;
     682                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     683                 :          0 :                                 }
     684         [ +  + ]:         20 :                         } else if (str[0] == '=') {
     685         [ +  + ]:          5 :                                 if (state == OPERATOR_STRING) {
     686                 :          3 :                                         state = NEXT_IS_STRING;
     687                 :          3 :                                 } else {
     688                 :          2 :                                         state = NEXT_IS_INT;
     689                 :            :                                 }
     690                 :          5 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     691         [ +  - ]:          5 :                                 if (str[1] == '=') {
     692                 :          5 :                                         str++;
     693   [ #  #  #  # ]:          5 :                                 } else if (str[1] == '~' && state == NEXT_IS_STRING) {
     694                 :          0 :                                         str++;
     695                 :          0 :                                         collate_nocase = true;
     696                 :          0 :                                 }
     697         [ -  + ]:          7 :                         } else if (str[0] == '!') {
     698         [ +  - ]:          2 :                                 if (str[1] == '=') {
     699                 :          2 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     700                 :          2 :                                         fprintf(sqlcond->fp, "%c", str[1]);
     701         [ #  # ]:          2 :                                 } else if (str[1] == '~') {
     702                 :          0 :                                         fprintf(sqlcond->fp, " NOT GLOB ");
     703                 :          0 :                                 } else {
     704                 :          0 :                                         fprintf(stderr, "expecting = or ~ after !\n");
     705                 :          0 :                                         return (EPKG_FATAL);
     706                 :            :                                 }
     707                 :          2 :                                 str++;
     708         [ +  - ]:          2 :                                 if (state == OPERATOR_STRING) {
     709                 :          2 :                                         state = NEXT_IS_STRING;
     710                 :          2 :                                 } else {
     711                 :          0 :                                         state = NEXT_IS_INT;
     712                 :            :                                 }
     713   [ -  +  #  # ]:          2 :                                 if (str[0] == '~' && state == NEXT_IS_STRING) {
     714                 :          0 :                                         str++;
     715                 :          0 :                                         collate_nocase = true;
     716                 :          0 :                                 }
     717                 :          2 :                         } else {
     718                 :          0 :                                 fprintf(stderr, "an operator is expected, got %c\n", str[0]);
     719                 :          0 :                                 return (EPKG_FATAL);
     720                 :            :                         }
     721   [ +  +  +  + ]:         82 :                 } else if (state == NEXT_IS_STRING || state == NEXT_IS_INT) {
     722         [ +  + ]:         30 :                         if (isspace(str[0])) {
     723                 :            :                                 /* do nothing */
     724                 :         10 :                         } else {
     725         [ +  + ]:         20 :                                 if (state == NEXT_IS_STRING) {
     726         [ -  + ]:          5 :                                         if (str[0] == '"') {
     727                 :          0 :                                                 state = QUOTEDSTRING;
     728         [ -  + ]:          5 :                                         } else if (str[0] == '\'') {
     729                 :          0 :                                                 state = SQUOTEDSTRING;
     730                 :          0 :                                         } else {
     731                 :          5 :                                                 state = STRING;
     732                 :          5 :                                                 str--;
     733                 :            :                                         }
     734                 :          5 :                                         fprintf(sqlcond->fp, "%c", '\'');
     735                 :          5 :                                 } else {
     736         [ +  - ]:         15 :                                         if (!isdigit(str[0])) {
     737                 :          0 :                                                 fprintf(stderr, "a number is expected, got: %c\n", str[0]);
     738                 :          0 :                                                 return (EPKG_FATAL);
     739                 :            :                                         }
     740                 :         15 :                                         state = INT;
     741                 :         15 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     742                 :            :                                 }
     743                 :            :                         }
     744         [ +  + ]:         52 :                 } else if (state == INT) {
     745         [ -  + ]:          2 :                         if (!isdigit(str[0])) {
     746                 :          2 :                                 state = POST_EXPR;
     747                 :          2 :                                 str--;
     748                 :          2 :                         } else {
     749                 :          0 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     750                 :            :                         }
     751   [ -  +  #  #  :         22 :                 } else if (state == STRING || state == QUOTEDSTRING || state == SQUOTEDSTRING) {
                   #  # ]
     752   [ +  -  +  -  :         20 :                         if ((state == STRING && isspace(str[0])) ||
                   #  # ]
     753   [ -  +  #  # ]:         20 :                             (state == QUOTEDSTRING && str[0] == '"') ||
     754         [ -  + ]:         20 :                             (state == SQUOTEDSTRING && str[0] == '\'')) {
     755                 :          0 :                                 fprintf(sqlcond->fp, "%c", '\'');
     756                 :          0 :                                 state = POST_EXPR;
     757         [ #  # ]:          0 :                                 if (collate_nocase) {
     758                 :          0 :                                         fprintf(sqlcond->fp, " COLLATE NOCASE ");
     759                 :          0 :                                         collate_nocase = false;
     760                 :          0 :                                 }
     761                 :          0 :                         } else {
     762                 :         20 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     763         [ -  + ]:         20 :                                 if (str[0] == '\'')
     764                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     765   [ -  +  #  # ]:         20 :                                 else if (str[0] == '%' && for_remote)
     766                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     767                 :            :                         }
     768                 :         20 :                 }
     769                 :        108 :                 str++;
     770                 :            :         }
     771         [ +  + ]:         18 :         if (state == STRING) {
     772                 :          5 :                 fprintf(sqlcond->fp, "%c", '\'');
     773                 :          5 :                 state = POST_EXPR;
     774         [ +  - ]:          5 :                 if (collate_nocase) {
     775                 :          0 :                         fprintf(sqlcond->fp, " COLLATE NOCASE ");
     776                 :          0 :                         collate_nocase = false;
     777                 :          0 :                 }
     778                 :          5 :         }
     779                 :            : 
     780   [ +  +  +  - ]:         18 :         if (state != POST_EXPR && state != INT) {
     781                 :          0 :                 fprintf(stderr, "unexpected end of expression\n");
     782                 :          0 :                 return (EPKG_FATAL);
     783         [ -  + ]:         18 :         } else if (bracket_level > 0) {
     784                 :          0 :                 fprintf(stderr, "unexpected end of expression (too many open brackets)\n");
     785                 :          0 :                 return (EPKG_FATAL);
     786                 :            :         }
     787                 :            : 
     788                 :         18 :         return (EPKG_OK);
     789                 :         18 : }
     790                 :            : 
     791                 :            : int
     792                 :         49 : analyse_query_string(char *qstr, struct query_flags *q_flags, const unsigned int q_flags_len, int *flags, char *multiline)
     793                 :            : {
     794                 :            :         unsigned int i, j, k;
     795                 :         49 :         unsigned int valid_flag = 0;
     796                 :         49 :         unsigned int valid_opts = 0;
     797                 :            :         size_t len;
     798                 :            : 
     799                 :         49 :         j = 0; /* shut up scanbuild */
     800                 :            : 
     801         [ +  - ]:         49 :         if (strchr(qstr, '%') == NULL) {
     802                 :          0 :                 fprintf(stderr, "Invalid query: query should contain a format string\n");
     803                 :          0 :                 return (EPKG_FATAL);
     804                 :            :         }
     805                 :            : 
     806         [ +  + ]:        162 :         while (qstr[0] != '\0') {
     807         [ +  + ]:        113 :                 if (qstr[0] == '%') {
     808                 :         77 :                         qstr++;
     809                 :         77 :                         valid_flag = 0;
     810                 :            : 
     811         [ -  + ]:        994 :                         for (i = 0; i < q_flags_len; i++) {
     812                 :            :                                 /* found the flag */
     813         [ +  + ]:        994 :                                 if (qstr[0] == q_flags[i].flag) {
     814                 :         77 :                                         valid_flag = 1;
     815                 :            : 
     816                 :            :                                         /* if the flag is followed by additional options */
     817         [ +  + ]:         77 :                                         if (q_flags[i].options[0] != '\0') {
     818                 :         31 :                                                 qstr++;
     819                 :         31 :                                                 valid_opts = 0;
     820                 :            : 
     821                 :         31 :                                                 len = strlen(q_flags[i].options);
     822         [ -  + ]:         69 :                                                 for (j = 0; j < len; j++) {
     823         [ +  + ]:         69 :                                                         if (qstr[0] == q_flags[i].options[j]) {
     824                 :         31 :                                                                 valid_opts = 1;
     825                 :         31 :                                                                 break;
     826                 :            :                                                         }
     827                 :         38 :                                                 }
     828                 :            : 
     829         [ +  - ]:         31 :                                                 if (valid_opts == 0) {
     830                 :          0 :                                                         fprintf(stderr, "Invalid query: '%%%c' should be followed by:", q_flags[i].flag);
     831                 :            : 
     832                 :          0 :                                                         len = strlen(q_flags[i].options);
     833         [ #  # ]:          0 :                                                         for (j = 0; j < len; j++)
     834                 :          0 :                                                                 fprintf(stderr, " %c%c", q_flags[i].options[j],
     835                 :          0 :                                                                                 q_flags[i].options[j + 1] == '\0' ?
     836                 :            :                                                                                 '\n' : ',');
     837                 :            : 
     838                 :          0 :                                                         return (EPKG_FATAL);
     839                 :            :                                                 }
     840                 :         31 :                                         }
     841                 :            : 
     842                 :            :                                         /* if this is a multiline flag */
     843         [ +  + ]:         77 :                                         if (q_flags[i].multiline == 1) {
     844   [ +  +  -  + ]:         31 :                                                 if (*multiline != 0 && *multiline != q_flags[i].flag) {
     845                 :          0 :                                                         fprintf(stderr, "Invalid query: '%%%c' and '%%%c' cannot be queried at the same time\n",
     846                 :          0 :                                                                         *multiline, q_flags[i].flag);
     847                 :          0 :                                                         return (EPKG_FATAL);
     848                 :            :                                                 } else {
     849                 :         31 :                                                         *multiline = q_flags[i].flag;
     850                 :            :                                                 }
     851                 :         31 :                                         }
     852                 :            : 
     853                 :            :                                         /* handle the '?' flag cases */
     854   [ +  +  +  + ]:         77 :                                         if (q_flags[i].flag == '?' || q_flags[i].flag == '#') {
     855         [ -  + ]:         18 :                                                 for (k = 0; k < q_flags_len; k++)
     856         [ +  + ]:         18 :                                                         if (q_flags[k].flag == q_flags[i].options[j]) {
     857                 :          4 :                                                                 *flags |= q_flags[k].dbflags;
     858                 :          4 :                                                                 break;
     859                 :            :                                                         }
     860                 :          4 :                                         } else {
     861                 :         73 :                                                 *flags |= q_flags[i].dbflags;
     862                 :            :                                         }
     863                 :            : 
     864                 :         77 :                                         break; /* don't iterate over the rest of the flags */
     865                 :            :                                 }
     866                 :        917 :                         }
     867                 :            : 
     868         [ +  - ]:         77 :                         if (valid_flag == 0) {
     869                 :          0 :                                 fprintf(stderr, "Unknown query format key: '%%%c'\n", qstr[0]);
     870                 :          0 :                                 return (EPKG_FATAL);
     871                 :            :                         }
     872                 :         77 :                 }
     873                 :            : 
     874                 :        113 :                 qstr++;
     875                 :            :         }
     876                 :            : 
     877                 :         49 :         return (EPKG_OK);
     878                 :         49 : }
     879                 :            : 
     880                 :            : void
     881                 :          0 : usage_query(void)
     882                 :            : {
     883                 :          0 :         fprintf(stderr, "Usage: pkg query <query-format> <pkg-name>\n");
     884                 :          0 :         fprintf(stderr, "       pkg query [-a] <query-format>\n");
     885                 :          0 :         fprintf(stderr, "       pkg query -F <pkg-name> <query-format>\n");
     886                 :          0 :         fprintf(stderr, "       pkg query -e <evaluation> <query-format>\n");
     887                 :          0 :         fprintf(stderr, "       pkg query [-Cgix] <query-format> <pattern> <...>\n\n");
     888                 :          0 :         fprintf(stderr, "For more information see 'pkg help query.'\n");
     889                 :          0 : }
     890                 :            : 
     891                 :            : int
     892                 :         37 : exec_query(int argc, char **argv)
     893                 :            : {
     894                 :         37 :         struct pkgdb            *db = NULL;
     895                 :         37 :         struct pkgdb_it         *it = NULL;
     896                 :         37 :         struct pkg              *pkg = NULL;
     897                 :         37 :         char                    *pkgname = NULL;
     898                 :         37 :         int                      query_flags = PKG_LOAD_BASIC;
     899                 :         37 :         match_t                  match = MATCH_EXACT;
     900                 :            :         int                      ch;
     901                 :            :         int                      ret;
     902                 :         37 :         int                      retcode = EXIT_SUCCESS;
     903                 :            :         int                      i;
     904                 :         37 :         char                     multiline = 0;
     905                 :         37 :         int                      nprinted = 0;
     906                 :         37 :         char                    *condition = NULL;
     907                 :         37 :         const char              *condition_sql = NULL;
     908                 :         37 :         xstring                 *sqlcond = NULL;
     909                 :         37 :         const unsigned int       q_flags_len = NELEM(accepted_query_flags);
     910                 :            : 
     911                 :         37 :         struct option longopts[] = {
     912                 :            :                 { "all",              no_argument,            NULL,   'a' },
     913                 :            :                 { "case-sensitive",   no_argument,            NULL,   'C' },
     914                 :            :                 { "evaluate",         required_argument,      NULL,   'e' },
     915                 :            :                 { "file",             required_argument,      NULL,   'F' },
     916                 :            :                 { "glob",             no_argument,            NULL,   'g' },
     917                 :            :                 { "case-insensitive", no_argument,            NULL,   'i' },
     918                 :            :                 { "regex",            no_argument,            NULL,   'x' },
     919                 :            :                 { NULL,                 0,                      NULL,   0   },
     920                 :            :         };
     921                 :            : 
     922         [ +  + ]:         60 :         while ((ch = getopt_long(argc, argv, "+aCe:F:gix", longopts, NULL)) != -1) {
     923   [ -  +  +  +  :         23 :                 switch (ch) {
             -  -  +  - ]
     924                 :            :                 case 'a':
     925                 :          0 :                         match = MATCH_ALL;
     926                 :          0 :                         break;
     927                 :            :                 case 'C':
     928                 :          0 :                         pkgdb_set_case_sensitivity(true);
     929                 :          0 :                         break;
     930                 :            :                 case 'e':
     931                 :         13 :                         condition = optarg;
     932                 :         13 :                         break;
     933                 :            :                 case 'F':
     934                 :          8 :                         pkgname = optarg;
     935                 :          8 :                         break;
     936                 :            :                 case 'g':
     937                 :          1 :                         match = MATCH_GLOB;
     938                 :          1 :                         break;
     939                 :            :                 case 'i':
     940                 :          0 :                         pkgdb_set_case_sensitivity(false);
     941                 :          0 :                         break;
     942                 :            :                 case 'x':
     943                 :          1 :                         match = MATCH_REGEX;
     944                 :          1 :                         break;
     945                 :            :                 default:
     946                 :          0 :                         usage_query();
     947                 :          0 :                         return (EXIT_FAILURE);
     948                 :            :                 }
     949                 :            :         }
     950                 :            : 
     951                 :         37 :         argc -= optind;
     952                 :         37 :         argv += optind;
     953                 :            : 
     954   [ +  -  +  - ]:         37 :         if ((match == MATCH_ALL || pkgname != NULL)
     955         [ +  + ]:         37 :             && argc > 1) {
     956                 :          0 :                 usage_query();
     957                 :          0 :                 retcode = EXIT_FAILURE;
     958                 :          0 :                 goto cleanup;
     959                 :            :         }
     960                 :            : 
     961         [ +  - ]:         37 :         if (argc == 0) {
     962                 :          0 :                 usage_query();
     963                 :          0 :                 retcode = EXIT_FAILURE;
     964                 :          0 :                 goto cleanup;
     965                 :            :         }
     966                 :            : 
     967                 :            :         /* Default to all packages if no pkg provided */
     968   [ +  +  +  +  :         37 :         if (argc == 1 && pkgname == NULL && match == MATCH_EXACT) {
                   -  + ]
     969                 :         10 :                 match = MATCH_ALL;
     970   [ +  +  #  # ]:         37 :         } else if (((argc == 1) ^ (match == MATCH_ALL)) && pkgname == NULL
     971         [ -  + ]:          8 :                         && condition == NULL) {
     972                 :          0 :                 usage_query();
     973                 :          0 :                 retcode = EXIT_FAILURE;
     974                 :          0 :                 goto cleanup;
     975                 :            :         }
     976                 :            : 
     977   [ -  +  -  + ]:         74 :         if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len,
     978                 :         37 :                         &query_flags, &multiline) != EPKG_OK) {
     979                 :          0 :                 retcode = EXIT_FAILURE;
     980                 :          0 :                 goto cleanup;
     981                 :            :         }
     982                 :            : 
     983         [ +  + ]:         37 :         if (pkgname != NULL) {
     984                 :            :                 /* Use a manifest or compact manifest if possible. */
     985                 :          8 :                 int open_flags = 0;
     986   [ +  +  +  + ]:         16 :                 if ((query_flags & ~(PKG_LOAD_DEPS|
     987                 :            :                                      PKG_LOAD_OPTIONS|
     988                 :            :                                      PKG_LOAD_CATEGORIES|
     989                 :            :                                      PKG_LOAD_LICENSES|
     990                 :            :                                      PKG_LOAD_USERS|
     991                 :            :                                      PKG_LOAD_GROUPS|
     992                 :            :                                      PKG_LOAD_SHLIBS_REQUIRED|
     993                 :            :                                      PKG_LOAD_SHLIBS_PROVIDED|
     994                 :            :                                      PKG_LOAD_ANNOTATIONS|
     995                 :            :                                      PKG_LOAD_CONFLICTS|
     996                 :            :                                      PKG_LOAD_PROVIDES|
     997                 :          8 :                                      PKG_LOAD_REQUIRES)) == 0) {
     998                 :          3 :                         open_flags = PKG_OPEN_MANIFEST_COMPACT;
     999         [ +  + ]:          8 :                 } else if ((query_flags & PKG_LOAD_FILES) == 0) {
    1000                 :          2 :                         open_flags = PKG_OPEN_MANIFEST_ONLY;
    1001                 :          2 :                 }
    1002         [ -  + ]:          8 :                 if (pkg_open(&pkg, pkgname, open_flags) != EPKG_OK) {
    1003                 :          0 :                         retcode = EXIT_FAILURE;
    1004                 :          0 :                         goto cleanup;
    1005                 :            :                 }
    1006                 :            : 
    1007                 :          8 :                 print_query(pkg, argv[0], multiline);
    1008                 :          8 :                 retcode = EXIT_SUCCESS;
    1009                 :          8 :                 goto cleanup;
    1010                 :            :         }
    1011                 :            : 
    1012         [ +  + ]:         29 :         if (condition != NULL) {
    1013                 :         13 :                 sqlcond = xstring_new();
    1014         [ -  + ]:         13 :                 if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) {
    1015                 :          0 :                         retcode = EXIT_FAILURE;
    1016                 :          0 :                         goto cleanup;
    1017                 :            :                 }
    1018                 :         13 :         }
    1019                 :            : 
    1020                 :         29 :         ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
    1021         [ -  + ]:         29 :         if (ret == EPKG_ENOACCESS) {
    1022                 :          0 :                 warnx("Insufficient privileges to query the package database");
    1023                 :          0 :                 retcode = EXIT_FAILURE;
    1024                 :          0 :                 goto cleanup;
    1025         [ -  + ]:         29 :         } else if (ret == EPKG_ENODB) {
    1026         [ #  # ]:          0 :                 if (!quiet)
    1027                 :          0 :                         warnx("No packages installed");
    1028                 :          0 :                 retcode = EXIT_SUCCESS;
    1029                 :          0 :                 goto cleanup;
    1030         [ -  + ]:         29 :         } else if (ret != EPKG_OK) {
    1031                 :          0 :                 retcode = EXIT_FAILURE;
    1032                 :          0 :                 goto cleanup;
    1033                 :            :         }
    1034                 :            : 
    1035                 :         29 :         ret = pkgdb_open(&db, PKGDB_DEFAULT);
    1036         [ -  + ]:         29 :         if (ret != EPKG_OK) {
    1037                 :          0 :                 retcode = EXIT_FAILURE;
    1038                 :          0 :                 goto cleanup;
    1039                 :            :         }
    1040                 :            : 
    1041                 :         29 :         pkg_drop_privileges();
    1042         [ -  + ]:         29 :         if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
    1043                 :          0 :                 warnx("Cannot get a read lock on a database, it is locked by another process");
    1044                 :          0 :                 retcode = EXIT_FAILURE;
    1045                 :          0 :                 goto cleanup;
    1046                 :            :         }
    1047                 :            : 
    1048         [ +  + ]:         29 :         if (sqlcond) {
    1049                 :         13 :                 fflush(sqlcond->fp);
    1050                 :         13 :                 condition_sql = sqlcond->buf;
    1051                 :         13 :         }
    1052                 :         29 :         i = 1;
    1053                 :         33 :         do {
    1054         [ +  + ]:         33 :                 pkgname = i < argc ? argv[i] : NULL;
    1055                 :            : 
    1056         [ +  - ]:         33 :                 if ((it = pkgdb_query_cond(db, condition_sql, pkgname, match)) == NULL) {
    1057   [ #  #  #  # ]:          0 :                         warnx("DEBUG: %s/%s\n", condition_sql ? condition_sql : "-", pkgname ? pkgname : "-");
    1058                 :          0 :                         retcode = EXIT_FAILURE;
    1059                 :          0 :                         break;
    1060                 :            :                 }
    1061                 :            : 
    1062         [ +  + ]:         58 :                 while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
    1063                 :         25 :                         nprinted++;
    1064                 :         25 :                         print_query(pkg, argv[0], multiline);
    1065                 :            :                 }
    1066                 :            : 
    1067         [ -  + ]:         33 :                 if (ret != EPKG_END) {
    1068                 :          0 :                         retcode = EXIT_FAILURE;
    1069                 :          0 :                         break;
    1070                 :            :                 }
    1071                 :            : 
    1072                 :         33 :                 pkgdb_it_free(it);
    1073                 :         33 :                 i++;
    1074         [ +  + ]:         33 :         } while (i < argc);
    1075                 :            : 
    1076   [ +  +  +  +  :         30 :         if (nprinted == 0 && match != MATCH_ALL && retcode == EXIT_SUCCESS) {
                   +  - ]
    1077                 :            :                 /* ensure to return a non-zero status when no package
    1078                 :            :                  were found. */
    1079                 :          1 :                 retcode = EXIT_FAILURE;
    1080                 :          1 :         }
    1081                 :            : 
    1082                 :            : cleanup:
    1083                 :         37 :         xstring_free(sqlcond);
    1084                 :            : 
    1085                 :         37 :         pkg_free(pkg);
    1086                 :            : 
    1087                 :         37 :         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
    1088                 :         37 :         pkgdb_close(db);
    1089                 :            : 
    1090                 :         37 :         return (retcode);
    1091                 :         37 : }

Generated by: LCOV version 1.15