svn commit: samba r3933 - in trunk/source/smbd: .
jra at samba.org
jra at samba.org
Wed Nov 24 03:41:55 GMT 2004
Author: jra
Date: 2004-11-24 03:41:54 +0000 (Wed, 24 Nov 2004)
New Revision: 3933
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=3933
Log:
Correctly check for the top length bit in LARGE_READX.
Jeremy.
Modified:
trunk/source/smbd/reply.c
Changeset:
Modified: trunk/source/smbd/reply.c
===================================================================
--- trunk/source/smbd/reply.c 2004-11-24 01:03:26 UTC (rev 3932)
+++ trunk/source/smbd/reply.c 2004-11-24 03:41:54 UTC (rev 3933)
@@ -33,6 +33,7 @@
extern char magic_char;
extern int global_oplock_break;
unsigned int smb_echo_count = 0;
+extern uint32 global_client_caps;
extern BOOL global_encrypted_passwords_negotiated;
@@ -1716,7 +1717,7 @@
Fail for readbraw.
****************************************************************************/
-void fail_readraw(void)
+static void fail_readraw(void)
{
pstring errstr;
slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
@@ -1724,12 +1725,46 @@
exit_server(errstr);
}
+#if defined(WITH_SENDFILE)
/****************************************************************************
+ Fake (read/write) sendfile. Returns -1 on read or write fail.
+****************************************************************************/
+
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
+{
+ ssize_t ret=0;
+
+ /* Paranioa check... */
+ if (nread > bufsize) {
+ fail_readraw();
+ }
+
+ if (nread > 0) {
+ ret = read_file(fsp,buf,startpos,nread);
+ if (ret == -1) {
+ return -1;
+ }
+ }
+
+ /* If we had a short read, fill with zeros. */
+ if (ret < nread) {
+ memset(outbuf, '\0', nread - ret);
+ }
+
+ if (write_data(smbd_server_fd(),buf,nread) != nread) {
+ return -1;
+ }
+
+ return (ssize_t)nread;
+}
+#endif
+
+/****************************************************************************
Use sendfile in readbraw.
****************************************************************************/
void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
- ssize_t mincount, char *outbuf)
+ ssize_t mincount, char *outbuf, int out_buffsize)
{
ssize_t ret=0;
@@ -1751,12 +1786,21 @@
if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
/*
- * Special hack for broken Linux with no 64 bit clean sendfile. If we
- * return ENOSYS then pretend we just got a normal read.
+ * Special hack for broken Linux with no working sendfile. If we
+ * return EINTR we sent the header but not the rest of the data.
+ * Fake this up by doing read/write calls.
*/
- if (errno == ENOSYS) {
+ if (errno == EINTR) {
+ /* Ensure we don't do this again. */
set_use_sendfile(SNUM(conn), False);
- goto normal_read;
+ DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
+
+ if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
+ DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server("send_file_readbraw fake_sendfile failed");
+ }
+ return;
}
DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
@@ -1766,7 +1810,6 @@
}
- normal_read:
#endif
if (nread > 0) {
@@ -1789,7 +1832,7 @@
Reply to a readbraw (core+ protocol).
****************************************************************************/
-int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
+int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
{
extern struct current_user current_user;
ssize_t maxcount,mincount;
@@ -1904,7 +1947,7 @@
DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
(int)maxcount, (int)mincount, (int)nread ) );
- send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
+ send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
DEBUG(5,("readbraw finished\n"));
END_PROFILE(SMBreadbraw);
@@ -2068,7 +2111,7 @@
Reply to a read and X - possibly using sendfile.
****************************************************************************/
-int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
+int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
{
ssize_t nread = -1;
@@ -2116,12 +2159,22 @@
if ( SMB_VFS_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.
+ * Special hack for broken Linux with no working sendfile. If we
+ * return EINTR we sent the header but not the rest of the data.
+ * Fake this up by doing read/write calls.
*/
- if (errno == ENOSYS) {
+ if (errno == EINTR) {
+ /* Ensure we don't do this again. */
set_use_sendfile(SNUM(conn), False);
- goto normal_read;
+ DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
+
+ if (fake_sendfile(fsp, startpos, smb_maxcnt, data,
+ len_outbuf - (data-outbuf)) == -1) {
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server("send_file_readX: fake_sendfile failed");
+ }
+ return;
}
DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
@@ -2134,8 +2187,6 @@
return -1;
}
- normal_read:
-
#endif
nread = read_file(fsp,data,startpos,smb_maxcnt);
@@ -2183,6 +2234,10 @@
set_message(outbuf,12,0,True);
+ if (global_client_caps & CAP_LARGE_READX) {
+ smb_maxcnt |= ((((size_t)SVAL(inbuf,smb_vwv7)) & 1 )<<16);
+ }
+
if(CVAL(inbuf,smb_wct) == 12) {
#ifdef LARGE_SMB_OFF_T
/*
More information about the samba-cvs
mailing list