Branch data 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/resource.h>
37 : : #include <sys/types.h>
38 : : #ifdef HAVE_LIBJAIL
39 : : #include <sys/sysctl.h>
40 : : #endif
41 : : #include <sys/wait.h>
42 : : #include <sys/socket.h>
43 : :
44 : : #ifdef HAVE_CAPSICUM
45 : : #include <sys/capsicum.h>
46 : : #endif
47 : :
48 : : #include <err.h>
49 : : #include <string.h>
50 : : #include <unistd.h>
51 : : #include <errno.h>
52 : : #include <time.h>
53 : : #include <signal.h>
54 : : #ifdef HAVE_LIBUTIL_H
55 : : #include <libutil.h>
56 : : #endif
57 : : #include <tllist.h>
58 : :
59 : : #include <bsd_compat.h>
60 : :
61 : : #include "pkg.h"
62 : : #include "pkgcli.h"
63 : : #include "xmalloc.h"
64 : :
65 : : #define STALL_TIME 5
66 : :
67 : : xstring *messages = NULL;
68 : : xstring *conflicts = NULL;
69 : :
70 : : struct cleanup {
71 : : void *data;
72 : : void (*cb)(void *);
73 : : };
74 : :
75 : : static char *progress_message = NULL;
76 : : static xstring *msg_buf = NULL;
77 : : static int last_progress_percent = -1;
78 : : static bool progress_started = false;
79 : : static bool progress_interrupted = false;
80 : : static bool progress_debit = false;
81 : : static int64_t last_tick = 0;
82 : : static int64_t stalled;
83 : : static int64_t bytes_per_second;
84 : : static time_t last_update;
85 : : static time_t begin = 0;
86 : : static int add_deps_depth;
87 : : static tll(struct cleanup *) cleanup_list = tll_init();
88 : : static bool signal_handler_installed = false;
89 : :
90 : : /* units for format_size */
91 : : static const char *unit_SI[] = { " ", "k", "M", "G", "T", };
92 : :
93 : : static void draw_progressbar(int64_t current, int64_t total);
94 : :
95 : : static void
96 : 0 : cleanup_handler(int dummy __unused)
97 : : {
98 : : struct cleanup *ev;
99 : :
100 [ # # ]: 0 : if (tll_length(cleanup_list) == 0)
101 : 0 : return;
102 : 0 : warnx("\nsignal received, cleaning up");
103 [ # # # # : 0 : tll_foreach(cleanup_list, it) {
# # ]
104 : 0 : ev = it->item;
105 : 0 : ev->cb(ev->data);
106 : 0 : }
107 : 0 : exit(1);
108 : : }
109 : :
110 : : static void
111 : 0 : format_rate_SI(char *buf, int size, off_t bytes)
112 : : {
113 : : int i;
114 : :
115 : 0 : bytes *= 100;
116 [ # # # # : 0 : for (i = 0; bytes >= 100*1000 && unit_SI[i][0] != 'T'; i++)
# # ]
117 : 0 : bytes = (bytes + 500) / 1000;
118 [ # # ]: 0 : if (i == 0) {
119 : 0 : i++;
120 : 0 : bytes = (bytes + 500) / 1000;
121 : 0 : }
122 : 0 : snprintf(buf, size, "%3lld.%1lld%sB",
123 : 0 : (long long) (bytes + 5) / 100,
124 : 0 : (long long) (bytes + 5) / 10 % 10,
125 : 0 : unit_SI[i]);
126 : 0 : }
127 : :
128 : : void
129 : 0 : job_status_end(xstring *msg)
130 : : {
131 : 0 : fflush(msg->fp);
132 : 0 : printf("%s\n", msg->buf);
133 : 0 : xstring_reset(msg);
134 : 0 : }
135 : :
136 : : void
137 : 425 : job_status_begin(xstring *msg)
138 : : {
139 : : int n;
140 : :
141 : 425 : xstring_reset(msg);
142 : : #ifdef HAVE_LIBJAIL
143 : : static char hostname[MAXHOSTNAMELEN] = "";
144 : : static int jailed = -1;
145 : : size_t intlen;
146 : :
147 [ + + ]: 425 : if (jailed == -1) {
148 : 198 : intlen = sizeof(jailed);
149 [ + - + - ]: 396 : if (sysctlbyname("security.jail.jailed", &jailed, &intlen,
150 : 198 : NULL, 0) == -1)
151 : 0 : jailed = 0;
152 : 198 : }
153 : :
154 [ + - ]: 425 : if (jailed == 1) {
155 [ # # ]: 0 : if (hostname[0] == '\0')
156 : 0 : gethostname(hostname, sizeof(hostname));
157 : :
158 : 0 : fprintf(msg->fp, "[%s] ", hostname);
159 : 0 : }
160 : : #endif
161 : :
162 : : /* Only used for pkg-add right now. */
163 [ + + ]: 425 : if (add_deps_depth) {
164 [ + - ]: 5 : if (add_deps_depth > 1) {
165 [ # # ]: 0 : for (n = 0; n < (2 * add_deps_depth); ++n) {
166 [ # # # # ]: 0 : if (n % 4 == 0 && n < (2 * add_deps_depth))
167 : 0 : fprintf(msg->fp, "|");
168 : : else
169 : 0 : fprintf(msg->fp, " ");
170 : 0 : }
171 : 0 : }
172 : 5 : fprintf(msg->fp, "`-- ");
173 : 5 : }
174 : :
175 [ + + + + : 425 : if ((nbtodl > 0 || nbactions > 0) && nbdone > 0)
+ + ]
176 [ + + ]: 189 : fprintf(msg->fp, "[%d/%d] ", nbdone, (nbtodl) ? nbtodl : nbactions);
177 [ + + - + ]: 425 : if (nbtodl > 0 && nbtodl == nbdone) {
178 : 13 : nbtodl = 0;
179 : 13 : nbdone = 0;
180 : 13 : }
181 : 425 : }
182 : :
183 : : void
184 : 1374 : progressbar_start(const char *pmsg)
185 : : {
186 [ + + ]: 1374 : if (progress_message) {
187 : 308 : free(progress_message);
188 : 308 : progress_message = NULL;
189 : 308 : }
190 : :
191 [ + + ]: 1374 : if (quiet)
192 : 883 : return;
193 [ + + ]: 491 : if (pmsg != NULL)
194 : 285 : progress_message = xstrdup(pmsg);
195 : : else {
196 : 206 : fflush(msg_buf->fp);
197 : 206 : progress_message = xstrdup(msg_buf->buf);
198 : : }
199 : 491 : last_progress_percent = -1;
200 : 491 : last_tick = 0;
201 : 491 : begin = last_update = time(NULL);
202 : 491 : bytes_per_second = 0;
203 : 491 : stalled = 0;
204 : :
205 : 491 : progress_started = true;
206 : 491 : progress_interrupted = false;
207 [ - + ]: 491 : if (!isatty(STDOUT_FILENO))
208 : 491 : printf("%s: ", progress_message);
209 : : else
210 : 0 : printf("%s: 0%%", progress_message);
211 : 1374 : }
212 : :
213 : : void
214 : 2246 : progressbar_tick(int64_t current, int64_t total)
215 : : {
216 : : int percent;
217 : :
218 [ + + + + ]: 2246 : if (!quiet && progress_started) {
219 [ - + ]: 1043 : if (isatty(STDOUT_FILENO))
220 : 0 : draw_progressbar(current, total);
221 : : else {
222 [ + + ]: 1043 : if (progress_interrupted) {
223 : 6 : printf("%s...", progress_message);
224 [ + - ]: 1043 : } else if (!getenv("NO_TICK")){
225 [ # # ]: 0 : percent = (total != 0) ? (current * 100. / total) : 100;
226 [ # # ]: 0 : if (last_progress_percent / 10 < percent / 10) {
227 : 0 : last_progress_percent = percent;
228 [ # # ]: 0 : putchar('.');
229 : 0 : fflush(stdout);
230 : 0 : }
231 : 0 : }
232 [ + + ]: 1043 : if (current >= total)
233 : 488 : progressbar_stop();
234 : : }
235 : 1043 : }
236 : 2246 : progress_interrupted = false;
237 : 2246 : }
238 : :
239 : : void
240 : 488 : progressbar_stop(void)
241 : : {
242 [ - + ]: 488 : if (progress_started) {
243 [ - + ]: 488 : if (!isatty(STDOUT_FILENO))
244 : 488 : printf(" done");
245 [ + + ]: 488 : putchar('\n');
246 : 488 : }
247 : 488 : last_progress_percent = -1;
248 : 488 : progress_started = false;
249 : 488 : progress_interrupted = false;
250 : 488 : }
251 : :
252 : : static void
253 : 0 : draw_progressbar(int64_t current, int64_t total)
254 : : {
255 : : int percent;
256 : : int64_t transferred;
257 : 0 : time_t elapsed = 0, now = 0;
258 : : char buf[8];
259 : : int64_t bytes_left;
260 : : int cur_speed;
261 : : int hours, minutes, seconds;
262 : : float age_factor;
263 : :
264 [ # # ]: 0 : if (!progress_started) {
265 : 0 : progressbar_stop();
266 : 0 : return;
267 : : }
268 : :
269 [ # # ]: 0 : if (progress_debit) {
270 : 0 : now = time(NULL);
271 [ # # ]: 0 : elapsed = (now >= last_update) ? now - last_update : 0;
272 : 0 : }
273 : :
274 [ # # ]: 0 : percent = (total != 0) ? (current * 100. / total) : 100;
275 : :
276 : : /**
277 : : * Wait for interval for debit bars to keep calc per second.
278 : : * If not debit, show on every % change, or if ticking after
279 : : * an interruption (which removed our progressbar output).
280 : : */
281 [ # # # # : 0 : if (current >= total || (progress_debit && elapsed >= 1) ||
# # # # ]
282 [ # # ]: 0 : (!progress_debit &&
283 [ # # ]: 0 : (percent != last_progress_percent || progress_interrupted))) {
284 : 0 : last_progress_percent = percent;
285 : :
286 : 0 : printf("\r%s: %3d%%", progress_message, percent);
287 [ # # ]: 0 : if (progress_debit) {
288 : 0 : transferred = current - last_tick;
289 : 0 : last_tick = current;
290 : 0 : bytes_left = total - current;
291 [ # # ]: 0 : if (bytes_left <= 0) {
292 : 0 : elapsed = now - begin;
293 : : /* Always show at least 1 second at end. */
294 [ # # ]: 0 : if (elapsed == 0)
295 : 0 : elapsed = 1;
296 : : /* Calculate true total speed when done */
297 : 0 : transferred = total;
298 : 0 : bytes_per_second = 0;
299 : 0 : }
300 : :
301 [ # # ]: 0 : if (elapsed != 0)
302 : 0 : cur_speed = (transferred / elapsed);
303 : : else
304 : 0 : cur_speed = transferred;
305 : :
306 : : #define AGE_FACTOR_SLOW_START 3
307 [ # # ]: 0 : if (now - begin <= AGE_FACTOR_SLOW_START)
308 : 0 : age_factor = 0.4;
309 : : else
310 : 0 : age_factor = 0.9;
311 : :
312 [ # # ]: 0 : if (bytes_per_second != 0) {
313 : 0 : bytes_per_second =
314 : 0 : (bytes_per_second * age_factor) +
315 : 0 : (cur_speed * (1.0 - age_factor));
316 : 0 : } else
317 : 0 : bytes_per_second = cur_speed;
318 : :
319 : 0 : humanize_number(buf, sizeof(buf),
320 : 0 : current,"B", HN_AUTOSCALE, HN_IEC_PREFIXES);
321 : 0 : printf(" %*s", (int)sizeof(buf), buf);
322 : :
323 [ # # ]: 0 : if (bytes_left > 0)
324 : 0 : format_rate_SI(buf, sizeof(buf), transferred);
325 : : else /* Show overall speed when done */
326 : 0 : format_rate_SI(buf, sizeof(buf),
327 : 0 : bytes_per_second);
328 : 0 : printf(" %s/s ", buf);
329 : :
330 [ # # ]: 0 : if (!transferred)
331 : 0 : stalled += elapsed;
332 : : else
333 : 0 : stalled = 0;
334 : :
335 [ # # ]: 0 : if (stalled >= STALL_TIME)
336 : 0 : printf(" - stalled -");
337 [ # # # # ]: 0 : else if (bytes_per_second == 0 && bytes_left > 0)
338 : 0 : printf(" --:-- ETA");
339 : : else {
340 [ # # ]: 0 : if (bytes_left > 0)
341 : 0 : seconds = bytes_left / bytes_per_second;
342 : : else
343 : 0 : seconds = elapsed;
344 : :
345 : 0 : hours = seconds / 3600;
346 : 0 : seconds -= hours * 3600;
347 : 0 : minutes = seconds / 60;
348 : 0 : seconds -= minutes * 60;
349 : :
350 [ # # ]: 0 : if (hours != 0)
351 : 0 : printf("%02d:%02d:%02d", hours,
352 : 0 : minutes, seconds);
353 : : else
354 : 0 : printf(" %02d:%02d", minutes, seconds);
355 : :
356 [ # # ]: 0 : if (bytes_left > 0)
357 : 0 : printf(" ETA");
358 : : else
359 : 0 : printf(" ");
360 : : }
361 : 0 : last_update = now;
362 : 0 : }
363 : 0 : fflush(stdout);
364 : 0 : }
365 [ # # ]: 0 : if (current >= total)
366 : 0 : progressbar_stop();
367 : 0 : }
368 : :
369 : : int
370 : 6695 : event_callback(void *data, struct pkg_event *ev)
371 : : {
372 : 6695 : struct pkg *pkg = NULL, *pkg_new, *pkg_old;
373 : : struct cleanup *evtmp;
374 : 6695 : int *debug = data;
375 : : struct pkg_event_conflict *cur_conflict;
376 : 6695 : const char *filename, *reponame = NULL;
377 : :
378 [ + + ]: 6695 : if (msg_buf == NULL) {
379 : 673 : msg_buf = xstring_new();
380 : 673 : }
381 : :
382 : : /*
383 : : * If a progressbar has been interrupted by another event, then
384 : : * we need to add a newline to prevent bad formatting.
385 : : */
386 [ + + + + : 6695 : if (progress_started && ev->type != PKG_EVENT_PROGRESS_TICK &&
+ + ]
387 : 33 : !progress_interrupted) {
388 [ - + ]: 9 : putchar('\n');
389 : 9 : progress_interrupted = true;
390 : 9 : }
391 : :
392 [ - + + - : 6695 : switch(ev->type) {
+ + + + +
- - + - -
+ - - - -
+ + - + +
+ + - + +
+ - - + +
+ + + + -
+ + + + +
- - - - -
+ + + + ]
393 : : case PKG_EVENT_ERRNO:
394 : 0 : warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg,
395 : 0 : strerror(ev->e_errno.no));
396 : 0 : break;
397 : : case PKG_EVENT_ERROR:
398 : 104 : warnx("%s", ev->e_pkg_error.msg);
399 : 104 : break;
400 : : case PKG_EVENT_NOTICE:
401 [ + + ]: 23 : if (!quiet)
402 : 22 : printf("%s\n", ev->e_pkg_notice.msg);
403 : 23 : break;
404 : : case PKG_EVENT_DEVELOPER_MODE:
405 : 0 : warnx("DEVELOPER_MODE: %s", ev->e_pkg_error.msg);
406 : 0 : break;
407 : : case PKG_EVENT_UPDATE_ADD:
408 [ # # # # ]: 0 : if (quiet || !isatty(STDOUT_FILENO))
409 : 0 : break;
410 : 0 : printf("\rPushing new entries %d/%d", ev->e_upd_add.done, ev->e_upd_add.total);
411 [ # # ]: 0 : if (ev->e_upd_add.total == ev->e_upd_add.done)
412 [ # # ]: 0 : putchar('\n');
413 : 0 : break;
414 : : case PKG_EVENT_UPDATE_REMOVE:
415 [ # # # # ]: 0 : if (quiet || !isatty(STDOUT_FILENO))
416 : 0 : break;
417 : 0 : printf("\rRemoving entries %d/%d", ev->e_upd_remove.done, ev->e_upd_remove.total);
418 [ # # ]: 0 : if (ev->e_upd_remove.total == ev->e_upd_remove.done)
419 [ # # ]: 0 : putchar('\n');
420 : 0 : break;
421 : : case PKG_EVENT_FETCH_BEGIN:
422 [ + + ]: 150 : if (nbtodl > 0)
423 : 1 : nbdone++;
424 [ + + ]: 150 : if (quiet)
425 : 22 : break;
426 : 128 : filename = strrchr(ev->e_fetching.url, '/');
427 [ + - ]: 128 : if (filename != NULL) {
428 : 128 : filename++;
429 : 128 : } else {
430 : : /*
431 : : * We failed at being smart, so display
432 : : * the entire url.
433 : : */
434 : 0 : filename = ev->e_fetching.url;
435 : : }
436 : 128 : job_status_begin(msg_buf);
437 : 128 : progress_debit = true;
438 : 128 : fprintf(msg_buf->fp, "Fetching %s", filename);
439 : 128 : break;
440 : : case PKG_EVENT_FETCH_FINISHED:
441 : 150 : progress_debit = false;
442 : 150 : break;
443 : : case PKG_EVENT_INSTALL_BEGIN:
444 [ + + ]: 215 : if (quiet)
445 : 58 : break;
446 : 157 : job_status_begin(msg_buf);
447 : :
448 : 157 : pkg = ev->e_install_begin.pkg;
449 : 314 : pkg_fprintf(msg_buf->fp, "Installing %n-%v...\n", pkg,
450 : 157 : pkg);
451 : 157 : fflush(msg_buf->fp);
452 : 157 : printf("%s", msg_buf->buf);
453 : 157 : break;
454 : : case PKG_EVENT_INSTALL_FINISHED:
455 [ + + ]: 210 : if (quiet)
456 : 58 : break;
457 : 152 : break;
458 : : case PKG_EVENT_EXTRACT_BEGIN:
459 [ + + ]: 110 : if (quiet)
460 : 50 : break;
461 : : else {
462 : 60 : job_status_begin(msg_buf);
463 : 60 : pkg = ev->e_install_begin.pkg;
464 : 60 : pkg_fprintf(msg_buf->fp, "Extracting %n-%v", pkg, pkg);
465 : 60 : fflush(msg_buf->fp);
466 : : }
467 : 60 : break;
468 : : case PKG_EVENT_EXTRACT_FINISHED:
469 : 110 : break;
470 : : case PKG_EVENT_ADD_DEPS_BEGIN:
471 : 17 : ++add_deps_depth;
472 : 17 : break;
473 : : case PKG_EVENT_ADD_DEPS_FINISHED:
474 : 17 : --add_deps_depth;
475 : 17 : break;
476 : : case PKG_EVENT_INTEGRITYCHECK_BEGIN:
477 [ + + ]: 171 : if (quiet)
478 : 71 : break;
479 : 100 : printf("Checking integrity...");
480 : 100 : break;
481 : : case PKG_EVENT_INTEGRITYCHECK_FINISHED:
482 [ + + ]: 171 : if (quiet)
483 : 71 : break;
484 : 100 : printf(" done (%d conflicting)\n", ev->e_integrity_finished.conflicting);
485 [ + + ]: 100 : if (conflicts != NULL) {
486 : 11 : fflush(conflicts->fp);
487 : 11 : printf("%s", conflicts->buf);
488 : 11 : xstring_free(conflicts);
489 : 11 : conflicts = NULL;
490 : 11 : }
491 : 100 : break;
492 : : case PKG_EVENT_INTEGRITYCHECK_CONFLICT:
493 [ # # ]: 0 : if (*debug == 0)
494 : 0 : break;
495 : 0 : printf("\nConflict found on path %s between %s and ",
496 : 0 : ev->e_integrity_conflict.pkg_path,
497 : 0 : ev->e_integrity_conflict.pkg_uid);
498 : 0 : cur_conflict = ev->e_integrity_conflict.conflicts;
499 [ # # ]: 0 : while (cur_conflict) {
500 [ # # ]: 0 : if (cur_conflict->next)
501 : 0 : printf("%s, ", cur_conflict->uid);
502 : : else
503 : 0 : printf("%s", cur_conflict->uid);
504 : :
505 : 0 : cur_conflict = cur_conflict->next;
506 : : }
507 : 0 : printf("\n");
508 : 0 : break;
509 : : case PKG_EVENT_DEINSTALL_BEGIN:
510 [ + + ]: 44 : if (quiet)
511 : 7 : break;
512 : :
513 : 37 : job_status_begin(msg_buf);
514 : :
515 : 37 : pkg = ev->e_install_begin.pkg;
516 : 37 : pkg_fprintf(msg_buf->fp, "Deinstalling %n-%v...\n", pkg, pkg);
517 : 37 : fflush(msg_buf->fp);
518 : 37 : printf("%s", msg_buf->buf);
519 : 37 : break;
520 : : case PKG_EVENT_DEINSTALL_FINISHED:
521 [ + + ]: 35 : if (quiet)
522 : 6 : break;
523 : 29 : break;
524 : : case PKG_EVENT_DELETE_FILES_BEGIN:
525 [ + + ]: 24 : if (quiet)
526 : 6 : break;
527 : : else {
528 : 18 : job_status_begin(msg_buf);
529 : 18 : pkg = ev->e_install_begin.pkg;
530 : 36 : pkg_fprintf(msg_buf->fp, "Deleting files for %n-%v",
531 : 18 : pkg, pkg);
532 : : }
533 : 18 : break;
534 : : case PKG_EVENT_DELETE_FILES_FINISHED:
535 : 24 : break;
536 : : case PKG_EVENT_UPGRADE_BEGIN:
537 [ + + ]: 33 : if (quiet)
538 : 8 : break;
539 : 25 : pkg_new = ev->e_upgrade_begin.n;
540 : 25 : pkg_old = ev->e_upgrade_begin.o;
541 : :
542 : 25 : job_status_begin(msg_buf);
543 : :
544 [ + - - + ]: 25 : switch (pkg_version_change_between(pkg_new, pkg_old)) {
545 : : case PKG_DOWNGRADE:
546 : 0 : pkg_fprintf(msg_buf->fp, "Downgrading %n from %v to %v...\n",
547 : 0 : pkg_new, pkg_old, pkg_new);
548 : 0 : break;
549 : : case PKG_REINSTALL:
550 : 8 : pkg_fprintf(msg_buf->fp, "Reinstalling %n-%v...\n",
551 : 4 : pkg_old, pkg_old);
552 : 4 : break;
553 : : case PKG_UPGRADE:
554 : 42 : pkg_fprintf(msg_buf->fp, "Upgrading %n from %v to %v...\n",
555 : 21 : pkg_new, pkg_old, pkg_new);
556 : 21 : break;
557 : : }
558 : 25 : fflush(msg_buf->fp);
559 : 25 : printf("%s", msg_buf->buf);
560 : 25 : break;
561 : : case PKG_EVENT_UPGRADE_FINISHED:
562 [ + + ]: 33 : if (quiet)
563 : 8 : break;
564 : 25 : break;
565 : : case PKG_EVENT_LOCKED:
566 : 0 : pkg = ev->e_locked.pkg;
567 : 0 : pkg_printf("\n%n-%v is locked and may not be modified\n", pkg, pkg);
568 : 0 : break;
569 : : case PKG_EVENT_REQUIRED:
570 : 0 : pkg = ev->e_required.pkg;
571 : 0 : pkg_printf("\n%n-%v is required by: %r%{%rn-%rv%| %}", pkg, pkg, pkg);
572 [ # # ]: 0 : if (ev->e_required.force == 1)
573 : 0 : fprintf(stderr, ", deleting anyway\n");
574 : : else
575 : 0 : fprintf(stderr, "\n");
576 : 0 : break;
577 : : case PKG_EVENT_ALREADY_INSTALLED:
578 [ # # ]: 0 : if (quiet)
579 : 0 : break;
580 : 0 : pkg = ev->e_already_installed.pkg;
581 : 0 : pkg_printf("the most recent version of %n-%v is already installed\n",
582 : 0 : pkg, pkg);
583 : 0 : break;
584 : : case PKG_EVENT_NOT_FOUND:
585 : 0 : printf("Package '%s' was not found in "
586 : 0 : "the repositories\n", ev->e_not_found.pkg_name);
587 : 0 : break;
588 : : case PKG_EVENT_MISSING_DEP:
589 : 5 : warnx("Missing dependency '%s'",
590 : 5 : pkg_dep_name(ev->e_missing_dep.dep));
591 : 5 : break;
592 : : case PKG_EVENT_NOREMOTEDB:
593 : 0 : fprintf(stderr, "Unable to open remote database \"%s\". "
594 : 0 : "Try running '%s update' first.\n", ev->e_remotedb.repo,
595 : 0 : getprogname());
596 : 0 : break;
597 : : case PKG_EVENT_NOLOCALDB:
598 : 0 : fprintf(stderr, "Local package database nonexistent!\n");
599 : 0 : break;
600 : : case PKG_EVENT_NEWPKGVERSION:
601 : 2 : newpkgversion = true;
602 : 2 : printf("New version of pkg detected; it needs to be "
603 : : "installed first.\n");
604 : 2 : break;
605 : : case PKG_EVENT_FILE_MISMATCH:
606 : 0 : pkg = ev->e_file_mismatch.pkg;
607 : 0 : pkg_fprintf(stderr, "%n-%v: checksum mismatch for %Fn\n", pkg,
608 : 0 : pkg, ev->e_file_mismatch.file);
609 : 0 : break;
610 : : case PKG_EVENT_FILE_MISSING:
611 : 0 : pkg = ev->e_file_missing.pkg;
612 : 0 : pkg_fprintf(stderr, "%n-%v: missing file %Fn\n", pkg, pkg,
613 : 0 : ev->e_file_missing.file);
614 : 0 : break;
615 : : case PKG_EVENT_PLUGIN_ERRNO:
616 : 0 : warnx("%s: %s(%s): %s",
617 : 0 : pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
618 : 0 : ev->e_plugin_errno.func, ev->e_plugin_errno.arg,
619 : 0 : strerror(ev->e_plugin_errno.no));
620 : 0 : break;
621 : : case PKG_EVENT_PLUGIN_ERROR:
622 : 0 : warnx("%s: %s",
623 : 0 : pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
624 : 0 : ev->e_plugin_error.msg);
625 : 0 : break;
626 : : case PKG_EVENT_PLUGIN_INFO:
627 [ # # ]: 0 : if (quiet)
628 : 0 : break;
629 : 0 : printf("%s: %s\n",
630 : 0 : pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
631 : 0 : ev->e_plugin_info.msg);
632 : 0 : break;
633 : : case PKG_EVENT_INCREMENTAL_UPDATE:
634 [ + + ]: 72 : if (!quiet)
635 : 61 : printf("%s repository update completed. %d packages processed.\n",
636 : 61 : ev->e_incremental_update.reponame,
637 : 61 : ev->e_incremental_update.processed);
638 : 72 : break;
639 : : case PKG_EVENT_DEBUG:
640 : 98 : fprintf(stderr, "DBG(%d)[%d]> %s\n", ev->e_debug.level,
641 : 49 : (int)getpid(), ev->e_debug.msg);
642 : 49 : break;
643 : : case PKG_EVENT_QUERY_YESNO:
644 [ # # ]: 0 : return ( ev->e_query_yesno.deft ?
645 : 0 : query_yesno(true, ev->e_query_yesno.msg, "[Y/n]") :
646 : 0 : query_yesno(false, ev->e_query_yesno.msg, "[y/N]") );
647 : : break;
648 : : case PKG_EVENT_QUERY_SELECT:
649 : 0 : return query_select(ev->e_query_select.msg, ev->e_query_select.items,
650 : 0 : ev->e_query_select.ncnt, ev->e_query_select.deft);
651 : : break;
652 : : case PKG_EVENT_SANDBOX_CALL:
653 : 16 : return ( pkg_handle_sandboxed_call(ev->e_sandbox_call.call,
654 : 8 : ev->e_sandbox_call.fd,
655 : 8 : ev->e_sandbox_call.userdata) );
656 : : break;
657 : : case PKG_EVENT_SANDBOX_GET_STRING:
658 : 144 : return ( pkg_handle_sandboxed_get_string(ev->e_sandbox_call_str.call,
659 : 72 : ev->e_sandbox_call_str.result,
660 : 72 : ev->e_sandbox_call_str.len,
661 : 72 : ev->e_sandbox_call_str.userdata) );
662 : : break;
663 : : case PKG_EVENT_PROGRESS_START:
664 : 1374 : progressbar_start(ev->e_progress_start.msg);
665 : 1374 : break;
666 : : case PKG_EVENT_PROGRESS_TICK:
667 : 4492 : progressbar_tick(ev->e_progress_tick.current,
668 : 2246 : ev->e_progress_tick.total);
669 : 2246 : break;
670 : : case PKG_EVENT_BACKUP:
671 : 0 : fprintf(msg_buf->fp, "Backing up");
672 : 0 : break;
673 : : case PKG_EVENT_RESTORE:
674 : 0 : fprintf(msg_buf->fp, "Restoring");
675 : 0 : break;
676 : : case PKG_EVENT_NEW_ACTION:
677 : 207 : nbdone++;
678 : 207 : break;
679 : : case PKG_EVENT_MESSAGE:
680 [ + + ]: 28 : if (messages == NULL)
681 : 27 : messages = xstring_new();
682 : 28 : fprintf(messages->fp, "%s", ev->e_pkg_message.msg);
683 : 28 : break;
684 : : case PKG_EVENT_CLEANUP_CALLBACK_REGISTER:
685 [ + + ]: 185 : if (!signal_handler_installed) {
686 : 130 : signal(SIGINT, cleanup_handler);
687 : 130 : signal_handler_installed = true;
688 : 130 : }
689 : 185 : evtmp = xmalloc(sizeof(struct cleanup));
690 : 185 : evtmp->cb = ev->e_cleanup_callback.cleanup_cb;
691 : 185 : evtmp->data = ev->e_cleanup_callback.data;
692 [ - + + - : 185 : tll_push_back(cleanup_list, evtmp);
# # - + -
+ ]
693 : 185 : break;
694 : : case PKG_EVENT_CLEANUP_CALLBACK_UNREGISTER:
695 [ + + ]: 247 : if (!signal_handler_installed)
696 : 62 : break;
697 [ + - - + : 185 : tll_foreach(cleanup_list, it) {
# # ]
698 : 185 : evtmp = it->item;
699 [ + - - + ]: 185 : if (evtmp->cb == ev->e_cleanup_callback.cleanup_cb &&
700 : 185 : evtmp->data == ev->e_cleanup_callback.data) {
701 [ + - - + : 185 : tll_remove_and_free(cleanup_list, it, free);
- + ]
702 : 185 : break;
703 : : }
704 : 0 : }
705 : 185 : break;
706 : : case PKG_EVENT_CONFLICTS:
707 [ + + ]: 23 : if (conflicts == NULL) {
708 : 13 : conflicts = xstring_new();
709 : 13 : }
710 : 46 : pkg_fprintf(conflicts->fp, " - %n-%v",
711 : 23 : ev->e_conflicts.p1, ev->e_conflicts.p1);
712 [ + + ]: 23 : if (pkg_repos_total_count() > 1) {
713 : 4 : pkg_get(ev->e_conflicts.p1, PKG_ATTR_REPONAME, &reponame);
714 : 8 : fprintf(conflicts->fp, " [%s]",
715 [ + - ]: 4 : reponame == NULL ? "installed" : reponame);
716 : 4 : }
717 : 46 : pkg_fprintf(conflicts->fp, " conflicts with %n-%v",
718 : 23 : ev->e_conflicts.p2, ev->e_conflicts.p2);
719 [ + + ]: 23 : if (pkg_repos_total_count() > 1) {
720 : 4 : pkg_get(ev->e_conflicts.p2, PKG_ATTR_REPONAME, &reponame);
721 : 8 : fprintf(conflicts->fp, " [%s]",
722 [ + + ]: 4 : reponame == NULL ? "installed" : reponame);
723 : 4 : }
724 : 46 : fprintf(conflicts->fp, " on %s\n",
725 : 23 : ev->e_conflicts.path);
726 : 23 : break;
727 : : case PKG_EVENT_TRIGGER:
728 [ + + ]: 537 : if (!quiet) {
729 [ - + ]: 1 : if (ev->e_trigger.cleanup)
730 : 0 : printf("==> Cleaning up trigger: %s\n", ev->e_trigger.name);
731 : : else
732 : 1 : printf("==> Running trigger: %s\n", ev->e_trigger.name);
733 : 1 : }
734 : : default:
735 : 536 : break;
736 : : }
737 : :
738 : 6615 : return 0;
739 : 6695 : }
|