/ncftp-3.2.5/ncftp/progress.c
C | 501 lines | 394 code | 64 blank | 43 comment | 87 complexity | a428790d717a5a1348e45b1f9efefacf MD5 | raw file
Possible License(s): AGPL-3.0
- /* progress.c
- *
- * Copyright (c) 1992-2005 by Mike Gleason.
- * All rights reserved.
- *
- */
- #include "syshdrs.h"
- #ifdef PRAGMA_HDRSTOP
- # pragma hdrstop
- #endif
- #include "util.h"
- #include "trace.h"
- #include "progress.h"
- #include "readln.h"
- #ifdef ncftp
- # include "log.h"
- # include "pref.h"
- #endif /* ncftp */
- extern const char *tcap_normal;
- extern const char *tcap_reverse;
- extern int gScreenColumns;
- #ifdef ncftp
- extern char gRemoteCWD[];
- #endif /* ncftp */
- double
- FileSize(const double size, const char **uStr0, double *const uMult0)
- {
- double uMult, uTotal;
- const char *uStr;
- /* The comparisons below may look odd, but the reason
- * for them is that we only want a maximum of 3 digits
- * before the decimal point. (I.e., we don't want to
- * see "1017.2 kB", instead we want "0.99 MB".
- */
- if (size > (999.5 * kGigabyte)) {
- uStr = "TB";
- uMult = kTerabyte;
- } else if (size > (999.5 * kMegabyte)) {
- uStr = "GB";
- uMult = kGigabyte;
- } else if (size > (999.5 * kKilobyte)) {
- uStr = "MB";
- uMult = kMegabyte;
- } else if (size > 999.5) {
- uStr = "kB";
- uMult = 1024;
- } else {
- uStr = "B";
- uMult = 1;
- }
- if (uStr0 != NULL)
- *uStr0 = uStr;
- if (uMult0 != NULL)
- *uMult0 = uMult;
- uTotal = size / ((double) uMult);
- if (uTotal < 0.0)
- uTotal = 0.0;
- return (uTotal);
- } /* FileSize */
- void
- PrSizeAndRateMeter(const FTPCIPtr cip, int mode)
- {
- double rate = 0.0;
- const char *rStr;
- static const char *uStr;
- static double uMult;
- char localName[32];
- char line[128];
- int i;
- switch (mode) {
- case kPrInitMsg:
- if (cip->expectedSize != kSizeUnknown) {
- cip->progress = PrStatBar;
- PrStatBar(cip, mode);
- return;
- }
- (void) FileSize((double) cip->expectedSize, &uStr, &uMult);
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- AbbrevStr(localName, cip->lname, sizeof(localName) - 2, 0);
- if ((cip->usingTAR) && (strlen(localName) < (sizeof(localName) - 6))) {
- STRNCAT(localName, " (TAR)");
- }
- (void) STRNCAT(localName, ":");
- }
- if (cip->useProgressMeter) {
- #ifdef ncftp
- if (cip->usingTAR) {
- if (OneTimeMessage("tar") != 0) {
- (void) fprintf(stderr, "\n\
- Note: NcFTP is using on-the-fly TAR on the remote server, which retrieves the\n\
- entire directory as one operation. This allows you to preserve exact file\n\
- timestamps, ownerships, and permissions, as well as a slight performance\n\
- boost.\n\
- \n\
- If you would rather retrieve each file individually, use the \"-T\" flag with\n\
- \"get\". TAR mode cannot be resumed if the transfer fails, so if that happens\n\
- try \"get -T\" to resume the directory transfer.\n\n");
- }
- }
- #endif /* ncftp */
- (void) fprintf(stderr, "%-32s", localName);
- }
- break;
- case kPrUpdateMsg:
- rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- AbbrevStr(localName, cip->lname, sizeof(localName) - 2, 0);
- if ((cip->usingTAR) && (strlen(localName) < (sizeof(localName) - 6))) {
- STRNCAT(localName, " (TAR)");
- }
- (void) STRNCAT(localName, ":");
- }
- #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
- (void) sprintf(line, "%-32s %10lld bytes %6.2f %s/s",
- localName,
- (longest_int) (cip->bytesTransferred + cip->startPoint),
- rate,
- rStr
- );
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
- (void) sprintf(line, "%-32s %10qd bytes %6.2f %s/s",
- localName,
- (longest_int) (cip->bytesTransferred + cip->startPoint),
- rate,
- rStr
- );
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
- (void) sprintf(line, "%-32s %10I64d bytes %6.2f %s/s",
- localName,
- (longest_int) (cip->bytesTransferred + cip->startPoint),
- rate,
- rStr
- );
- #else
- (void) sprintf(line, "%-32s %10ld bytes %6.2f %s/s",
- localName,
- (long) (cip->bytesTransferred + cip->startPoint),
- rate,
- rStr
- );
- #endif
- /* Pad the rest of the line with spaces, to erase any
- * stuff that might have been left over from the last
- * update.
- */
- for (i = (int) strlen(line); i < 80 - 2; i++)
- line[i] = ' ';
- line[i] = '\0';
- /* Print the updated information. */
- (void) fprintf(stderr, "\r%s", line);
- #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
- SetXtermTitle("%s - [%lld bytes]", cip->lname, (longest_int) (cip->bytesTransferred + cip->startPoint));
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
- SetXtermTitle("%s - [%qd bytes]", cip->lname, (longest_int) (cip->bytesTransferred + cip->startPoint));
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
- SetXtermTitle("%s - [%I64d bytes]", cip->lname, (longest_int) (cip->bytesTransferred + cip->startPoint));
- #else
- SetXtermTitle("%s - [%ld bytes]", cip->lname, (long) (cip->bytesTransferred + cip->startPoint));
- #endif
- break;
- case kPrEndMsg:
- (void) fprintf(stderr, "\n\r");
- #ifdef ncftp
- if (cip->rname != NULL) {
- char url[256];
- FileToURL(url, sizeof(url), cip->rname, gRemoteCWD, cip->startingWorkingDirectory, cip->user, cip->pass, cip->host, cip->port);
- LogXfer((cip->netMode == kNetReading) ? "get" : "put", url);
- }
- #endif
- break;
- }
- } /* PrSizeAndRateMeter */
- void
- PrStatBar(const FTPCIPtr cip, int mode)
- {
- double rate, done;
- int secLeft, minLeft;
- const char *rStr;
- static const char *uStr;
- static double uTotal, uMult;
- const char *stall;
- char localName[80];
- char line[128];
- int i;
- switch (mode) {
- case kPrInitMsg:
- fflush(stdout);
- if (cip->expectedSize == kSizeUnknown) {
- cip->progress = PrSizeAndRateMeter;
- PrSizeAndRateMeter(cip, mode);
- return;
- }
- uTotal = FileSize((double) cip->expectedSize, &uStr, &uMult);
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- /* Leave room for a ':' and '\0'. */
- AbbrevStr(localName, cip->lname, sizeof(localName) - 2, 0);
- (void) STRNCAT(localName, ":");
- }
- if (cip->useProgressMeter)
- (void) fprintf(stderr, "%-32s", localName);
- break;
- case kPrUpdateMsg:
- secLeft = (int) (cip->secLeft + 0.5);
- minLeft = secLeft / 60;
- secLeft = secLeft - (minLeft * 60);
- if (minLeft > 999) {
- minLeft = 999;
- secLeft = 59;
- }
- rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);
- done = (double) (cip->bytesTransferred + cip->startPoint) / uMult;
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- AbbrevStr(localName, cip->lname, 31, 0);
- (void) STRNCAT(localName, ":");
- }
- if (cip->canceling > 0)
- stall = "X";
- else if (cip->stalled < 2)
- stall = " ";
- else if (cip->stalled < 15)
- stall = "-";
- else
- stall = "=";
- (void) sprintf(line, "%-32s ETA: %3d:%02d %6.2f/%6.2f %.2s %6.2f %.2s/s %s ",
- localName,
- minLeft,
- secLeft,
- done,
- uTotal,
- uStr,
- rate,
- rStr,
- stall
- );
- /* Print the updated information. */
- (void) fprintf(stderr, "\r%s", line);
- SetXtermTitle("%s - [%.1f%%]", cip->lname, cip->percentCompleted);
- break;
- case kPrEndMsg:
- rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);
- done = (double) (cip->bytesTransferred + cip->startPoint) / uMult;
- if (cip->expectedSize == (cip->bytesTransferred + cip->startPoint)) {
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- AbbrevStr(localName, cip->lname, 52, 0);
- (void) STRNCAT(localName, ":");
- }
- (void) sprintf(line, "%-53s %6.2f %.2s %6.2f %.2s/s ",
- localName,
- uTotal,
- uStr,
- rate,
- rStr
- );
- } else {
- if (cip->lname == NULL) {
- localName[0] = '\0';
- } else {
- AbbrevStr(localName, cip->lname, 45, 0);
- (void) STRNCAT(localName, ":");
- }
- (void) sprintf(line, "%-46s %6.2f/%6.2f %.2s %6.2f %.2s/s ",
- localName,
- done,
- uTotal,
- uStr,
- rate,
- rStr
- );
- }
- /* Pad the rest of the line with spaces, to erase any
- * stuff that might have been left over from the last
- * update.
- */
- for (i = (int) strlen(line); i < 80 - 2; i++)
- line[i] = ' ';
- line[i] = '\0';
- /* Print the updated information. */
- (void) fprintf(stderr, "\r%s\n\r", line);
- #ifdef ncftp
- if (cip->rname != NULL) {
- char url[256];
- FileToURL(url, sizeof(url), cip->rname, gRemoteCWD, cip->startingWorkingDirectory, cip->user, cip->pass, cip->host, cip->port);
- LogXfer((cip->netMode == kNetReading) ? "get" : "put", url);
- }
- #endif
- break;
- }
- } /* PrStatBar */
- /* This one is the brainchild of my comrade, Phil Dietz. It shows the
- * progress as a fancy bar graph.
- */
- void
- PrPhilBar(const FTPCIPtr cip, int mode)
- {
- int perc;
- longest_int s;
- int curBarLen;
- static int maxBarLen;
- char spec1[64], spec3[64];
- static char bar[256];
- int i;
- int secsLeft, minLeft;
- static const char *uStr;
- static double uMult;
- double rate;
- const char *rStr;
- switch (mode) {
- case kPrInitMsg:
- if (cip->expectedSize == kSizeUnknown) {
- cip->progress = PrSizeAndRateMeter;
- PrSizeAndRateMeter(cip, mode);
- return;
- }
- (void) FileSize((double) cip->expectedSize, &uStr, &uMult);
- fflush(stdout);
- fprintf(stderr, "%s file: %s \n",
- (cip->netMode == kNetReading) ? "Receiving" : "Sending",
- cip->lname
- );
-
- for (i=0; i < (int) sizeof(bar) - 1; i++)
- bar[i] = '=';
- bar[i] = '\0';
- /* Compute the size of the bar itself. This sits between
- * two numbers, one on each side of the screen. So the
- * bar length will vary, depending on how many digits we
- * need to display the size of the file.
- */
- maxBarLen = gScreenColumns - 1 - 28;
- for (s = cip->expectedSize; s > 0; s /= 10L)
- maxBarLen--;
-
- /* Create a specification we can hand to printf. */
- #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
- (void) sprintf(spec1, " 0 %%%ds %%lld bytes. ETA: --:--", maxBarLen);
-
- /* Print the first invocation, which is an empty graph
- * plus the other stuff.
- */
- fprintf(stderr, spec1, " ", cip->expectedSize);
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
- (void) sprintf(spec1, " 0 %%%ds %%qd bytes. ETA: --:--", maxBarLen);
- fprintf(stderr, spec1, " ", cip->expectedSize);
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
- (void) sprintf(spec1, " 0 %%%ds %%I64d bytes. ETA: --:--", maxBarLen);
- fprintf(stderr, spec1, " ", cip->expectedSize);
- #else
- (void) sprintf(spec1, " 0 %%%ds %%ld bytes. ETA: --:--", maxBarLen);
- fprintf(stderr, spec1, " ", (long) cip->expectedSize);
- #endif
- fflush(stdout);
- break;
- case kPrUpdateMsg:
- /* Compute how much of the bar should be colored in. */
- curBarLen = (int) (cip->percentCompleted * 0.01 * (double)maxBarLen);
- /* Colored portion must be at least one character so
- * the spec isn't '%0s' which would screw the right side
- * of the indicator.
- */
- if (curBarLen < 1)
- curBarLen = 1;
-
- bar[curBarLen - 1] = '>';
- bar[curBarLen] = '\0';
- /* Make the spec, so we can print the bar and the other stuff. */
- STRNCPY(spec1, "\r%3d%% 0 ");
- #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
- (void) sprintf(spec3, "%%%ds %%lld bytes. %s%%3d:%%02d",
- maxBarLen - curBarLen,
- "ETA:"
- );
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
- (void) sprintf(spec3, "%%%ds %%qd bytes. %s%%3d:%%02d",
- maxBarLen - curBarLen,
- "ETA:"
- );
- #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
- (void) sprintf(spec3, "%%%ds %%I64d bytes. %s%%3d:%%02d",
- maxBarLen - curBarLen,
- "ETA:"
- );
- #else
- (void) sprintf(spec3, "%%%ds %%ld bytes. %s%%3d:%%02d",
- maxBarLen - curBarLen,
- "ETA:"
- );
- #endif
-
- /* We also show the percentage as a number at the left side. */
- perc = (int) (cip->percentCompleted);
- secsLeft = (int) (cip->secLeft);
- minLeft = secsLeft / 60;
- secsLeft = secsLeft - (minLeft * 60);
- if (minLeft > 999) {
- minLeft = 999;
- secsLeft = 59;
- }
-
- /* Print the updated information. */
- fprintf(stderr, spec1, perc);
- fprintf(stderr, "%s%s%s", tcap_reverse, bar, tcap_normal);
- fprintf(stderr, spec3,
- "",
- cip->expectedSize,
- minLeft,
- secsLeft
- );
- bar[curBarLen - 1] = '=';
- bar[curBarLen] = '=';
- fflush(stdout);
- SetXtermTitle("%s - [%.1f%%]", cip->lname, cip->percentCompleted);
- break;
- case kPrEndMsg:
- printf("\n");
- rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);
- (void) fprintf(stderr, "%s: finished in %ld:%02ld:%02ld, %.2f %s/s\n",
- (cip->lname == NULL) ? "remote" : cip->lname,
- (long) cip->sec / 3600L,
- ((long) cip->sec / 60L) % 60L,
- ((long) cip->sec % 60L),
- rate,
- rStr
- );
- #ifdef ncftp
- if (cip->rname != NULL) {
- char url[256];
- FileToURL(url, sizeof(url), cip->rname, gRemoteCWD, cip->startingWorkingDirectory, cip->user, cip->pass, cip->host, cip->port);
- LogXfer((cip->netMode == kNetReading) ? "get" : "put", url);
- }
- #endif
- break;
- }
- } /* PrPhilBar */