📄 betaftpd_complete.patch
字号:
+ +- del_fd(f->sock);++ assert((f->state == FTRAN_STATE_CONNECTING) || (f->state == FTRAN_STATE_TRANSFERING));+ +- if (tempsock == -1) {+- destroy_ftran(f);+- continue;+- }++ assert(f->sock == e->fd);++++/* 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 ((f->state == FTRAN_STATE_CONNECTING)) {++ /* FIXME: should retrieve the status of the non blocking connect before initiating++ * transfer++ */++ init_file_transfer(f);+ +- f->sock = tempsock;+- ioctl(f->sock, FIONBIO, &one);+- init_file_transfer(f);+-#if WANT_UPLOAD+- if (f->upload) continue;+-#endif+- }+- if (f->state < 5) {+- init_file_transfer(f);+ #if WANT_UPLOAD+- if (f->upload) continue;++ if (f->upload)++ return 0; /* FIXME */+ #endif+- }++ }++++ assert(f->state == FTRAN_STATE_TRANSFERING);++++ do {+ +- /* for download, we send the first packets right away */+ #if WANT_UPLOAD+- if (f->upload) {+- if (do_upload(f)) continue;+- } else++ if (f->upload) {++ transfer_status = do_upload(f);++ } else+ #endif+- if (do_download(f)) continue;++ transfer_status = do_download(f);+ +- /* do_{upload,download} returned 0, the transfer is complete */+- if (!numeric(f->owner, 226, "Transfer complete."))+- continue;+- time(&(f->owner->last_transfer));++ if (transfer_status == FTRAN_IORESULT_BLOCKED)++ return;++ }++ while (transfer_status == FTRAN_IORESULT_PARTIAL);++++ assert((transfer_status == FTRAN_IORESULT_COMPLETE) || (transfer_status == FTRAN_IORESULT_FAILED));++++ if (transfer_status == FTRAN_IORESULT_COMPLETE) {++ /* do_{upload,download} returned TRANSFER_STATUS_COMPLETE, the transfer is complete */++ if (!numeric(f->owner, 226, "Transfer complete"))++ return 1;++ time(&(f->owner->last_transfer));++ }++ else {++ if (!numeric(f->owner, 550, "Transfer Failed"))++ return 1;++ }+ + #if WANT_XFERLOG+- if (!f->dir_listing) {+- write_xferlog(f);+- }++ if (!f->dir_listing)++ write_xferlog(f);+ #endif+ +- destroy_ftran(f);++ destroy_ftran(f);+++ #if WANT_FULLSCREEN+- update_display(first_conn);++ update_display(first_conn);+ #endif+- }+ +- return checked_through;++ return 0;+ }+ + #if WANT_UPLOAD+-int do_upload(struct ftran *f)++enum ftran_ioready do_upload(struct ftran *f)+ {+ char upload_buf[16384];++ enum ftran_ioresult upload_status;+ int size;+ #if WANT_ASCII+ /* keep buffer size small in ascii transfers +@@ -714,26 +807,39 @@+ size = ascii_uploadfilter(upload_buf, size);+ }+ #endif+- if (size > 0 && (write(f->local_file, upload_buf, size) == size)) {+- return 1;+- } else if (size == -1) {+- /* don't write xferlog... or? */+- numeric(f->owner, 426, strerror(errno));+- destroy_ftran(f);+- return 1;+- }+- return 0;++ if ((size == -1) && (errno == EWOULDBLOCK))++ upload_status = FTRAN_IORESULT_BLOCKED;++ else if ((size == -1) && (errno != EWOULDBLOCK)) {++ upload_status = FTRAN_IORESULT_FAILED;++ /* don't write xferlog... or? */++ numeric(f->owner, 426, strerror(errno));++ }++ else if (size > 0) {++ if (write(f->local_file, upload_buf, size) == size)++ upload_status = FTRAN_IORESULT_PARTIAL;++ else++ upload_status = FTRAN_IORESULT_FAILED;++ }++ else if (size == 0) ++ upload_status = FTRAN_IORESULT_COMPLETE;++ ++ DPRINT("f->sock %d, size %d, upload status %d\n",f->sock,size,f->pos,upload_status);++ return upload_status;+ } + #endif+ +-int do_download(struct ftran *f)++/* Return TRUE if there is more to send, FALSE if the caller++ * can destroy the ftran.++ * On exit, the ftran is never destroyed, that's the caller's job.++ */++enum ftran_ioresult do_download(struct ftran *f)+ {+ #if defined(TCP_CORK) && defined(SOL_TCP)+ unsigned int zero = 0;+ #endif+ char *sendfrom_buf;+- int bytes_to_send;+- int more_to_send = 0;++ int bytes_to_send,nbytes;++ enum ftran_ioresult download_status;+ + #if !HAVE_MMAP+ char buf[MAX_BLOCK_SIZE];+@@ -749,8 +854,8 @@+ * Here we use a rather simplified sending `algorithm',+ * leaving most of the quirks to the system calls.+ */++ /* FIXME: don't activate this if WANT_ASCII && (f->ascii_mode == 1) */+ if (sendfile_supported == 1 && f->dir_listing == 0) {+- int err;+ size = f->size - f->pos;+ + if (size > f->block_size) size = f->block_size;+@@ -758,30 +863,39 @@+ + #ifdef TCP_CORK+ if (size != f->block_size) {+- setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));++ err=setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));+ } + #endif+ +- err = sendfile(f->sock, f->local_file, &f->pos, size);+- return (f->pos < f->size) && (err > -1);++ nbytes = sendfile(f->sock, f->local_file, &f->pos, size);++ if (nbytes == -1) assert(errno != EINTR);++ if (f->pos == f->size) ++ download_status = FTRAN_IORESULT_COMPLETE;++ else if (nbytes > -1)++ download_status = FTRAN_IORESULT_PARTIAL;++ else if (errno == EWOULDBLOCK)++ download_status = FTRAN_IORESULT_BLOCKED;++ else++ download_status = FTRAN_IORESULT_FAILED;++++ DPRINT("f->sock %d, f->local_file %d, f->pos %d, size %d, bytes sent %d download_status %d\n",f->sock,f->local_file,f->pos,size,nbytes,download_status);++++ return download_status;+ }+ #endif+ + #if HAVE_MMAP+ size = f->size - f->pos;+-+ if (size > f->block_size) size = f->block_size;+ if (size < 0) size = 0;+ + bytes_to_send = size;+ sendfrom_buf = f->file_data + f->pos;+ #else+- bytes_to_send = read(f->local_file, buf, f->block_size);++ bytes_to_send = pread(f->local_file, buf, f->block_size,f->pos);+ sendfrom_buf = buf;+ #endif+ +- if (bytes_to_send == f->block_size) more_to_send = 1;+-+ #if WANT_ASCII+ if (f->ascii_mode == 1) {+ bytes_to_send = ascii_downloadfilter(sendfrom_buf,+@@ -790,27 +904,35 @@+ }+ #endif /* WANT_ASCII */+ +-#if defined(TCP_CORK) && defined(SOL_TCP)+- /* if we believe this is the last packet, unset TCP_CORK */+- if (more_to_send == 0) {+- setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));+- }+-#endif+-+- size = send(f->sock, sendfrom_buf, bytes_to_send, 0);+- if (size < bytes_to_send) more_to_send = 1;++ nbytes = send(f->sock, sendfrom_buf, bytes_to_send, 0);+ + #if WANT_ASCII+- if (f->ascii_mode == 1 && size < bytes_to_send && size > 0) {+- size = ascii_findlength(sendfrom_buf, size);++ if (f->ascii_mode == 1 && nbytes < bytes_to_send && nbytes > 0) {++ size = ascii_findlength(sendfrom_buf, nbytes);+ }+ #endif+ +-#if HAVE_MMAP+ if (size > 0) f->pos += size;++++ if (f->pos == f->size)++ download_status = FTRAN_IORESULT_COMPLETE;++ else if ( ((nbytes == bytes_to_send) && (f->pos < f->size)) || ((nbytes < bytes_to_send) && (nbytes > -1)) )++ download_status = FTRAN_IORESULT_PARTIAL;++ else if (errno == EWOULDBLOCK)++ download_status = FTRAN_IORESULT_BLOCKED;++ else ++ download_status = FTRAN_IORESULT_FAILED;++++ DPRINT("send returns %d, bytes to send %d, with errno %d, transfer status = %d\n",nbytes,bytes_to_send,errno,download_status);++++#if defined(TCP_CORK) && defined(SOL_TCP)++ /* if we believe this is the last packet, unset TCP_CORK */++ if (download_status == FTRAN_IORESULT_COMPLETE) {++ int err=setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));++ }+ #endif+ +- return more_to_send;++ return download_status;+ }+ + #if WANT_XFERLOG+@@ -875,40 +997,31 @@+ int main(void)+ {+ int server_sock;++ struct rlimit rlimit;+ +-#if HAVE_POLL+- /* the sets are declared globally if we use poll() */+-#else+- fd_set fds, fds_send;+-#endif++ getrlimit(RLIMIT_NOFILE,&rlimit);++ FD_MAX = rlimit.rlim_max;++ printf("FD_MAX set to %d\n",FD_MAX);+ + /*setlinebuf(stdout);*/+ setvbuf(stdout, (char *)NULL, _IOLBF, 0); + + signal(SIGPIPE, SIG_IGN);+ +++ printf("BetaFTPD version %s, Copyright (C) 1999-2000 Steinar H. Gunderson\n", VERSION);+ puts("BetaFTPD comes with ABSOLUTELY NO WARRANTY; for details see the file");+ puts("COPYING. This is free software, and you are welcome to redistribute it");+ puts("under certain conditions; again see the file COPYING for details.");+ puts("");+ ++ + /* we don't need stdin */+ close(0);+ +-#if HAVE_POLL+- {+- int i;+- for (i = 0; i < FD_MAX; i++) {+- fds[i].fd = -1;+- fds[i].events = 0;+- }+- }+-#else+- FD_ZERO(&master_fds);+- FD_ZERO(&master_send_fds);+-#endif+-++ own_pid=getpid();++ rn_init(&rns,FD_MAX);++ rn_setSignum(&rns,SIGRTMIN);+ server_sock = create_server_socket();+ + #if WANT_FULLSCREEN+@@ -916,6 +1029,7 @@+ #endif+ + /* init dummy first connection */+++ first_conn = alloc_new_conn(-1);+ first_ftran = alloc_new_ftran(0, NULL);+ #if WANT_DCACHE+@@ -968,102 +1082,42 @@+ if (errno == ENOSYS) sendfile_supported = 0;+ }+ #endif++ /* create the header of the list containing all the deleted objects++ * (both conn and ftran). ++ */+ +- for ( ;; ) {+- int i;+-#ifndef HAVE_POLL+- struct timeval timeout;+-#endif+-+- /*screw_clients(); //look for memory errors */++ destroyed_list_header = (struct list_element *) calloc(1,sizeof(struct list_element));+ ++ for ( ;; ) {++ int i,err;++ + #if WANT_FULLSCREEN+ update_display(first_conn);+ #endif+-+-#if HAVE_POLL+- i = poll(fds, highest_fds + 1, 60000);+-#if 0+- {+- int j;+- for (j=0; j<=highest_fds; j++) {+- if (fds[j].revents) printf("fds[%d].fd %d, .revents %x\n", j, fds[j].fd, fds[j].revents);++ ++ err=rn_waitAndDispatchEvents(&rns,100000);++ if (err) {++ if (err == EBADF) {++ /* fill in here later */+ }+- }+-#endif+-#else+- /* reset fds (gets changed by select()) */+- fds = master_fds;+- fds_send = master_send_fds;+-+- /*+- * wait up to 60 secs for any activity +- */+- timeout.tv_sec = 60;+- timeout.tv_usec = 0;+-+- i = select(FD_SETSIZE, &fds, &fds_send, NULL, &timeout);+-#endif+-+- if (i == -1) {+- if (errno == EBADF) {+-#if !HAVE_POLL+- /* don't like this, but we have to */+- clear_bad_fds(&server_sock);+-#endif+- } else if (errno != EINTR) {+-#if HAVE_POLL+- perror("poll()");+-#else+- perror("select()");+-#endif++ else if (err == EWOULDBLOCK) {+ continue;+ }+ }++ ++ /* once waitAndDispatchEvents has returned, we can delete ++ * the list of destroyed objects.++ */+ +-#if HAVE_POLL+- /* fix an invalid server socket */+- if (fds[server_sock].revents & POLLERR) {+- del_fd(server_sock);+- server_sock = create_server_socket();+- }+-#endif+-++ purge_destroyed_list(); ++ + /* remove any timed out sockets */+ if (time_to_check) {+ time_out_sockets();+ #if WANT_DCACHE+- time_out_dcache();++ time_out_dcache();+ #endif+- time_to_check = 0;+- }+-+- if (i <= 0) continue;+-+-#if HAVE_POLL+- i -= process_all_sendfiles(i);+- process_all_clients(i);+-#else+- /* sends are given highest `priority' */+- i -= process_all_sendfiles(&fds_send, i);+-+- /* incoming PASV connections and uploads */+- i -= process_all_sendfiles(&fds, i);+-+- /*+- * check the incoming PASV connections first, so+- * process_all_clients() won't be confused.+- */ +- process_all_clients(&fds, i);+-#endif+-+-#if HAVE_POLL+- if (fds[server_sock].revents & POLLIN) {+-#else+- if (FD_ISSET(server_sock, &fds)) {+-#endif+- accept_new_client(&server_sock);+- i--;++ time_to_check = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -