LCOV - code coverage report
Current view: top level - src - query.c (source / functions) Hit Total Coverage
Test: rapport Lines: 311 654 47.6 %
Date: 2021-12-10 16:22:55 Functions: 5 6 83.3 %
Branches: 185 405 45.7 %

           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                 :        178 : format_str(struct pkg *pkg, xstring *dest, const char *qstr, const void *data)
      82                 :            : {
      83                 :            :         bool automatic;
      84                 :            :         bool locked;
      85                 :            :         bool vital;
      86                 :            : 
      87                 :        178 :         xstring_reset(dest);
      88                 :            : 
      89         [ +  + ]:        576 :         while (qstr[0] != '\0') {
      90         [ +  + ]:        398 :                 if (qstr[0] == '%') {
      91                 :        274 :                         qstr++;
      92   [ -  +  +  -  :        274 :                         switch (qstr[0]) {
          -  -  -  +  -  
          +  -  -  -  -  
          +  +  -  -  -  
          +  +  -  +  -  
          -  -  -  -  -  
          -  -  -  +  +  
                      - ]
      93                 :            :                         case 'n':
      94                 :         72 :                                 pkg_fprintf(dest->fp, "%n", pkg);
      95                 :         72 :                                 break;
      96                 :            :                         case 'v':
      97                 :         12 :                                 pkg_fprintf(dest->fp, "%v", pkg);
      98                 :         12 :                                 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                 :          8 :                                 pkg_fprintf(dest->fp, "%c", pkg);
     113                 :          8 :                                 break;
     114                 :            :                         case 'w':
     115                 :          0 :                                 pkg_fprintf(dest->fp, "%w", pkg);
     116                 :          0 :                                 break;
     117                 :            :                         case 'a':
     118                 :         38 :                                 pkg_get(pkg, PKG_AUTOMATIC, &automatic);
     119                 :         38 :                                 fprintf(dest->fp, "%d", automatic);
     120                 :         38 :                                 break;
     121                 :            :                         case 'k':
     122                 :          0 :                                 pkg_get(pkg, PKG_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                 :          8 :                                 qstr++;
     140   [ -  -  -  -  :          8 :                                 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                 :          4 :                                         pkg_fprintf(dest->fp, "%?F", pkg);
     152                 :          4 :                                         break;
     153                 :            :                                 case 'O':
     154                 :          4 :                                         pkg_fprintf(dest->fp, "%?O", pkg);
     155                 :          4 :                                         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                 :          8 :                                 break;
     179                 :            :                         case '#':
     180                 :          8 :                                 qstr++;
     181   [ -  -  -  -  :          8 :                                 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                 :          4 :                                         pkg_fprintf(dest->fp, "%#F", pkg);
     193                 :          4 :                                         break;
     194                 :            :                                 case 'O':
     195                 :          4 :                                         pkg_fprintf(dest->fp, "%#O", pkg);
     196                 :          4 :                                         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                 :          8 :                                 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                 :         24 :                                 qstr++;
     231         [ +  + ]:         24 :                                 if (qstr[0] == 'n')
     232                 :          8 :                                         pkg_fprintf(dest->fp, "%dn", data);
     233         [ +  + ]:         16 :                                 else if (qstr[0] == 'o')
     234                 :          8 :                                         pkg_fprintf(dest->fp, "%do", data);
     235         [ -  + ]:          8 :                                 else if (qstr[0] == 'v')
     236                 :          8 :                                         pkg_fprintf(dest->fp, "%dv", data);
     237                 :         24 :                                 break;
     238                 :            :                         case 'r':
     239                 :         60 :                                 qstr++;
     240         [ +  + ]:         60 :                                 if (qstr[0] == 'n')
     241                 :         20 :                                         pkg_fprintf(dest->fp, "%rn", data);
     242         [ +  + ]:         40 :                                 else if (qstr[0] == 'o')
     243                 :         20 :                                         pkg_fprintf(dest->fp, "%ro", data);
     244         [ -  + ]:         20 :                                 else if (qstr[0] == 'v')
     245                 :         20 :                                         pkg_fprintf(dest->fp, "%rv", data);
     246                 :         60 :                                 break;
     247                 :            :                         case 'C':
     248                 :          0 :                                 pkg_fprintf(dest->fp, "%Cn", data);
     249                 :          0 :                                 break;
     250                 :            :                         case 'F':
     251                 :         20 :                                 qstr++;
     252         [ +  - ]:         20 :                                 if (qstr[0] == 'p')
     253                 :         20 :                                         pkg_fprintf(dest->fp, "%Fn", data);
     254         [ #  # ]:          0 :                                 else if (qstr[0] == 's')
     255                 :          0 :                                         pkg_fprintf(dest->fp, "%Fs", data);
     256                 :         20 :                                 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                 :         16 :                                 pkg_get(pkg, PKG_VITAL, &vital);
     299                 :         16 :                                 fprintf(dest->fp, "%d", vital);
     300                 :         16 :                                 break;
     301                 :            :                         case 'X':
     302                 :          8 :                                 pkg_fprintf(dest->fp, "%X", pkg);
     303                 :          8 :                                 break;
     304                 :            :                         case '%':
     305                 :          0 :                                 fprintf(dest->fp, "%c", '%');
     306                 :          0 :                                 break;
     307                 :            :                         }
     308         [ -  + ]:        398 :                 } 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                 :        124 :                         fprintf(dest->fp, "%c", qstr[0]);
     335                 :            :                 }
     336                 :        398 :                 qstr++;
     337                 :            :         }
     338                 :        178 :         fflush(dest->fp);
     339                 :        178 : }
     340                 :            : 
     341                 :            : void
     342                 :        170 : print_query(struct pkg *pkg, char *qstr, char multiline)
     343                 :            : {
     344                 :            :         xstring                 *output;
     345                 :        170 :         struct pkg_dep          *dep    = NULL;
     346                 :        170 :         struct pkg_option       *option = NULL;
     347                 :        170 :         struct pkg_file         *file   = NULL;
     348                 :        170 :         struct pkg_dir          *dir    = NULL;
     349                 :            :         char                    *buf;
     350                 :            :         struct pkg_kv           *kv;
     351                 :            : 
     352                 :        170 :         output = xstring_new();
     353                 :            : 
     354   [ +  +  +  -  :        170 :         switch (multiline) {
          -  +  -  -  -  
             -  -  -  - ]
     355                 :            :         case 'd':
     356         [ +  + ]:         16 :                 while (pkg_deps(pkg, &dep) == EPKG_OK) {
     357                 :          8 :                         format_str(pkg, output, qstr, dep);
     358                 :          8 :                         printf("%s\n", output->buf);
     359                 :            :                 }
     360                 :          8 :                 break;
     361                 :            :         case 'r':
     362         [ +  + ]:         40 :                 while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
     363                 :         20 :                         format_str(pkg, output, qstr, dep);
     364                 :         20 :                         printf("%s\n", output->buf);
     365                 :            :                 }
     366                 :         20 :                 break;
     367                 :            :         case 'C':
     368                 :          0 :                 buf = NULL;
     369         [ #  # ]:          0 :                 while (pkg_categories(pkg, &buf) == EPKG_OK) {
     370                 :          0 :                         format_str(pkg, output, qstr, buf);
     371                 :          0 :                         printf("%s\n", output->buf);
     372                 :            :                 }
     373                 :          0 :                 break;
     374                 :            :         case 'O':
     375         [ #  # ]:          0 :                 while (pkg_options(pkg, &option) == EPKG_OK) {
     376                 :          0 :                         format_str(pkg, output, qstr, option);
     377                 :          0 :                         printf("%s\n", output->buf);
     378                 :            :                 }
     379                 :          0 :                 break;
     380                 :            :         case 'F':
     381         [ +  + ]:         32 :                 while (pkg_files(pkg, &file) == EPKG_OK) {
     382                 :         20 :                         format_str(pkg, output, qstr, file);
     383                 :         20 :                         printf("%s\n", output->buf);
     384                 :            :                 }
     385                 :         12 :                 break;
     386                 :            :         case 'D':
     387         [ #  # ]:          0 :                 while (pkg_dirs(pkg, &dir) == EPKG_OK) {
     388                 :          0 :                         format_str(pkg, output, qstr, dir);
     389                 :          0 :                         printf("%s\n", output->buf);
     390                 :            :                 }
     391                 :          0 :                 break;
     392                 :            :         case 'L':
     393                 :          0 :                 buf = NULL;
     394         [ #  # ]:          0 :                 while (pkg_licenses(pkg, &buf) == EPKG_OK) {
     395                 :          0 :                         format_str(pkg, output, qstr, buf);
     396                 :          0 :                         printf("%s\n", output->buf);
     397                 :            :                 }
     398                 :          0 :                 break;
     399                 :            :         case 'U':
     400                 :          0 :                 buf = NULL;
     401         [ #  # ]:          0 :                 while (pkg_users(pkg, &buf) == EPKG_OK) {
     402                 :          0 :                         format_str(pkg, output, qstr, buf);
     403                 :          0 :                         printf("%s\n", output->buf);
     404                 :            :                 }
     405                 :          0 :                 break;
     406                 :            :         case 'G':
     407                 :          0 :                 buf = NULL;
     408         [ #  # ]:          0 :                 while (pkg_groups(pkg, &buf) == EPKG_OK) {
     409                 :          0 :                         format_str(pkg, output, qstr, buf);
     410                 :          0 :                         printf("%s\n", output->buf);
     411                 :            :                 }
     412                 :          0 :                 break;
     413                 :            :         case 'B':
     414                 :          0 :                 buf = NULL;
     415         [ #  # ]:          0 :                 while (pkg_shlibs_required(pkg, &buf) == EPKG_OK) {
     416                 :          0 :                         format_str(pkg, output, qstr, buf);
     417                 :          0 :                         printf("%s\n", output->buf);
     418                 :            :                 }
     419                 :          0 :                 break;
     420                 :            :         case 'b':
     421                 :          0 :                 buf = NULL;
     422         [ #  # ]:          0 :                 while (pkg_shlibs_provided(pkg, &buf) == EPKG_OK) {
     423                 :          0 :                         format_str(pkg, output, qstr, buf);
     424                 :          0 :                         printf("%s\n", output->buf);
     425                 :            :                 }
     426                 :          0 :                 break;
     427                 :            :         case 'A':
     428                 :          0 :                 pkg_get(pkg, PKG_ANNOTATIONS, &kv);
     429         [ #  # ]:          0 :                 while (kv != NULL) {
     430                 :          0 :                         format_str(pkg, output, qstr, kv);
     431                 :          0 :                         printf("%s\n", output->buf);
     432                 :          0 :                         kv = kv->next;
     433                 :            :                 }
     434                 :          0 :                 break;
     435                 :            :         default:
     436                 :        130 :                 format_str(pkg, output, qstr, dep);
     437                 :        130 :                 printf("%s\n", output->buf);
     438                 :        130 :                 break;
     439                 :            :         }
     440                 :        170 :         xstring_free(output);
     441                 :        170 : }
     442                 :            : 
     443                 :            : typedef enum {
     444                 :            :         NONE,
     445                 :            :         NEXT_IS_INT,
     446                 :            :         OPERATOR_INT,
     447                 :            :         INT,
     448                 :            :         NEXT_IS_STRING,
     449                 :            :         OPERATOR_STRING,
     450                 :            :         STRING,
     451                 :            :         QUOTEDSTRING,
     452                 :            :         SQUOTEDSTRING,
     453                 :            :         POST_EXPR,
     454                 :            : } state_t;
     455                 :            : 
     456                 :            : int
     457                 :         72 : format_sql_condition(const char *str, xstring *sqlcond, bool for_remote)
     458                 :            : {
     459                 :         72 :         state_t state = NONE;
     460                 :         72 :         unsigned int bracket_level = 0;
     461                 :            :         const char *sqlop;
     462                 :            : 
     463                 :         72 :         fprintf(sqlcond->fp, " WHERE ");
     464         [ +  + ]:        504 :         while (str[0] != '\0') {
     465         [ +  + ]:        432 :                 if (state == NONE) {
     466         [ +  + ]:         88 :                         if (str[0] == '%') {
     467                 :         80 :                                 str++;
     468   [ +  +  -  -  :         80 :                                 switch (str[0]) {
          -  -  -  -  +  
          -  -  -  -  -  
                   -  - ]
     469                 :            :                                 case 'n':
     470                 :         20 :                                         fprintf(sqlcond->fp, "name");
     471                 :         20 :                                         state = OPERATOR_STRING;
     472                 :         20 :                                         break;
     473                 :            :                                 case 'o':
     474                 :          0 :                                         fprintf(sqlcond->fp, "origin");
     475                 :          0 :                                         state = OPERATOR_STRING;
     476                 :          0 :                                         break;
     477                 :            :                                 case 'p':
     478                 :          0 :                                         fprintf(sqlcond->fp, "prefix");
     479                 :          0 :                                         state = OPERATOR_STRING;
     480                 :          0 :                                         break;
     481                 :            :                                 case 'm':
     482                 :          0 :                                         fprintf(sqlcond->fp, "maintainer");
     483                 :          0 :                                         state = OPERATOR_STRING;
     484                 :          0 :                                         break;
     485                 :            :                                 case 'c':
     486                 :          0 :                                         fprintf(sqlcond->fp, "comment");
     487                 :          0 :                                         state = OPERATOR_STRING;
     488                 :          0 :                                         break;
     489                 :            :                                 case 'w':
     490                 :          0 :                                         fprintf(sqlcond->fp, "www");
     491                 :          0 :                                         state = OPERATOR_STRING;
     492                 :          0 :                                         break;
     493                 :            :                                 case 's':
     494                 :          0 :                                         fprintf(sqlcond->fp, "flatsize");
     495                 :          0 :                                         state = OPERATOR_INT;
     496                 :          0 :                                         break;
     497                 :            :                                 case 'a':
     498         [ +  - ]:          4 :                                         if (for_remote)
     499                 :          0 :                                                 goto bad_option;
     500                 :          4 :                                         fprintf(sqlcond->fp, "automatic");
     501                 :          4 :                                         state = OPERATOR_INT;
     502                 :          4 :                                         break;
     503                 :            :                                 case 'q':
     504                 :          0 :                                         fprintf(sqlcond->fp, "arch");
     505                 :          0 :                                         state = OPERATOR_STRING;
     506                 :          0 :                                         break;
     507                 :            :                                 case 'k':
     508         [ #  # ]:          0 :                                         if (for_remote)
     509                 :          0 :                                                 goto bad_option;
     510                 :          0 :                                         fprintf(sqlcond->fp, "locked");
     511                 :          0 :                                         state = OPERATOR_INT;
     512                 :          0 :                                         break;
     513                 :            :                                 case 'M':
     514         [ #  # ]:          0 :                                         if (for_remote)
     515                 :          0 :                                                 goto bad_option;
     516                 :          0 :                                         fprintf(sqlcond->fp, "message");
     517                 :          0 :                                         state = OPERATOR_STRING;
     518                 :          0 :                                         break;
     519                 :            :                                 case 't':
     520         [ #  # ]:          0 :                                         if (for_remote)
     521                 :          0 :                                                 goto bad_option;
     522                 :          0 :                                         fprintf(sqlcond->fp, "time");
     523                 :          0 :                                         state = OPERATOR_INT;
     524                 :          0 :                                         break;
     525                 :            :                                 case 'e':
     526                 :          0 :                                         fprintf(sqlcond->fp, "desc");
     527                 :          0 :                                         state = OPERATOR_STRING;
     528                 :          0 :                                         break;
     529                 :            :                                 case 'V':
     530         [ #  # ]:          0 :                                         if (for_remote)
     531                 :          0 :                                                 goto bad_option;
     532                 :          0 :                                         fprintf(sqlcond->fp, "vital");
     533                 :          0 :                                         state = OPERATOR_INT;
     534                 :          0 :                                         break;
     535                 :            :                                 case '#': /* FALLTHROUGH */
     536                 :            :                                 case '?':
     537                 :         56 :                                         sqlop = (str[0] == '#' ? "COUNT(*)" : "COUNT(*) > 0");
     538                 :         56 :                                         str++;
     539   [ +  +  -  -  :         56 :                                         switch (str[0]) {
          +  +  -  -  -  
             -  -  -  - ]
     540                 :            :                                                 case 'd':
     541                 :         12 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM deps AS d WHERE d.package_id=p.id)", sqlop);
     542                 :         12 :                                                         break;
     543                 :            :                                                 case 'r':
     544                 :         28 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM deps AS d WHERE d.origin=p.origin)", sqlop);
     545                 :         28 :                                                         break;
     546                 :            :                                                 case 'C':
     547                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_categories AS d WHERE d.package_id=p.id)", sqlop);
     548                 :          0 :                                                         break;
     549                 :            :                                                 case 'F':
     550         [ #  # ]:          0 :                                                         if (for_remote)
     551                 :          0 :                                                                 goto bad_option;
     552                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM files AS d WHERE d.package_id=p.id)", sqlop);
     553                 :          0 :                                                         break;
     554                 :            :                                                 case 'O':
     555                 :         12 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_option AS d WHERE d.package_id=p.id)", sqlop);
     556                 :         12 :                                                         break;
     557                 :            :                                                 case 'D':
     558         [ -  + ]:          4 :                                                         if (for_remote)
     559                 :          0 :                                                                 goto bad_option;
     560                 :          4 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_directories AS d WHERE d.package_id=p.id)", sqlop);
     561                 :          4 :                                                         break;
     562                 :            :                                                 case 'L':
     563                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_licenses AS d WHERE d.package_id=p.id)", sqlop);
     564                 :          0 :                                                         break;
     565                 :            :                                                 case 'U':
     566         [ #  # ]:          0 :                                                         if (for_remote)
     567                 :          0 :                                                                 goto bad_option;
     568                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_users AS d WHERE d.package_id=p.id)", sqlop);
     569                 :          0 :                                                         break;
     570                 :            :                                                 case 'G':
     571         [ #  # ]:          0 :                                                         if (for_remote)
     572                 :          0 :                                                                 goto bad_option;
     573                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_groups AS d WHERE d.package_id=p.id)", sqlop);
     574                 :          0 :                                                         break;
     575                 :            :                                                 case 'B':
     576                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_shlibs_required AS d WHERE d.package_id=p.id)", sqlop);
     577                 :          0 :                                                         break;
     578                 :            :                                                 case 'b':
     579                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_shlibs_provided AS d WHERE d.package_id=p.id)", sqlop);
     580                 :          0 :                                                         break;
     581                 :            :                                                 case 'A':
     582                 :          0 :                                                         fprintf(sqlcond->fp, "(SELECT %s FROM pkg_annotation AS d WHERE d.package_id=p.id)", sqlop);
     583                 :          0 :                                                         break;
     584                 :            :                                                 default:
     585                 :          0 :                                                         goto bad_option;
     586                 :            :                                         }
     587                 :         56 :                                         state = OPERATOR_INT;
     588                 :         56 :                                         break;
     589                 :            :                                 default:
     590                 :            : bad_option:
     591                 :          0 :                                         fprintf(stderr, "malformed evaluation string\n");
     592                 :          0 :                                         return (EPKG_FATAL);
     593                 :            :                                 }
     594                 :         80 :                         } else {
     595      [ -  +  - ]:          8 :                                 switch (str[0]) {
     596                 :            :                                 case '(':
     597                 :          0 :                                         bracket_level++;
     598                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     599                 :          0 :                                         break;
     600                 :            :                                 case ' ':
     601                 :            :                                 case '\t':
     602                 :          8 :                                         break;
     603                 :            :                                 default:
     604                 :          0 :                                         fprintf(stderr, "unexpected character: %c\n", str[0]);
     605                 :          0 :                                         return (EPKG_FATAL);
     606                 :            :                                 }
     607                 :            :                         }
     608         [ +  + ]:        432 :                 } else if (state == POST_EXPR) {
     609   [ +  -  -  +  :         16 :                         switch (str[0]) {
                      - ]
     610                 :            :                         case ')':
     611         [ #  # ]:          0 :                                 if (bracket_level == 0) {
     612                 :          0 :                                         fprintf(stderr, "too many closing brackets.\n");
     613                 :          0 :                                         return (EPKG_FATAL);
     614                 :            :                                 }
     615                 :          0 :                                 bracket_level--;
     616                 :          0 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     617                 :          0 :                                 break;
     618                 :            :                         case ' ':
     619                 :            :                         case '\t':
     620                 :          8 :                                 break;
     621                 :            :                         case '|':
     622         [ #  # ]:          0 :                                 if (str[1] == '|') {
     623                 :          0 :                                         str++;
     624                 :          0 :                                         state = NONE;
     625                 :          0 :                                         fprintf(sqlcond->fp, " OR ");
     626                 :          0 :                                         break;
     627                 :            :                                 } else {
     628                 :          0 :                                         fprintf(stderr, "unexpected character %c\n", str[1]);
     629                 :          0 :                                         return (EPKG_FATAL);
     630                 :            :                                 }
     631                 :            :                         case '&':
     632         [ +  - ]:          8 :                                 if (str[1] == '&') {
     633                 :          8 :                                         str++;
     634                 :          8 :                                         state = NONE;
     635                 :          8 :                                         fprintf(sqlcond->fp, " AND ");
     636                 :          8 :                                         break;
     637                 :            :                                 } else {
     638                 :          0 :                                         fprintf(stderr, "unexpected character %c\n", str[1]);
     639                 :          0 :                                         return (EPKG_FATAL);
     640                 :            :                                 }
     641                 :            :                         default:
     642                 :          0 :                                 fprintf(stderr, "unexpected character %c\n", str[0]);
     643                 :          0 :                                 return (EPKG_FATAL);
     644                 :            :                         }
     645   [ +  +  +  + ]:        344 :                 } else if (state == OPERATOR_STRING || state == OPERATOR_INT) {
     646                 :            :                         /* only operators or space are allowed here */
     647         [ +  + ]:        120 :                         if (isspace(str[0])) {
     648                 :            :                                 /* do nothing */
     649         [ -  + ]:        120 :                         } else if (str[0] == '~' ) {
     650         [ #  # ]:          0 :                                 if (state != OPERATOR_STRING) {
     651                 :          0 :                                         fprintf(stderr, "~ expected only for string testing\n");
     652                 :          0 :                                         return (EPKG_FATAL);
     653                 :            :                                 }
     654                 :          0 :                                 state = NEXT_IS_STRING;
     655                 :          0 :                                 fprintf(sqlcond->fp, " GLOB ");
     656   [ +  +  -  + ]:         80 :                         } else if (str[0] == '>' || str[0] == '<') {
     657         [ +  - ]:         52 :                                 if (state != OPERATOR_INT) {
     658                 :          0 :                                         fprintf(stderr, "> expected only for integers\n");
     659                 :          0 :                                         return (EPKG_FATAL);
     660                 :            :                                 }
     661                 :         52 :                                 state = NEXT_IS_INT;
     662                 :         52 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     663         [ +  - ]:         52 :                                 if (str[1] == '=') {
     664                 :          0 :                                         str++;
     665                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     666                 :          0 :                                 }
     667         [ +  + ]:         80 :                         } else if (str[0] == '=') {
     668         [ +  + ]:         20 :                                 if (state == OPERATOR_STRING) {
     669                 :         12 :                                         state = NEXT_IS_STRING;
     670                 :         12 :                                 } else {
     671                 :          8 :                                         state = NEXT_IS_INT;
     672                 :            :                                 }
     673                 :         20 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     674         [ -  + ]:         20 :                                 if (str[1] == '=') {
     675                 :         20 :                                         str++;
     676                 :         20 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     677                 :         20 :                                 }
     678         [ +  - ]:         28 :                         } else if (str[0] == '!') {
     679         [ +  - ]:          8 :                                 if (str[1] == '=') {
     680                 :          8 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     681                 :          8 :                                         fprintf(sqlcond->fp, "%c", str[1]);
     682         [ #  # ]:          8 :                                 } else if (str[1] == '~') {
     683                 :          0 :                                         fprintf(sqlcond->fp, " NOT GLOB ");
     684                 :          0 :                                 } else {
     685                 :          0 :                                         fprintf(stderr, "expecting = or ~ after !\n");
     686                 :          0 :                                         return (EPKG_FATAL);
     687                 :            :                                 }
     688                 :          8 :                                 str++;
     689         [ +  - ]:          8 :                                 if (state == OPERATOR_STRING) {
     690                 :          8 :                                         state = NEXT_IS_STRING;
     691                 :          8 :                                 } else {
     692                 :          0 :                                         state = NEXT_IS_INT;
     693                 :            :                                 }
     694                 :          8 :                         } else {
     695                 :          0 :                                 fprintf(stderr, "an operator is expected, got %c\n", str[0]);
     696                 :          0 :                                 return (EPKG_FATAL);
     697                 :            :                         }
     698   [ +  +  +  + ]:        328 :                 } else if (state == NEXT_IS_STRING || state == NEXT_IS_INT) {
     699         [ +  + ]:        120 :                         if (isspace(str[0])) {
     700                 :            :                                 /* do nothing */
     701                 :         40 :                         } else {
     702         [ +  + ]:         80 :                                 if (state == NEXT_IS_STRING) {
     703         [ -  + ]:         20 :                                         if (str[0] == '"') {
     704                 :          0 :                                                 state = QUOTEDSTRING;
     705         [ -  + ]:         20 :                                         } else if (str[0] == '\'') {
     706                 :          0 :                                                 state = SQUOTEDSTRING;
     707                 :          0 :                                         } else {
     708                 :         20 :                                                 state = STRING;
     709                 :         20 :                                                 str--;
     710                 :            :                                         }
     711                 :         20 :                                         fprintf(sqlcond->fp, "%c", '\'');
     712                 :         20 :                                 } else {
     713         [ +  - ]:         60 :                                         if (!isdigit(str[0])) {
     714                 :          0 :                                                 fprintf(stderr, "a number is expected, got: %c\n", str[0]);
     715                 :          0 :                                                 return (EPKG_FATAL);
     716                 :            :                                         }
     717                 :         60 :                                         state = INT;
     718                 :         60 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     719                 :            :                                 }
     720                 :            :                         }
     721         [ +  + ]:        208 :                 } else if (state == INT) {
     722         [ -  + ]:          8 :                         if (!isdigit(str[0])) {
     723                 :          8 :                                 state = POST_EXPR;
     724                 :          8 :                                 str--;
     725                 :          8 :                         } else {
     726                 :          0 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     727                 :            :                         }
     728   [ -  +  #  #  :         88 :                 } else if (state == STRING || state == QUOTEDSTRING || state == SQUOTEDSTRING) {
                   #  # ]
     729   [ +  -  -  + ]:         80 :                         if ((state == STRING && isspace(str[0])) ||
     730         [ -  + ]:         80 :                             (state == QUOTEDSTRING && str[0] == '"') ||
     731         [ -  + ]:         80 :                             (state == SQUOTEDSTRING && str[0] == '\'')) {
     732                 :          0 :                                 fprintf(sqlcond->fp, "%c", '\'');
     733                 :          0 :                                 state = POST_EXPR;
     734                 :          0 :                         } else {
     735                 :         80 :                                 fprintf(sqlcond->fp, "%c", str[0]);
     736         [ -  + ]:         80 :                                 if (str[0] == '\'')
     737                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     738   [ -  +  #  # ]:         80 :                                 else if (str[0] == '%' && for_remote)
     739                 :          0 :                                         fprintf(sqlcond->fp, "%c", str[0]);
     740                 :            :                         }
     741                 :         80 :                 }
     742                 :        432 :                 str++;
     743                 :            :         }
     744         [ +  + ]:         72 :         if (state == STRING) {
     745                 :         20 :                 fprintf(sqlcond->fp, "%c", '\'');
     746                 :         20 :                 state = POST_EXPR;
     747                 :         20 :         }
     748                 :            : 
     749   [ +  +  +  - ]:         72 :         if (state != POST_EXPR && state != INT) {
     750                 :          0 :                 fprintf(stderr, "unexpected end of expression\n");
     751                 :          0 :                 return (EPKG_FATAL);
     752         [ -  + ]:         72 :         } else if (bracket_level > 0) {
     753                 :          0 :                 fprintf(stderr, "unexpected end of expression (too many open brackets)\n");
     754                 :          0 :                 return (EPKG_FATAL);
     755                 :            :         }
     756                 :            : 
     757                 :         72 :         return (EPKG_OK);
     758                 :         72 : }
     759                 :            : 
     760                 :            : int
     761                 :        198 : analyse_query_string(char *qstr, struct query_flags *q_flags, const unsigned int q_flags_len, int *flags, char *multiline)
     762                 :            : {
     763                 :            :         unsigned int i, j, k;
     764                 :        198 :         unsigned int valid_flag = 0;
     765                 :        198 :         unsigned int valid_opts = 0;
     766                 :            : 
     767                 :        198 :         j = 0; /* shut up scanbuild */
     768                 :            : 
     769         [ +  - ]:        198 :         if (strchr(qstr, '%') == NULL) {
     770                 :          0 :                 fprintf(stderr, "Invalid query: query should contain a format string\n");
     771                 :          0 :                 return (EPKG_FATAL);
     772                 :            :         }
     773                 :            : 
     774         [ +  + ]:        652 :         while (qstr[0] != '\0') {
     775         [ +  + ]:        454 :                 if (qstr[0] == '%') {
     776                 :        310 :                         qstr++;
     777                 :        310 :                         valid_flag = 0;
     778                 :            : 
     779         [ -  + ]:       4238 :                         for (i = 0; i < q_flags_len; i++) {
     780                 :            :                                 /* found the flag */
     781         [ +  + ]:       4238 :                                 if (qstr[0] == q_flags[i].flag) {
     782                 :        310 :                                         valid_flag = 1;
     783                 :            : 
     784                 :            :                                         /* if the flag is followed by additional options */
     785         [ +  + ]:        310 :                                         if (q_flags[i].options[0] != '\0') {
     786                 :        124 :                                                 qstr++;
     787                 :        124 :                                                 valid_opts = 0;
     788                 :            : 
     789         [ -  + ]:        276 :                                                 for (j = 0; j < strlen(q_flags[i].options); j++) {
     790         [ +  + ]:        276 :                                                         if (qstr[0] == q_flags[i].options[j]) {
     791                 :        124 :                                                                 valid_opts = 1;
     792                 :        124 :                                                                 break;
     793                 :            :                                                         }
     794                 :        152 :                                                 }
     795                 :            : 
     796         [ +  - ]:        124 :                                                 if (valid_opts == 0) {
     797                 :          0 :                                                         fprintf(stderr, "Invalid query: '%%%c' should be followed by:", q_flags[i].flag);
     798                 :            : 
     799         [ #  # ]:          0 :                                                         for (j = 0; j < strlen(q_flags[i].options); j++)
     800                 :          0 :                                                                 fprintf(stderr, " %c%c", q_flags[i].options[j],
     801                 :          0 :                                                                                 q_flags[i].options[j + 1] == '\0' ?
     802                 :            :                                                                                 '\n' : ',');
     803                 :            : 
     804                 :          0 :                                                         return (EPKG_FATAL);
     805                 :            :                                                 }
     806                 :        124 :                                         }
     807                 :            : 
     808                 :            :                                         /* if this is a multiline flag */
     809         [ +  + ]:        310 :                                         if (q_flags[i].multiline == 1) {
     810   [ +  +  -  + ]:        124 :                                                 if (*multiline != 0 && *multiline != q_flags[i].flag) {
     811                 :          0 :                                                         fprintf(stderr, "Invalid query: '%%%c' and '%%%c' cannot be queried at the same time\n",
     812                 :          0 :                                                                         *multiline, q_flags[i].flag);
     813                 :          0 :                                                         return (EPKG_FATAL);
     814                 :            :                                                 } else {
     815                 :        124 :                                                         *multiline = q_flags[i].flag;
     816                 :            :                                                 }
     817                 :        124 :                                         }
     818                 :            : 
     819                 :            :                                         /* handle the '?' flag cases */
     820   [ +  +  +  + ]:        310 :                                         if (q_flags[i].flag == '?' || q_flags[i].flag == '#') {
     821         [ -  + ]:         72 :                                                 for (k = 0; k < q_flags_len; k++)
     822         [ +  + ]:         72 :                                                         if (q_flags[k].flag == q_flags[i].options[j]) {
     823                 :         16 :                                                                 *flags |= q_flags[k].dbflags;
     824                 :         16 :                                                                 break;
     825                 :            :                                                         }
     826                 :         16 :                                         } else {
     827                 :        294 :                                                 *flags |= q_flags[i].dbflags;
     828                 :            :                                         }
     829                 :            : 
     830                 :        310 :                                         break; /* don't iterate over the rest of the flags */
     831                 :            :                                 }
     832                 :       3928 :                         }
     833                 :            : 
     834         [ +  - ]:        310 :                         if (valid_flag == 0) {
     835                 :          0 :                                 fprintf(stderr, "Unknown query format key: '%%%c'\n", qstr[0]);
     836                 :          0 :                                 return (EPKG_FATAL);
     837                 :            :                         }
     838                 :        310 :                 }
     839                 :            : 
     840                 :        454 :                 qstr++;
     841                 :            :         }
     842                 :            : 
     843                 :        198 :         return (EPKG_OK);
     844                 :        198 : }
     845                 :            : 
     846                 :            : void
     847                 :          0 : usage_query(void)
     848                 :            : {
     849                 :          0 :         fprintf(stderr, "Usage: pkg query <query-format> <pkg-name>\n");
     850                 :          0 :         fprintf(stderr, "       pkg query [-a] <query-format>\n");
     851                 :          0 :         fprintf(stderr, "       pkg query -F <pkg-name> <query-format>\n");
     852                 :          0 :         fprintf(stderr, "       pkg query -e <evaluation> <query-format>\n");
     853                 :          0 :         fprintf(stderr, "       pkg query [-Cgix] <query-format> <pattern> <...>\n\n");
     854                 :          0 :         fprintf(stderr, "For more information see 'pkg help query.'\n");
     855                 :          0 : }
     856                 :            : 
     857                 :            : int
     858                 :        166 : exec_query(int argc, char **argv)
     859                 :            : {
     860                 :        166 :         struct pkgdb            *db = NULL;
     861                 :        166 :         struct pkgdb_it         *it = NULL;
     862                 :        166 :         struct pkg              *pkg = NULL;
     863                 :        166 :         struct pkg_manifest_key *keys = NULL;
     864                 :        166 :         char                    *pkgname = NULL;
     865                 :        166 :         int                      query_flags = PKG_LOAD_BASIC;
     866                 :        166 :         match_t                  match = MATCH_EXACT;
     867                 :            :         int                      ch;
     868                 :            :         int                      ret;
     869                 :        166 :         int                      retcode = EXIT_SUCCESS;
     870                 :            :         int                      i;
     871                 :        166 :         char                     multiline = 0;
     872                 :        166 :         int                      nprinted = 0;
     873                 :        166 :         char                    *condition = NULL;
     874                 :        166 :         const char              *condition_sql = NULL;
     875                 :        166 :         xstring                 *sqlcond = NULL;
     876                 :        166 :         const unsigned int       q_flags_len = NELEM(accepted_query_flags);
     877                 :            : 
     878                 :        166 :         struct option longopts[] = {
     879                 :            :                 { "all",              no_argument,            NULL,   'a' },
     880                 :            :                 { "case-sensitive",   no_argument,            NULL,   'C' },
     881                 :            :                 { "evaluate",         required_argument,      NULL,   'e' },
     882                 :            :                 { "file",             required_argument,      NULL,   'F' },
     883                 :            :                 { "glob",             no_argument,            NULL,   'g' },
     884                 :            :                 { "case-insensitive", no_argument,            NULL,   'i' },
     885                 :            :                 { "regex",            no_argument,            NULL,   'x' },
     886                 :            :                 { NULL,                 0,                      NULL,   0   },
     887                 :            :         };
     888                 :            : 
     889         [ +  + ]:        258 :         while ((ch = getopt_long(argc, argv, "+aCe:F:gix", longopts, NULL)) != -1) {
     890   [ -  -  +  +  :         92 :                 switch (ch) {
             +  -  +  - ]
     891                 :            :                 case 'a':
     892                 :          0 :                         match = MATCH_ALL;
     893                 :          0 :                         break;
     894                 :            :                 case 'C':
     895                 :          0 :                         pkgdb_set_case_sensitivity(true);
     896                 :          0 :                         break;
     897                 :            :                 case 'e':
     898                 :         52 :                         condition = optarg;
     899                 :         52 :                         break;
     900                 :            :                 case 'F':
     901                 :         32 :                         pkgname = optarg;
     902                 :         32 :                         break;
     903                 :            :                 case 'g':
     904                 :          4 :                         match = MATCH_GLOB;
     905                 :          4 :                         break;
     906                 :            :                 case 'i':
     907                 :          0 :                         pkgdb_set_case_sensitivity(false);
     908                 :          0 :                         break;
     909                 :            :                 case 'x':
     910                 :          4 :                         match = MATCH_REGEX;
     911                 :          4 :                         break;
     912                 :            :                 default:
     913                 :          0 :                         usage_query();
     914                 :          0 :                         return (EXIT_FAILURE);
     915                 :            :                 }
     916                 :            :         }
     917                 :            : 
     918                 :        166 :         argc -= optind;
     919                 :        166 :         argv += optind;
     920                 :            : 
     921         [ +  - ]:        166 :         if (argc == 0) {
     922                 :          0 :                 usage_query();
     923                 :          0 :                 return (EXIT_FAILURE);
     924                 :            :         }
     925                 :            : 
     926                 :            :         /* Default to all packages if no pkg provided */
     927   [ +  +  +  +  :        166 :         if (argc == 1 && pkgname == NULL && match == MATCH_EXACT) {
                   -  + ]
     928                 :         40 :                 match = MATCH_ALL;
     929   [ +  +  #  # ]:        166 :         } else if (((argc == 1) ^ (match == MATCH_ALL)) && pkgname == NULL
     930         [ -  + ]:         32 :                         && condition == NULL) {
     931                 :          0 :                 usage_query();
     932                 :          0 :                 return (EXIT_FAILURE);
     933                 :            :         }
     934                 :            : 
     935   [ -  +  -  + ]:        332 :         if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len,
     936                 :        166 :                         &query_flags, &multiline) != EPKG_OK)
     937                 :          0 :                 return (EXIT_FAILURE);
     938                 :            : 
     939         [ +  + ]:        166 :         if (pkgname != NULL) {
     940                 :            :                 /* Use a manifest or compact manifest if possible. */
     941                 :         32 :                 int open_flags = 0;
     942   [ +  +  +  + ]:         64 :                 if ((query_flags & ~(PKG_LOAD_DEPS|
     943                 :            :                                      PKG_LOAD_OPTIONS|
     944                 :            :                                      PKG_LOAD_CATEGORIES|
     945                 :            :                                      PKG_LOAD_LICENSES|
     946                 :            :                                      PKG_LOAD_USERS|
     947                 :            :                                      PKG_LOAD_GROUPS|
     948                 :            :                                      PKG_LOAD_SHLIBS_REQUIRED|
     949                 :            :                                      PKG_LOAD_SHLIBS_PROVIDED|
     950                 :            :                                      PKG_LOAD_ANNOTATIONS|
     951                 :            :                                      PKG_LOAD_CONFLICTS|
     952                 :            :                                      PKG_LOAD_PROVIDES|
     953                 :         32 :                                      PKG_LOAD_REQUIRES)) == 0) {
     954                 :         12 :                         open_flags = PKG_OPEN_MANIFEST_COMPACT;
     955         [ +  + ]:         32 :                 } else if ((query_flags & PKG_LOAD_FILES) == 0) {
     956                 :          8 :                         open_flags = PKG_OPEN_MANIFEST_ONLY;
     957                 :          8 :                 }
     958                 :         32 :                 pkg_manifest_keys_new(&keys);
     959         [ -  + ]:         32 :                 if (pkg_open(&pkg, pkgname, keys, open_flags) != EPKG_OK) {
     960                 :          0 :                         return (EXIT_FAILURE);
     961                 :            :                 }
     962                 :            : 
     963                 :         32 :                 pkg_manifest_keys_free(keys);
     964                 :         32 :                 print_query(pkg, argv[0], multiline);
     965                 :         32 :                 pkg_free(pkg);
     966                 :         32 :                 return (EXIT_SUCCESS);
     967                 :            :         }
     968                 :            : 
     969         [ +  + ]:        134 :         if (condition != NULL) {
     970                 :         52 :                 sqlcond = xstring_new();
     971         [ -  + ]:         52 :                 if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) {
     972                 :          0 :                         xstring_free(sqlcond);
     973                 :          0 :                         return (EXIT_FAILURE);
     974                 :            :                 }
     975                 :         52 :         }
     976                 :            : 
     977                 :        134 :         ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
     978         [ -  + ]:        134 :         if (ret == EPKG_ENOACCESS) {
     979                 :          0 :                 warnx("Insufficient privileges to query the package database");
     980                 :          0 :                 return (EXIT_FAILURE);
     981         [ -  + ]:        134 :         } else if (ret == EPKG_ENODB) {
     982         [ #  # ]:          0 :                 if (!quiet)
     983                 :          0 :                         warnx("No packages installed");
     984                 :          0 :                 return (EXIT_SUCCESS);
     985         [ -  + ]:        134 :         } else if (ret != EPKG_OK)
     986                 :          0 :                 return (EXIT_FAILURE);
     987                 :            : 
     988                 :        134 :         ret = pkgdb_open(&db, PKGDB_DEFAULT);
     989         [ -  + ]:        134 :         if (ret != EPKG_OK)
     990                 :          0 :                 return (EXIT_FAILURE);
     991                 :            : 
     992                 :        134 :         drop_privileges();
     993         [ +  - ]:        134 :         if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
     994                 :          0 :                 pkgdb_close(db);
     995                 :          0 :                 warnx("Cannot get a read lock on a database, it is locked by another process");
     996                 :          0 :                 return (EXIT_FAILURE);
     997                 :            :         }
     998                 :            : 
     999         [ +  + ]:        134 :         if (sqlcond) {
    1000                 :         52 :                 fflush(sqlcond->fp);
    1001                 :         52 :                 condition_sql = sqlcond->buf;
    1002                 :         52 :         }
    1003                 :        134 :         i = 1;
    1004                 :        134 :         do {
    1005         [ +  + ]:        150 :                 pkgname = i < argc ? argv[i] : NULL;
    1006                 :            : 
    1007         [ +  - ]:        150 :                 if ((it = pkgdb_query_cond(db, condition_sql, pkgname, match)) == NULL) {
    1008   [ #  #  #  # ]:          0 :                         warnx("DEBUG: %s/%s\n", condition_sql ? condition_sql : "-", pkgname ? pkgname : "-");
    1009                 :          0 :                         retcode = EXIT_FAILURE;
    1010                 :          0 :                         break;
    1011                 :            :                 }
    1012                 :            : 
    1013         [ +  + ]:        268 :                 while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
    1014                 :        118 :                         nprinted++;
    1015                 :        118 :                         print_query(pkg, argv[0], multiline);
    1016                 :            :                 }
    1017                 :            : 
    1018         [ +  - ]:        150 :                 if (ret != EPKG_END) {
    1019                 :          0 :                         retcode = EXIT_FAILURE;
    1020                 :          0 :                         break;
    1021                 :            :                 }
    1022                 :            : 
    1023                 :        150 :                 pkgdb_it_free(it);
    1024                 :        150 :                 i++;
    1025         [ +  + ]:        150 :         } while (i < argc);
    1026                 :            : 
    1027   [ +  +  +  +  :        134 :         if (nprinted == 0 && match != MATCH_ALL && retcode == EXIT_SUCCESS) {
                   +  - ]
    1028                 :            :                 /* ensure to return a non-zero status when no package
    1029                 :            :                  were found. */
    1030                 :          4 :                 retcode = EXIT_FAILURE;
    1031                 :          4 :         }
    1032                 :            : 
    1033                 :        134 :         pkg_free(pkg);
    1034                 :            : 
    1035                 :        134 :         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
    1036                 :        134 :         pkgdb_close(db);
    1037                 :            : 
    1038                 :        134 :         return (retcode);
    1039                 :        166 : }

Generated by: LCOV version 1.15