📄 ftp.c
字号:
/* FTP support. Copyright (C) 2000 Kalum Somaratna This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* * HAVE_CONFIG_H */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <errno.h>#include <ctype.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <sys/socket.h>#include <sys/time.h>#include <signal.h>#include <setjmp.h>#include <assert.h>#include "main.h"#include "connect.h"#include "misc.h"#include "url.h"#include "ftp.h"#include "netrc.h"#include "runtime.h"#include "debug.h"#define UNIMPLEMENTED_CMD(a) ((a == 500) || (a == 502) || (a == 504))/* * return the numeric response of the ftp server by reading the first 3 * characters in the buffer */int get_ftp_return(const char *ftp_buffer){ char code[4]; strncpy(code, ftp_buffer, 3); code[3] = '\0'; return atoi(code);}int ftp_check_msg(int sock, char *szBuffer, int len){ int ret; if ((ret = krecv(sock, szBuffer, len, MSG_PEEK, rt.timeout)) == -1) { message("Error checking for ftp data-: %s", strerror(errno)); return ret; } return ret;}int ftp_read_msg(int sock, char *szBuffer, int len){ int ret; if ((ret = krecv(sock, szBuffer, len, 0, rt.timeout)) == -1) { message("Error Receiving ftp data-: %s", strerror(errno)); return ret; } return ret;}uerr_t ftp_send_msg(int sock, char *szBuffer, int len){ if (ksend(sock, szBuffer, len, 0, rt.timeout) == -1) { message("Error Sending ftp data-: %s", strerror(errno)); return FTPERR; } return FTPOK;}uerr_t ftp_get_line(int control_sock, char *buffer){ int iLen, iBuffLen = 0, ret = 0; char *szPtr = buffer, ch = 0; while ((iBuffLen < FTP_BUFFER_SIZE) && ((ret = ftp_check_msg(control_sock, &ch, 1)) > 0)) { iLen = ftp_read_msg(control_sock, &ch, 1); if (iLen != 1) { return FTPERR; } iBuffLen += iLen; *szPtr = ch; szPtr += iLen; if (ch == '\n') break; /* * we have a line: return */ } /* * Check for error returned in ftp_check_message */ if (ret == -1) return FTPERR; *(szPtr + 1) = '\0'; return FTPOK;}uerr_t ftp_get_reply(int sock, char *szBuffer){ int cont = 0; int code; char * tmp = alloca(FTP_BUFFER_SIZE); memset(szBuffer, 0, FTP_BUFFER_SIZE); if (ftp_get_line(sock, szBuffer) != FTPOK) { return FTPERR; } debug_prz("message =%s\n", szBuffer); if (!isdigit(*szBuffer)) return FTPERR; if (*szBuffer == '\0') return FTPERR; code = get_ftp_return(szBuffer); if (szBuffer[3] == '-') cont = 1; else cont = 0; (void) strtok_r(szBuffer, "\r\n",&tmp); while (cont) { if (ftp_get_line(sock, szBuffer) != FTPOK) { return FTPERR; } debug_prz("message =%s\n", szBuffer); /* Server closed the connection */ if (*szBuffer == '\0') return FTPERR; if ((get_ftp_return(szBuffer) == code) && (szBuffer[3] == ' ')) cont = 0; (void) strtok_r(szBuffer, "\r\n", &tmp); } return FTPOK;}uerr_t ftp_ascii(int sock){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; snprintf(szBuffer, sizeof(szBuffer), "TYPE A\r\n"); err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); if (err != FTPOK) { return err; } if (*szBuffer != '2') { return FTPUNKNOWNTYPE; } return FTPOK;}uerr_t ftp_binary(int sock){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; snprintf(szBuffer, sizeof(szBuffer), "TYPE I\r\n"); err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); if (err != FTPOK) { return err; } if (*szBuffer != '2') { return FTPUNKNOWNTYPE; } return FTPOK;}uerr_t ftp_port(int sock, char *command){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; strcpy(szBuffer, command); err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); if (err != FTPOK) { return err; } if (*szBuffer != '2') { return FTPPORTERR; } return FTPOK;}uerr_t ftp_list(int sock, char *file){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; if (snprintf(szBuffer, sizeof(szBuffer), "LIST %s\r\n", file) >= sizeof(szBuffer)) { return NOTENOUGHMEM; /* FIXME: Better error */ } err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); if (err != FTPOK) { return err; } if (*szBuffer == '5') { return FTPNSFOD; } if (*szBuffer != '1') { return FTPERR; } return FTPOK;}uerr_t ftp_retr(int sock, char *file){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; if (snprintf(szBuffer, sizeof(szBuffer), "RETR %s\r\n", file) >= sizeof(szBuffer)) { return NOTENOUGHMEM; /* FIXME: Better error */ } err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); if (err != FTPOK) { return err; } if (*szBuffer == '5') { return FTPNSFOD; } if (*szBuffer != '1') { return FTPERR; } return FTPOK;}/* * does the PASV command */uerr_t ftp_pasv(int sock, unsigned char *addr){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; unsigned char *p; int i; snprintf(szBuffer, sizeof(szBuffer), "%s", "PASV\r\n"); err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = ftp_get_reply(sock, szBuffer); debug_prz("FTP PASV Header =%s\n", szBuffer); if (err != FTPOK) { return err; } if (*szBuffer != '2') { return FTPNOPASV; } /* * parse it */ p = (unsigned char *) szBuffer; for (p += 4; *p && !isdigit(*p); p++); if (!*p) return FTPINVPASV; for (i = 0; i < 6; i++) { addr[i] = 0; for (; isdigit(*p); p++) addr[i] = (*p - '0') + 10 * addr[i]; if (*p == ',') p++; else if (i < 5) { return FTPINVPASV; } } return FTPOK;}uerr_t ftp_rest(int sock, off_t bytes){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; if (snprintf(szBuffer, sizeof(szBuffer), "REST %Ld\r\n", (long long) bytes) >= sizeof(szBuffer)) { return NOTENOUGHMEM; /* FIXME: Better error */ } err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = (ftp_get_reply(sock, szBuffer)); if (err != FTPOK) { return err; } if (*szBuffer != '3') { return FTPRESTFAIL; } return FTPOK;}/* * CWD command */uerr_t ftp_cwd(int sock, char *dir){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; if (snprintf(szBuffer, sizeof(szBuffer), "CWD %s\r\n", dir) >= sizeof(szBuffer)) { return NOTENOUGHMEM; /* FIXME: Better error */ } err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = (ftp_get_reply(sock, szBuffer)); if (err != FTPOK) { return err; } /* * check and see whether the CWD succeeded */ if (*szBuffer == '5') { return FTPNSFOD; } if (*szBuffer != '2') { return CWDFAIL; } /* * all ok */ return FTPOK;}/* * Returns the Current working directory in dir */uerr_t ftp_pwd(int sock, char *dir){ char szBuffer[FTP_BUFFER_SIZE]; uerr_t err; char *r, *l; snprintf(szBuffer, sizeof(szBuffer), "PWD\r\n"); err = ftp_send_msg(sock, szBuffer, strlen(szBuffer)); if (err != FTPOK) { return err; } err = (ftp_get_reply(sock, szBuffer)); if (err != FTPOK) { return err; } /* * check and see wether the PWD succeeded */ if (*szBuffer == '5') { return FTPPWDERR; } if (*szBuffer != '2') { return PWDFAIL; } if ((r = strrchr(szBuffer, '"')) != NULL) { l = strchr(szBuffer, '"'); if ((l != NULL) && (l != r)) { *r = '\0'; ++l; strcpy(dir, l); *r = '"'; } } else { if ((r = strchr(szBuffer, ' ')) != NULL) { *r = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -