ftpXfer2.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:5k
源码类别:

VxWorks

开发平台:

C/C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <selectLib.h>
  6. #include <errnoLib.h>
  7. #include <ftpLib.h>
  8. #include "config.h"
  9. #include "sysLib.h"
  10. #include "netinet/in.h"
  11. #include "sockLib.h"
  12. #include "ftpXfer2.h"
  13. #define FTP_DATA_CONN_TIMEOUT 20 /* sec */
  14. /*
  15.  * ftpXfer2
  16.  *
  17.  * This routine replaces VxWorks ftpXfer and doesn't have a bug that can
  18.  * cause very small file transfers to fail.  In particular, it calls
  19.  * select() on both the data and control sockets, and if they become
  20.  * ready at the SAME TIME (as opposed to just the data socket), vxWorks
  21.  * falsely assumes an error.
  22.  */
  23. extern BOOL ftpVerbose;
  24. STATUS ftpXfer2(char *host, char *user, char *passwd, char *acct,
  25. char *cmd, char *dirname, char *filename,
  26. int *pCtrlSock, int *pDataSock)
  27. {
  28.     int ctrlSock = ERROR, dataSock = ERROR;
  29.     struct fd_set  rfd;
  30.     int result;
  31.     struct timeval tmo;
  32.     char *errmsg = NULL;
  33.     if (ftpVerbose)
  34. printf("ftpXfer2: hookup host=%s file=%sn", host, filename);
  35.     if ((ctrlSock = ftpHookup(host)) == ERROR) {
  36. errmsg = "server unreachable";
  37. goto error;
  38.     }
  39.     *pCtrlSock = ctrlSock;
  40.     if (ftpVerbose)
  41. printf("ftpXfer2: login user=%sn", user);
  42.     if (ftpLogin(ctrlSock, user, passwd, acct) != OK) {
  43. errmsg = "authentication failed";
  44. goto error;
  45.     }
  46.     if (ftpVerbose)
  47. printf("ftpXfer2: set binaryn");
  48.     if (ftpCommand(ctrlSock, "TYPE I", 0, 0, 0, 0, 0, 0) != FTP_COMPLETE) {
  49. errmsg = "set binary mode failed";
  50. goto error;
  51.     }
  52.     if (dirname[0]) {
  53. if (ftpVerbose)
  54.     printf("ftpXfer2: cd %sn", dirname);
  55. if (ftpCommand(ctrlSock, "CWD %s",
  56.        (int) dirname, 0, 0, 0, 0, 0) != FTP_COMPLETE) {
  57.     errmsg = "change directory failed";
  58.     goto error;
  59. }
  60.     }
  61.     /*
  62.      * Retry loop for transient errors, such as the remote host being
  63.      * unable to assign the requested port number.
  64.      */
  65.  retry_transient_error:
  66.     /*
  67.      * If this is a transfer command requiring a data connection,
  68.      * first establish socket for server to connect back to.
  69.      */
  70.     if (pDataSock) {
  71. int len;
  72. short port;
  73. struct sockaddr_in  ownAddr;
  74. struct sockaddr_in  dataAddr;
  75. if (ftpVerbose)
  76.     printf("ftpXfer2: set binaryn");
  77. /* Find out our own address */
  78. len = sizeof (ownAddr);
  79. if (getsockname(ctrlSock, (struct sockaddr *) &ownAddr, &len) < 0) {
  80.     errmsg = "FTP could not get own addr";
  81.     goto error;
  82. }
  83. if ((dataSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  84.     errmsg = "FTP could not create data socket";
  85.     goto error;
  86. }
  87. dataAddr = ownAddr;
  88. dataAddr.sin_port = htons(0);
  89. if (bind(dataSock,
  90.  (struct sockaddr *) &dataAddr,
  91.  sizeof (dataAddr)) != OK) {
  92.     close(dataSock);
  93.     errmsg = "FTP could not bind data socket";
  94.     goto error;
  95. }
  96. /* Read back to find out what port was bound */
  97. len = sizeof (dataAddr);
  98. if (getsockname(dataSock, (struct sockaddr *) &dataAddr, &len) < 0) {
  99.     errmsg = "FTP could not get data addr";
  100.     goto error;
  101. }
  102. port = ntohs(dataAddr.sin_port);
  103. if (listen(dataSock, 1) < 0) {
  104.     close(dataSock);
  105.     errmsg = "FTP could not listen on data socket";
  106.     goto error;
  107. }
  108. /* Use PORT command to inform server of data socket address */
  109. if (ftpCommand(ctrlSock,
  110.        "PORT %d,%d,%d,%d,%d,%d",
  111.        (int) ((UINT8 *) &dataAddr.sin_addr)[0],
  112.        (int) ((UINT8 *) &dataAddr.sin_addr)[1],
  113.        (int) ((UINT8 *) &dataAddr.sin_addr)[2],
  114.        (int) ((UINT8 *) &dataAddr.sin_addr)[3],
  115.        (int) (port >> 8),
  116.        (int) (port & 0xff)) != FTP_COMPLETE) {
  117.     close(dataSock);
  118.     errmsg = "FTP could not send PORT command";
  119.     goto error;
  120. }
  121.     }
  122.     /*
  123.      * Send the FTP command.
  124.      */
  125.     if (ftpVerbose)
  126. printf("ftpXfer2: command %sn", cmd);
  127.     result = ftpCommand(ctrlSock, cmd, (int) filename, 0, 0, 0, 0, 0);
  128.     if (ftpVerbose)
  129. printf("ftpXfer2: result %dn", result);
  130.     switch (result) {
  131.     case FTP_TRANSIENT:
  132. if (pDataSock)
  133.     close(dataSock);
  134. goto retry_transient_error;
  135.     case FTP_COMPLETE:
  136.     case FTP_CONTINUE:
  137. if (pDataSock) {
  138.     close(dataSock);
  139.     errmsg = "server returned COMPLETE or CONTINUE instead of PRELIM";
  140.     goto error;
  141. }
  142. return OK; /* Non-transfer command succeeded */
  143.     case FTP_PRELIM:
  144. if (! pDataSock) {
  145.     errmsg = "server returned PRELIM for non-transfer command";
  146.     goto error;
  147. }
  148. break; /* Continue below to start transfer */
  149.     default:
  150. if (pDataSock)
  151.     close(dataSock);
  152. errmsg = "command failed";
  153. goto error;
  154.     }
  155.     /*
  156.      * Wait for server to connect back on data socket.
  157.      * Use select to provide a timeout.
  158.      */
  159.     FD_ZERO(&rfd);
  160.     FD_SET(dataSock, &rfd);
  161.     tmo.tv_sec = FTP_DATA_CONN_TIMEOUT;
  162.     tmo.tv_usec = 0;
  163.     if (ftpVerbose)
  164. printf("ftpXfer2: wait for datan");
  165.     if (select(FD_SETSIZE, &rfd, NULL, NULL, &tmo) <= 0) {
  166. if (pDataSock)
  167.     close(dataSock);
  168. errmsg = "data conn failed or timed out";
  169. goto error;
  170.     }
  171.     if (ftpVerbose)
  172. printf("ftpXfer2: get data connn");
  173.     if ((dataSock = ftpDataConnGet(dataSock)) == ERROR) {
  174. errmsg = "failed to accept server connection";
  175. goto error;
  176.     }
  177.     *pDataSock = dataSock;
  178.     if (ftpVerbose)
  179. printf("ftpXfer2: return OKn");
  180.     return OK;
  181.  error:
  182.     if (errmsg && ftpVerbose)
  183. printErr("FTP ERROR: %s (errno=%d)n", errmsg, errnoGet());
  184.     if (ctrlSock != ERROR) {
  185. (void) ftpCommand(ctrlSock, "QUIT", 0, 0, 0, 0, 0, 0);
  186. close(ctrlSock);
  187.     }
  188.     if (ftpVerbose)
  189. printf("ftpXfer2: return ERRORn");
  190.     return ERROR;
  191. }