Logo Search packages:      
Sourcecode: ncftp version File versions

progress.c

/* progress.c
 *
 * Copyright (c) 1992-2004 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 */

Generated by  Doxygen 1.6.0   Back to index