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_putmem.c < prev    next >
C/C++ Source or Header  |  2007-07-29  |  5KB  |  228 lines

  1. /* io_putmem.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. int
  18. FTPPutFileFromMemory(
  19.     const FTPCIPtr cip,
  20.     const char *volatile dstfile,
  21.     const char *volatile src,
  22.     const size_t srcLen,
  23.     const int appendflag)
  24. {
  25.     const char *cp;
  26.     const char *cmd;
  27.     int tmpResult, result;
  28.     read_return_t nread;
  29.     write_return_t nwrote;
  30.     size_t bufSize;
  31.     const char *srcLim;
  32.     const char *volatile srcp;
  33. #if !defined(NO_SIGNALS)
  34.     int sj;
  35.     volatile FTPSigProc osigpipe;
  36.     volatile FTPCIPtr vcip;
  37. #endif    /* NO_SIGNALS */
  38.  
  39.     if (cip->buf == NULL) {
  40.         FTPLogError(cip, kDoPerror, "Transfer buffer not allocated.\n");
  41.         cip->errNo = kErrNoBuf;
  42.         return (cip->errNo);
  43.     }
  44.  
  45.     cip->usingTAR = 0;
  46.  
  47.     /* For Put, we can't recover very well if it turns out restart
  48.      * didn't work, so check beforehand.
  49.      */
  50.     FTPCheckForRestartModeAvailability(cip); 
  51.  
  52.     FTPSetUploadSocketBufferSize(cip);
  53.  
  54. #ifdef NO_SIGNALS
  55. #else    /* NO_SIGNALS */
  56.     vcip = cip;
  57.     osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData);
  58.  
  59.     gGotBrokenData = 0;
  60.     gCanBrokenDataJmp = 0;
  61.  
  62. #ifdef HAVE_SIGSETJMP
  63.     sj = sigsetjmp(gBrokenDataJmp, 1);
  64. #else
  65.     sj = setjmp(gBrokenDataJmp);
  66. #endif    /* HAVE_SIGSETJMP */
  67.  
  68.     if (sj != 0) {
  69.         (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
  70.         FTPShutdownHost(vcip);
  71.         vcip->errNo = kErrRemoteHostClosedConnection;
  72.         return(vcip->errNo);
  73.     }
  74.     gCanBrokenDataJmp = 1;
  75. #endif    /* NO_SIGNALS */
  76.  
  77.     cmd = appendflag == kAppendYes ? "APPE" : "STOR";
  78.     tmpResult = FTPStartDataCmd(
  79.         cip,
  80.         kNetWriting,
  81.         kTypeBinary,
  82.         (longest_int) 0,
  83.         "%s %s",
  84.         cmd,
  85.         dstfile
  86.     );
  87.  
  88.     if (tmpResult < 0) {
  89.         cip->errNo = tmpResult;
  90. #if !defined(NO_SIGNALS)
  91.         (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
  92. #endif    /* NO_SIGNALS */
  93.         return (cip->errNo);
  94.     }
  95.  
  96.     result = kNoErr;
  97.     bufSize = cip->bufSize;
  98.  
  99.     FTPInitIOTimer(cip);
  100.     cip->expectedSize = (longest_int) srcLen;
  101.     cip->lname = NULL;    /* could be NULL */
  102.     cip->rname = dstfile;
  103.     srcp = src;
  104.     srcLim = src + srcLen;
  105.     FTPStartIOTimer(cip);
  106.     {
  107.         /* binary */
  108.         for (;;) {
  109. #if !defined(NO_SIGNALS)
  110.             gCanBrokenDataJmp = 0;
  111. #endif    /* NO_SIGNALS */
  112.             nread = (read_return_t) bufSize;
  113.             if ((size_t) (srcLim - srcp) < bufSize) {
  114.                 nread = (read_return_t) (srcLim - srcp);
  115.                 if (nread == 0) {
  116.                     result = kNoErr;
  117.                     break;
  118.                 }
  119.             }
  120.             cip->bytesTransferred += (longest_int) nread;
  121.             cp = srcp;
  122.             srcp += nread;
  123.  
  124. #if !defined(NO_SIGNALS)
  125.             gCanBrokenDataJmp = 1;
  126.             if (cip->xferTimeout > 0)
  127.                 (void) alarm(cip->xferTimeout);
  128. #endif    /* NO_SIGNALS */
  129.             do {
  130.                 if (! WaitForRemoteOutput(cip)) {    /* could set cancelXfer */
  131.                     cip->errNo = result = kErrDataTimedOut;
  132.                     FTPLogError(cip, kDontPerror, "Remote write timed out.\n");
  133.                     goto brk;
  134.                 }
  135.                 if (cip->cancelXfer > 0) {
  136.                     FTPAbortDataTransfer(cip);
  137.                     result = cip->errNo = kErrDataTransferAborted;
  138.                     goto brk;
  139.                 }
  140.  
  141. #ifdef NO_SIGNALS
  142.                 nwrote = (write_return_t) SWrite(cip->dataSocket, cp, (size_t) nread, (int) cip->xferTimeout, kNoFirstSelect);
  143.                 if (nwrote < 0) {
  144.                     if (nwrote == kTimeoutErr) {
  145.                         cip->errNo = result = kErrDataTimedOut;
  146.                         FTPLogError(cip, kDontPerror, "Remote write timed out.\n");
  147.                     } else if (errno == EPIPE) {
  148.                         cip->errNo = result = kErrSocketWriteFailed;
  149.                         errno = EPIPE;
  150.                         FTPLogError(cip, kDoPerror, "Lost data connection to remote host.\n");
  151.                     } else if (errno == EINTR) {
  152.                         continue;
  153.                     } else {
  154.                         cip->errNo = result = kErrSocketWriteFailed;
  155.                         FTPLogError(cip, kDoPerror, "Remote write failed.\n");
  156.                     }
  157.                     (void) shutdown(cip->dataSocket, 2);
  158.                     goto brk;
  159.                 }
  160. #else    /* NO_SIGNALS */
  161.                 nwrote = write(cip->dataSocket, cp, (write_size_t) nread);
  162.                 if (nwrote < 0) {
  163.                     if ((gGotBrokenData != 0) || (errno == EPIPE)) {
  164.                         cip->errNo = result = kErrSocketWriteFailed;
  165.                         errno = EPIPE;
  166.                         FTPLogError(cip, kDoPerror, "Lost data connection to remote host.\n");
  167.                     } else if (errno == EINTR) {
  168.                         continue;
  169.                     } else {
  170.                         cip->errNo = result = kErrSocketWriteFailed;
  171.                         FTPLogError(cip, kDoPerror, "Remote write failed.\n");
  172.                     }
  173.                     (void) shutdown(cip->dataSocket, 2);
  174.                     goto brk;
  175.                 }
  176. #endif    /* NO_SIGNALS */
  177.                 cp += nwrote;
  178.                 nread -= nwrote;
  179.             } while (nread > 0);
  180.             FTPUpdateIOTimer(cip);
  181.         }
  182.     }
  183. brk:
  184.  
  185.     /* This looks very bizarre, since
  186.      * we will be checking the socket
  187.      * for readability here!
  188.      *
  189.      * The reason for this is that we
  190.      * want to be able to timeout a
  191.      * small put.  So, we close the
  192.      * write end of the socket first,
  193.      * which tells the server we're
  194.      * done writing.  We then wait
  195.      * for the server to close down
  196.      * the whole socket (we know this
  197.      * when the socket is ready for
  198.      * reading an EOF), which tells
  199.      * us that the file was completed.
  200.      */
  201.     (void) shutdown(cip->dataSocket, 1);
  202.     (void) WaitForRemoteInput(cip);
  203.  
  204. #if !defined(NO_SIGNALS)
  205.     gCanBrokenDataJmp = 0;
  206.     if (cip->xferTimeout > 0)
  207.         (void) alarm(0);
  208. #endif    /* NO_SIGNALS */
  209.     tmpResult = FTPEndDataCmd(cip, 1);
  210.     if ((tmpResult < 0) && (result == kNoErr)) {
  211.         cip->errNo = result = kErrSTORFailed;
  212.     }
  213.     FTPStopIOTimer(cip);
  214.  
  215.     if (result == kNoErr) {
  216.         /* The store succeeded;  If we were
  217.          * uploading to a temporary file,
  218.          * move the new file to the new name.
  219.          */
  220.         cip->numUploads++;
  221.     }
  222.  
  223. #if !defined(NO_SIGNALS)
  224.     (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
  225. #endif    /* NO_SIGNALS */
  226.     return (result);
  227. }    /* FTPPutFileFromMemory */
  228.