home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / older_versions / ncftp-3.2.2-src.tar.bz2 / ncftp-3.2.2-src.tar / ncftp-3.2.2 / libncftp / io_util.c < prev    next >
C/C++ Source or Header  |  2005-01-01  |  9KB  |  368 lines

  1. /* io_util.c
  2.  *
  3.  * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
  4.  * All rights reserved.
  5.  *
  6.  */
  7.  
  8. #include "syshdrs.h"
  9. #ifdef PRAGMA_HDRSTOP
  10. #    pragma hdrstop
  11. #endif
  12.  
  13. #ifndef NO_SIGNALS
  14. #    define NO_SIGNALS 1
  15. #endif
  16.  
  17. #ifndef O_BINARY
  18.     /* Needed for platforms using different EOLN sequence (i.e. DOS) */
  19. #    ifdef _O_BINARY
  20. #        define O_BINARY _O_BINARY
  21. #    else
  22. #        define O_BINARY 0
  23. #    endif
  24. #endif
  25.  
  26. double
  27. FTPDuration(struct timeval *t0)
  28. {
  29.     struct timeval t1;
  30.     double sec;
  31.  
  32.     (void) gettimeofday(&t1, NULL);
  33.     if (t0->tv_usec > t1.tv_usec) {
  34.         t1.tv_usec += 1000000;
  35.         t1.tv_sec--;
  36.     }
  37.     sec = ((double) (t1.tv_usec - t0->tv_usec) * 0.000001)
  38.         + (t1.tv_sec - t0->tv_sec);
  39.  
  40.     return (sec);
  41. }    /* FTPDuration */
  42.  
  43.  
  44.  
  45.  
  46. void
  47. FTPInitIOTimer(const FTPCIPtr cip)
  48. {
  49.     cip->bytesTransferred = (longest_int) 0;
  50.     cip->expectedSize = kSizeUnknown;
  51.     cip->mdtm = kModTimeUnknown;
  52.     cip->rname = NULL;
  53.     cip->lname = NULL;
  54.     cip->kBytesPerSec = -1.0;
  55.     cip->percentCompleted = -1.0;
  56.     cip->sec = -1.0;
  57.     cip->secLeft = -1.0;
  58.     cip->nextProgressUpdate = 0;
  59.     cip->stalled = 0;
  60.     cip->dataTimedOut = 0;
  61.     cip->useProgressMeter = 1;
  62.     (void) gettimeofday(&cip->t0, NULL);
  63. }    /* FTPInitIOTimer */
  64.  
  65.  
  66.  
  67.  
  68. void
  69. FTPStartIOTimer(const FTPCIPtr cip)
  70. {
  71.     (void) gettimeofday(&cip->t0, NULL);
  72.     if (cip->progress != (FTPProgressMeterProc) 0)
  73.         (*cip->progress)(cip, kPrInitMsg);
  74. }    /* FTPStartIOTimer */
  75.  
  76.  
  77.  
  78.  
  79. void
  80. FTPUpdateIOTimer(const FTPCIPtr cip)
  81. {
  82.     double sec;
  83.     struct timeval *t0, t1;
  84.     time_t now;
  85.  
  86.     (void) time(&now);
  87.     if ((now < cip->nextProgressUpdate) && (cip->canceling == 0))
  88.         return;
  89.     now += 1;
  90.     cip->nextProgressUpdate = now;
  91.  
  92.     (void) gettimeofday(&t1, NULL);
  93.     t0 = &cip->t0;
  94.  
  95.     if (t0->tv_usec > t1.tv_usec) {
  96.         t1.tv_usec += 1000000;
  97.         t1.tv_sec--;
  98.     }
  99.     sec = ((double) (t1.tv_usec - t0->tv_usec) * 0.000001)
  100.         + (t1.tv_sec - t0->tv_sec);
  101.     if (sec > 0.0) {
  102.         cip->kBytesPerSec = ((double) cip->bytesTransferred) / (1024.0 * sec);
  103.     } else {
  104.         cip->kBytesPerSec = -1.0;
  105.     }
  106.     if (cip->expectedSize == kSizeUnknown) {
  107.         cip->percentCompleted = -1.0;
  108.         cip->secLeft = -1.0;
  109.     } else if (cip->expectedSize <= 0) {
  110.         cip->percentCompleted = 100.0;
  111.         cip->secLeft = 0.0;
  112.     } else {
  113.         cip->percentCompleted = ((double) (100.0 * (cip->bytesTransferred + cip->startPoint))) / ((double) cip->expectedSize);
  114.         if (cip->percentCompleted >= 100.0) {
  115.             cip->percentCompleted = 100.0;
  116.             cip->secLeft = 0.0;
  117.         } else if (cip->percentCompleted <= 0.0) {
  118.             cip->secLeft = 999.0;
  119.         }
  120.         if (cip->kBytesPerSec > 0.0) {
  121.             cip->secLeft = ((cip->expectedSize - cip->bytesTransferred - cip->startPoint) / 1024.0) / cip->kBytesPerSec;
  122.             if (cip->secLeft < 0.0)
  123.                 cip->secLeft = 0.0;
  124.         }
  125.     }
  126.     cip->sec = sec;
  127.     if ((cip->progress != (FTPProgressMeterProc) 0) && (cip->useProgressMeter != 0))
  128.         (*cip->progress)(cip, kPrUpdateMsg);
  129. }    /* FTPUpdateIOTimer */
  130.  
  131.  
  132.  
  133.  
  134. void
  135. FTPStopIOTimer(const FTPCIPtr cip)
  136. {
  137.     cip->nextProgressUpdate = 0;    /* force last update */
  138.     FTPUpdateIOTimer(cip);
  139.     if (cip->progress != (FTPProgressMeterProc) 0)
  140.         (*cip->progress)(cip, kPrEndMsg);
  141. }    /* FTPStopIOTimer */
  142.  
  143.  
  144.  
  145.  
  146. /* The purpose of this is to provide updates for the progress meters
  147.  * during lags.  Return zero if the operation timed-out.
  148.  */
  149. int
  150. WaitForRemoteInput(const FTPCIPtr cip)
  151. {
  152.     fd_set ss, ss2;
  153.     struct timeval tv;
  154.     int result;
  155.     int fd;
  156.     int wsecs;
  157.     int xferTimeout;
  158.     int ocancelXfer;
  159.  
  160.     xferTimeout = cip->xferTimeout;
  161.     if (xferTimeout < 1)
  162.         return (1);
  163.  
  164.     fd = cip->dataSocket;
  165.     if (fd < 0)
  166.         return (1);
  167.  
  168.     if (cip->dataTimedOut > 0) {
  169.         cip->dataTimedOut++;
  170.         return (0);    /* already timed-out */
  171.     }
  172.  
  173.     ocancelXfer = cip->cancelXfer;
  174.     wsecs = 0;
  175.     cip->stalled = 0;
  176.  
  177.     while ((xferTimeout <= 0) || (wsecs < xferTimeout)) {
  178.         if ((cip->cancelXfer != 0) && (ocancelXfer == 0)) {
  179.             /* leave cip->stalled -- could have been stalled and then canceled. */
  180.             return (1);
  181.         }
  182.         MY_FD_ZERO(&ss);
  183. #if defined(__DECC) || defined(__DECCXX)
  184. #pragma message save
  185. #pragma message disable trunclongint
  186. #endif
  187.         MY_FD_SET(fd, &ss);
  188. #if defined(__DECC) || defined(__DECCXX)
  189. #pragma message restore
  190. #endif
  191.         ss2 = ss;
  192.         tv.tv_sec = 1;
  193.         tv.tv_usec = 0;
  194.         result = select(fd + 1, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG234 &ss2, &tv);
  195.         if (result == 1) {
  196.             /* ready */
  197.             cip->stalled = 0;
  198.             return (1);
  199.         } else if (result < 0) {
  200.             if (errno != EINTR) {
  201.                 cip->stalled = 0;
  202.                 return (1);    /* Ready to read error */
  203.             }
  204.         } else {
  205.             wsecs++;
  206.             cip->stalled = wsecs;
  207.         }
  208.         FTPUpdateIOTimer(cip);
  209.     }
  210.  
  211. #if !defined(NO_SIGNALS)
  212.     /* Shouldn't get here -- alarm() should have
  213.      * went off by now.
  214.      */
  215.     (void) kill(getpid(), SIGALRM);
  216. #endif    /* NO_SIGNALS */
  217.  
  218.     cip->dataTimedOut++;
  219.     return (0);    /* timed-out */
  220. }    /* WaitForRemoteInput */
  221.  
  222.  
  223.  
  224.  
  225. /* The purpose of this is to provide updates for the progress meters
  226.  * during lags.  Return zero if the operation timed-out.
  227.  */
  228. int
  229. WaitForRemoteOutput(const FTPCIPtr cip)
  230. {
  231.     fd_set ss, ss2;
  232.     struct timeval tv;
  233.     int result;
  234.     int fd;
  235.     int wsecs;
  236.     int xferTimeout;
  237.     int ocancelXfer;
  238.  
  239.     xferTimeout = cip->xferTimeout;
  240.     if (xferTimeout < 1)
  241.         return (1);
  242.  
  243.     fd = cip->dataSocket;
  244.     if (fd < 0)
  245.         return (1);
  246.  
  247.     if (cip->dataTimedOut > 0) {
  248.         cip->dataTimedOut++;
  249.         return (0);    /* already timed-out */
  250.     }
  251.  
  252.     ocancelXfer = cip->cancelXfer;
  253.     wsecs = 0;
  254.     cip->stalled = 0;
  255.  
  256.     while ((xferTimeout <= 0) || (wsecs < xferTimeout)) {
  257.         if ((cip->cancelXfer != 0) && (ocancelXfer == 0)) {
  258.             /* leave cip->stalled -- could have been stalled and then canceled. */
  259.             return (1);
  260.         }
  261.         MY_FD_ZERO(&ss);
  262. #if defined(__DECC) || defined(__DECCXX)
  263. #pragma message save
  264. #pragma message disable trunclongint
  265. #endif
  266.         MY_FD_SET(fd, &ss);
  267. #if defined(__DECC) || defined(__DECCXX)
  268. #pragma message restore
  269. #endif
  270.         ss2 = ss;
  271.         tv.tv_sec = 1;
  272.         tv.tv_usec = 0;
  273.         result = select(fd + 1, NULL, SELECT_TYPE_ARG234 &ss, SELECT_TYPE_ARG234 &ss2, &tv);
  274.         if (result == 1) {
  275.             /* ready */
  276.             cip->stalled = 0;
  277.             return (1);
  278.         } else if (result < 0) {
  279.             if (errno != EINTR) {
  280.                 cip->stalled = 0;
  281.                 return (1);    /* Ready to read error */
  282.             }
  283.         } else {
  284.             wsecs++;
  285.             cip->stalled = wsecs;
  286.         }
  287.         FTPUpdateIOTimer(cip);
  288.     }
  289.  
  290. #if !defined(NO_SIGNALS)
  291.     /* Shouldn't get here -- alarm() should have
  292.      * went off by now.
  293.      */
  294.     (void) kill(getpid(), SIGALRM);
  295. #endif    /* NO_SIGNALS */
  296.  
  297.     cip->dataTimedOut++;
  298.     return (0);    /* timed-out */
  299. }    /* WaitForRemoteOutput */
  300.  
  301.  
  302.  
  303.  
  304. void
  305. AutomaticallyUseASCIIModeDependingOnExtension(const FTPCIPtr cip, const char *const pathName, int *const xtype)
  306. {
  307.     if ((*xtype == kTypeBinary) && (cip->asciiFilenameExtensions != NULL)) {
  308.         if (FilenameExtensionIndicatesASCII(pathName, cip->asciiFilenameExtensions)) {
  309.             /* Matched -- send this file in ASCII mode
  310.              * instead of binary since it's extension
  311.              * appears to be that of a text file.
  312.              */
  313.             *xtype = kTypeAscii;
  314.         }
  315.     }
  316. }    /* AutomaticallyUseASCIIModeDependingOnExtension */
  317.  
  318.  
  319.  
  320. void
  321. FTPCheckForRestartModeAvailability(const FTPCIPtr cip)
  322. {
  323.     if (cip->hasREST == kCommandAvailabilityUnknown) {
  324.         (void) FTPSetTransferType(cip, kTypeBinary);
  325.         if (FTPSetStartOffset(cip, (longest_int) 1) == kNoErr) {
  326.             /* Now revert -- we still may not end up
  327.              * doing it.
  328.              */
  329.             FTPSetStartOffset(cip, (longest_int) -1);
  330.         }
  331.     }
  332. }    /* FTPCheckForRestartModeAvailability */
  333.  
  334.  
  335.  
  336. void
  337. FTPSetUploadSocketBufferSize(const FTPCIPtr cip)
  338. {
  339.     /* If dataSocketSBufSize is non-zero, it means you
  340.      * want to explicitly try to set the size of the
  341.      * socket's I/O buffer.
  342.      *
  343.      * If it is zero, it means you want to just use the
  344.      * TCP stack's default value, which is typically
  345.      * between 8 and 64 kB.
  346.      *
  347.      * If you try to set the buffer larger than 64 kB,
  348.      * the TCP stack should try to use RFC 1323 to
  349.      * negotiate "TCP Large Windows" which may yield
  350.      * significant performance gains.
  351.      */
  352.     if ((cip->numUploads == 0) && (cip->dataSocketSBufSize != 0)) {
  353.         if (cip->hasSITE_STORBUFSIZE == kCommandAvailable)
  354.             (void) FTPCmd(cip, "SITE STORBUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
  355.         else if (cip->hasSITE_SBUFSIZ == kCommandAvailable)
  356.             (void) FTPCmd(cip, "SITE SBUFSIZ %lu", (unsigned long) cip->dataSocketSBufSize);
  357.         else if (cip->hasSITE_SBUFSZ == kCommandAvailable)
  358.             (void) FTPCmd(cip, "SITE SBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
  359.         /* At least one server implemenation has RBUFSZ but not
  360.          * SBUFSZ and instead uses RBUFSZ for both.
  361.          */
  362.         else if ((cip->hasSITE_SBUFSZ != kCommandAvailable) && (cip->hasSITE_RBUFSZ == kCommandAvailable))
  363.             (void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
  364.         else if (cip->hasSITE_BUFSIZE == kCommandAvailable)
  365.             (void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
  366.     }
  367. }    /* FTPSetUploadSocketBufferSize */
  368.