reactos/rosapps/net/ncftp/ncftp/progress.c
Steven Edwards 86bda6b3d9 Added ncftp to rosapps
svn path=/trunk/; revision=2453
2001-12-30 06:31:25 +00:00

498 lines
13 KiB
C

/* progress.c
*
* Copyright (c) 1992-2001 by Mike Gleason.
* All rights reserved.
*
*/
#include "syshdrs.h"
#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_boldface;
extern const char *tcap_underline;
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->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 %.1s",
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 */