⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 betaftpd_complete.patch

📁 linux下编译交叉工具链的工具源码
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+-	close(fd);++    switch (state) {++    case FTRAN_STATE_NONE:++	return "FTRAN_STATE_NONE";++    case FTRAN_STATE_LISTENING:++	return "FTRAN_STATE_LISTENING";++    case FTRAN_STATE_CONNECTED_NO_CMD:++	return "FTRAN_STATE_CONNECTED_NO_CMD";++    case FTRAN_STATE_LISTENING_GOT_CMD:++	return "FTRAN_STATE_LISTENING_GOT_CMD";++    case FTRAN_STATE_GOTPORT:++	return "FTRAN_STATE_GOTPORT";++    case FTRAN_STATE_CONNECTING:++	return "FTRAN_STATE_CONNECTING";++    case FTRAN_STATE_TRANSFERING:++	return "FTRAN_STATE_TRANSFERING";++    case FTRAN_STATE_DESTROYED:++	return "FTRAN_STATE_DESTROYED";++    default:++	;++    }++    assert(FALSE);++    return "UNKNOWN";++}++++const char *conn_convert_to_string(enum conn_state cstate)++{++    switch (cstate) {++    case CONN_STATE_INIT:++    	return "CONN_STATE_INIT";++    case CONN_STATE_WAIT_USER:++    	return "CONN_STATE_WAIT_USER";++    case CONN_STATE_WAIT_PASS:++    	return "CONN_STATE_WAIT_PASS";++    case CONN_STATE_READY:++    	return "CONN_STATE_READY";++    case CONN_STATE_DESTROYED:++    	return "CONN_STATE_DESTROYED";++    default:++	;++    }++    assert(FALSE);++    return "UNKNOWN";+ }+ + #if 0+@@ -334,6 +331,18 @@+         }+ }+ ++void purge_destroyed_list() {++++	struct list_element *elem = destroyed_list_header->next;++	destroyed_list_header->next = NULL;++	while (elem != NULL)++	{++	    struct list_element *next = elem->next;++	    free(elem);++	    elem=next;++	}++}+++ /*+  * remove_from_linked_list():+  *		Removes an element (conn, ftran or dcache) from its linked list,+@@ -343,7 +352,7 @@+ {+ 	if (elem->prev != NULL) elem->prev->next = elem->next;+ 	if (elem->next != NULL) elem->next->prev = elem->prev;+-	free(elem);++	add_to_linked_list(destroyed_list_header,elem);+ }+ + /*+@@ -360,14 +369,20 @@+ 	if (c == NULL) return c;+ + 	c->prev_conn = NULL;++	c->transfer = NULL;++	c->sock = sock;++	c->buf_len =  c->rest_pos = 0;++	c->auth = CONN_STATE_INIT;++	conn_GOTO(c,CONN_STATE_INIT);+ 	c->next_conn = NULL;+ + 	if (sock != -1) {+-		ioctl(sock, FIONBIO, &one);+-		if (add_fd(sock, POLLIN) != 0) {++		rn_prepare_fd_for_add(sock,own_pid);++		if (rn_add(&rns,sock,client_eventhandler,c) != 0) {+ 			/* temp unavail */+ 			send(sock, "230 Server too busy, please try again later.\r\n", 46, 0);+ 			close(sock);++			c->sock = ILLEGAL_FD;+ 			return NULL;+ 		}+ +@@ -379,9 +394,6 @@+ 		c->prev_conn = NULL;+ 	}+ +-	c->transfer = NULL;+-	c->sock = sock;+-	c->buf_len = c->auth = c->rest_pos = 0;+ #if WANT_ASCII+ 	c->ascii_mode = 0;+ #endif+@@ -429,9 +441,12 @@+ #endif+ 	f->owner = (struct conn * const)c;+ 	f->sock = sock;+-	f->state = 0;+-	f->local_file = -1;+-++	f->state = FTRAN_STATE_NONE;++	ftran_GOTO(f,FTRAN_STATE_NONE); /* For logging */++	f->local_file = f->size = f->block_size = -1; ++	f->pos = 0;++	f->tran_start=0;++      + #if WANT_DCACHE+ 	f->dir_cache = NULL;+ #endif+@@ -445,12 +460,16 @@+  *		Destroy a control connection, remove it from the linked+  *		list, and clean up after it.+  */+-void destroy_conn(struct conn * const c)++void _destroy_conn(struct conn * const c)+ {+ 	if (c == NULL) return;+-	del_fd(c->sock);++	if (c->sock == ILLEGAL_FD) return;++	rn_del(&rns,c->sock);++	close(c->sock);++	c->sock = ILLEGAL_FD;+ + 	destroy_ftran(c->transfer);++	conn_GOTO(c,CONN_STATE_DESTROYED);+ 	remove_from_linked_list((struct list_element *)c);+ }+ +@@ -467,15 +486,22 @@+  *		If you wonder why I check for `defined(SOL_TCP)' and don't+  *		provide an alternative, see the comments on init_file_transfer().+  */+-void destroy_ftran(struct ftran * const f)++void _destroy_ftran(struct ftran * const f)+ {+ 	const unsigned int zero = 0;++	int err;+ + 	if (f == NULL) return;++	if (f->state == FTRAN_STATE_DESTROYED) return;++++	if (f->sock != ILLEGAL_FD) {+ #if defined(TCP_CORK) && defined(SOL_TCP)+-	setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));++		err=setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));+ #endif+-	del_fd(f->sock);++	        rn_del(&rns,f->sock);++	        close(f->sock);++		f->sock = ILLEGAL_FD;++	}+ + #if WANT_DCACHE+ 	if (f->dir_cache) {+@@ -504,188 +530,255 @@+ + 	f->owner->transfer = NULL;+ +++ #if WANT_DCACHE+ 	if (f->dir_cache != NULL) f->dir_cache->use_count--;+ #endif+ ++	ftran_GOTO(f,FTRAN_STATE_DESTROYED);+ 	remove_from_linked_list((struct list_element *)f);+ }+ + /*+- * process_all_clients():+- *		Processes all the _control_ connections in active_clients+- *		(normally returned from a select(), there are at max+- *		NUM_AC active connections in the set), sending them+- *		through to the command parser if a command has been+- *		entered.++ *client_eventhandler():++ 		rn_WaitAndDispatch calls this function as the event handler for ++		any event occuring on a client connection. +  */+-#if HAVE_POLL+-int process_all_clients(const int num_ac)+-#else+-int process_all_clients(const fd_set * const active_clients, const int num_ac)+-#endif++++int client_eventhandler(rn_pollevent_t * e)+ {+-	struct conn *c = NULL, *next = first_conn->next_conn;+-	int checked_through = 0;++    int bytes_avail,status,loop_cnt;++    struct conn *c = e->client.data;+ +-	/* run through the linked list */+-	while (next != NULL && checked_through < num_ac) {+-		int bytes_avail;++    DPRINT("c->auth = %s\n",conn_convert_to_string(c->auth));+ +-		c = next;+-		next = c->next_conn;+-#if HAVE_POLL+-		if ((fds[c->sock].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) == 0) {+-			continue;+-		}+-#else+-		if (!FD_ISSET(c->sock, active_clients)) {+-			continue;+-		}+-#endif++    if (c->auth == CONN_STATE_DESTROYED) ++	return 0;+ +-		checked_through++;++/* Normally we would close the connection if we receive a POLLHUP,++ * but there seems to be a bug in epoll in which it sends spurious POLLHUP++ */+ +-		bytes_avail = recv(c->sock, c->recv_buf + c->buf_len,+-				   255 - c->buf_len, 0);+-		if (bytes_avail <= 0) {+-			/*+-			 * select() has already told us there's something about+-			 * this socket, so if we get a return value of zero, the+-			 * client has closed the socket. If we get a return value+-			 * of -1 (error), we close the socket ourselves.+-			 *+-			 * We do the same for poll(), even though we actually have+-			 * bits that tell us what is happening (in case of new +-			 * input AND error/hangup at the same time, we do an+-			 * explicit check at the bottom of the loop as well).+-			 */+-			destroy_conn(c);+-			continue;+-		}++    if (e->revents & (rn_POLLERR /* | rn_POLLHUP */)) {++	DPRINT("revents %x\n", e->revents);++	destroy_conn(c);++	return 1;++    }+ +-		/* overrun = disconnect */+-		if (c->buf_len + bytes_avail > 254) {+-			if (numeric(c, 503, "Buffer overrun; disconnecting."))+-				destroy_conn(c);+-			continue;++    loop_cnt = 0;++    /* Loop until EWOULDBLOCK or error */++    while (1) {++	bytes_avail =++	    recv(c->sock, c->recv_buf + c->buf_len, 255 - c->buf_len, 0);++++	loop_cnt++;++	DPRINT("loop count = %d, recv returns %d\n",loop_cnt,bytes_avail);++	if (bytes_avail > 0) {++	    /* overrun = disconnect */++	    if (c->buf_len + bytes_avail > 254) {++		if (numeric(c, 503, "Buffer overrun; disconnecting.")) {++		    /* numeric didn't destroy the connection, so we get to. */++		    destroy_conn(c);+ 		}++		/* connection is destroyed by here */++		return 1;++	    }++++	    /* normal case */++	    c->buf_len += bytes_avail;++	    status = parse_command(c);+ +-		c->buf_len += bytes_avail;+-		parse_command(c);++	    /* a return of 0 means connection is freed. */++	    if (!status) break;+ +-		/* FIXME: c could be invalid here, as parse_command can destroy it +-		if (fds[c->sock].revents & (POLLERR|POLLHUP|POLLNVAL)) {+-                        destroy_conn(c);+-                }+-		*/++	} else if (bytes_avail < 0) {++	    if (errno == EWOULDBLOCK)++		break;++	    if (errno != EINTR) {++		DPRINT("errno %d, destroying connection\n", errno);++		destroy_conn(c);++		return 1;++	    }++	} else /* if (bytes_avail == 0) */ {++	    /*++	     * select() has already told us there's something about++	     * this socket, so if we get a return value of zero, the++	     * client has closed the socket. If we get a return value++	     * of -1 (error), we close the socket ourselves.++	     *++	     * We do the same for poll(), even though we actually have++	     * bits that tell us what is happening (in case of new ++	     * input AND error/hangup at the same time, we do an++	     * explicit check at the bottom of the loop as well).++	     */++	    if (loop_cnt == 1) {++		DPRINT("EOF destroying connection,cnt = %d\n",loop_cnt);++		destroy_conn(c);++		return 1;++	    } else++		break;+ 	}+-	return checked_through;++    }++    return 0;+ }+ +-/*+- * process_all_sendfiles():+- *		Sends data to all clients that are ready to receive it.+- *		Also checks for data connections that are newly-connected,+- *		and handler xferlog entries for the files that are finished.++/* ftran_listening_ioready():++ * 	This eventhandler is instantiated when a PASV command is received. The ++ * 	state of ftran when this is invoked can be one of FTRAN_STATE_LISTENING++ * 	or FTRAN_STATE_LISTENING_GOT_CMD depending on whether another command is++ * 	received before this eventhandler can be called.+  */+-#if HAVE_POLL+-int process_all_sendfiles(const int num_ac)+-#else+-int process_all_sendfiles(fd_set * const active_clients, const int num_ac)+-#endif++++int ftran_listening_ioready(rn_pollevent_t *e)+ {+-	struct ftran *f = NULL, *next = first_ftran->next_ftran;+-	int checked_through = 0;+-	struct sockaddr tempaddr;+-	int tempaddr_len = sizeof(tempaddr);+- +-	while (next != NULL && checked_through < num_ac) {+-		f = next;+-		next = f->next_ftran;++	struct ftran *f = e->client.data;++++	if (f->state == FTRAN_STATE_DESTROYED) ++	    return 0;++++	assert((f->state == FTRAN_STATE_LISTENING) || (f->state == FTRAN_STATE_LISTENING_GOT_CMD));++++	assert(f->sock == e->fd);++++	DPRINT("fd %d, state %d\n", f->sock, f->state);++++/* Normally we would close the connection if we receive a POLLHUP,++ * but there seems to be a bug in epoll in which it sends spurious POLLHUP++ */++	if (e->revents & (rn_POLLERR /* | rn_POLLHUP */ )) {++		destroy_ftran(f);++		return 0;++	}+ +-#if HAVE_POLL+-		if (fds[f->sock].revents & (POLLHUP|POLLERR|POLLNVAL)) {++	/* We only expect one connect, but looping needs to be done to take care of interrupted system calls */++	for(;;){++		struct sockaddr tempaddr;++		int tempaddr_len = sizeof(tempaddr);++		const unsigned int one = 1;++++		int tempsock = accept(f->sock, (struct sockaddr *)&tempaddr,&tempaddr_len);++		DPRINT("accept returned fd %d\n", tempsock);++++		if (tempsock == -1) {++			if (errno == EWOULDBLOCK) ++				 break;++			else if ((errno == EINTR) || (errno == EPROTO) || (errno == ECONNABORTED)) ++				continue;+ 			destroy_ftran(f);+-			continue;+-		}+-#endif++			break;++		} ++		/* done accepting */++		rn_del(&rns,f->sock);		++		close(f->sock);++		++		f->sock = tempsock;+ +-		/* state = 2: incoming PASV, state >3: send file */+-#if HAVE_POLL+-		if ((f->state < 2) || (f->state == 3) ||  (fds[f->sock].revents & (POLLIN|POLLOUT)) == 0) {+-#else+-		if ((f->state < 2) || (f->state == 3) || !FD_ISSET(f->sock, active_clients)) {+-#endif+-			continue;++		if (f->state == FTRAN_STATE_LISTENING)++		{++		    f->state = FTRAN_STATE_CONNECTED_NO_CMD;++		}++		else if (f->state == FTRAN_STATE_LISTENING_GOT_CMD)++		{++			ftran_GOTO(f,FTRAN_STATE_TRANSFERING);++		    	init_file_transfer(f); /* this function will fake the first event ++						  by calling ftran_data_ioready that might++						  destroy ftran++						 */++		}++		break;+ 		}++	++	assert((f->state == FTRAN_STATE_CONNECTED_NO_CMD) || (f->state == FTRAN_STATE_TRANSFERING) || (f->state == FTRAN_STATE_DESTROYED) || (f->state == FTRAN_STATE_LISTENING) || (f->state == FTRAN_STATE_LISTENING_GOT_CMD)); ++	return 0;++}+ +-		checked_through++;++/* ftran_data_ioready():++ *        Sends data to client that are ready to receive it,++ *         and handle xferlog entries for the files that are finished.++ *                 ++ */++int ftran_data_ioready(rn_pollevent_t * e)++{++    enum ftran_ioresult transfer_status;++    struct ftran *f = e->client.data;+ +-#if HAVE_POLL+-		/* Nothing is needed for the poll() version? */+-#else+-		FD_CLR(f->sock, active_clients);+-#endif++    if (f->state == FTRAN_STATE_DESTROYED) ++	return 0;+ +-		if (f->state == 2) {		/* incoming PASV */+-			const unsigned int one = 1;+-			const int tempsock = accept(f->sock, (struct sockaddr *)&tempaddr,+-							&tempaddr_len);++    DPRINT("fd %d, state %d\n", f->sock, f->state);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -