]> git.sesse.net Git - betaftpd/blobdiff - ftpd.c
get_num_files(): Fixed a memory leak (thanks, mtrace ;-) ).
[betaftpd] / ftpd.c
diff --git a/ftpd.c b/ftpd.c
index 1e2752c670401ecb96c5fb2a6a6e70fb8823b623..b35a9a04b1509d638204dd34061ba87c41420a6f 100644 (file)
--- a/ftpd.c
+++ b/ftpd.c
 #include <linux/socket.h>
 #endif
 
+#if HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#endif
+
 #if HAVE_MMAP
 #include <sys/mman.h>
 #endif
@@ -198,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
@@ -557,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
@@ -579,11 +587,7 @@ 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;
                }
 #else
@@ -603,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;
@@ -619,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;
 }
@@ -725,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
@@ -788,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;
 
@@ -999,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
@@ -1375,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