X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ftpd.c;h=b35a9a04b1509d638204dd34061ba87c41420a6f;hb=9e83a47a9d9bd9a8020a80393e1f0e03bb34efe7;hp=473624e53ba55e8a115e8fdb3798dc343b9fe448;hpb=4b83f8e50792b459dfd8a6ffe470c2fccb524e7b;p=betaftpd diff --git a/ftpd.c b/ftpd.c index 473624e..b35a9a0 100644 --- a/ftpd.c +++ b/ftpd.c @@ -112,6 +112,10 @@ #include #endif +#if HAVE_LINUX_TCP_H +#include +#endif + #if HAVE_MMAP #include #endif @@ -171,13 +175,6 @@ #include #endif -/* Debug printing -- remove before 0.0.8 final */ -#if 1 -#define DPRINT(s) -#else -#define DPRINT(s) printf s -#endif - #ifndef MAP_FAILED #define MAP_FAILED -1 #endif @@ -205,6 +202,10 @@ fd_set master_fds, master_send_fds; FILE *xferlog = NULL; #endif +#if HAVE_LINUX_SENDFILE +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 @@ -262,7 +263,6 @@ int vsnprintf(char *str, size_t n, const char *format, va_list ap) */ int add_fd(const int fd, const int events) { - DPRINT(("add_fd(%d, %x)\n", fd, events)); #if HAVE_POLL if (fd >= FD_MAX) { printf("add_fd(%d, %x): failed\n", fd, events); @@ -289,7 +289,6 @@ int add_fd(const int fd, const int events) */ void del_fd(const int fd) { - DPRINT(("del_fd(%d)\n", fd)); #if HAVE_POLL if (fd >= FD_MAX) return; @@ -365,7 +364,6 @@ struct conn *alloc_new_conn(const int sock) { const unsigned int one = 1; struct conn *c = (struct conn *)(malloc(sizeof(struct conn))); - DPRINT(("alloc_new_conn(%d)\n", sock)); if (c == NULL) return c; @@ -480,14 +478,11 @@ struct dcache *alloc_new_dcache() */ void destroy_conn(struct conn * const c) { - DPRINT(("destroy_conn:\n")); if (c == NULL) return; del_fd(c->sock); destroy_ftran(c->transfer); remove_from_linked_list((struct list_element *)c); - - DPRINT(("destroy_conn done.\n")); } /* @@ -570,7 +565,7 @@ void destroy_dcache(struct dcache * const d) /* * process_all_clients(): - * Processes all the control connections in active_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 @@ -585,8 +580,6 @@ int process_all_clients(const fd_set * const active_clients, const int num_ac) struct conn *c = NULL, *next = first_conn->next_conn; int checked_through = 0; - DPRINT(("process_all_clients: num_ac %d\n", num_ac)); - /* run through the linked list */ while (next != NULL && checked_through < num_ac) { int bytes_avail; @@ -594,14 +587,9 @@ int process_all_clients(const fd_set * const active_clients, const int num_ac) c = next; next = c->next_conn; #if HAVE_POLL - if (fds[c->sock].revents & (POLLERR|POLLHUP|POLLNVAL)) { - destroy_conn(c); - continue; - } - if (!fds[c->sock].revents & POLLIN) { + if ((fds[c->sock].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) == 0) { continue; } - DPRINT(("process_all_clients: fd %d has POLLIN set\n", c->sock)); #else if (!FD_ISSET(c->sock, active_clients)) { continue; @@ -619,8 +607,10 @@ int process_all_clients(const fd_set * const active_clients, const int num_ac) * client has closed the socket. If we get a return value * of -1 (error), we close the socket ourselves. * - * Just to be safe, we include this code for poll() as - * well. + * 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; @@ -635,6 +625,10 @@ int process_all_clients(const fd_set * const active_clients, const int num_ac) c->buf_len += bytes_avail; parse_command(c); + + if (fds[c->sock].revents & (POLLERR|POLLHUP|POLLNVAL)) { + destroy_conn(c); + } } return checked_through; } @@ -741,7 +735,7 @@ int process_all_sendfiles(fd_set * const active_clients, const int num_ac) int do_upload(struct ftran *f) { char upload_buf[16384]; - int avail, size; + int size; #if WANT_ASCII /* keep buffer size small in ascii transfers to prevent process stalling while filtering @@ -804,11 +798,7 @@ int do_download(struct ftran *f) * Here we use a rather simplified sending `algorithm', * leaving most of the quirks to the system calls. */ - if (f->dir_listing == 0 -#if WANT_UPLOAD - && f->upload == 0 -#endif - ) { + if (sendfile_supported == 1 && f->dir_listing == 0) { int err; size = f->size - f->pos; @@ -1015,6 +1005,19 @@ int main(void) alarm(60); signal(SIGALRM, handle_alarm); +#if HAVE_LINUX_SENDFILE + /* check that sendfile() is really implemented (same check as configure does) */ + { + int out_fd = 1, in_fd = 0; + off_t offset = 0; + size_t size = 1024; + + errno = 0; + sendfile(out_fd, in_fd, &offset, size); + if (errno == ENOSYS) sendfile_supported = 0; + } +#endif + for ( ;; ) { int i; #ifndef HAVE_POLL @@ -1029,7 +1032,6 @@ int main(void) #if HAVE_POLL i = poll(fds, highest_fds + 1, 60000); - DPRINT(("poll returns %d\n", i)); #if 0 { int j; @@ -1252,7 +1254,6 @@ void numeric(struct conn * const c, const int numeric, const char * const format i = vsnprintf(buf, 256, fmt, args); va_end(args); - DPRINT((buf)); err = send(c->sock, buf, i, 0); if (err == -1 && errno == EPIPE) { destroy_conn(c); @@ -1393,7 +1394,7 @@ void init_file_transfer(struct ftran * const f) #if HAVE_MMAP if (f->dir_listing == 0) { #if HAVE_LINUX_SENDFILE - int do_mmap = 0; + int do_mmap = (sendfile_supported) ? 0 : 1; #else int do_mmap = 1; #endif @@ -1540,11 +1541,12 @@ void clear_bad_fds(int * const server_sock) * dump_file(): Dumps a file on the control connection. Used for * welcome messages and the likes. Note that outbuf * is so big, to prevent any crashing from users creating - * weird .message files (like 1024 LFs)... + * weird .message files (like 1024 LFs)... The size of + * the file is limited to 1024 bytes (by truncation). */ void dump_file(struct conn * const c, const int num, const char * const filename) { - char buf[1024], outbuf[8192]; + char buf[1024], outbuf[5121]; char *ptr = outbuf + 4; int i, j = -1; @@ -1583,28 +1585,26 @@ void list_readmes(struct conn * const c) const time_t now = time(NULL); int i; - if (glob("README*", 0, NULL, &pglob) == 0) { - for (i = 0; i < pglob.gl_pathc; i++) { - const char * const temp = pglob.gl_pathv[i]; - struct stat buf; - char str[2048]; + if (glob("README*", 0, NULL, &pglob) != 0) return; - char *tm; + for (i = 0; i < pglob.gl_pathc; i++) { + struct stat buf; + char str[256]; + char *tm; - if (stat(temp, &buf) == -1) continue; + if (stat(pglob.gl_pathv[i], &buf) == -1) continue; - /* remove trailing LF */ - tm = ctime(&buf.st_mtime); - tm[strlen(tm) - 1] = 0; + /* remove trailing LF */ + tm = ctime(&buf.st_mtime); + tm[strlen(tm) - 1] = 0; - sprintf(str, "250-Please read the file %s\r\n" - "250-\tIt was last modified %s - %ld days ago\r\n", - temp, tm, - (now - buf.st_mtime) / 86400); - send(c->sock, str, strlen(str), 0); - } - globfree(&pglob); - } + snprintf(str, 256, "250-Please read the file %s\r\n" + "250-\tIt was last modified %s - %ld days ago\r\n", + pglob.gl_pathv[i], tm, + (now - buf.st_mtime) / 86400); + send(c->sock, str, strlen(str), 0); + } + globfree(&pglob); } #endif