LCOV - code coverage report
Current view: top level - src - ftplib.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 255 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 18 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         ftplib.c
       4              :   Created by:   Originally written by Oleg Orel (orel@lpuds.oea.ihep.su),
       5              :                 translated from UNIX to NT by Urs Rohrer (rohrer@psi.ch),
       6              :                 simplified and adapted for MIDAS by Stefan Ritt.
       7              : 
       8              :   Contents:     File Transfer Protocol library
       9              : 
      10              :   $Id$
      11              : 
      12              : \********************************************************************/
      13              : 
      14              : #include "midas.h"
      15              : #include "msystem.h"
      16              : #include "ftplib.h"
      17              : 
      18              : #ifndef FTP_SUCCESS
      19              : #define FTP_SUCCESS                   1
      20              : #define FTP_NET_ERROR               802
      21              : #define FTP_FILE_ERROR              803
      22              : #define FTP_RESPONSE_ERROR          804
      23              : #define FTP_INVALID_ARG             805
      24              : #endif
      25              : 
      26              : static char bars[] = "/-\\|";
      27              : int (*ftp_debug_func) (const char *message);
      28              : int (*ftp_error_func) (const char *message);
      29              : 
      30              : /*------------------------------------------------------------------*/
      31              : 
      32            0 : void ftp_debug(int (*debug_func) (const char *message), int (*error_func) (const char *message))
      33              : /* set message display functions for debug and error messages */
      34              : {
      35            0 :    ftp_debug_func = debug_func;
      36            0 :    ftp_error_func = error_func;
      37            0 : }
      38              : 
      39              : /*------------------------------------------------------------------*/
      40              : 
      41            0 : int ftp_connect(FTP_CON ** con, const char *host_name, unsigned short port)
      42              : /* Connect to a FTP server on a host at a given port (usually 21).
      43              :    Return a FTP_CON structure if successful */
      44              : {
      45              :    struct sockaddr_in bind_addr;
      46              :    int sock;
      47              :    char str[4000];
      48              :    int status;
      49              :    struct hostent *phe;
      50              : 
      51            0 :    *con = NULL;
      52              : 
      53              : #ifdef OS_WINNT
      54              :    {
      55              :       WSADATA WSAData;
      56              : 
      57              :       /* Start windows sockets */
      58              :       if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
      59              :          return FTP_NET_ERROR;
      60              :    }
      61              : #endif
      62              : 
      63            0 :    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      64            0 :       if (ftp_error_func)
      65            0 :          ftp_error_func("cannot create socket");
      66            0 :       return FTP_NET_ERROR;
      67              :    }
      68              : 
      69              :    /* connect to remote node */
      70            0 :    memset(&bind_addr, 0, sizeof(bind_addr));
      71            0 :    bind_addr.sin_family = AF_INET;
      72            0 :    bind_addr.sin_addr.s_addr = 0;
      73            0 :    bind_addr.sin_port = htons(port);
      74              : 
      75              : #ifdef OS_VXWORKS
      76              :    {
      77              :       INT host_addr;
      78              : 
      79              :       host_addr = hostGetByName(host_name);
      80              :       memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
      81              :    }
      82              : #else
      83            0 :    phe = gethostbyname(host_name);
      84            0 :    if (phe == NULL) {
      85            0 :       if (ftp_error_func)
      86            0 :          ftp_error_func("cannot get host name");
      87            0 :       return RPC_NET_ERROR;
      88              :    }
      89            0 :    memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
      90              : #endif
      91              : 
      92              : #ifdef OS_UNIX
      93              :    do {
      94            0 :       status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
      95              : 
      96              :       /* don't return if an alarm signal was cought */
      97            0 :    } while (status == -1 && errno == EINTR);
      98              : #else
      99              :    status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
     100              : #endif
     101              : 
     102            0 :    if (status != 0) {
     103            0 :       sprintf(str, "cannot connect to host %s, port %d", host_name, port);
     104            0 :       if (ftp_error_func)
     105            0 :          ftp_error_func(str);
     106            0 :       return FTP_NET_ERROR;
     107              :    }
     108              : 
     109              : 
     110            0 :    *con = (FTP_CON *) malloc(sizeof(FTP_CON));
     111            0 :    (*con)->sock = sock;
     112            0 :    (*con)->data = 0;
     113              : 
     114            0 :    memset(str, 0, sizeof(str));
     115            0 :    status = ftp_get_message(*con, str);
     116              : 
     117              :    /* check for status */
     118            0 :    if (status == FTP_QUIT || !ftp_good(status, 120, 220, EOF)) {
     119            0 :       closesocket(sock);
     120            0 :       free(*con);
     121            0 :       return FTP_NET_ERROR;
     122              :    }
     123              : 
     124            0 :    return FTP_SUCCESS;
     125              : }
     126              : 
     127              : /*------------------------------------------------------------------*/
     128              : 
     129            0 : int ftp_send_message(FTP_CON * con, const char *message)
     130              : /* send a message to a FTP server */
     131              : {
     132            0 :    if (send(con->sock, message, strlen(message), 0) == -1)
     133            0 :       return FTP_NET_ERROR;
     134              : 
     135            0 :    if (send(con->sock, "\r\n", 2, 0) == -1)
     136            0 :       return FTP_NET_ERROR;
     137              : 
     138            0 :    if (ftp_debug_func != NULL)
     139            0 :       ftp_debug_func(message);
     140              : 
     141            0 :    return FTP_SUCCESS;
     142              : }
     143              : 
     144              : /*------------------------------------------------------------------*/
     145              : 
     146            0 : int ftp_command(FTP_CON * con, const char *command, const char *param, ...)
     147              : /* execute FTP command, check for return codes */
     148              : {
     149              :    va_list args;
     150              :    char str[256];
     151              :    int status, code;
     152              :    BOOL result_ok;
     153              : 
     154              :    /* compose command string */
     155            0 :    sprintf(str, command, param);
     156              : 
     157              :    /* send command */
     158            0 :    if (ftp_send_message(con, str) != FTP_SUCCESS)
     159            0 :       return FTP_NET_ERROR;
     160              : 
     161              :    /* read reply */
     162            0 :    status = ftp_get_message(con, str);
     163            0 :    if (status == FTP_QUIT)
     164            0 :       return FTP_NET_ERROR;
     165              : 
     166              :    /* check reply code */
     167            0 :    va_start(args, param);
     168              : 
     169            0 :    result_ok = FALSE;
     170              :    do {
     171            0 :       code = va_arg(args, int);
     172            0 :       if (code == EOF)
     173            0 :          break;
     174              : 
     175            0 :       if (code == status)
     176            0 :          result_ok = TRUE;
     177              : 
     178            0 :    } while (!result_ok);
     179              : 
     180            0 :    va_end(args);
     181              : 
     182            0 :    if (!result_ok) {
     183            0 :       if (ftp_error_func != NULL)
     184            0 :          ftp_error_func(str);
     185              : 
     186            0 :       return FTP_RESPONSE_ERROR;
     187              :    }
     188              : 
     189            0 :    return -status;
     190              : }
     191              : 
     192              : /*------------------------------------------------------------------*/
     193              : 
     194            0 : int ftp_get_message(FTP_CON * con, char *message)
     195              : /* read message from FTP server */
     196              : {
     197              :    int i;
     198              : 
     199            0 :    for (i = 0;; i++) {
     200            0 :       if (recv(con->sock, &message[i], 1, 0) != 1)
     201            0 :          return FTP_QUIT;
     202              : 
     203            0 :       if (i > 1 && message[i] == 10 && message[i - 1] == 13)
     204            0 :          break;
     205              :    }
     206              : 
     207            0 :    message[i - 1] = 0;
     208              : 
     209            0 :    con->err_no = atoi(message);
     210              : 
     211            0 :    if (ftp_debug_func != NULL)
     212            0 :       ftp_debug_func(message);
     213              : 
     214              :    /* check for continuation message */
     215            0 :    if (message[3] == '-')
     216            0 :       ftp_get_message(con, message + strlen(message));
     217              : 
     218            0 :    return con->err_no;
     219              : }
     220              : 
     221              : /*------------------------------------------------------------------*/
     222              : 
     223            0 : BOOL ftp_good(int number, ...)
     224              : /* check if number matches any code from argument list */
     225              : {
     226              :    va_list args;
     227              :    BOOL result;
     228              :    int code;
     229              : 
     230            0 :    va_start(args, number);
     231            0 :    result = FALSE;
     232              : 
     233              :    do {
     234            0 :       code = va_arg(args, int);
     235            0 :       if (code == EOF)
     236            0 :          break;
     237              : 
     238            0 :       if (code == number)
     239            0 :          result = TRUE;
     240              : 
     241            0 :    } while (!result);
     242              : 
     243            0 :    va_end(args);
     244              : 
     245            0 :    return result;
     246              : }
     247              : 
     248              : /*------------------------------------------------------------------*/
     249              : 
     250            0 : int ftp_data(FTP_CON * con, const char *command, const char *file)
     251              : /* open data socket */
     252              : {
     253              :    struct sockaddr_in data, from;
     254              :    struct hostent *host;
     255              :    char host_name[256];
     256              :    int listen_socket, data_socket;
     257            0 :    unsigned int len = sizeof(data), fromlen = sizeof(from);
     258            0 :    int one = 1, status;
     259              :    char *a, *b;
     260              : 
     261            0 :    memset(&data, 0, sizeof(data));
     262            0 :    memset(&from, 0, sizeof(from));
     263              : 
     264            0 :    if (gethostname(host_name, sizeof(host_name)) == -1)
     265            0 :       return FTP_NET_ERROR;
     266              : 
     267            0 :    if ((host = (struct hostent *) gethostbyname(host_name)) == 0)
     268            0 :       return FTP_NET_ERROR;
     269              : 
     270            0 :    if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     271            0 :       return FTP_NET_ERROR;
     272              : 
     273            0 :    if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
     274            0 :                   (char *) &one, sizeof(one)) < 0) {
     275            0 :       closesocket(listen_socket);
     276            0 :       return FTP_NET_ERROR;
     277              :    }
     278              : 
     279            0 :    data.sin_family = AF_INET;
     280            0 :    data.sin_port = htons(0);
     281            0 :    data.sin_addr.s_addr = *(unsigned long *) *(host->h_addr_list);
     282              : 
     283            0 :    if (bind(listen_socket, (struct sockaddr *) &data, sizeof(data)) == -1) {
     284            0 :       closesocket(listen_socket);
     285            0 :       return FTP_NET_ERROR;
     286              :    }
     287              : 
     288              : #ifdef OS_WINNT
     289              :    if (getsockname(listen_socket, (struct sockaddr *) &data, (int *)&len) < 0) {
     290              : #else
     291            0 :    if (getsockname(listen_socket, (struct sockaddr *) &data, &len) < 0) {
     292              : #endif
     293            0 :       closesocket(listen_socket);
     294            0 :       return FTP_NET_ERROR;
     295              :    }
     296              : 
     297            0 :    if (listen(listen_socket, 1) != 0) {
     298            0 :       closesocket(listen_socket);
     299            0 :       return FTP_NET_ERROR;
     300              :    }
     301              : 
     302            0 :    a = (char *) &data.sin_addr;
     303            0 :    b = (char *) &data.sin_port;
     304              : 
     305            0 :    status = ftp_port(con, FTP_CUT(a[0]), FTP_CUT(a[1]), FTP_CUT(a[2]),
     306            0 :                      FTP_CUT(a[3]), FTP_CUT(b[0]), FTP_CUT(b[1]));
     307            0 :    if (status != FTP_SUCCESS)
     308            0 :       return FTP_NET_ERROR;
     309              : 
     310            0 :    status = ftp_command(con, command, file, 200, 120, 150, 125, 250, EOF);
     311            0 :    if (status >= 0)
     312            0 :       return status;
     313              : 
     314              : #ifdef OS_WINNT
     315              :    data_socket = accept(listen_socket, (struct sockaddr *) &from, (int *)&fromlen);
     316              : #else
     317            0 :    data_socket = accept(listen_socket, (struct sockaddr *) &from, &fromlen);
     318              : #endif
     319              : 
     320            0 :    if (data_socket == -1) {
     321            0 :       closesocket(listen_socket);
     322            0 :       return FTP_NET_ERROR;
     323              :    }
     324              : 
     325            0 :    closesocket(listen_socket);
     326              : 
     327            0 :    con->data = data_socket;
     328              : 
     329            0 :    return status;
     330              : }
     331              : 
     332              : /*------------------------------------------------------------------*/
     333              : 
     334            0 : int ftp_close(FTP_CON * con)
     335              : /* close data connection */
     336              : {
     337              :    char str[256];
     338              : 
     339            0 :    closesocket(con->data);
     340              : 
     341            0 :    return ftp_get_message(con, str);
     342              : }
     343              : 
     344              : /*------------------------------------------------------------------*/
     345              : 
     346            0 : int ftp_send(int sock, const char *buffer, int n_bytes_to_write)
     347              : /* send number of bytes over socket */
     348              : {
     349              :    int n_bytes_left, n_written;
     350              : 
     351            0 :    n_bytes_left = n_bytes_to_write;
     352              : 
     353            0 :    while (n_bytes_left > 0) {
     354            0 :       n_written = send(sock, buffer, n_bytes_left > 8192 ? 8192 : n_bytes_left, 0);
     355            0 :       if (n_written <= 0)
     356            0 :          return n_bytes_to_write - n_bytes_left;
     357              : 
     358            0 :       n_bytes_left -= n_written;
     359            0 :       buffer += n_written;
     360              :    }
     361              : 
     362            0 :    return n_bytes_to_write;
     363              : }
     364              : 
     365              : /*------------------------------------------------------------------*/
     366              : 
     367            0 : int ftp_receive(int sock, char *buffer, int bsize)
     368              : /* receive buffer from socket, return number of received bytes */
     369              : {
     370              :    int count, i;
     371              : 
     372            0 :    i = 0;
     373              :    while (TRUE) {
     374            0 :       count = recv(sock, buffer + i, bsize - 1 - i, 0);
     375            0 :       if (count <= 0)
     376            0 :          return i;
     377              : 
     378            0 :       i += count;
     379            0 :       buffer[i] = 0;
     380              : 
     381            0 :       if (i >= bsize - 1)
     382            0 :          return i;
     383              :    }
     384              : }
     385              : 
     386              : /*------------------------------------------------------------------*/
     387              : 
     388            0 : int ftp_login(FTP_CON ** con, const char *host, unsigned short port,
     389              :               const char *user, const char *password, const char *account)
     390              : /* FTP login with username and password */
     391              : {
     392              :    int status;
     393              : 
     394            0 :    status = ftp_connect(con, host, port);
     395            0 :    if (status != FTP_SUCCESS)
     396            0 :       return status;
     397              : 
     398            0 :    status = ftp_user(*con, user);
     399            0 :    if (status >= 0)
     400            0 :       return status;
     401              : 
     402            0 :    if (status == -230)
     403            0 :       return status;
     404              : 
     405            0 :    if (status == -332) {
     406            0 :       if (account == NULL)
     407            0 :          return FTP_NET_ERROR;
     408              : 
     409            0 :       status = ftp_account(*con, account);
     410            0 :       if (status < 1)
     411            0 :          return status;
     412              : 
     413            0 :       if (status == -230)
     414            0 :          return status;
     415              :    }
     416              : 
     417            0 :    return ftp_password(*con, password);
     418              : }
     419              : 
     420              : /*------------------------------------------------------------------*/
     421              : 
     422            0 : int ftp_bye(FTP_CON * con)
     423              : /* disconnect from FTP server */
     424              : {
     425              :    char str[256];
     426              : 
     427            0 :    ftp_send_message(con, "QUIT");
     428            0 :    ftp_get_message(con, str);
     429              : 
     430            0 :    closesocket(con->sock);
     431            0 :    free(con);
     432              : 
     433            0 :    return FTP_SUCCESS;
     434              : }
     435              : 
     436              : /*------------------------------------------------------------------*/
     437              : 
     438            0 : int ftp_port(FTP_CON * con, int a, int b, int c, int d, int e, int f)
     439              : /* set port for data connection */
     440              : {
     441              :    char cmd[256];
     442              :    int status;
     443              : 
     444            0 :    sprintf(cmd, "PORT %d,%d,%d,%d,%d,%d", a, b, c, d, e, f);
     445            0 :    if (ftp_send_message(con, cmd) != FTP_SUCCESS)
     446            0 :       return FTP_NET_ERROR;
     447              : 
     448            0 :    status = ftp_get_message(con, cmd);
     449            0 :    if (status == FTP_QUIT)
     450            0 :       return FTP_QUIT;
     451              : 
     452            0 :    if (!ftp_good(status, 200, EOF))
     453            0 :       return FTP_NET_ERROR;
     454              : 
     455            0 :    return FTP_SUCCESS;
     456              : }
     457              : 
     458              : /*------------------------------------------------------------------*/
     459              : 
     460            0 : int ftp_move(FTP_CON * con, const char *oldname, const char *newname)
     461              : /* move/rename file */
     462              : {
     463              :    int status;
     464              : 
     465            0 :    status = ftp_command(con, "RNFR %s", oldname, 200, 350, EOF);
     466              : 
     467            0 :    if (status < 0)
     468            0 :       return ftp_command(con, "RNTO %s", newname, 200, 250, EOF);
     469              :    else
     470            0 :       return status;
     471              : }
     472              : 
     473              : /*------------------------------------------------------------------*/
     474              : 
     475            0 : int ftp_get(FTP_CON * con, const char *local_name, const char *remote_name)
     476              : /* get file */
     477              : {
     478              :    int fh;
     479              :    int status;
     480              :    char buff[8192];
     481              :    char str[256];
     482              :    int count, i;
     483            0 :    long total = 0;
     484              :    DWORD start, stop;
     485              : 
     486            0 :    if (ftp_open_read(con, remote_name) >= 0)
     487            0 :       return con->err_no;
     488              : 
     489            0 :    if ((fh = open(local_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644)) == -1)
     490            0 :       return FTP_FILE_ERROR;
     491              : 
     492            0 :    start = ss_millitime();
     493              : 
     494            0 :    while ((count = ftp_receive(con->data, buff, sizeof(buff))) > 0) {
     495            0 :       total += write(fh, buff, count);
     496            0 :       i = 0;
     497            0 :       if (ftp_debug_func != NULL) {
     498            0 :          printf("%c\r", bars[(i++) % 4]);
     499            0 :          fflush(stdout);
     500              :       }
     501              :    }
     502              : 
     503            0 :    close(fh);
     504            0 :    stop = ss_millitime();
     505              : 
     506            0 :    status = ftp_close(con);
     507            0 :    if (ftp_debug_func != NULL) {
     508            0 :       sprintf(str, "%ld bytes received in %1.2f seconds (%1.2lf kB/sec).",
     509            0 :               total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
     510            0 :       ftp_debug_func(str);
     511              :    }
     512              : 
     513            0 :    return status;
     514              : }
     515              : 
     516              : /*------------------------------------------------------------------*/
     517              : 
     518            0 : int ftp_put(FTP_CON * con, const char *local_name, const char *remote_name)
     519              : /* put file */
     520              : {
     521              :    int fh;
     522              :    int status;
     523              :    char buff[8193];
     524              :    char str[256];
     525            0 :    int count, i = 0;
     526            0 :    long total = 0;
     527              :    DWORD start, stop;
     528              : 
     529            0 :    if (ftp_open_write(con, remote_name) >= 0)
     530            0 :       return con->err_no;
     531              : 
     532            0 :    if ((fh = open(local_name, O_BINARY)) == -1)
     533            0 :       return FTP_FILE_ERROR;
     534              : 
     535            0 :    start = ss_millitime();
     536              : 
     537            0 :    while ((count = read(fh, buff, 8192)) > 0) {
     538            0 :       total += ftp_send(con->data, buff, count);
     539            0 :       if (ftp_debug_func != NULL) {
     540            0 :          printf("%c\r", bars[(i++) % 4]);
     541            0 :          fflush(stdout);
     542              :       }
     543              :    }
     544              : 
     545            0 :    close(fh);
     546            0 :    stop = ss_millitime();
     547              : 
     548            0 :    status = ftp_close(con);
     549            0 :    if (ftp_debug_func != NULL) {
     550            0 :       sprintf(str, "%ld bytes sent in %1.2f seconds (%1.2lf kB/sec).",
     551            0 :               total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
     552            0 :       ftp_debug_func(str);
     553              :    }
     554              : 
     555            0 :    return status;
     556              : }
     557              : 
     558              : /*------------------------------------------------------------------*/
     559              : 
     560            0 : char *ftp_pwd(FTP_CON * con)
     561              : /* show present working directory */
     562              : {
     563              :    static char str[256];
     564              :    char tmp[256];
     565              :    int status;
     566              : 
     567            0 :    str[0] = 0;
     568            0 :    if (ftp_send_message(con, "PWD") != FTP_SUCCESS)
     569            0 :       return str;
     570              : 
     571            0 :    status = ftp_get_message(con, tmp);
     572              : 
     573            0 :    if (status != 257) {
     574            0 :       if (ftp_error_func != NULL)
     575            0 :          ftp_error_func(tmp);
     576              : 
     577            0 :       return str;
     578              :    }
     579              : 
     580            0 :    sscanf(tmp, "%*[^\"]%*c%[^\"]%*s", str);
     581              : 
     582            0 :    return str;
     583              : }
     584              : 
     585              : /*------------------------------------------------------------------*/
     586              : 
     587            0 : int ftp_dir(FTP_CON * con, const char *file)
     588              : /* display directory */
     589              : {
     590              :    char command[256], buffer[8192];
     591              : 
     592            0 :    if (file == NULL || *file == '\0')
     593            0 :       strcpy(command, "LIST");
     594              :    else
     595            0 :       sprintf(command, "LIST %s", file);
     596              : 
     597            0 :    if (ftp_data(con, command, "") >= 0)
     598            0 :       return con->err_no;
     599              : 
     600            0 :    while (ftp_receive(con->data, buffer, sizeof(buffer)))
     601            0 :       printf("%s", buffer);
     602              : 
     603            0 :    return ftp_close(con);
     604              : }
     605              : 
     606              : /*------------------------------------------------------------------*/
        

Generated by: LCOV version 2.0-1