📄 betaftpd_complete.patch
字号:
++ if (f == NULL) ++ return 1;+ + i = sscanf(c->recv_buf, "%3hu,%3hu,%3hu,%3hu,%3hu,%3hu", &a0, &a1, &a2, &a3, &p0, &p1);+ if (i < 6) {+@@ -421,10 +417,7 @@+ ((unsigned char)(p0) << 8) ++ ((unsigned char)(p1) ));+ f->sock = sock;+- f->state = 3;+-+- i = 1; +- ioctl(f->sock, FIONBIO, &one);++ ftran_GOTO(f,FTRAN_STATE_GOTPORT);+ }+ return 1;+ }+@@ -440,19 +433,26 @@+ unsigned int one = 1;+ struct sockaddr_in addr;+ +- if ((c->transfer != NULL) && (c->transfer->state >= 4)) {++ if ((c->transfer != NULL) && (c->transfer->state == FTRAN_STATE_TRANSFERING)) {+ return numeric(c, 503, "Sorry, only one transfer at once.");+ }+ destroy_ftran(c->transfer);+ + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);+ TRAP_ERROR(sock == -1, 500, return 1);+- err = add_fd(sock, POLLIN);+- TRAP_ERROR(err != 0, 501, return 1);+-+ c->transfer = f = alloc_new_ftran(sock, c);++ if (f == NULL) ++ return 1;+ +- ioctl(sock, FIONBIO, &one);++ ftran_GOTO(f,FTRAN_STATE_LISTENING);++ rn_prepare_fd_for_add(f->sock,own_pid);++ err = rn_add(&rns,f->sock,ftran_listening_ioready,f);++ if (err != 0) {++ close(f->sock);++ f->sock = ILLEGAL_FD;++ destroy_ftran(f);++ TRAP_ERROR(err != 0, 501, return 1);++ }+ + /* setup socket */+ tmp = sizeof(addr);+@@ -469,7 +469,6 @@+ + err = listen(f->sock, 1);+ TRAP_ERROR(err == -1, 500, return 1);+- f->state = 1;+ + return numeric(c, 227, "Entering passive mode (%u,%u,%u,%u,%u,%u)",+ (htonl(addr.sin_addr.s_addr) & 0xff000000) >> 24,+@@ -604,7 +603,7 @@+ int fd;+ struct ftran *f = c->transfer;+ +- if ((f == NULL) || ((f->state != 1) && (f->state != 3))) {++ if ((f == NULL) || ((f->state != FTRAN_STATE_LISTENING) && (f->state != FTRAN_STATE_GOTPORT) && (f->state != FTRAN_STATE_CONNECTED_NO_CMD))) {+ return numeric(c, 425, "No data connection set up; please use PASV or PORT.");+ }+ +@@ -670,7 +669,7 @@+ struct ftran *f = c->transfer;+ int fd;+ +- if ((f == NULL) || ((f->state != 1) && (f->state != 3))) {++ if ((f == NULL) || ((f->state != FTRAN_STATE_LISTENING) && (f->state != FTRAN_STATE_GOTPORT) && (f->state != FTRAN_STATE_CONNECTED_NO_CMD))) {+ return numeric(c, 425, "No data connection set up; please use PASV or PORT.");+ }+ +@@ -912,24 +911,6 @@+ * Note that we need to bypass numeric(), to get a multi-line+ * reply.+ */+-#if WANT_STAT+-char conn_state[5][27] = {+- "Not logged in",+- "Waiting for e-mail address",+- "Waiting for password",+- "Logged in",+- "Waiting for password", /* actually non-existant user */+-};+-+-char ftran_state[6][42] = {+- "Not initialized",+- "Decided PASV address/port",+- "Waiting on PASV socket",+- "Got PORT address/port",+- "Connecting on PORT address/port",+- "Transferring file (or connecting on PORT)"+-};+-#endif+ + int cmd_stat(struct conn * const c)+ { +@@ -950,11 +931,11 @@+ " Data connection state: %s\r\n"+ "211 End of status\r\n",+ inet_ntoa(((struct sockaddr_in *)(&(c->addr)))->sin_addr),+- conn_state[c->auth],++ conn_convert_to_string(c->auth),+ #if WANT_ASCII+ (c->ascii_mode == 1) ? "ASCII, FORM: Nonprint" : "Image",+ #endif+- (f) ? ftran_state[f->state] : ftran_state[0]);++ (f) ? ftran_convert_to_string(f->state) : convert_to_string(FTRAN_STATE_NONE));+ + i = strlen(buf);+ +@@ -1174,7 +1155,7 @@+ if (status == -1)+ destroy_ftran(c->transfer);+ if (status != 1)+- return status;++ return 1;+ + #if WANT_DCACHE+ getcwd(cwd, 256);+@@ -1204,9 +1185,11 @@+ #if HAVE_MMAP+ {+ int num_files = get_num_files(c, ptr, lo, &status);+- if (status != 1) +- return status;+-++ if (status != 1) {++ numeric(f->owner, 226, "Transfer complete");++ destroy_ftran(c->transfer); ++ return 1;++ }+ size = num_files * 160;+ f->file_data = malloc(size + 1);+ TRAP_ERROR(f->file_data == NULL, 550, return -1);+@@ -1219,7 +1202,7 @@+ if (status == -1)+ destroy_ftran(c->transfer);+ if (status != 1)+- return status;++ return 1;+ + #if WANT_DCACHE+ populate_dcache(f, cwd, ptr, lo);+@@ -1419,10 +1402,14 @@+ }+ + chdir(temp);+- pos = list_core(c, "*", tmp2, lo, pstatus,+ #if HAVE_MMAP+- size, pos);++ pos = ++#endif++ list_core(c, "*", tmp2, lo, pstatus++#if HAVE_MMAP++ ,size, pos+ #endif++ );+ chdir("..");+ if (*pstatus != 1)+ return 0; /* caller will destroy_ftran if *pstatus is -1 */+@@ -1556,8 +1543,8 @@+ int cmd_rein(struct conn * const c)+ {+ destroy_ftran(c->transfer);+- c->buf_len = c->auth = c->rest_pos = 0;+-++ c->buf_len = c->rest_pos = 0;++ conn_GOTO(c,CONN_STATE_INIT);+ /* equals: strcpy(c->curr_dir, "/") ; strcpy(c->last_cmd, ""); */+ c->curr_dir[0] = '/';+ #if WANT_FULLSCREEN+@@ -1585,6 +1572,7 @@+ {+ while (first_conn->next_conn)+ destroy_conn(first_conn->next_conn);++ rn_shutdown(&rns);+ exit(0);+ }+ #endif+@@ -1597,13 +1585,17 @@+ *+ * To me, this command seems optimizable, but I'm not really+ * sure where :-)++ * This function returns 0 if connection has been destroyed, ++ * 1 otherwise. + */+-void parse_command(struct conn *c)++++int parse_command(struct conn *c)+ {+- int cmlen;++ int cmlen,status;+ const struct handler *h = handler_table; /* first entry */+ +- if (c == NULL) return;++ if (c == NULL) ++ return 0;+ + /* strip any leading non-ASCII characters (including CR/LFs) */+ while (c->buf_len > 0 && (c->recv_buf[0] < 'a' || c->recv_buf[0] > 'z')+@@ -1613,7 +1605,8 @@+ + /* scan, searching for CR or LF */ + cmlen = strcspn(c->recv_buf, "\r\n");+- if (cmlen >= c->buf_len) return;++ if (cmlen >= c->buf_len) ++ return 1;+ + #if WANT_FULLSCREEN+ strncpy(c->last_cmd, c->recv_buf, cmlen);+@@ -1625,7 +1618,7 @@+ (strncasecmp(c->recv_buf, h->cmd_name, strlen(h->cmd_name)) == 0)) {+ if (c->auth < h->min_auth) {+ if (!numeric(c, 503, "Please login with USER and PASS."))+- return;++ return 1;+ while (c->recv_buf[0] != '\n') remove_bytes(c, 1);+ } else {+ char schar;+@@ -1649,7 +1642,8 @@+ c->recv_buf[cmlen] = 0;+ + /* result of zero means the connection is freed */+- if (h->callback(c)) {++ status = h->callback(c);++ if (status) {+ c->recv_buf[cmlen] = schar;+ #if !WANT_NONROOT+ if (h->do_setuid) seteuid(getuid());+@@ -1657,7 +1651,7 @@+ remove_bytes(c, cmlen);+ }+ }+- return;++ return status;+ }+ } while ((++h)->callback != NULL);+ +@@ -1673,8 +1667,10 @@+ * nonroot notice: prepare_for_transfer() assumes all access+ * checks are already done.+ */+-void prepare_for_transfer(struct ftran *f)++int prepare_for_transfer(struct ftran *f)+ {++ int err;+++ #if WANT_NONROOT+ #warning No nonroot checking for prepare_for_transfer() yet+ #endif+@@ -1694,14 +1690,29 @@+ }+ #endif+ +- if (f->state == 1) { /* PASV connection */+- f->state = 2; /* waiting */+- } else if (f->state == 3) { /* PORT connection */+- f->state = 4;++ if (f->state == FTRAN_STATE_LISTENING) { /* PASV connection */++ ftran_GOTO(f,FTRAN_STATE_LISTENING_GOT_CMD);++ }++ else if (f->state == FTRAN_STATE_CONNECTED_NO_CMD)++ {++ ftran_GOTO(f,FTRAN_STATE_TRANSFERING);++ init_file_transfer(f);++ }++ else if (f->state == FTRAN_STATE_GOTPORT) { /* PORT connection */++ struct conn * const c = f->owner;++ ftran_GOTO(f,FTRAN_STATE_CONNECTING);++ rn_prepare_fd_for_add(f->sock,own_pid);++ err = rn_add(&rns,f->sock, ftran_data_ioready,f);++ if (err != 0) {++ close(f->sock);++ f->sock = ILLEGAL_FD;++ destroy_ftran(f);++ TRAP_ERROR(err != 0, 501, return 1);++ }+ connect(f->sock, (struct sockaddr *)&f->sin, sizeof(f->sin));+- add_fd(f->sock, POLLOUT);+ }+ time(&(f->tran_start));++ return 1;+ }+ + /*+@@ -1850,8 +1861,9 @@+ #warning No nonroot checking for prepare_for_listing() yet+ #endif+ +- if ((f == NULL) || ((f->state != 1) && (f->state != 3))) {+- return numeric(c, 425, "No data connection set up; please use PASV or PORT.");++ if ((f == NULL) || ((f->state != FTRAN_STATE_LISTENING) && (f->state != FTRAN_STATE_GOTPORT) && (f->state != FTRAN_STATE_CONNECTED_NO_CMD))) {++ numeric(c, 425, "No data connection set up; please use PASV or PORT.");++ return -1;+ }+ + /*+diff -ur betaftpd-0.0.8pre17/cmds.h betaftpd/cmds.h+--- betaftpd-0.0.8pre17/cmds.h 2003-07-29 09:40:48.000000000 -0700++++ betaftpd/cmds.h 2003-07-29 09:33:12.000000000 -0700+@@ -35,9 +35,10 @@+ * If TRAP_ERROR_DEBUG is defined, some extra debugging info is+ * sent. Don't enable this for a normal server, it could be a+ * security risk.++ * FIXME: return value of numeric must be propagated to caller!+ */+ #undef TRAP_ERROR_DEBUG+-/* #define TRAP_ERROR_DEBUG 1 */++ #define TRAP_ERROR_DEBUG 1 + + #ifdef TRAP_ERROR_DEBUG+ #define TRAP_ERROR(x, num, y) TRAP_ERROR_INTERNAL(x, num, y, __FILE__, __LINE__)+@@ -98,8 +99,8 @@+ #endif+ + int cmd_cwd_internal(struct conn * const c, const char * const newd);+-void parse_command(struct conn *c);+-void prepare_for_transfer(struct ftran *f);++int parse_command(struct conn *c);++int prepare_for_transfer(struct ftran *f);+ char decode_mode(mode_t mode);+ char *translate_path(struct conn * const c, char * const path, int *pstatus);+ int do_openfile(struct conn * const c, char * const path,+@@ -121,7 +122,7 @@+ #endif+ );+ char classify(const mode_t mode);+-void do_store(struct conn * const c, int append);++int do_store(struct conn * const c, int append);+ char *do_pwd(struct conn * const c, char * const retbuf, const char * const dir);+ + #ifndef HAVE_POLL+diff -ur betaftpd-0.0.8pre17/ftpd.c betaftpd/ftpd.c+--- betaftpd-0.0.8pre17/ftpd.c 2003-07-29 09:40:48.000000000 -0700++++ betaftpd/ftpd.c 2003-07-29 09:39:28.000000000 -0700+@@ -13,6 +13,7 @@+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.++ Portions Copyright (C) Ixia Communications 2003 Dan Kegel,Rohan Chitradurga + */+ + /*+@@ -148,6 +149,13 @@+ #include <sys/sendfile.h>+ #endif+ ++#include <sys/resource.h>++++#ifndef TRUE++#define TRUE 1++#define FALSE 0++#endif+++ /*+ * <linux/socket.h> does not export this to glibc2 systems, and it isn't+ * always defined anywhere else.+@@ -177,18 +185,12 @@+ struct dcache *first_dcache = NULL;+ #endif+ +-#if HAVE_POLL+-unsigned int highest_fds = 0;++rn_t rns;++pid_t own_pid;+ +-#define FD_MAX 1024+-#define fds_send fds+-struct pollfd fds[FD_MAX];++struct list_element *destroyed_list_header = NULL;+ +-#define MAXCLIENTS FD_MAX+-#else+-fd_set master_fds, master_send_fds;+-#define MAXCLIENTS FD_SETSIZE+-#endif++long int FD_MAX;+ + #if WANT_XFERLOG+ FILE *xferlog = NULL;+@@ -198,6 +200,7 @@+ int sendfile_supported = 1;+ #endif+ +++ /*+ * This variable specifies if it's soon time to check for timed out+ * clients, and timed out directory listing cache entries. It is+@@ -249,56 +252,50 @@+ }+ #endif+ +-/*+- * add_fd(): Add an fd to the set we monitor. Return 0 on success.+- * This code is shared between poll() and select() versions.+- */+-int add_fd(const int fd, const int events)+-{+-#if HAVE_POLL+- if (fd >= FD_MAX) {+- printf("add_fd(%d, %x): failed\n", fd, events);+- return E2BIG;+- }+-+- fds[fd].fd = fd;+- fds[fd].events = events;+- if (highest_fds < fd) +- highest_fds = fd;+-#else +- if (fd >= FD_SETSIZE)+- return E2BIG;+- if (events & POLLIN)+- FD_SET(fd, &master_fds);+- if (events & POLLOUT)+- FD_SET(fd, &master_send_fds);+-#endif+- return 0;+-}+-+-/*+- * del_fd(): Close and remove an fd from the set(s) we monitor. (See also add_fd().)+- */+-void del_fd(const int fd)++const char *ftran_convert_to_string(enum ftran_state state)+ {+-#if HAVE_POLL+- if (fd >= FD_MAX)+- return;+-+- fds[fd].fd = -1;+- fds[fd].events = 0;+-+- /* Reduce poll()'s workload by not making it watch past end of array */+- while ((highest_fds > 0) && (fds[highest_fds].fd == -1))+- highest_fds--;+-#else +- if (fd >= FD_SETSIZE)+- return;+- FD_CLR(fd, &master_fds);+- FD_CLR(fd, &master_send_fds);+-#endif+-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -