diff options
author | Jeremy Allison <jra@samba.org> | 2007-10-30 16:22:24 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2007-10-30 16:22:24 -0700 |
commit | c3250149e12338fac5093991b385ad2807c92d1f (patch) | |
tree | fa1e5387fb10d02b1f09da59fc20d7a8520e65fc /source3/smbd/reply.c | |
parent | 4367f4b4d4ce075f3fe8e88e68dbda47e2252349 (diff) | |
download | samba-c3250149e12338fac5093991b385ad2807c92d1f.tar.gz samba-c3250149e12338fac5093991b385ad2807c92d1f.tar.bz2 samba-c3250149e12338fac5093991b385ad2807c92d1f.zip |
Add new parameter, "min receivefile size" (by default set
to zero). If non-zero, writeX calls greater than this
value will be left in the socket buffer for later handling
with recvfile (or userspace equivalent). Definition of
recvfile for your system is left as an exercise for
the reader (I'm working on getting splice working :-).
Jeremy.
(This used to be commit 11c03b75ddbcb6e36b231bb40a1773d1c550621c)
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r-- | source3/smbd/reply.c | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 38ce797eeb..4c1ed56d4f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3494,7 +3494,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) } if (numtowrite>0) { - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d " @@ -3572,7 +3572,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) exit_server_cleanly("secondary writebraw failed"); } - nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite); + nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite); if (nwritten == -1) { TALLOC_FREE(buf); reply_unixerror(req, ERRHRD, ERRdiskfull); @@ -3686,7 +3686,7 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req) if(numtowrite == 0) { nwritten = 0; } else { - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } status = sync_file(conn, fsp, False /* write through */); @@ -3808,7 +3808,7 @@ void reply_write(connection_struct *conn, struct smb_request *req) return; } } else - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); status = sync_file(conn, fsp, False); if (!NT_STATUS_IS_OK(status)) { @@ -3841,6 +3841,64 @@ void reply_write(connection_struct *conn, struct smb_request *req) } /**************************************************************************** + Ensure a buffer is a valid writeX for recvfile purposes. +****************************************************************************/ + +#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \ + (2*14) + /* word count (including bcc) */ \ + 1 /* pad byte */) + +bool is_valid_writeX_buffer(char *inbuf) +{ + size_t numtowrite; + connection_struct *conn = NULL; + unsigned int doff = 0; + size_t len = smb_len(inbuf); + + if (CVAL(inbuf,smb_com) != SMBwriteX || + CVAL(inbuf,smb_vwv0) != 0xFF || + CVAL(inbuf,smb_wct) != 14) { + return false; + } + conn = conn_find(SVAL(inbuf, smb_tid)); + if (conn == NULL) { + return false; + } + if (IS_IPC(conn)) { + return false; + } + numtowrite = SVAL(inbuf,smb_vwv10); + numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + if (numtowrite == 0) { + return false; + } + /* Ensure the sizes match up. */ + doff = SVAL(inbuf,smb_vwv11); + + if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) { + /* no pad byte...old smbclient :-( */ + return false; + } + + if (len - doff != numtowrite) { + DEBUG(10,("is_valid_writeX_buffer: doff mismatch " + "len = %u, doff = %u, numtowrite = %u\n", + (unsigned int)len, + (unsigned int)doff, + (unsigned int)numtowrite )); + return false; + } + + DEBUG(10,("is_valid_writeX_buffer: true " + "len = %u, doff = %u, numtowrite = %u\n", + (unsigned int)len, + (unsigned int)doff, + (unsigned int)numtowrite )); + + return true; +} + +/**************************************************************************** Reply to a write and X. ****************************************************************************/ @@ -3875,10 +3933,18 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16); } - if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { - reply_doserror(req, ERRDOS, ERRbadmem); - END_PROFILE(SMBwriteX); - return; + if (req->unread_bytes) { + if (numtowrite != req->unread_bytes) { + reply_doserror(req, ERRDOS, ERRbadmem); + END_PROFILE(SMBwriteX); + return; + } + } else { + if (smb_doff > smblen || smb_doff + numtowrite > smblen) { + reply_doserror(req, ERRDOS, ERRbadmem); + END_PROFILE(SMBwriteX); + return; + } } /* If it's an IPC, pass off the pipe handler. */ @@ -3947,15 +4013,16 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) nwritten = 0; } else { - if (schedule_aio_write_and_X(conn, req, fsp, data, startpos, - numtowrite)) { + if (req->unread_bytes == 0 && + schedule_aio_write_and_X(conn, req, fsp, data, + startpos, numtowrite)) { END_PROFILE(SMBwriteX); return; } - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } - + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteX); @@ -4264,7 +4331,7 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req) return; } - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); set_filetime(conn, fsp->fsp_name, mtime); @@ -4726,7 +4793,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) data = smb_buf(req->inbuf) + 3; - if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) { reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBsplwr); return; |