diff options
author | Jeremy Allison <jra@samba.org> | 2002-09-14 00:34:46 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2002-09-14 00:34:46 +0000 |
commit | febd3f929b0f922a4bac69aa131089da4675cb1e (patch) | |
tree | ef55a75fde1e2317df914782898d056342b60d02 /source3 | |
parent | 10297d8cd3bfdef44ea6fdf4d0520fe6c613108c (diff) | |
download | samba-febd3f929b0f922a4bac69aa131089da4675cb1e.tar.gz samba-febd3f929b0f922a4bac69aa131089da4675cb1e.tar.bz2 samba-febd3f929b0f922a4bac69aa131089da4675cb1e.zip |
Added fix for broken Linux (no sendfile64). When offset + count > 2GB
then return ENOSYS and let the upper layer handle it.
Jeremy
(This used to be commit 872dfd87cda585c33c3823b06580cb301567a9b9)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/sendfile.c | 57 | ||||
-rw-r--r-- | source3/smbd/reply.c | 7 |
2 files changed, 64 insertions, 0 deletions
diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 6e093c31ff..2707495d5b 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -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) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 02aa53807c..878e21f4c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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"); |