LCOV - code coverage report
Current view: top level - src - event.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 150 436 34.4 %
Date: 2015-08-15 Functions: 6 13 46.2 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2011-2014 Baptiste Daroussin <bapt@FreeBSD.org>
       3             :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4             :  * Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
       5             :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       6             :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       7             :  * Copyright (c) 2015 Matthew Seaman <matthew@FreeBSD.org>
       8             :  * All rights reserved.
       9             :  * 
      10             :  * Redistribution and use in source and binary forms, with or without
      11             :  * modification, are permitted provided that the following conditions
      12             :  * are met:
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer
      15             :  *    in this position and unchanged.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  * 
      20             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      21             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      22             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      23             :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      24             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      25             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      29             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30             :  */
      31             : 
      32             : #ifdef HAVE_CONFIG_H
      33             : #include "pkg_config.h"
      34             : #endif
      35             : 
      36             : #include <sys/types.h>
      37             : #include <sys/sysctl.h>
      38             : #include <sys/wait.h>
      39             : #include <sys/socket.h>
      40             : 
      41             : #ifdef HAVE_CAPSICUM
      42             : #include <sys/capability.h>
      43             : #endif
      44             : 
      45             : #include <err.h>
      46             : #include <string.h>
      47             : #include <unistd.h>
      48             : #include <errno.h>
      49             : #include <signal.h>
      50             : #ifdef HAVE_LIBUTIL_H
      51             : #include <libutil.h>
      52             : #endif
      53             : 
      54             : #include <bsd_compat.h>
      55             : 
      56             : #include "pkg.h"
      57             : #include "pkgcli.h"
      58             : 
      59             : #define STALL_TIME 5
      60             : 
      61             : struct sbuf *messages = NULL;
      62             : 
      63             : static char *progress_message = NULL;
      64             : static struct sbuf *msg_buf = NULL;
      65             : static int last_progress_percent = -1;
      66             : static bool progress_started = false;
      67             : static bool progress_interrupted = false;
      68             : static bool progress_debit = false;
      69             : static int64_t last_tick = 0;
      70             : static int64_t stalled;
      71             : static int64_t bytes_per_second;
      72             : static time_t last_update;
      73             : static time_t begin = 0;
      74             : static int add_deps_depth;
      75             : 
      76             : /* units for format_size */
      77             : static const char *unit_SI[] = { " ", "k", "M", "G", "T", };
      78             : static const char *unit_IEC[] = { "  ", "Ki", "Mi", "Gi", "Ti", };
      79             : 
      80             : static void draw_progressbar(int64_t current, int64_t total);
      81             : 
      82             : static void
      83           0 : format_rate_IEC(char *buf, int size, off_t bytes)
      84             : {
      85             :         int i;
      86             : 
      87           0 :         bytes *= 100;
      88           0 :         for (i = 0; bytes >= 100*1000 && unit_IEC[i][0] != 'T'; i++)
      89           0 :                 bytes = (bytes + 512) / 1024;
      90           0 :         if (i == 0) {
      91           0 :                 i++;
      92           0 :                 bytes = (bytes + 512) / 1024;
      93             :         }
      94           0 :         snprintf(buf, size, "%3lld.%1lld%s%s",
      95           0 :             (long long) (bytes + 5) / 100,
      96           0 :             (long long) (bytes + 5) / 10 % 10,
      97             :             unit_IEC[i],
      98             :             i ? "B" : " ");
      99           0 : }
     100             : 
     101             : static void
     102           0 : format_size_IEC(char *buf, int size, off_t bytes)
     103             : {
     104             :         int i;
     105             : 
     106           0 :         for (i = 0; bytes >= 10000 && unit_IEC[i][0] != 'T'; i++)
     107           0 :                 bytes = (bytes + 512) / 1024;
     108           0 :         snprintf(buf, size, "%4lld%s%s",
     109             :             (long long) bytes,
     110             :             unit_IEC[i],
     111             :             i ? "B" : " ");
     112           0 : }
     113             : 
     114             : static void
     115           0 : format_rate_SI(char *buf, int size, off_t bytes)
     116             : {
     117             :         int i;
     118             : 
     119           0 :         bytes *= 100;
     120           0 :         for (i = 0; bytes >= 100*1000 && unit_SI[i][0] != 'T'; i++)
     121           0 :                 bytes = (bytes + 500) / 1000;
     122           0 :         if (i == 0) {
     123           0 :                 i++;
     124           0 :                 bytes = (bytes + 500) / 1000;
     125             :         }
     126           0 :         snprintf(buf, size, "%3lld.%1lld%s%s",
     127           0 :             (long long) (bytes + 5) / 100,
     128           0 :             (long long) (bytes + 5) / 10 % 10,
     129             :             unit_SI[i],
     130             :             i ? "B" : " ");
     131           0 : }
     132             : 
     133             : static void
     134           0 : format_size_SI(char *buf, int size, off_t bytes)
     135             : {
     136             :         int i;
     137             : 
     138           0 :         for (i = 0; bytes >= 10000 && unit_SI[i][0] != 'T'; i++)
     139           0 :                 bytes = (bytes + 500) / 1000;
     140           0 :         snprintf(buf, size, "%4lld%s%s",
     141             :             (long long) bytes,
     142             :             unit_SI[i],
     143             :             i ? "B" : " ");
     144           0 : }
     145             : 
     146             : void
     147           0 : job_status_end(struct sbuf *msg)
     148             : {
     149           0 :         sbuf_finish(msg);
     150           0 :         printf("%s\n", sbuf_data(msg));
     151             :         /*printf("\033]0; %s\007", sbuf_data(msg));*/
     152           0 :         sbuf_clear(msg);
     153           0 : }
     154             : 
     155             : void
     156          83 : job_status_begin(struct sbuf *msg)
     157             : {
     158             :         int n;
     159             : 
     160          83 :         sbuf_clear(msg);
     161             : #ifdef HAVE_LIBJAIL
     162             :         static char hostname[MAXHOSTNAMELEN] = "";
     163             :         static int jailed = -1;
     164             :         size_t intlen;
     165             : 
     166          83 :         if (jailed == -1) {
     167          39 :                 intlen = sizeof(jailed);
     168          39 :                 if (sysctlbyname("security.jail.jailed", &jailed, &intlen,
     169             :                     NULL, 0) == -1)
     170           0 :                         jailed = 0;
     171             :         }
     172             : 
     173          83 :         if (jailed == 1) {
     174           0 :                 if (hostname[0] == '\0')
     175           0 :                         gethostname(hostname, sizeof(hostname));
     176             : 
     177           0 :                 sbuf_printf(msg, "[%s] ", hostname);
     178             :         }
     179             : #endif
     180             : 
     181             :         /* Only used for pkg-add right now. */
     182          83 :         if (add_deps_depth) {
     183           1 :                 if (add_deps_depth > 1) {
     184           0 :                         for (n = 0; n < (2 * add_deps_depth); ++n) {
     185           0 :                                 if (n % 4 == 0 && n < (2 * add_deps_depth))
     186           0 :                                         sbuf_cat(msg, "|");
     187             :                                 else
     188           0 :                                         sbuf_cat(msg, " ");
     189             :                         }
     190             :                 }
     191           1 :                 sbuf_cat(msg, "`-- ");
     192             :         }
     193             : 
     194          83 :         if (nbactions > 0 && nbdone > 0)
     195          34 :                 sbuf_printf(msg, "[%d/%d] ", nbdone, nbactions);
     196          83 : }
     197             : 
     198             : static int
     199           0 : event_sandboxed_call(pkg_sandbox_cb func, int fd, void *ud)
     200             : {
     201             :         pid_t pid;
     202             :         int status, ret;
     203             : 
     204           0 :         ret = -1;
     205           0 :         pid = fork();
     206             : 
     207           0 :         switch(pid) {
     208             :         case -1:
     209           0 :                 warn("fork failed");
     210           0 :                 return (EPKG_FATAL);
     211             :                 break;
     212             :         case 0:
     213           0 :                 break;
     214             :         default:
     215             :                 /* Parent process */
     216           0 :                 while (waitpid(pid, &status, 0) == -1) {
     217           0 :                         if (errno != EINTR) {
     218           0 :                                 warn("Sandboxed process pid=%d", (int)pid);
     219           0 :                                 ret = -1;
     220           0 :                                 break;
     221             :                         }
     222             :                 }
     223             : 
     224           0 :                 if (WIFEXITED(status)) {
     225           0 :                         ret = WEXITSTATUS(status);
     226             :                 }
     227           0 :                 if (WIFSIGNALED(status)) {
     228             :                         /* Process got some terminating signal, hence stop the loop */
     229           0 :                         fprintf(stderr, "Sandboxed process pid=%d terminated abnormally by signal: %d\n",
     230             :                                         (int)pid, WTERMSIG(status));
     231           0 :                         ret = -1;
     232             :                 }
     233           0 :                 return (ret);
     234             :         }
     235             : 
     236             :         /* Here comes child process */
     237             : #ifdef HAVE_CAPSICUM
     238           0 :         if (cap_enter() < 0 && errno != ENOSYS) {
     239           0 :                 warn("cap_enter() failed");
     240           0 :                 return (EPKG_FATAL);
     241             :         }
     242             : #endif
     243             : 
     244             :         /*
     245             :          * XXX: if capsicum is not enabled we basically have no idea of how to
     246             :          * make a sandbox
     247             :          */
     248           0 :         ret = func(fd, ud);
     249             : 
     250           0 :         _exit(ret);
     251             : }
     252             : 
     253             : static int
     254          14 : event_sandboxed_get_string(pkg_sandbox_cb func, char **result, int64_t *len,
     255             :                 void *ud)
     256             : {
     257             :         pid_t pid;
     258          14 :         int     status, ret = EPKG_OK;
     259          14 :         int pair[2], r, allocated_len = 0, off = 0;
     260          14 :         char *buf = NULL;
     261             : 
     262          14 :         if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
     263           0 :                 warn("socketpair failed");
     264           0 :                 return (EPKG_FATAL);
     265             :         }
     266             : 
     267          14 :         pid = fork();
     268             : 
     269          14 :         switch(pid) {
     270             :         case -1:
     271           0 :                 warn("fork failed");
     272           0 :                 return (EPKG_FATAL);
     273             :                 break;
     274             :         case 0:
     275           0 :                 break;
     276             :         default:
     277             :                 /* Parent process */
     278          14 :                 close(pair[0]);
     279             :                 /*
     280             :                  * We use blocking IO here as if the child is terminated we would have
     281             :                  * EINTR here
     282             :                  */
     283          14 :                 buf = malloc(BUFSIZ);
     284          14 :                 if (buf == NULL) {
     285           0 :                         warn("malloc failed");
     286           0 :                         return (EPKG_FATAL);
     287             :                 }
     288          14 :                 allocated_len = BUFSIZ;
     289             :                 do {
     290          14 :                         if (off >= allocated_len) {
     291           0 :                                 allocated_len *= 2;
     292           0 :                                 buf = realloc(buf, allocated_len);
     293           0 :                                 if (buf == NULL) {
     294           0 :                                         warn("realloc failed");
     295           0 :                                         return (EPKG_FATAL);
     296             :                                 }
     297             :                         }
     298             : 
     299          14 :                         r = read(pair[1], buf + off, allocated_len - off);
     300          14 :                         if (r == -1 && errno != EINTR) {
     301           0 :                                 free(buf);
     302           0 :                                 warn("read failed");
     303           0 :                                 return (EPKG_FATAL);
     304             :                         }
     305          14 :                         else if (r > 0) {
     306           0 :                                 off += r;
     307             :                         }
     308          14 :                 } while (r > 0);
     309             : 
     310             :                 /* Fill the result buffer */
     311          14 :                 *len = off;
     312          14 :                 *result = buf;
     313          14 :                 if (*result == NULL) {
     314           0 :                         warn("malloc failed");
     315           0 :                         kill(pid, SIGTERM);
     316           0 :                         ret = EPKG_FATAL;
     317             :                 }
     318          28 :                 while (waitpid(pid, &status, 0) == -1) {
     319           0 :                         if (errno != EINTR) {
     320           0 :                                 warn("Sandboxed process pid=%d", (int)pid);
     321           0 :                                 ret = -1;
     322           0 :                                 break;
     323             :                         }
     324             :                 }
     325             : 
     326          14 :                 if (WIFEXITED(status)) {
     327          14 :                         ret = WEXITSTATUS(status);
     328             :                 }
     329          14 :                 if (WIFSIGNALED(status)) {
     330             :                         /* Process got some terminating signal, hence stop the loop */
     331           0 :                         fprintf(stderr, "Sandboxed process pid=%d terminated abnormally by signal: %d\n",
     332             :                                         (int)pid, WTERMSIG(status));
     333           0 :                         ret = -1;
     334             :                 }
     335          14 :                 return (ret);
     336             :         }
     337             : 
     338             :         /* Here comes child process */
     339           0 :         close(pair[1]);
     340             : 
     341             : #ifdef HAVE_CAPSICUM
     342           0 :         if (cap_enter() < 0 && errno != ENOSYS) {
     343           0 :                 warn("cap_enter() failed");
     344           0 :                 return (EPKG_FATAL);
     345             :         }
     346             : #endif
     347             : 
     348             :         /*
     349             :          * XXX: if capsicum is not enabled we basically have no idea of how to
     350             :          * make a sandbox
     351             :          */
     352           0 :         ret = func(pair[0], ud);
     353             : 
     354           0 :         close(pair[0]);
     355             : 
     356           0 :         _exit(ret);
     357             : }
     358             : 
     359             : void
     360         276 : progressbar_start(const char *pmsg)
     361             : {
     362         276 :         free(progress_message);
     363         276 :         progress_message = NULL;
     364             : 
     365         276 :         if (quiet)
     366         454 :                 return;
     367          98 :         if (pmsg != NULL)
     368          62 :                 progress_message = strdup(pmsg);
     369             :         else {
     370          36 :                 sbuf_finish(msg_buf);
     371          36 :                 progress_message = strdup(sbuf_data(msg_buf));
     372             :         }
     373          98 :         last_progress_percent = -1;
     374          98 :         last_tick = 0;
     375          98 :         begin = last_update = time(NULL);
     376          98 :         bytes_per_second = 0;
     377          98 :         stalled = 0;
     378             : 
     379          98 :         progress_started = true;
     380          98 :         progress_interrupted = false;
     381          98 :         if (!isatty(STDOUT_FILENO))
     382          98 :                 printf("%s: ", progress_message);
     383             :         else
     384           0 :                 printf("%s:   0%%", progress_message);
     385             : }
     386             : 
     387             : void
     388         378 : progressbar_tick(int64_t current, int64_t total)
     389             : {
     390             :         int percent;
     391             : 
     392         378 :         if (!quiet && progress_started) {
     393         180 :                 if (isatty(STDOUT_FILENO))
     394           0 :                         draw_progressbar(current, total);
     395             :                 else {
     396         180 :                         if (progress_interrupted) {
     397           0 :                                 printf("%s...", progress_message);
     398         180 :                         } else if (!getenv("NO_TICK")){
     399           0 :                                 percent = (total != 0) ? (current * 100. / total) : 100;
     400           0 :                                 if (last_progress_percent / 10 < percent / 10) {
     401           0 :                                         last_progress_percent = percent;
     402           0 :                                         printf(".");
     403           0 :                                         fflush(stdout);
     404             :                                 }
     405             :                         }
     406         180 :                         if (current >= total)
     407          76 :                                 progressbar_stop();
     408             :                 }
     409             :         }
     410         378 :         progress_interrupted = false;
     411         378 : }
     412             : 
     413             : void
     414          76 : progressbar_stop(void)
     415             : {
     416          76 :         if (progress_started) {
     417          76 :                 if (!isatty(STDOUT_FILENO))
     418          76 :                         printf(" done");
     419          76 :                 putchar('\n');
     420             :         }
     421          76 :         last_progress_percent = -1;
     422          76 :         progress_started = false;
     423          76 :         progress_interrupted = false;
     424          76 : }
     425             : 
     426             : static void
     427           0 : draw_progressbar(int64_t current, int64_t total)
     428             : {
     429             :         int percent;
     430             :         int64_t transferred;
     431           0 :         time_t elapsed = 0, now = 0;
     432             :         char buf[8];
     433             :         int64_t bytes_left;
     434             :         int cur_speed;
     435             :         int hours, minutes, seconds;
     436             :         float age_factor;
     437             : 
     438           0 :         if (!progress_started) {
     439           0 :                 progressbar_stop();
     440           0 :                 return;
     441             :         }
     442             : 
     443           0 :         if (progress_debit) {
     444           0 :                 now = time(NULL);
     445           0 :                 elapsed = (now >= last_update) ? now - last_update : 0;
     446             :         }
     447             : 
     448           0 :         percent = (total != 0) ? (current * 100. / total) : 100;
     449             : 
     450             :         /**
     451             :          * Wait for interval for debit bars to keep calc per second.
     452             :          * If not debit, show on every % change, or if ticking after
     453             :          * an interruption (which removed our progressbar output).
     454             :          */
     455           0 :         if (current >= total || (progress_debit && elapsed >= 1) ||
     456           0 :             (!progress_debit &&
     457           0 :             (percent != last_progress_percent || progress_interrupted))) {
     458           0 :                 last_progress_percent = percent;
     459             : 
     460           0 :                 printf("\r%s: %3d%%", progress_message, percent);
     461           0 :                 if (progress_debit) {
     462           0 :                         transferred = current - last_tick;
     463           0 :                         last_tick = current;
     464           0 :                         bytes_left = total - current;
     465           0 :                         if (bytes_left <= 0) {
     466           0 :                                 elapsed = now - begin;
     467             :                                 /* Always show at least 1 second at end. */
     468           0 :                                 if (elapsed == 0)
     469           0 :                                         elapsed = 1;
     470             :                                 /* Calculate true total speed when done */
     471           0 :                                 transferred = total;
     472           0 :                                 bytes_per_second = 0;
     473             :                         }
     474             : 
     475           0 :                         if (elapsed != 0)
     476           0 :                                 cur_speed = (transferred / elapsed);
     477             :                         else
     478           0 :                                 cur_speed = transferred;
     479             : 
     480             : #define AGE_FACTOR_SLOW_START 3
     481           0 :                         if (now - begin <= AGE_FACTOR_SLOW_START)
     482           0 :                                 age_factor = 0.4;
     483             :                         else
     484           0 :                                 age_factor = 0.9;
     485             : 
     486           0 :                         if (bytes_per_second != 0) {
     487           0 :                                 bytes_per_second =
     488           0 :                                     (bytes_per_second * age_factor) +
     489           0 :                                     (cur_speed * (1.0 - age_factor));
     490             :                         } else
     491           0 :                                 bytes_per_second = cur_speed;
     492             : 
     493           0 :                         humanize_number(buf, sizeof(buf),
     494             :                             current,"B", HN_AUTOSCALE, HN_IEC_PREFIXES);
     495           0 :                         printf(" %*s", (int)sizeof(buf), buf);
     496             : 
     497           0 :                         if (bytes_left > 0)
     498           0 :                                 format_rate_SI(buf, sizeof(buf), transferred);
     499             :                         else /* Show overall speed when done */
     500           0 :                                 format_rate_SI(buf, sizeof(buf),
     501             :                                     bytes_per_second);
     502           0 :                         printf(" %s/s ", buf);
     503             : 
     504           0 :                         if (!transferred)
     505           0 :                                 stalled += elapsed;
     506             :                         else
     507           0 :                                 stalled = 0;
     508             : 
     509           0 :                         if (stalled >= STALL_TIME)
     510           0 :                                 printf(" - stalled -");
     511           0 :                         else if (bytes_per_second == 0 && bytes_left > 0)
     512           0 :                                 printf("   --:-- ETA");
     513             :                         else {
     514           0 :                                 if (bytes_left > 0)
     515           0 :                                         seconds = bytes_left / bytes_per_second;
     516             :                                 else
     517           0 :                                         seconds = elapsed;
     518             : 
     519           0 :                                 hours = seconds / 3600;
     520           0 :                                 seconds -= hours * 3600;
     521           0 :                                 minutes = seconds / 60;
     522           0 :                                 seconds -= minutes * 60;
     523             : 
     524           0 :                                 if (hours != 0)
     525           0 :                                         printf("%02d:%02d:%02d", hours,
     526             :                                             minutes, seconds);
     527             :                                 else
     528           0 :                                         printf("   %02d:%02d", minutes, seconds);
     529             : 
     530           0 :                                 if (bytes_left > 0)
     531           0 :                                         printf(" ETA");
     532             :                                 else
     533           0 :                                         printf("    ");
     534             :                         }
     535           0 :                         last_update = now;
     536             :                 }
     537           0 :                 fflush(stdout);
     538             :         }
     539           0 :         if (current >= total)
     540           0 :                 progressbar_stop();
     541             : }
     542             : 
     543             : int
     544         912 : event_callback(void *data, struct pkg_event *ev)
     545             : {
     546         912 :         struct pkg *pkg = NULL, *pkg_new, *pkg_old;
     547         912 :         int *debug = data;
     548             :         struct pkg_event_conflict *cur_conflict;
     549             :         const char *filename;
     550             : 
     551         912 :         if (msg_buf == NULL) {
     552         140 :                 msg_buf = sbuf_new_auto();
     553             :         }
     554             : 
     555             :         /*
     556             :          * If a progressbar has been interrupted by another event, then
     557             :          * we need to add a newline to prevent bad formatting.
     558             :          */
     559         912 :         if (progress_started && ev->type != PKG_EVENT_PROGRESS_TICK &&
     560           0 :             !progress_interrupted) {
     561           0 :                 putchar('\n');
     562           0 :                 progress_interrupted = true;
     563             :         }
     564             : 
     565         912 :         switch(ev->type) {
     566             :         case PKG_EVENT_ERRNO:
     567           0 :                 warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg,
     568             :                     strerror(ev->e_errno.no));
     569           0 :                 break;
     570             :         case PKG_EVENT_ERROR:
     571          14 :                 warnx("%s", ev->e_pkg_error.msg);
     572          14 :                 break;
     573             :         case PKG_EVENT_NOTICE:
     574           0 :                 if (!quiet)
     575           0 :                         printf("%s\n", ev->e_pkg_notice.msg);
     576           0 :                 break;
     577             :         case PKG_EVENT_DEVELOPER_MODE:
     578           0 :                 warnx("DEVELOPER_MODE: %s", ev->e_pkg_error.msg);
     579           0 :                 break;
     580             :         case PKG_EVENT_UPDATE_ADD:
     581           0 :                 if (quiet || !isatty(STDOUT_FILENO))
     582             :                         break;
     583           0 :                 printf("\rPushing new entries %d/%d", ev->e_upd_add.done, ev->e_upd_add.total);
     584           0 :                 if (ev->e_upd_add.total == ev->e_upd_add.done)
     585           0 :                         printf("\n");
     586           0 :                 break;
     587             :         case PKG_EVENT_UPDATE_REMOVE:
     588           0 :                 if (quiet || !isatty(STDOUT_FILENO))
     589             :                         break;
     590           0 :                 printf("\rRemoving entries %d/%d", ev->e_upd_remove.done, ev->e_upd_remove.total);
     591           0 :                 if (ev->e_upd_remove.total == ev->e_upd_remove.done)
     592           0 :                         printf("\n");
     593           0 :                 break;
     594             :         case PKG_EVENT_FETCH_BEGIN:
     595          14 :                 if (quiet)
     596           0 :                         break;
     597          14 :                 filename = strrchr(ev->e_fetching.url, '/');
     598          14 :                 if (filename != NULL) {
     599          14 :                         filename++;
     600             :                 } else {
     601             :                         /*
     602             :                          * We failed at being smart, so display
     603             :                          * the entire url.
     604             :                          */
     605           0 :                         filename = ev->e_fetching.url;
     606             :                 }
     607          14 :                 job_status_begin(msg_buf);
     608          14 :                 progress_debit = true;
     609          14 :                 sbuf_printf(msg_buf, "Fetching %s", filename);
     610             : 
     611          14 :                 break;
     612             :         case PKG_EVENT_FETCH_FINISHED:
     613          14 :                 progress_debit = false;
     614          14 :                 break;
     615             :         case PKG_EVENT_INSTALL_BEGIN:
     616          42 :                 if (quiet)
     617           1 :                         break;
     618             :                 else {
     619          41 :                         nbdone++;
     620          41 :                         job_status_begin(msg_buf);
     621             : 
     622          41 :                         pkg = ev->e_install_begin.pkg;
     623          41 :                         pkg_sbuf_printf(msg_buf, "Installing %n-%v...\n", pkg,
     624             :                             pkg);
     625          41 :                         sbuf_finish(msg_buf);
     626          41 :                         printf("%s", sbuf_data(msg_buf));
     627             :                 }
     628          41 :                 break;
     629             :         case PKG_EVENT_INSTALL_FINISHED:
     630          39 :                 if (quiet)
     631           1 :                         break;
     632          38 :                 pkg = ev->e_install_finished.pkg;
     633          38 :                 if (pkg_has_message(pkg)) {
     634           0 :                         if (messages == NULL)
     635           0 :                                 messages = sbuf_new_auto();
     636           0 :                         pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n",
     637             :                             pkg, pkg, pkg);
     638             :                 }
     639          38 :                 break;
     640             :         case PKG_EVENT_EXTRACT_BEGIN:
     641          18 :                 if (quiet)
     642           1 :                         break;
     643             :                 else {
     644          17 :                         job_status_begin(msg_buf);
     645          17 :                         pkg = ev->e_install_begin.pkg;
     646          17 :                         pkg_sbuf_printf(msg_buf, "Extracting %n-%v", pkg, pkg);
     647             :                 }
     648          17 :                 break;
     649             :         case PKG_EVENT_EXTRACT_FINISHED:
     650          18 :                 break;
     651             :         case PKG_EVENT_ADD_DEPS_BEGIN:
     652          11 :                 ++add_deps_depth;
     653          11 :                 break;
     654             :         case PKG_EVENT_ADD_DEPS_FINISHED:
     655          11 :                 --add_deps_depth;
     656          11 :                 break;
     657             :         case PKG_EVENT_INTEGRITYCHECK_BEGIN:
     658          15 :                 if (quiet)
     659           0 :                         break;
     660          15 :                 printf("Checking integrity...");
     661          15 :                 break;
     662             :         case PKG_EVENT_INTEGRITYCHECK_FINISHED:
     663          15 :                 if (quiet)
     664           0 :                         break;
     665          15 :                 printf(" done (%d conflicting)\n", ev->e_integrity_finished.conflicting);
     666          15 :                 break;
     667             :         case PKG_EVENT_INTEGRITYCHECK_CONFLICT:
     668           0 :                 if (*debug == 0)
     669           0 :                         break;
     670           0 :                 printf("\nConflict found on path %s between %s and ",
     671             :                     ev->e_integrity_conflict.pkg_path,
     672             :                     ev->e_integrity_conflict.pkg_uid);
     673           0 :                 cur_conflict = ev->e_integrity_conflict.conflicts;
     674           0 :                 while (cur_conflict) {
     675           0 :                         if (cur_conflict->next)
     676           0 :                                 printf("%s, ", cur_conflict->uid);
     677             :                         else
     678           0 :                                 printf("%s", cur_conflict->uid);
     679             : 
     680           0 :                         cur_conflict = cur_conflict->next;
     681             :                 }
     682           0 :                 printf("\n");
     683           0 :                 break;
     684             :         case PKG_EVENT_DEINSTALL_BEGIN:
     685           6 :                 if (quiet)
     686           0 :                         break;
     687           6 :                 nbdone++;
     688             : 
     689           6 :                 job_status_begin(msg_buf);
     690             : 
     691           6 :                 pkg = ev->e_install_begin.pkg;
     692           6 :                 pkg_sbuf_printf(msg_buf, "Deinstalling %n-%v...\n", pkg, pkg);
     693           6 :                 sbuf_finish(msg_buf);
     694           6 :                 printf("%s", sbuf_data(msg_buf));
     695           6 :                 break;
     696             :         case PKG_EVENT_DEINSTALL_FINISHED:
     697           6 :                 if (quiet)
     698           0 :                         break;
     699           6 :                 break;
     700             :         case PKG_EVENT_DELETE_FILES_BEGIN:
     701           5 :                 if (quiet)
     702           0 :                         break;
     703             :                 else {
     704           5 :                         job_status_begin(msg_buf);
     705           5 :                         pkg = ev->e_install_begin.pkg;
     706           5 :                         pkg_sbuf_printf(msg_buf, "Deleting files for %n-%v",
     707             :                             pkg, pkg);
     708             :                 }
     709           5 :                 break;
     710             :         case PKG_EVENT_DELETE_FILES_FINISHED:
     711           5 :                 break;
     712             :         case PKG_EVENT_UPGRADE_BEGIN:
     713           0 :                 if (quiet)
     714           0 :                         break;
     715           0 :                 pkg_new = ev->e_upgrade_begin.n;
     716           0 :                 pkg_old = ev->e_upgrade_begin.o;
     717           0 :                 nbdone++;
     718             : 
     719           0 :                 job_status_begin(msg_buf);
     720             : 
     721           0 :                 switch (pkg_version_change_between(pkg_new, pkg_old)) {
     722             :                 case PKG_DOWNGRADE:
     723           0 :                         pkg_sbuf_printf(msg_buf, "Downgrading %n from %v to %v...\n",
     724             :                             pkg_new, pkg_old, pkg_new);
     725           0 :                         break;
     726             :                 case PKG_REINSTALL:
     727           0 :                         pkg_sbuf_printf(msg_buf, "Reinstalling %n-%v...\n",
     728             :                     pkg_old, pkg_old);
     729           0 :                         break;
     730             :                 case PKG_UPGRADE:
     731           0 :                         pkg_sbuf_printf(msg_buf, "Upgrading %n from %v to %v...\n",
     732             :                             pkg_new, pkg_old, pkg_new);
     733           0 :                         break;
     734             :                 }
     735           0 :                 sbuf_finish(msg_buf);
     736           0 :                 printf("%s", sbuf_data(msg_buf));
     737           0 :                 break;
     738             :         case PKG_EVENT_UPGRADE_FINISHED:
     739           0 :                 if (quiet)
     740           0 :                         break;
     741           0 :                 pkg_new = ev->e_upgrade_finished.n;
     742           0 :                 if (pkg_has_message(pkg_new)) {
     743           0 :                         if (messages == NULL)
     744           0 :                                 messages = sbuf_new_auto();
     745           0 :                         pkg_sbuf_printf(messages, "Message for %n-%v:\n %M\n",
     746             :                                 pkg_new, pkg_new, pkg_new);
     747             :                 }
     748           0 :                 break;
     749             :         case PKG_EVENT_LOCKED:
     750           0 :                 pkg = ev->e_locked.pkg;
     751           0 :                 pkg_printf("\n%n-%v is locked and may not be modified\n", pkg, pkg);
     752           0 :                 break;
     753             :         case PKG_EVENT_REQUIRED:
     754           0 :                 pkg = ev->e_required.pkg;
     755           0 :                 pkg_printf("\n%n-%v is required by: %r%{%rn-%rv%| %}", pkg, pkg, pkg);
     756           0 :                 if (ev->e_required.force == 1)
     757           0 :                         fprintf(stderr, ", deleting anyway\n");
     758             :                 else
     759           0 :                         fprintf(stderr, "\n");
     760           0 :                 break;
     761             :         case PKG_EVENT_ALREADY_INSTALLED:
     762           0 :                 if (quiet)
     763           0 :                         break;
     764           0 :                 pkg = ev->e_already_installed.pkg;
     765           0 :                 pkg_printf("the most recent version of %n-%v is already installed\n",
     766             :                                 pkg, pkg);
     767           0 :                 break;
     768             :         case PKG_EVENT_NOT_FOUND:
     769           0 :                 printf("Package '%s' was not found in "
     770             :                     "the repositories\n", ev->e_not_found.pkg_name);
     771           0 :                 break;
     772             :         case PKG_EVENT_MISSING_DEP:
     773           4 :                 warnx("Missing dependency '%s'",
     774           4 :                     pkg_dep_name(ev->e_missing_dep.dep));
     775           4 :                 break;
     776             :         case PKG_EVENT_NOREMOTEDB:
     777           0 :                 fprintf(stderr, "Unable to open remote database \"%s\". "
     778             :                     "Try running '%s update' first.\n", ev->e_remotedb.repo,
     779             :                     getprogname());
     780           0 :                 break;
     781             :         case PKG_EVENT_NOLOCALDB:
     782           0 :                 fprintf(stderr, "Local package database nonexistent!\n");
     783           0 :                 break;
     784             :         case PKG_EVENT_NEWPKGVERSION:
     785           0 :                 newpkgversion = true;
     786           0 :                 printf("New version of pkg detected; it needs to be "
     787             :                     "installed first.\n");
     788           0 :                 break;
     789             :         case PKG_EVENT_FILE_MISMATCH:
     790           0 :                 pkg = ev->e_file_mismatch.pkg;
     791           0 :                 pkg_fprintf(stderr, "%n-%v: checksum mismatch for %Fn\n", pkg,
     792             :                     pkg, ev->e_file_mismatch.file);
     793           0 :                 break;
     794             :         case PKG_EVENT_PLUGIN_ERRNO:
     795           0 :                 warnx("%s: %s(%s): %s",
     796             :                     pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
     797             :                     ev->e_plugin_errno.func, ev->e_plugin_errno.arg,
     798             :                     strerror(ev->e_plugin_errno.no));
     799           0 :                 break;
     800             :         case PKG_EVENT_PLUGIN_ERROR:
     801           0 :                 warnx("%s: %s",
     802             :                     pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
     803             :                     ev->e_plugin_error.msg);
     804           0 :                 break;
     805             :         case PKG_EVENT_PLUGIN_INFO:
     806           0 :                 if (quiet)
     807           0 :                         break;
     808           0 :                 printf("%s: %s\n",
     809             :                     pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
     810             :                     ev->e_plugin_info.msg);
     811           0 :                 break;
     812             :         case PKG_EVENT_INCREMENTAL_UPDATE:
     813           7 :                 if (!quiet)
     814           7 :                         printf("%s repository update completed. %d packages processed.\n",
     815             :                             ev->e_incremental_update.reponame,
     816             :                             ev->e_incremental_update.processed);
     817           7 :                 break;
     818             :         case PKG_EVENT_DEBUG:
     819           0 :                 fprintf(stderr, "DBG(%d)[%d]> %s\n", ev->e_debug.level,
     820             :                         (int)getpid(), ev->e_debug.msg);
     821           0 :                 break;
     822             :         case PKG_EVENT_QUERY_YESNO:
     823           0 :                 return ( ev->e_query_yesno.deft ?
     824           0 :                         query_yesno(true, ev->e_query_yesno.msg, "[Y/n]") :
     825           0 :                         query_yesno(false, ev->e_query_yesno.msg, "[y/N]") );
     826             :                 break;
     827             :         case PKG_EVENT_QUERY_SELECT:
     828           0 :                 return query_select(ev->e_query_select.msg, ev->e_query_select.items,
     829             :                         ev->e_query_select.ncnt, ev->e_query_select.deft);
     830             :                 break;
     831             :         case PKG_EVENT_SANDBOX_CALL:
     832           0 :                 return ( event_sandboxed_call(ev->e_sandbox_call.call,
     833             :                                 ev->e_sandbox_call.fd,
     834             :                                 ev->e_sandbox_call.userdata) );
     835             :                 break;
     836             :         case PKG_EVENT_SANDBOX_GET_STRING:
     837          14 :                 return ( event_sandboxed_get_string(ev->e_sandbox_call_str.call,
     838             :                                 ev->e_sandbox_call_str.result,
     839             :                                 ev->e_sandbox_call_str.len,
     840             :                                 ev->e_sandbox_call_str.userdata) );
     841             :                 break;
     842             :         case PKG_EVENT_PROGRESS_START:
     843         276 :                 progressbar_start(ev->e_progress_start.msg);
     844         276 :                 break;
     845             :         case PKG_EVENT_PROGRESS_TICK:
     846         378 :                 progressbar_tick(ev->e_progress_tick.current,
     847             :                     ev->e_progress_tick.total);
     848         378 :                 break;
     849             :         case PKG_EVENT_BACKUP:
     850           0 :                 sbuf_cat(msg_buf, "Backing up");
     851           0 :                 sbuf_finish(msg_buf);
     852           0 :                 break;
     853             :         case PKG_EVENT_RESTORE:
     854           0 :                 sbuf_cat(msg_buf, "Restoring");
     855           0 :                 sbuf_finish(msg_buf);
     856           0 :                 break;
     857             :         default:
     858           0 :                 break;
     859             :         }
     860             : 
     861         898 :         return 0;
     862             : }

Generated by: LCOV version 1.10