00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <sys/time.h>
00026 #include <unistd.h>
00027 #include <dirent.h>
00028 #include <wchar.h>
00029
00030 #include <alpm.h>
00031
00032
00033 #include "callback.h"
00034 #include "util.h"
00035 #include "conf.h"
00036
00037
00038 #define LOG_STR_LEN 256
00039 #define FILENAME_TRIM_LEN 23
00040
00041
00042 static float rate_last;
00043 static int xfered_last;
00044 static struct timeval initial_time;
00045
00046
00047 static int prevpercent = 0;
00048
00049
00050 static int on_progress = 0;
00051 static alpm_list_t *output = NULL;
00052
00053
00054
00055
00056
00057
00058
00059 static float get_update_timediff(int first_call)
00060 {
00061 float retval = 0.0;
00062 static struct timeval last_time = {0, 0};
00063
00064
00065 if(first_call) {
00066 gettimeofday(&last_time, NULL);
00067 } else {
00068 struct timeval this_time;
00069 float diff_sec, diff_usec;
00070
00071 gettimeofday(&this_time, NULL);
00072 diff_sec = this_time.tv_sec - last_time.tv_sec;
00073 diff_usec = this_time.tv_usec - last_time.tv_usec;
00074
00075 retval = diff_sec + (diff_usec / 1000000.0);
00076
00077
00078 if(retval < UPDATE_SPEED_SEC) {
00079 retval = 0.0;
00080 } else {
00081 last_time = this_time;
00082
00083 }
00084 }
00085
00086 return(retval);
00087 }
00088
00089
00090 static void fill_progress(const int graph_percent, const int display_percent,
00091 const int proglen)
00092 {
00093 const unsigned int hashlen = proglen - 8;
00094 const unsigned int hash = graph_percent * hashlen / 100;
00095 static unsigned int lasthash = 0, mouth = 0;
00096 unsigned int i;
00097
00098
00099
00100 if(graph_percent == 0) {
00101 lasthash = 0;
00102 mouth = 0;
00103 }
00104
00105
00106 if(proglen > 8) {
00107 printf(" [");
00108 for(i = hashlen; i > 1; --i) {
00109
00110 if(config->chomp) {
00111 if(i > hashlen - hash) {
00112 printf("-");
00113 } else if(i == hashlen - hash) {
00114 if(lasthash == hash) {
00115 if(mouth) {
00116 printf("\033[1;33mC\033[m");
00117 } else {
00118 printf("\033[1;33mc\033[m");
00119 }
00120 } else {
00121 lasthash = hash;
00122 mouth = mouth == 1 ? 0 : 1;
00123 if(mouth) {
00124 printf("\033[1;33mC\033[m");
00125 } else {
00126 printf("\033[1;33mc\033[m");
00127 }
00128 }
00129 } else if(i%3 == 0) {
00130 printf("\033[0;37mo\033[m");
00131 } else {
00132 printf("\033[0;37m \033[m");
00133 }
00134 }
00135 else if(i > hashlen - hash) {
00136 printf("#");
00137 } else {
00138 printf("-");
00139 }
00140 }
00141 printf("]");
00142 }
00143
00144 if(proglen > 5) {
00145 printf(" %3d%%", display_percent);
00146 }
00147
00148 if(graph_percent == 100) {
00149 printf("\n");
00150 } else {
00151 printf("\r");
00152 }
00153 fflush(stdout);
00154 }
00155
00156
00157
00158
00159 void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)
00160 {
00161 char str[LOG_STR_LEN] = "";
00162
00163 switch(event) {
00164 case PM_TRANS_EVT_CHECKDEPS_START:
00165 printf(_("checking dependencies...\n"));
00166 break;
00167 case PM_TRANS_EVT_FILECONFLICTS_START:
00168 if(config->noprogressbar) {
00169 printf(_("checking for file conflicts...\n"));
00170 }
00171 break;
00172 case PM_TRANS_EVT_RESOLVEDEPS_START:
00173 printf(_("resolving dependencies...\n"));
00174 break;
00175 case PM_TRANS_EVT_INTERCONFLICTS_START:
00176 printf(_("looking for inter-conflicts...\n"));
00177 break;
00178 case PM_TRANS_EVT_ADD_START:
00179 if(config->noprogressbar) {
00180 printf(_("installing %s...\n"), alpm_pkg_get_name(data1));
00181 }
00182 break;
00183 case PM_TRANS_EVT_ADD_DONE:
00184 snprintf(str, LOG_STR_LEN, "installed %s (%s)\n",
00185 alpm_pkg_get_name(data1),
00186 alpm_pkg_get_version(data1));
00187 alpm_logaction(str);
00188 break;
00189 case PM_TRANS_EVT_REMOVE_START:
00190 if(config->noprogressbar) {
00191 printf(_("removing %s...\n"), alpm_pkg_get_name(data1));
00192 }
00193 break;
00194 case PM_TRANS_EVT_REMOVE_DONE:
00195 snprintf(str, LOG_STR_LEN, "removed %s (%s)\n",
00196 alpm_pkg_get_name(data1),
00197 alpm_pkg_get_version(data1));
00198 alpm_logaction(str);
00199 break;
00200 case PM_TRANS_EVT_UPGRADE_START:
00201 if(config->noprogressbar) {
00202 printf(_("upgrading %s...\n"), alpm_pkg_get_name(data1));
00203 }
00204 break;
00205 case PM_TRANS_EVT_UPGRADE_DONE:
00206 snprintf(str, LOG_STR_LEN, "upgraded %s (%s -> %s)\n",
00207 (char *)alpm_pkg_get_name(data1),
00208 (char *)alpm_pkg_get_version(data2),
00209 (char *)alpm_pkg_get_version(data1));
00210 alpm_logaction(str);
00211 break;
00212 case PM_TRANS_EVT_INTEGRITY_START:
00213 printf(_("checking package integrity...\n"));
00214 break;
00215 case PM_TRANS_EVT_DELTA_INTEGRITY_START:
00216 printf(_("checking delta integrity...\n"));
00217 break;
00218 case PM_TRANS_EVT_DELTA_PATCHES_START:
00219 printf(_("applying deltas...\n"));
00220 break;
00221 case PM_TRANS_EVT_DELTA_PATCH_START:
00222 printf(_("generating %s with %s... "), (char *)data1, (char *)data2);
00223 break;
00224 case PM_TRANS_EVT_DELTA_PATCH_DONE:
00225 printf(_("success!\n"));
00226 break;
00227 case PM_TRANS_EVT_DELTA_PATCH_FAILED:
00228 printf(_("failed.\n"));
00229 break;
00230 case PM_TRANS_EVT_SCRIPTLET_INFO:
00231 printf("%s", (char*)data1);
00232 break;
00233 case PM_TRANS_EVT_PRINTURI:
00234 printf("%s/%s\n", (char*)data1, (char*)data2);
00235 break;
00236 case PM_TRANS_EVT_RETRIEVE_START:
00237 printf(_(":: Retrieving packages from %s...\n"), (char*)data1);
00238 break;
00239
00240 case PM_TRANS_EVT_FILECONFLICTS_DONE:
00241 case PM_TRANS_EVT_EXTRACT_DONE:
00242 case PM_TRANS_EVT_CHECKDEPS_DONE:
00243 case PM_TRANS_EVT_RESOLVEDEPS_DONE:
00244 case PM_TRANS_EVT_INTERCONFLICTS_DONE:
00245 case PM_TRANS_EVT_INTEGRITY_DONE:
00246 case PM_TRANS_EVT_DELTA_INTEGRITY_DONE:
00247 case PM_TRANS_EVT_DELTA_PATCHES_DONE:
00248
00249 break;
00250 }
00251 fflush(stdout);
00252 }
00253
00254
00255
00256 void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
00257 void *data3, int *response)
00258 {
00259 char str[LOG_STR_LEN] = "";
00260
00261 switch(event) {
00262 case PM_TRANS_CONV_INSTALL_IGNOREPKG:
00263 if(data2) {
00264
00265 snprintf(str, LOG_STR_LEN, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "),
00266 alpm_pkg_get_name(data1),
00267 alpm_pkg_get_name(data2));
00268 *response = yesno(str);
00269 } else {
00270 snprintf(str, LOG_STR_LEN, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "),
00271 alpm_pkg_get_name(data1));
00272 *response = yesno(str);
00273 }
00274 break;
00275 case PM_TRANS_CONV_REMOVE_HOLDPKG:
00276 snprintf(str, LOG_STR_LEN, _(":: %s is designated as a HoldPkg. Remove anyway? [Y/n] "),
00277 alpm_pkg_get_name(data1));
00278 *response = yesno(str);
00279 break;
00280 case PM_TRANS_CONV_REPLACE_PKG:
00281 if(!config->noconfirm) {
00282 snprintf(str, LOG_STR_LEN, _(":: Replace %s with %s/%s? [Y/n] "),
00283 alpm_pkg_get_name(data1),
00284 (char *)data3,
00285 alpm_pkg_get_name(data2));
00286 *response = yesno(str);
00287 } else {
00288 printf(_("Replacing %s with %s/%s\n."),
00289 alpm_pkg_get_name(data1),
00290 (char *)data3,
00291 alpm_pkg_get_name(data2));
00292 *response = 1;
00293 }
00294 break;
00295 case PM_TRANS_CONV_CONFLICT_PKG:
00296 snprintf(str, LOG_STR_LEN, _(":: %s conflicts with %s. Remove %s? [Y/n] "),
00297 (char *)data1,
00298 (char *)data2,
00299 (char *)data2);
00300 *response = yesno(str);
00301 break;
00302 case PM_TRANS_CONV_LOCAL_NEWER:
00303 if(!config->op_s_downloadonly) {
00304 snprintf(str, LOG_STR_LEN, _(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] "),
00305 alpm_pkg_get_name(data1),
00306 alpm_pkg_get_version(data1));
00307 *response = yesno(str);
00308 } else {
00309 *response = 1;
00310 }
00311 break;
00312 case PM_TRANS_CONV_CORRUPTED_PKG:
00313 if(!config->noconfirm) {
00314 snprintf(str, LOG_STR_LEN, _(":: File %s is corrupted. Do you want to delete it? [Y/n] "),
00315 (char *)data1);
00316 *response = yesno(str);
00317 } else {
00318 *response = 1;
00319 }
00320 break;
00321 }
00322 }
00323
00324
00325 void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,
00326 int howmany, int remain)
00327 {
00328 float timediff;
00329
00330
00331 const int infolen = 50;
00332 int tmp, digits, oprlen, textlen, pkglen;
00333 char *opr = NULL;
00334 wchar_t *wcopr = NULL;
00335
00336 if(config->noprogressbar) {
00337 return;
00338 }
00339
00340 if(percent == 0) {
00341 timediff = get_update_timediff(1);
00342 } else {
00343 timediff = get_update_timediff(0);
00344 }
00345
00346 if(percent > 0 && percent < 100 && !timediff) {
00347
00348
00349
00350
00351
00352 return;
00353 }
00354
00355
00356 if(!pkgname || percent == prevpercent) {
00357 return;
00358 }
00359
00360 prevpercent=percent;
00361
00362 switch (event) {
00363 case PM_TRANS_PROGRESS_ADD_START:
00364 opr = _("installing");
00365 break;
00366 case PM_TRANS_PROGRESS_UPGRADE_START:
00367 opr = _("upgrading");
00368 break;
00369 case PM_TRANS_PROGRESS_REMOVE_START:
00370 opr = _("removing");
00371 break;
00372 case PM_TRANS_PROGRESS_CONFLICTS_START:
00373 opr = _("checking for file conflicts");
00374 break;
00375 }
00376
00377 oprlen = strlen(opr);
00378 wcopr = calloc(oprlen, sizeof(wchar_t));
00379 if(!wcopr) {
00380 fprintf(stderr, "malloc failure: could not allocate %zd bytes\n",
00381 strlen(opr) * sizeof(wchar_t));
00382 return;
00383 }
00384 oprlen = mbstowcs(wcopr, opr, oprlen);
00385
00386
00387 digits = 1;
00388 tmp = howmany;
00389 while((tmp /= 10)) {
00390 ++digits;
00391 }
00392
00393
00394 textlen = infolen - 3 - (2 * digits);
00395
00396 pkglen = textlen - oprlen - 1;
00397
00398 switch (event) {
00399 case PM_TRANS_PROGRESS_ADD_START:
00400 case PM_TRANS_PROGRESS_UPGRADE_START:
00401 case PM_TRANS_PROGRESS_REMOVE_START:
00402
00403
00404
00405 printf("(%*d/%*d) %s %-*.*s", digits, remain, digits, howmany,
00406 opr, pkglen, pkglen, pkgname);
00407 break;
00408 case PM_TRANS_PROGRESS_CONFLICTS_START:
00409
00410
00411
00412 printf("(%*d/%*d) %-*s", digits, remain, digits, howmany,
00413 textlen, opr);
00414 break;
00415 }
00416
00417 free(wcopr);
00418
00419
00420 fill_progress(percent, percent, getcols() - infolen);
00421
00422 if(percent == 100) {
00423 alpm_list_t *i = NULL;
00424 on_progress = 0;
00425 for(i = output; i; i = i->next) {
00426 printf("%s", (char *)i->data);
00427 }
00428 fflush(stdout);
00429 FREELIST(output);
00430 } else {
00431 on_progress = 1;
00432 }
00433 }
00434
00435
00436 void cb_dl_progress(const char *filename, int file_xfered, int file_total,
00437 int list_xfered, int list_total)
00438 {
00439 const int infolen = 50;
00440 char *fname, *p;
00441
00442 float rate = 0.0, timediff = 0.0, f_xfered = 0.0;
00443 unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
00444 int graph_percent = 0, display_percent = 0;
00445 char rate_size = 'K', xfered_size = 'K';
00446 int xfered = 0, total = 0;
00447
00448
00449
00450 static int has_init = 0;
00451
00452 if(config->noprogressbar) {
00453 return;
00454 }
00455
00456
00457
00458 if (config->totaldownload && list_total > 0) {
00459 xfered = list_xfered;
00460 total = list_total;
00461 } else {
00462 xfered = file_xfered;
00463 total = file_total;
00464 }
00465
00466
00467
00468 if(file_xfered == 0) {
00469
00470 if (!(config->totaldownload && list_total > 0) ||
00471 (config->totaldownload && list_total > 0 && !has_init)) {
00472 gettimeofday(&initial_time, NULL);
00473 timediff = get_update_timediff(1);
00474 xfered_last = 0;
00475 rate_last = 0.0;
00476 has_init = 1;
00477 }
00478 rate = 0.0;
00479 eta_s = 0;
00480 } else if(file_xfered == file_total) {
00481
00482 struct timeval current_time;
00483 float diff_sec, diff_usec;
00484
00485 gettimeofday(¤t_time, NULL);
00486 diff_sec = current_time.tv_sec - initial_time.tv_sec;
00487 diff_usec = current_time.tv_usec - initial_time.tv_usec;
00488 timediff = diff_sec + (diff_usec / 1000000.0);
00489 rate = xfered / (timediff * 1024.0);
00490
00491
00492 eta_s = (int)(timediff + 0.5);
00493 } else {
00494
00495 timediff = get_update_timediff(0);
00496
00497 if(timediff < UPDATE_SPEED_SEC) {
00498
00499 return;
00500 }
00501 rate = (xfered - xfered_last) / (timediff * 1024.0);
00502
00503 rate = (rate + 2*rate_last) / 3;
00504 eta_s = (total - xfered) / (rate * 1024.0);
00505 rate_last = rate;
00506 xfered_last = xfered;
00507 }
00508
00509
00510 eta_h = eta_s / 3600;
00511 eta_s -= eta_h * 3600;
00512 eta_m = eta_s / 60;
00513 eta_s -= eta_m * 60;
00514
00515 fname = strdup(filename);
00516
00517 if((p = strstr(fname, PKGEXT)) || (p = strstr(fname, DBEXT))) {
00518 *p = '\0';
00519 }
00520 if(strlen(fname) > FILENAME_TRIM_LEN) {
00521 strcpy(fname + FILENAME_TRIM_LEN -3,"...");
00522 }
00523
00524
00525
00526
00527 if(rate > 2048.0) {
00528 rate /= 1024.0;
00529 rate_size = 'M';
00530 if(rate > 2048.0) {
00531 rate /= 1024.0;
00532 rate_size = 'G';
00533
00534 }
00535 }
00536
00537 f_xfered = xfered / 1024.0;
00538
00539 if(f_xfered > 2048.0) {
00540 f_xfered /= 1024.0;
00541 xfered_size = 'M';
00542 if(f_xfered > 2048.0) {
00543 f_xfered /= 1024.0;
00544 xfered_size = 'G';
00545
00546
00547
00548 }
00549 }
00550
00551 printf(" %-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", FILENAME_TRIM_LEN, fname,
00552 f_xfered, xfered_size, rate, rate_size, eta_h, eta_m, eta_s);
00553
00554 free(fname);
00555
00556
00557
00558 graph_percent = (int)((float)file_xfered) / ((float)file_total) * 100;
00559 display_percent = (int)((float)xfered) / ((float)total) * 100;
00560 fill_progress(graph_percent, display_percent, getcols() - infolen);
00561 return;
00562 }
00563
00564
00565 void cb_log(pmloglevel_t level, char *fmt, va_list args)
00566 {
00567 if(!strlen(fmt)) {
00568 return;
00569 }
00570
00571 if(on_progress) {
00572 char *string = NULL;
00573 pm_vasprintf(&string, level, fmt, args);
00574 if(string != NULL) {
00575 output = alpm_list_add(output, string);
00576 }
00577 } else {
00578 pm_vfprintf(stdout, level, fmt, args);
00579 }
00580 }
00581
00582