Added fix for broken Linux (no sendfile64). When offset + count > 2GB
authorJeremy Allison <jra@samba.org>
Sat, 14 Sep 2002 00:34:46 +0000 (00:34 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 14 Sep 2002 00:34:46 +0000 (00:34 +0000)
then return ENOSYS and let the upper layer handle it.
Jeremy
(This used to be commit 872dfd87cda585c33c3823b06580cb301567a9b9)

source3/lib/sendfile.c
source3/smbd/reply.c

index 6e093c31ffb999da94cc8b376a2e01b875eac5b3..2707495d5b36a910127142c83f2ce0465c5170a4 100644 (file)
@@ -74,6 +74,63 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of
        return count + hdr_len;
 }
 
+#elif defined(LINUX_BROKEN_SENDFILE_API)
+
+#include <sys/sendfile.h>
+
+#ifndef MSG_MORE
+#define MSG_MORE 0x8000
+#endif
+
+ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
+{
+       size_t total=0;
+       ssize_t ret;
+       ssize_t hdr_len = 0;
+
+       /* 
+        * Fix for broken Linux 2.4 systems with no working sendfile64().
+        * If the offset+count > 2 GB then pretend we don't have the
+        * system call sendfile at all. The upper later catches this
+        * and uses a normal read. JRA.
+        */
+
+       if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) {
+               errno = ENOSYS;
+               return -1;
+       }
+
+       /*
+        * Send the header first.
+        * Use MSG_MORE to cork the TCP output until sendfile is called.
+        */
+
+       if (header) {
+               hdr_len = header->length;
+               while (total < hd_len) {
+                       ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
+                       if (ret == -1)
+                               return -1;
+                       total += ret;
+               }
+       }
+
+       total = count;
+       while (total) {
+               ssize_t nwritten;
+               do {
+                       nwritten = sendfile(tofd, fromfd, &offset, total);
+               } while (nwritten == -1 && errno == EINTR);
+               if (nwritten == -1)
+                       return -1;
+               if (nwritten == 0)
+                       return -1; /* I think we're at EOF here... */
+               total -= nwritten;
+       }
+       return count + hdr_len;
+}
+
+
 #elif defined(SOLARIS_SENDFILE_API)
 
 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
index 02aa53807c6c2d64cdb950d3f68a83affa96b2ef..878e21f4c273c4d5ae34cc3dcde9443558317f33 100644 (file)
@@ -1730,6 +1730,13 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                header.free = NULL;
 
                if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
+                       /*
+                        * Special hack for broken Linux with no 64 bit clean sendfile. If we
+                        * return ENOSYS then pretend we just got a normal read.
+                        */
+                       if (errno == ENOSYS)
+                               goto normal_read;
+
                        DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
                                fsp->fsp_name, strerror(errno) ));
                        exit_server("send_file_readX sendfile failed");