LCOV - code coverage report
Current view: top level - src - utils.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 153 518 29.5 %
Date: 2015-08-15 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
       3             :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4             :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       5             :  * Copyright (c) 2012-2015 Matthew Seaman <matthew@FreeBSD.org>
       6             :  * Copyright (c) 2013-2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       7             :  * All rights reserved.
       8             :  * 
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer
      14             :  *    in this position and unchanged.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  * 
      19             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      20             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      21             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      22             :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      23             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      24             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      28             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29             :  */
      30             : 
      31             : #ifdef HAVE_CONFIG_H
      32             : #include "pkg_config.h"
      33             : #endif
      34             : 
      35             : #include <sys/param.h>
      36             : #include <sys/stat.h>
      37             : 
      38             : #include <err.h>
      39             : #include <fcntl.h>
      40             : #include <inttypes.h>
      41             : #ifdef HAVE_LIBUTIL_H
      42             : #include <libutil.h>
      43             : #endif
      44             : #include <string.h>
      45             : #include <unistd.h>
      46             : #include <stdarg.h>
      47             : #include <paths.h>
      48             : #define _WITH_GETLINE
      49             : #include <stdio.h>
      50             : #include <errno.h>
      51             : #include <pkg.h>
      52             : 
      53             : #include <bsd_compat.h>
      54             : 
      55             : #include "utlist.h"
      56             : #include "pkgcli.h"
      57             : 
      58             : bool
      59           0 : query_tty_yesno(bool r, const char *msg, ...)
      60             : {
      61             :         int      c;
      62             :         va_list  ap;
      63             :         int      tty_fd;
      64             :         FILE    *tty;
      65           0 :         int      tty_flags = O_RDWR;
      66             :         char    yesnomsg[1024];
      67             : 
      68             : #ifdef O_TTY_INIT
      69           0 :         tty_flags |= O_TTY_INIT;
      70             : #endif
      71           0 :         tty_fd = open(_PATH_TTY, tty_flags);
      72           0 :         if (tty_fd == -1) {
      73             :                 /* No ctty -- return the default answer */
      74           0 :                 if (default_yes)
      75           0 :                         return (true);
      76           0 :                 return (r);
      77             :         }
      78             : 
      79           0 :         tty = fdopen(tty_fd, "r+");
      80             : 
      81           0 :         strlcpy(yesnomsg, msg, sizeof(yesnomsg));
      82           0 :         if (default_yes || r)
      83           0 :                 strlcat(yesnomsg, "[Y/n]: ", sizeof(yesnomsg));
      84             :         else
      85           0 :                 strlcat(yesnomsg, "[y/N]: ", sizeof(yesnomsg));
      86             : 
      87           0 :         va_start(ap, msg);
      88           0 :         pkg_vfprintf(tty, yesnomsg, ap);
      89           0 :         va_end(ap);
      90             : 
      91           0 :         c = getc(tty);
      92           0 :         if (c == 'y' || c == 'Y')
      93           0 :                 r = true;
      94           0 :         else if (c == 'n' || c == 'N')
      95           0 :                 r = false;
      96           0 :         else if (c == '\n' || c == EOF) {
      97           0 :                 if (default_yes)
      98           0 :                         r = true;
      99             :                 /* Else, r is not modified. It's default value is kept. */
     100           0 :                 goto cleanup;
     101             :         }
     102             : 
     103           0 :         while ((c = getc(tty)) != '\n' && c != EOF)
     104           0 :                 continue;
     105             : 
     106             : cleanup:
     107           0 :         fclose(tty);
     108             : 
     109           0 :         return (r);
     110             : }
     111             : 
     112             : static bool
     113          16 : vquery_yesno(bool deft, const char *msg, va_list ap)
     114             : {
     115          16 :         char *line = NULL;
     116             :         char *out;
     117          16 :         size_t linecap = 0;
     118             :         int linelen;
     119          16 :         bool     r = deft;
     120             :         char    yesnomsg[1024];
     121             : 
     122             :         /* We use default value of yes or default in case of quiet mode */
     123          16 :         if (quiet)
     124           0 :                 return (yes || default_yes || r);
     125             : 
     126          16 :         if (dry_run)
     127           0 :                 return (yes || default_yes || r );
     128             : 
     129             :         /* Do not query user if we have specified yes flag */
     130          16 :         if (yes)
     131          16 :                 return (true);
     132             : 
     133           0 :         strlcpy(yesnomsg, msg, sizeof(yesnomsg));
     134           0 :         if (default_yes || r)
     135           0 :                 strlcat(yesnomsg, "[Y/n]: ", sizeof(yesnomsg));
     136             :         else
     137           0 :                 strlcat(yesnomsg, "[y/N]: ", sizeof(yesnomsg));
     138             : 
     139           0 :         pkg_vasprintf(&out, yesnomsg, ap);
     140           0 :         printf("%s", out);
     141             : 
     142             :         for (;;) {
     143           0 :                 if ((linelen = getline(&line, &linecap, stdin)) != -1) {
     144             : 
     145           0 :                         if (linelen == 1 && line[0] == '\n') {
     146           0 :                                 if (default_yes)
     147           0 :                                         r = true;
     148           0 :                                 break;
     149             :                         }
     150           0 :                         else if (linelen == 2) {
     151           0 :                                 if (line[0] == 'y' || line[0] == 'Y') {
     152           0 :                                         r = true;
     153           0 :                                         break;
     154             :                                 }
     155           0 :                                 else if (line[0] == 'n' || line[0] == 'N') {
     156           0 :                                         r = false;
     157           0 :                                         break;
     158             :                                 }
     159             :                         }
     160             :                         else {
     161           0 :                                 if (strcasecmp(line, "yes\n") == 0) {
     162           0 :                                         r = true;
     163           0 :                                         break;
     164             :                                 }
     165           0 :                                 else if (strcasecmp(line, "no\n") == 0) {
     166           0 :                                         r = false;
     167           0 :                                         break;
     168             :                                 }
     169             :                         }
     170           0 :                         printf("Please type 'Y[es]' or 'N[o]' to make selection\n");
     171           0 :                         printf("%s", out);
     172             :                 }
     173             :                 else {
     174           0 :                         if (errno == EINTR) {
     175           0 :                                 continue;
     176             :                         }
     177             :                         else {
     178           0 :                                 if (default_yes)
     179           0 :                                         r = true;
     180             :                                 /* Else, assume EOF as false */
     181           0 :                                 r = false;
     182           0 :                                 break;
     183             :                         }
     184             :                 }
     185           0 :         }
     186             : 
     187           0 :         free(out);
     188             : 
     189           0 :         return (r);
     190             : }
     191             : 
     192             : bool
     193          16 : query_yesno(bool deft, const char *msg, ...)
     194             : {
     195             :         va_list  ap;
     196             :         bool r;
     197             : 
     198          16 :         va_start(ap, msg);
     199          16 :         r = vquery_yesno(deft, msg, ap);
     200          16 :         va_end(ap);
     201             : 
     202          16 :         return (r);
     203             : }
     204             : 
     205             : int
     206           0 : query_select(const char *msg, const char **opts, int ncnt, int deft)
     207             : {
     208             :         int i;
     209           0 :         char *str = NULL;
     210           0 :         char *endpntr = NULL;
     211           0 :         size_t n = 0;
     212             : 
     213           0 :         printf("%s\n", msg);
     214           0 :         for (i = 0; i < ncnt; i++) {
     215           0 :                 if (i + 1 == deft)
     216             :                 {
     217           0 :                         printf("*[%d] %s\n",
     218           0 :                                 i + 1, opts[i]);
     219             :                 } else {
     220           0 :                         printf(" [%d] %s\n",
     221           0 :                                 i + 1, opts[i]);
     222             :                 }
     223             :         }
     224             : 
     225           0 :         i = deft;
     226           0 :         while (getline(&str, &n, stdin) == -1) {
     227           0 :                 if (errno == EINTR)
     228           0 :                         continue;
     229             :                 else
     230           0 :                         goto cleanup;
     231             :         }
     232           0 :         i = (int) strtoul(str, &endpntr, 10);
     233             : 
     234           0 :         if (endpntr == NULL || *endpntr == '\0') {
     235           0 :                 i = deft;
     236           0 :         } else if (*endpntr == '\n' || *endpntr == '\r') {
     237           0 :                 if (i > ncnt || i < 1)
     238           0 :                         i = deft;
     239             :         } else
     240           0 :                 i = -1;
     241             : 
     242             : cleanup:
     243           0 :         free(str);
     244           0 :         return (i);
     245             : }
     246             : 
     247             : /* what the pkg needs to load in order to display the requested info */
     248             : int
     249           7 : info_flags(uint64_t opt, bool remote)
     250             : {
     251           7 :         int flags = PKG_LOAD_BASIC;
     252             : 
     253           7 :         if (opt & INFO_CATEGORIES)
     254           0 :                 flags |= PKG_LOAD_CATEGORIES;
     255           7 :         if (opt & INFO_LICENSES)
     256           0 :                 flags |= PKG_LOAD_LICENSES;
     257           7 :         if (opt & (INFO_OPTIONS|INFO_OPTION_DEFAULTS|INFO_OPTION_DESCRIPTIONS))
     258           0 :                 flags |= PKG_LOAD_OPTIONS;
     259           7 :         if (opt & INFO_SHLIBS_REQUIRED)
     260           0 :                 flags |= PKG_LOAD_SHLIBS_REQUIRED;
     261           7 :         if (opt & INFO_SHLIBS_PROVIDED)
     262           0 :                 flags |= PKG_LOAD_SHLIBS_PROVIDED;
     263           7 :         if (opt & INFO_PROVIDED)
     264           0 :                 flags |= PKG_LOAD_PROVIDES;
     265           7 :         if (opt & INFO_REQUIRED)
     266           0 :                 flags |= PKG_LOAD_REQUIRES;
     267           7 :         if (opt & INFO_ANNOTATIONS)
     268           5 :                 flags |= PKG_LOAD_ANNOTATIONS;
     269           7 :         if (opt & INFO_DEPS)
     270           0 :                 flags |= PKG_LOAD_DEPS;
     271           7 :         if (opt & INFO_RDEPS)
     272           0 :                 flags |= PKG_LOAD_RDEPS;
     273           7 :         if (opt & INFO_FILES)
     274           0 :                 flags |= PKG_LOAD_FILES;
     275           7 :         if (opt & INFO_DIRS)
     276           0 :                 flags |= PKG_LOAD_DIRS;
     277           7 :         if (opt & INFO_USERS)
     278           0 :                 flags |= PKG_LOAD_USERS;
     279           7 :         if (opt & INFO_GROUPS)
     280           0 :                 flags |= PKG_LOAD_GROUPS;
     281           7 :         if (opt & INFO_RAW) {
     282           0 :                 flags |= PKG_LOAD_CATEGORIES      |
     283             :                          PKG_LOAD_LICENSES        |
     284             :                          PKG_LOAD_OPTIONS         |
     285             :                          PKG_LOAD_SHLIBS_REQUIRED |
     286             :                          PKG_LOAD_SHLIBS_PROVIDED |
     287             :                          PKG_LOAD_PROVIDES        |
     288             :                          PKG_LOAD_REQUIRES        |
     289             :                          PKG_LOAD_ANNOTATIONS     |
     290             :                          PKG_LOAD_DEPS;
     291           0 :                 if (!remote) {
     292           0 :                         flags |= PKG_LOAD_FILES  |
     293             :                                 PKG_LOAD_DIRS    |
     294             :                                 PKG_LOAD_USERS   |
     295             :                                 PKG_LOAD_GROUPS  |
     296             :                                 PKG_LOAD_SCRIPTS;
     297             :                 }
     298             :         }
     299             : 
     300           7 :         return flags;
     301             : }
     302             : 
     303             : void
     304           7 : print_info(struct pkg * const pkg, uint64_t options)
     305             : {
     306           7 :         bool print_tag = false;
     307           7 :         bool show_locks = false;
     308             :         const char *repourl;
     309             :         unsigned opt;
     310             :         int64_t flatsize, oldflatsize, pkgsize;
     311           7 :         int cout = 0;           /* Number of characters output */
     312             :         int info_num;           /* Number of different data items to print */
     313           7 :         int outflags = 0;
     314             : 
     315           7 :         pkg_get(pkg,
     316             :                 PKG_REPOURL,       &repourl,
     317             :                 PKG_FLATSIZE,      &flatsize,
     318             :                 PKG_OLD_FLATSIZE,  &oldflatsize,
     319             :                 PKG_PKGSIZE,       &pkgsize);
     320             : 
     321           7 :         if (options & INFO_RAW) {
     322           0 :                 switch (options & (INFO_RAW_YAML|INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) {
     323             :                 case INFO_RAW_YAML:
     324           0 :                         outflags |= PKG_MANIFEST_EMIT_PRETTY;
     325           0 :                         break;
     326             :                 case INFO_RAW_UCL:
     327           0 :                         outflags |= PKG_MANIFEST_EMIT_UCL;
     328           0 :                         break;
     329             :                 case INFO_RAW_JSON:
     330           0 :                         outflags |= PKG_MANIFEST_EMIT_JSON;
     331             :                 case INFO_RAW_JSON_COMPACT:
     332           0 :                         break;
     333             :                 }
     334           0 :                 if (pkg_type(pkg) == PKG_REMOTE)
     335           0 :                         outflags |= PKG_MANIFEST_EMIT_COMPACT;
     336             : 
     337           0 :                 pkg_emit_manifest_file(pkg, stdout, outflags, NULL);
     338             : 
     339           0 :                 return;
     340             :         }
     341             : 
     342             :         /* Show locking status when requested to display it and the
     343             :            package is locally installed */
     344           7 :         if (pkg_type(pkg) == PKG_INSTALLED && (options & INFO_LOCKED) != 0)
     345           0 :                 show_locks = true;
     346             : 
     347           7 :         if (!quiet) {
     348             :                 /* Print a tag-line identifying the package -- either
     349             :                    NAMEVER, ORIGIN or NAME (in that order of
     350             :                    preference).  This may be the only output from this
     351             :                    function */
     352             : 
     353           6 :                 if (options & INFO_TAG_NAMEVER)
     354           6 :                         cout = pkg_printf("%n-%v", pkg, pkg);
     355           0 :                 else if (options & INFO_TAG_ORIGIN)
     356           0 :                         cout = pkg_printf("%o", pkg);
     357           0 :                 else if (options & INFO_TAG_NAME)
     358           0 :                         cout = pkg_printf("%n", pkg);
     359             :         }
     360             : 
     361             :         /* If we printed a tag, and there are no other items to print,
     362             :            then just return now. If there's only one single-line item
     363             :            to print, show it at column 32 on the same line. If there's
     364             :            one multi-line item to print, start a new line. If there is
     365             :            more than one item to print per pkg, use 'key : value'
     366             :            style to show on a new line.  */
     367             : 
     368           7 :         info_num = 0;
     369         217 :         for (opt = 0x1U; opt <= INFO_LASTFIELD; opt <<= 1) 
     370         210 :                 if ((opt & options) != 0)
     371           6 :                         info_num++;
     372             : 
     373           7 :         if (info_num == 0 && cout > 0) {
     374           1 :                 printf("\n");
     375           1 :                 return;
     376             :         }
     377             : 
     378           6 :         if (info_num == 1) {
     379             :                 /* Only one item to print */
     380           6 :                 print_tag = false;
     381           6 :                 if (!quiet) {
     382           5 :                         if (options & INFO_MULTILINE)
     383           5 :                                 printf(":\n");
     384             :                         else {
     385           0 :                                 if (cout < 31)
     386           0 :                                         cout = 31 - cout;
     387             :                                 else
     388           0 :                                         cout = 1;
     389           0 :                                 printf("%*s", cout, " ");
     390             :                         }
     391             :                 }
     392             :         } else {
     393             :                 /* Several items to print */
     394           0 :                 print_tag = true;
     395           0 :                 if (!quiet)
     396           0 :                         printf("\n");
     397             :         }
     398             : 
     399         186 :         for (opt = 0x1; opt <= INFO_LASTFIELD; opt <<= 1) {
     400         180 :                 if ((opt & options) == 0)
     401         174 :                         continue;
     402             : 
     403           6 :                 switch (opt) {
     404             :                 case INFO_NAME:
     405           0 :                         if (print_tag)
     406           0 :                                 printf("%-15s: ", "Name");
     407           0 :                         pkg_printf("%n\n", pkg);
     408           0 :                         break;
     409             :                 case INFO_INSTALLED:
     410           0 :                         if (pkg_type(pkg) != PKG_REMOTE) {
     411           0 :                                 if (print_tag) {
     412           0 :                                         printf("%-15s: ", "Installed on");
     413           0 :                                         pkg_printf("%t%{%+%}\n", pkg);
     414             :                                 }
     415           0 :                         } else if (!print_tag)
     416           0 :                                 printf("\n");
     417           0 :                         break;
     418             :                 case INFO_VERSION:
     419           0 :                         if (print_tag)
     420           0 :                                 printf("%-15s: ", "Version");
     421           0 :                         pkg_printf("%v\n", pkg);
     422           0 :                         break;
     423             :                 case INFO_ORIGIN:
     424           1 :                         if (print_tag)
     425           0 :                                 printf("%-15s: ", "Origin");
     426           1 :                         pkg_printf("%o\n", pkg);
     427           1 :                         break;
     428             :                 case INFO_PREFIX:
     429           0 :                         if (print_tag)
     430           0 :                                 printf("%-15s: ", "Prefix");
     431           0 :                         pkg_printf("%p\n", pkg);
     432           0 :                         break;
     433             :                 case INFO_REPOSITORY:
     434           0 :                         if (pkg_type(pkg) == PKG_REMOTE &&
     435           0 :                             repourl != NULL && repourl[0] != '\0') {
     436           0 :                                 if (print_tag)
     437           0 :                                         printf("%-15s: ", "Repository");
     438           0 :                                 pkg_printf("%N [%S]\n", pkg, repourl);
     439           0 :                         } else if (!print_tag)
     440           0 :                                 printf("\n");
     441           0 :                         break;
     442             :                 case INFO_CATEGORIES:
     443           0 :                         if (print_tag)
     444           0 :                                 printf("%-15s: ", "Categories");
     445           0 :                         pkg_printf("%C%{%Cn%| %}\n", pkg);
     446           0 :                         break;
     447             :                 case INFO_LICENSES:
     448           0 :                         if (print_tag)
     449           0 :                                 printf("%-15s: ", "Licenses");
     450           0 :                         pkg_printf("%L%{%Ln%| %l %}\n", pkg);
     451           0 :                         break;
     452             :                 case INFO_MAINTAINER:
     453           0 :                         if (print_tag)
     454           0 :                                 printf("%-15s: ", "Maintainer");
     455           0 :                         pkg_printf("%m\n", pkg);
     456           0 :                         break;
     457             :                 case INFO_WWW:  
     458           0 :                         if (print_tag)
     459           0 :                                 printf("%-15s: ", "WWW");
     460           0 :                         pkg_printf("%w\n", pkg);
     461           0 :                         break;
     462             :                 case INFO_COMMENT:
     463           0 :                         if (print_tag)
     464           0 :                                 printf("%-15s: ", "Comment");
     465           0 :                         pkg_printf("%c\n", pkg);
     466           0 :                         break;
     467             :                 case INFO_OPTIONS:
     468           0 :                         if (pkg_list_count(pkg, PKG_OPTIONS) > 0) {
     469           0 :                                 if (print_tag)
     470           0 :                                         printf("%-15s:\n", "Options");
     471           0 :                                 if (quiet) 
     472           0 :                                         pkg_printf("%O%{%-15On: %Ov\n%|%}", pkg);
     473             :                                 else
     474           0 :                                         pkg_printf("%O%{\t%-15On: %Ov\n%|%}", pkg);
     475             :                         }
     476           0 :                         break;
     477             :                 case INFO_SHLIBS_REQUIRED:
     478           0 :                         if (pkg_list_count(pkg, PKG_SHLIBS_REQUIRED) > 0) {
     479           0 :                                 if (print_tag)
     480           0 :                                         printf("%-15s:\n", "Shared Libs required");
     481           0 :                                 if (quiet)
     482           0 :                                         pkg_printf("%B%{%Bn\n%|%}", pkg);
     483             :                                 else
     484           0 :                                         pkg_printf("%B%{\t%Bn\n%|%}", pkg);
     485             :                         }
     486           0 :                         break;
     487             :                 case INFO_SHLIBS_PROVIDED:
     488           0 :                         if (pkg_list_count(pkg, PKG_SHLIBS_PROVIDED) > 0) {
     489           0 :                                 if (print_tag)
     490           0 :                                         printf("%-15s:\n", "Shared Libs provided");
     491           0 :                                 if (quiet)
     492           0 :                                         pkg_printf("%b%{%bn\n%|%}", pkg);
     493             :                                 else
     494           0 :                                         pkg_printf("%b%{\t%bn\n%|%}", pkg);
     495             :                         }
     496           0 :                         break;
     497             :                 case INFO_REQUIRED:
     498           0 :                         if (pkg_list_count(pkg, PKG_REQUIRES) > 0) {
     499           0 :                                 if (print_tag)
     500           0 :                                         printf("%-15s:\n", "Requires");
     501           0 :                                 if (quiet)
     502           0 :                                         pkg_printf("%Y%{%Yn\n%|%}", pkg);
     503             :                                 else
     504           0 :                                         pkg_printf("%Y%{\t%Yn\n%|%}", pkg);
     505             :                         }
     506           0 :                         break;
     507             :                 case INFO_PROVIDED:
     508           0 :                         if (pkg_list_count(pkg, PKG_PROVIDES) > 0) {
     509           0 :                                 if (print_tag)
     510           0 :                                         printf("%-15s:\n", "Provides");
     511           0 :                                 if (quiet)
     512           0 :                                         pkg_printf("%y%{%yn\n%|%}", pkg);
     513             :                                 else
     514           0 :                                         pkg_printf("%y%{\t%yn\n%|%}", pkg);
     515             :                         }
     516           0 :                         break;
     517             :                 case INFO_ANNOTATIONS:
     518           5 :                         if (print_tag)
     519           0 :                                 printf("%-15s:\n", "Annotations");
     520           5 :                         if (quiet)
     521           0 :                                 pkg_printf("%A%{%-15An: %Av\n%|%}", pkg);
     522             :                         else
     523           5 :                                 pkg_printf("%A%{\t%-15An: %Av\n%|%}", pkg);
     524           5 :                         break;
     525             :                 case INFO_FLATSIZE:
     526           0 :                         if (print_tag)
     527           0 :                                 printf("%-15s: ", "Flat size");
     528           0 :                         pkg_printf("%#sB\n", pkg);
     529           0 :                         break;
     530             :                 case INFO_PKGSIZE: /* Remote pkgs only */
     531           0 :                         if (pkg_type(pkg) == PKG_REMOTE) {
     532           0 :                                 if (print_tag)
     533           0 :                                         printf("%-15s: ", "Pkg size");
     534           0 :                                 pkg_printf("%#xB\n", pkg);
     535           0 :                         } else if (!print_tag)
     536           0 :                                 printf("\n");
     537           0 :                         break;
     538             :                 case INFO_DESCR:
     539           0 :                         if (print_tag)
     540           0 :                                 printf("%-15s:\n", "Description");
     541           0 :                         pkg_printf("%e\n", pkg);
     542           0 :                         break;
     543             :                 case INFO_MESSAGE:
     544           0 :                         if (print_tag)
     545           0 :                                 printf("%-15s:\n", "Message");
     546           0 :                         if (pkg_has_message(pkg))
     547           0 :                                 pkg_printf("%M\n", pkg);
     548           0 :                         break;
     549             :                 case INFO_DEPS:
     550           0 :                         if (pkg_list_count(pkg, PKG_DEPS) > 0) {
     551           0 :                                 if (print_tag)
     552           0 :                                         printf("%-15s:\n", "Depends on");
     553           0 :                                 if (quiet) {
     554           0 :                                         if (show_locks) 
     555           0 :                                                 pkg_printf("%d%{%dn-%dv%#dk\n%|%}", pkg);
     556             :                                         else
     557           0 :                                                 pkg_printf("%d%{%dn-%dv\n%|%}", pkg);
     558             :                                 } else {
     559           0 :                                         if (show_locks)
     560           0 :                                                 pkg_printf("%d%{\t%dn-%dv%#dk\n%|%}", pkg);
     561             :                                         else
     562           0 :                                                 pkg_printf("%d%{\t%dn-%dv\n%|%}", pkg);
     563             :                                 }
     564             :                         }
     565           0 :                         break;
     566             :                 case INFO_RDEPS:
     567           0 :                         if (pkg_list_count(pkg, PKG_RDEPS) > 0) {
     568           0 :                                 if (print_tag)
     569           0 :                                         printf("%-15s:\n", "Required by");
     570           0 :                                 if (quiet) {
     571           0 :                                         if (show_locks) 
     572           0 :                                                 pkg_printf("%r%{%rn-%rv%#rk\n%|%}", pkg);
     573             :                                         else
     574           0 :                                                 pkg_printf("%r%{%rn-%rv\n%|%}", pkg);
     575             :                                 } else {
     576           0 :                                         if (show_locks)
     577           0 :                                                 pkg_printf("%r%{\t%rn-%rv%#rk\n%|%}", pkg);
     578             :                                         else
     579           0 :                                                 pkg_printf("%r%{\t%rn-%rv\n%|%}", pkg);
     580             :                                 }
     581             :                         }
     582           0 :                         break;
     583             :                 case INFO_FILES: /* Installed pkgs only */
     584           0 :                         if (pkg_type(pkg) != PKG_REMOTE &&
     585           0 :                             pkg_list_count(pkg, PKG_FILES) > 0) {
     586           0 :                                 if (print_tag)
     587           0 :                                         printf("%-15s:\n", "Files");
     588           0 :                                 if (quiet)
     589           0 :                                         pkg_printf("%F%{%Fn\n%|%}", pkg);
     590             :                                 else
     591           0 :                                         pkg_printf("%F%{\t%Fn\n%|%}", pkg);
     592             :                         }
     593           0 :                         break;
     594             :                 case INFO_DIRS: /* Installed pkgs only */
     595           0 :                         if (pkg_type(pkg) != PKG_REMOTE &&
     596           0 :                             pkg_list_count(pkg, PKG_DIRS) > 0) {
     597           0 :                                 if (print_tag)
     598           0 :                                         printf("%-15s:\n", "Directories");
     599           0 :                                 if (quiet)
     600           0 :                                         pkg_printf("%D%{%Dn\n%|%}", pkg);
     601             :                                 else
     602           0 :                                         pkg_printf("%D%{\t%Dn\n%|%}", pkg);
     603             :                         }
     604           0 :                         break;
     605             :                 case INFO_USERS: /* Installed pkgs only */
     606           0 :                         if (pkg_type(pkg) != PKG_REMOTE &&
     607           0 :                             pkg_list_count(pkg, PKG_USERS) > 0) {
     608           0 :                                 if (print_tag)
     609           0 :                                         printf("%-15s: ", "Users");
     610           0 :                                 pkg_printf("%U%{%Un%| %}\n", pkg);
     611             :                         }
     612           0 :                         break;
     613             :                 case INFO_GROUPS: /* Installed pkgs only */
     614           0 :                         if (pkg_type(pkg) != PKG_REMOTE &&
     615           0 :                             pkg_list_count(pkg, PKG_GROUPS) > 0) {
     616           0 :                                 if (print_tag)
     617           0 :                                         printf("%-15s: ", "Groups");
     618           0 :                                 pkg_printf("%G%{%Gn%| %}\n", pkg);
     619             :                         }
     620           0 :                         break;
     621             :                 case INFO_ARCH:
     622           0 :                         if (print_tag)
     623           0 :                                 printf("%-15s: ", "Architecture");
     624           0 :                         pkg_printf("%q\n", pkg);
     625           0 :                         break;
     626             :                 case INFO_REPOURL:
     627           0 :                         if (pkg_type(pkg) == PKG_REMOTE &&
     628           0 :                             repourl != NULL && repourl[0] != '\0') {
     629           0 :                                 if (print_tag)
     630           0 :                                         printf("%-15s: ", "Pkg URL");
     631           0 :                                 if (repourl[strlen(repourl) -1] == '/')
     632           0 :                                         pkg_printf("%S%R\n", repourl, pkg);
     633             :                                 else
     634           0 :                                         pkg_printf("%S/%R\n", repourl, pkg);
     635           0 :                         } else if (!print_tag)
     636           0 :                                 printf("\n");
     637           0 :                         break;
     638             :                 case INFO_LOCKED:
     639           0 :                         if (print_tag)
     640           0 :                                 printf("%-15s: ", "Locked");
     641           0 :                         pkg_printf("%?k\n", pkg);
     642           0 :                         break;
     643             :                 }
     644             :         }
     645             : }
     646             : 
     647             : enum pkg_display_type {
     648             :         PKG_DISPLAY_LOCKED = 0,
     649             :         PKG_DISPLAY_DELETE,
     650             :         PKG_DISPLAY_INSTALL,
     651             :         PKG_DISPLAY_UPGRADE,
     652             :         PKG_DISPLAY_DOWNGRADE,
     653             :         PKG_DISPLAY_REINSTALL,
     654             :         PKG_DISPLAY_FETCH,
     655             :         PKG_DISPLAY_MAX
     656             : };
     657             : struct pkg_solved_display_item {
     658             :         struct pkg *new, *old;
     659             :         enum pkg_display_type display_type;
     660             :         pkg_solved_t solved_type;
     661             :         struct pkg_solved_display_item *prev, *next;
     662             : };
     663             : 
     664             : static void
     665          32 : set_jobs_summary_pkg(struct pkg_jobs *jobs,
     666             :                 struct pkg *new_pkg, struct pkg *old_pkg,
     667             :                 pkg_solved_t type, int64_t *oldsize,
     668             :                 int64_t *newsize, int64_t *dlsize,
     669             :                 struct pkg_solved_display_item **disp)
     670             : {
     671             :         const char *oldversion, *repopath, *destdir;
     672             :         char path[MAXPATHLEN];
     673             :         int ret;
     674             :         struct stat st;
     675             :         int64_t flatsize, oldflatsize, pkgsize;
     676             :         struct pkg_solved_display_item *it;
     677             : 
     678          32 :         flatsize = oldflatsize = pkgsize = 0;
     679          32 :         oldversion = NULL;
     680             : 
     681          32 :         pkg_get(new_pkg, PKG_FLATSIZE, &flatsize, PKG_PKGSIZE, &pkgsize,
     682             :                 PKG_REPOPATH, &repopath);
     683          32 :         if (old_pkg != NULL)
     684          11 :                 pkg_get(old_pkg, PKG_VERSION, &oldversion, PKG_FLATSIZE, &oldflatsize);
     685             : 
     686          32 :         it = malloc(sizeof (*it));
     687          32 :         if (it == NULL) {
     688           0 :                 fprintf(stderr, "malloc failed for "
     689           0 :                                 "pkg_solved_display_item: %s", strerror (errno));
     690           0 :                 return;
     691             :         }
     692          32 :         it->new = new_pkg;
     693          32 :         it->old = old_pkg;
     694          32 :         it->solved_type = type;
     695             : 
     696          32 :         if (old_pkg != NULL && pkg_is_locked(old_pkg)) {
     697           0 :                 it->display_type = PKG_DISPLAY_LOCKED;
     698           0 :                 DL_APPEND(disp[it->display_type], it);
     699           0 :                 return;
     700             :         }
     701             : 
     702          32 :         destdir = pkg_jobs_destdir(jobs);
     703             : 
     704          32 :         switch (type) {
     705             :         case PKG_SOLVED_INSTALL:
     706             :         case PKG_SOLVED_UPGRADE:
     707          26 :                 ret = EPKG_FATAL;
     708             : 
     709          26 :                 if (destdir == NULL)
     710          26 :                         ret = pkg_repo_cached_name(new_pkg, path, sizeof(path));
     711           0 :                 else if (repopath != NULL) {
     712           0 :                         snprintf(path, sizeof(path), "%s/%s", destdir, repopath);
     713           0 :                         ret = EPKG_OK;
     714             :                 }
     715             : 
     716          26 :                 if ((ret == EPKG_OK || ret == EPKG_FATAL) && (stat(path, &st) == -1 || pkgsize != st.st_size))
     717             :                         /* file looks corrupted (wrong size),
     718             :                                            assume a checksum mismatch will
     719             :                                            occur later and the file will be
     720             :                                            fetched from remote again */
     721           0 :                         *dlsize += pkgsize;
     722             : 
     723          26 :                 if (old_pkg != NULL) {
     724          11 :                         switch (pkg_version_change_between(new_pkg, old_pkg)) {
     725             :                         case PKG_DOWNGRADE:
     726           0 :                                 it->display_type = PKG_DISPLAY_DOWNGRADE;
     727           0 :                                 break;
     728             :                         case PKG_REINSTALL:
     729           6 :                                 it->display_type = PKG_DISPLAY_REINSTALL;
     730             : 
     731           6 :                                 break;
     732             :                         case PKG_UPGRADE:
     733           5 :                                 it->display_type = PKG_DISPLAY_UPGRADE;
     734             : 
     735           5 :                                 break;
     736             :                         }
     737          11 :                         *oldsize += oldflatsize;
     738          11 :                         *newsize += flatsize;
     739             :                 } else {
     740          15 :                         it->display_type = PKG_DISPLAY_INSTALL;
     741          15 :                         *newsize += flatsize;
     742             :                 }
     743          26 :                 break;
     744             :         case PKG_SOLVED_DELETE:
     745           6 :                 *oldsize += flatsize;
     746           6 :                 it->display_type = PKG_DISPLAY_DELETE;
     747             : 
     748           6 :                 break;
     749             :         case PKG_SOLVED_UPGRADE_REMOVE:
     750             :                 /* Ignore split-upgrade packages for display */
     751           0 :                 free(it);
     752           0 :                 return;
     753             :                 break;
     754             : 
     755             :         case PKG_SOLVED_FETCH:
     756           0 :                 *newsize += pkgsize;
     757           0 :                 it->display_type = PKG_DISPLAY_FETCH;
     758             : 
     759           0 :                 if (destdir == NULL)
     760           0 :                         pkg_repo_cached_name(new_pkg, path, sizeof(path));
     761             :                 else
     762           0 :                         snprintf(path, sizeof(path), "%s/%s", destdir, repopath);
     763             : 
     764           0 :                 if (stat(path, &st) != -1) {
     765           0 :                         *oldsize += st.st_size;
     766             : 
     767           0 :                         if (pkgsize != st.st_size)
     768           0 :                                 *dlsize += pkgsize;
     769             :                         else {
     770           0 :                                 free(it);
     771           0 :                                 return;
     772             :                         }
     773             :                 }
     774             :                 else
     775           0 :                         *dlsize += pkgsize;
     776             : 
     777           0 :                 break;
     778             :         }
     779          32 :         DL_APPEND(disp[it->display_type], it);
     780             : }
     781             : 
     782             : static void
     783          32 : display_summary_item(struct pkg_solved_display_item *it, int64_t dlsize)
     784             : {
     785             :         const char *why;
     786             :         int64_t pkgsize;
     787             :         char size[8], tlsize[8];
     788             : 
     789          32 :         pkg_get(it->new, PKG_PKGSIZE, &pkgsize);
     790             : 
     791          32 :         switch (it->display_type) {
     792             :         case PKG_DISPLAY_LOCKED:
     793           0 :                 pkg_printf("\tPackage %n-%v is locked ", it->old, it->old);
     794           0 :                 switch (it->solved_type) {
     795             :                 case PKG_SOLVED_INSTALL:
     796             :                 case PKG_SOLVED_UPGRADE:
     797             :                         /* If it's a new install, then it
     798             :                          * cannot have been locked yet. */
     799           0 :                         pkg_printf("and may not be upgraded to version %v\n", it->new);
     800           0 :                         break;
     801             :                 case PKG_SOLVED_DELETE:
     802             :                 case PKG_SOLVED_UPGRADE_REMOVE:
     803           0 :                         printf("and may not be deinstalled\n");
     804          32 :                         return;
     805             :                         break;
     806             :                 case PKG_SOLVED_FETCH:
     807           0 :                         printf("but a new package can still be fetched\n");
     808           0 :                         break;
     809             :                 }
     810           0 :                 break;
     811             :         case PKG_DISPLAY_DELETE:
     812           6 :                 pkg_get(it->new, PKG_REASON, &why);
     813           6 :                 pkg_printf("\t%n-%v", it->new, it->new);
     814           6 :                 if (why != NULL)
     815           0 :                         printf(" (%s)", why);
     816           6 :                 printf("\n");
     817           6 :                 break;
     818             :         case PKG_DISPLAY_INSTALL:
     819          15 :                 pkg_printf("\t%n: %v", it->new, it->new);
     820          15 :                 if (pkg_repos_total_count() > 1)
     821           0 :                         pkg_printf(" [%N]", it->new);
     822          15 :                 printf("\n");
     823          15 :                 break;
     824             :         case PKG_DISPLAY_UPGRADE:
     825           5 :                 pkg_printf("\t%n: %v -> %v", it->new, it->old, it->new);
     826           5 :                 if (pkg_repos_total_count() > 1)
     827           0 :                         pkg_printf(" [%N]", it->new);
     828           5 :                 printf("\n");
     829           5 :                 break;
     830             :         case PKG_DISPLAY_DOWNGRADE:
     831           0 :                 pkg_printf("\t%n: %v -> %v", it->new, it->old, it->new);
     832           0 :                 if (pkg_repos_total_count() > 1)
     833           0 :                         pkg_printf(" [%N]", it->new);
     834           0 :                 printf("\n");
     835           0 :                 break;
     836             :         case PKG_DISPLAY_REINSTALL:
     837           6 :                 pkg_get(it->new, PKG_REASON, &why);
     838           6 :                 pkg_printf("\t%n-%v", it->new, it->new);
     839           6 :                 if (pkg_repos_total_count() > 1)
     840           0 :                         pkg_printf(" [%N]", it->new);
     841           6 :                 if (why != NULL)
     842           6 :                         printf(" (%s)", why);
     843           6 :                 printf("\n");
     844           6 :                 break;
     845             :         case PKG_DISPLAY_FETCH:
     846           0 :                 humanize_number(size, sizeof(size), pkgsize, "B",
     847             :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
     848           0 :                 humanize_number(tlsize, sizeof(size), dlsize, "B",
     849             :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
     850             : 
     851           0 :                 pkg_printf("\t%n-%v ", it->new, it->new);
     852           0 :                 printf("(%.2f%% of %s: %s)\n", ((double)100 * pkgsize) / (double)dlsize,
     853             :                                 tlsize, size);
     854           0 :                 break;
     855             :         default:
     856           0 :                 break;
     857             :         }
     858             : }
     859             : 
     860             : 
     861             : static const char* pkg_display_messages[PKG_DISPLAY_MAX + 1] = {
     862             :         [PKG_DISPLAY_LOCKED] = "Installed packages LOCKED",
     863             :         [PKG_DISPLAY_DELETE] = "Installed packages to be REMOVED",
     864             :         [PKG_DISPLAY_INSTALL] = "New packages to be INSTALLED",
     865             :         [PKG_DISPLAY_UPGRADE] = "Installed packages to be UPGRADED",
     866             :         [PKG_DISPLAY_DOWNGRADE] = "Installed packages to be DOWNGRADED",
     867             :         [PKG_DISPLAY_REINSTALL] = "Installed packages to be REINSTALLED",
     868             :         [PKG_DISPLAY_FETCH] = "New packages to be FETCHED",
     869             :         [PKG_DISPLAY_MAX] = NULL
     870             : };
     871             : 
     872             : int
     873          12 : print_jobs_summary(struct pkg_jobs *jobs, const char *msg, ...)
     874             : {
     875             :         struct pkg *new_pkg, *old_pkg;
     876          12 :         void *iter = NULL;
     877             :         char size[8];
     878             :         va_list ap;
     879          12 :         int type, displayed = 0;
     880             :         int64_t dlsize, oldsize, newsize;
     881             :         struct pkg_solved_display_item *disp[PKG_DISPLAY_MAX], *cur, *tmp;
     882          12 :         bool first = true;
     883             : 
     884          12 :         dlsize = oldsize = newsize = 0;
     885          12 :         type = pkg_jobs_type(jobs);
     886          12 :         memset(disp, 0, sizeof (disp));
     887             : 
     888          56 :         while (pkg_jobs_iter(jobs, &iter, &new_pkg, &old_pkg, &type))
     889          32 :                 set_jobs_summary_pkg(jobs, new_pkg, old_pkg, type, &oldsize,
     890             :                         &newsize, &dlsize, disp);
     891             : 
     892          96 :         for (type = 0; type < PKG_DISPLAY_MAX; type ++) {
     893          84 :                 if (disp[type] != NULL) {
     894             :                         /* Space between each section. */
     895          20 :                         if (!first)
     896           8 :                                 puts("");
     897             :                         else
     898          12 :                                 first = false;
     899          20 :                         if (msg != NULL) {
     900          12 :                                 va_start(ap, msg);
     901          12 :                                 vprintf(msg, ap);
     902          12 :                                 va_end(ap);
     903          12 :                                 fflush(stdout);
     904          12 :                                 msg = NULL;
     905             :                         }
     906          20 :                         printf("%s:\n", pkg_display_messages[type]);
     907          52 :                         DL_FOREACH_SAFE(disp[type], cur, tmp) {
     908          32 :                                 display_summary_item(cur, dlsize);
     909          32 :                                 displayed ++;
     910          32 :                                 free(cur);
     911             :                         }
     912             :                 }
     913             :         }
     914             : 
     915             :         /* Add an extra line before the size output. */
     916          12 :         if (oldsize != newsize || dlsize)
     917           0 :                 puts("");
     918             : 
     919          12 :         if (oldsize > newsize) {
     920           0 :                 humanize_number(size, sizeof(size), oldsize - newsize, "B",
     921             :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
     922           0 :                 printf("The operation will free %s.\n", size);
     923          12 :         } else if (newsize > oldsize) {
     924           0 :                 humanize_number(size, sizeof(size), newsize - oldsize, "B",
     925             :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
     926           0 :                 printf("The process will require %s more space.\n", size);
     927             :         }
     928             : 
     929          12 :         if (dlsize > 0) {
     930           0 :                 humanize_number(size, sizeof(size), dlsize, "B",
     931             :                     HN_AUTOSCALE, HN_IEC_PREFIXES);
     932           0 :                 printf("%s to be downloaded.\n", size);
     933             :         }
     934             : 
     935          12 :         return (displayed);
     936             : }
     937             : 
     938             : void
     939           0 : sbuf_flush(struct sbuf *buf)
     940             : {
     941           0 :         sbuf_finish(buf);
     942           0 :         printf("%s", sbuf_data(buf));
     943           0 :         sbuf_clear(buf);
     944           0 : }

Generated by: LCOV version 1.10