mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
Merge of transfer file code from 2.2, fix for readbraw.
Jeremy.
This commit is contained in:
@ -68,8 +68,8 @@ struct vfs_ops {
|
|||||||
|
|
||||||
int (*open)(struct connection_struct *conn, const char *fname, int flags, mode_t mode);
|
int (*open)(struct connection_struct *conn, const char *fname, int flags, mode_t mode);
|
||||||
int (*close)(struct files_struct *fsp, int fd);
|
int (*close)(struct files_struct *fsp, int fd);
|
||||||
ssize_t (*read)(struct files_struct *fsp, int fd, char *data, size_t n);
|
ssize_t (*read)(struct files_struct *fsp, int fd, void *data, size_t n);
|
||||||
ssize_t (*write)(struct files_struct *fsp, int fd, const char *data, size_t n);
|
ssize_t (*write)(struct files_struct *fsp, int fd, const void *data, size_t n);
|
||||||
SMB_OFF_T (*lseek)(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence);
|
SMB_OFF_T (*lseek)(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence);
|
||||||
int (*rename)(struct connection_struct *conn, const char *old, const char *new);
|
int (*rename)(struct connection_struct *conn, const char *old, const char *new);
|
||||||
int (*fsync)(struct files_struct *fsp, int fd);
|
int (*fsync)(struct files_struct *fsp, int fd);
|
||||||
|
@ -511,81 +511,54 @@ int set_blocking(int fd, BOOL set)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
transfer some data between two fd's
|
Transfer some data between two fd's.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
|
|
||||||
|
ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
|
||||||
|
ssize_t (*write_fn)(int, const void *, size_t))
|
||||||
{
|
{
|
||||||
static char *buf=NULL;
|
static char buf[16384];
|
||||||
static int size=0;
|
size_t total = 0;
|
||||||
char *buf1,*abuf;
|
ssize_t read_ret;
|
||||||
SMB_OFF_T total = 0;
|
size_t write_total = 0;
|
||||||
|
ssize_t write_ret;
|
||||||
|
|
||||||
DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
|
while (total < n) {
|
||||||
|
size_t num_to_read_thistime = MIN((n - total), sizeof(buf));
|
||||||
|
|
||||||
if (size == 0) {
|
read_ret = (*read_fn)(infd, buf + total, num_to_read_thistime);
|
||||||
size = lp_readsize();
|
if (read_ret == -1) {
|
||||||
size = MAX(size,1024);
|
DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
if (read_ret == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
while (!buf && size>0) {
|
write_total = 0;
|
||||||
buf = (char *)malloc(size+8);
|
|
||||||
if (!buf) size /= 2;
|
while (write_total < read_ret) {
|
||||||
}
|
write_ret = (*write_fn)(outfd,buf + total, read_ret);
|
||||||
|
|
||||||
|
if (write_ret == -1) {
|
||||||
|
DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (write_ret == 0)
|
||||||
|
return (ssize_t)total;
|
||||||
|
|
||||||
|
write_total += (size_t)write_ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (!buf) {
|
total += (size_t)read_ret;
|
||||||
DEBUG(0,("Can't allocate transfer buffer!\n"));
|
}
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
abuf = buf + (align%8);
|
return (ssize_t)total;
|
||||||
|
|
||||||
if (header)
|
|
||||||
n += headlen;
|
|
||||||
|
|
||||||
while (n > 0)
|
|
||||||
{
|
|
||||||
int s = (int)MIN(n,(SMB_OFF_T)size);
|
|
||||||
int ret,ret2=0;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
if (header && (headlen >= MIN(s,1024))) {
|
|
||||||
buf1 = header;
|
|
||||||
s = headlen;
|
|
||||||
ret = headlen;
|
|
||||||
headlen = 0;
|
|
||||||
header = NULL;
|
|
||||||
} else {
|
|
||||||
buf1 = abuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header && headlen > 0)
|
|
||||||
{
|
|
||||||
ret = MIN(headlen,size);
|
|
||||||
memcpy(buf1,header,ret);
|
|
||||||
headlen -= ret;
|
|
||||||
header += ret;
|
|
||||||
if (headlen <= 0) header = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s > ret)
|
|
||||||
ret += read(infd,buf1+ret,s-ret);
|
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
|
|
||||||
if (ret2 > 0) total += ret2;
|
|
||||||
/* if we can't write then dump excess data */
|
|
||||||
if (ret2 != ret)
|
|
||||||
transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
|
|
||||||
}
|
|
||||||
if (ret <= 0 || ret2 != ret)
|
|
||||||
return(total);
|
|
||||||
n -= ret;
|
|
||||||
}
|
|
||||||
return(total);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
|
||||||
|
{
|
||||||
|
return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, read, write);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
sleep for a specified number of milliseconds
|
sleep for a specified number of milliseconds
|
||||||
|
@ -78,7 +78,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0);
|
transfer_file(tmp_fd,outfd,st.st_size);
|
||||||
close(tmp_fd);
|
close(tmp_fd);
|
||||||
close(outfd);
|
close(outfd);
|
||||||
}
|
}
|
||||||
|
@ -1880,157 +1880,147 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
|||||||
return outsize;
|
return outsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Fail for readbraw.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void fail_readraw(void)
|
||||||
|
{
|
||||||
|
pstring errstr;
|
||||||
|
slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n",
|
||||||
|
strerror(errno) );
|
||||||
|
exit_server(errstr);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
reply to a readbraw (core+ protocol)
|
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 dum_buffsize)
|
||||||
{
|
{
|
||||||
size_t maxcount,mincount;
|
size_t maxcount,mincount;
|
||||||
size_t nread = 0;
|
size_t nread = 0;
|
||||||
SMB_OFF_T startpos;
|
SMB_OFF_T startpos;
|
||||||
char *header = outbuf;
|
char *header = outbuf;
|
||||||
ssize_t ret=0;
|
ssize_t ret=0;
|
||||||
files_struct *fsp;
|
files_struct *fsp;
|
||||||
START_PROFILE(SMBreadbraw);
|
START_PROFILE(SMBreadbraw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special check if an oplock break has been issued
|
* Special check if an oplock break has been issued
|
||||||
* and the readraw request croses on the wire, we must
|
* and the readraw request croses on the wire, we must
|
||||||
* return a zero length response here.
|
* return a zero length response here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(global_oplock_break)
|
if(global_oplock_break) {
|
||||||
{
|
_smb_setlen(header,0);
|
||||||
_smb_setlen(header,0);
|
if (write_data(smbd_server_fd(),header,4) != 4)
|
||||||
transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
|
fail_readraw();
|
||||||
DEBUG(5,("readbraw - oplock break finished\n"));
|
DEBUG(5,("readbraw - oplock break finished\n"));
|
||||||
END_PROFILE(SMBreadbraw);
|
END_PROFILE(SMBreadbraw);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsp = file_fsp(inbuf,smb_vwv0);
|
fsp = file_fsp(inbuf,smb_vwv0);
|
||||||
|
|
||||||
if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
|
if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
|
||||||
/*
|
/*
|
||||||
* fsp could be NULL here so use the value from the packet. JRA.
|
* fsp could be NULL here so use the value from the packet. JRA.
|
||||||
*/
|
*/
|
||||||
DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
|
DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
|
||||||
_smb_setlen(header,0);
|
_smb_setlen(header,0);
|
||||||
transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
|
if (write_data(smbd_server_fd(),header,4) != 4)
|
||||||
END_PROFILE(SMBreadbraw);
|
fail_readraw();
|
||||||
return(-1);
|
END_PROFILE(SMBreadbraw);
|
||||||
}
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
CHECK_FSP(fsp,conn);
|
CHECK_FSP(fsp,conn);
|
||||||
|
|
||||||
flush_write_cache(fsp, READRAW_FLUSH);
|
flush_write_cache(fsp, READRAW_FLUSH);
|
||||||
|
|
||||||
startpos = IVAL(inbuf,smb_vwv1);
|
startpos = IVAL(inbuf,smb_vwv1);
|
||||||
if(CVAL(inbuf,smb_wct) == 10) {
|
if(CVAL(inbuf,smb_wct) == 10) {
|
||||||
/*
|
/*
|
||||||
* This is a large offset (64 bit) read.
|
* This is a large offset (64 bit) read.
|
||||||
*/
|
*/
|
||||||
#ifdef LARGE_SMB_OFF_T
|
#ifdef LARGE_SMB_OFF_T
|
||||||
|
|
||||||
startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
|
startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
|
||||||
|
|
||||||
#else /* !LARGE_SMB_OFF_T */
|
#else /* !LARGE_SMB_OFF_T */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure we haven't been sent a >32 bit offset.
|
* Ensure we haven't been sent a >32 bit offset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(IVAL(inbuf,smb_vwv8) != 0) {
|
if(IVAL(inbuf,smb_vwv8) != 0) {
|
||||||
DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
|
DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
|
||||||
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
|
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
|
||||||
_smb_setlen(header,0);
|
_smb_setlen(header,0);
|
||||||
transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
|
if (write_data(smbd_server_fd(),header,4) != 4)
|
||||||
END_PROFILE(SMBreadbraw);
|
fail_readraw();
|
||||||
return(-1);
|
END_PROFILE(SMBreadbraw);
|
||||||
}
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* LARGE_SMB_OFF_T */
|
#endif /* LARGE_SMB_OFF_T */
|
||||||
|
|
||||||
if(startpos < 0) {
|
if(startpos < 0) {
|
||||||
DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
|
DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
|
||||||
(double)startpos ));
|
_smb_setlen(header,0);
|
||||||
_smb_setlen(header,0);
|
if (write_data(smbd_server_fd(),header,4) != 4)
|
||||||
transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
|
fail_readraw();
|
||||||
END_PROFILE(SMBreadbraw);
|
END_PROFILE(SMBreadbraw);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
|
maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
|
||||||
mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
|
mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
|
||||||
|
|
||||||
/* ensure we don't overrun the packet size */
|
/* ensure we don't overrun the packet size */
|
||||||
maxcount = MIN(65535,maxcount);
|
maxcount = MIN(65535,maxcount);
|
||||||
maxcount = MAX(mincount,maxcount);
|
maxcount = MAX(mincount,maxcount);
|
||||||
|
|
||||||
if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
|
if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
|
||||||
{
|
SMB_OFF_T size = fsp->size;
|
||||||
SMB_OFF_T size = fsp->size;
|
SMB_OFF_T sizeneeded = startpos + maxcount;
|
||||||
SMB_OFF_T sizeneeded = startpos + maxcount;
|
|
||||||
|
|
||||||
if (size < sizeneeded)
|
|
||||||
{
|
|
||||||
SMB_STRUCT_STAT st;
|
|
||||||
if (vfs_fstat(fsp,fsp->fd,&st) == 0)
|
|
||||||
size = st.st_size;
|
|
||||||
if (!fsp->can_write)
|
|
||||||
fsp->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
nread = MIN(maxcount,(size - startpos));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < mincount)
|
|
||||||
nread = 0;
|
|
||||||
|
|
||||||
DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
|
if (size < sizeneeded) {
|
||||||
fsp->fnum, (double)startpos,
|
SMB_STRUCT_STAT st;
|
||||||
(int)maxcount, (int)mincount, (int)nread ) );
|
if (vfs_fstat(fsp,fsp->fd,&st) == 0)
|
||||||
|
size = st.st_size;
|
||||||
|
if (!fsp->can_write)
|
||||||
|
fsp->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startpos >= size)
|
||||||
|
nread = 0;
|
||||||
|
else
|
||||||
|
nread = MIN(maxcount,(size - startpos));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nread < mincount)
|
||||||
|
nread = 0;
|
||||||
|
|
||||||
#if UNSAFE_READRAW
|
DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
|
||||||
{
|
(int)maxcount, (int)mincount, (int)nread ) );
|
||||||
BOOL seek_fail = False;
|
|
||||||
int predict=0;
|
if (nread > 0) {
|
||||||
_smb_setlen(header,nread);
|
ret = read_file(fsp,header+4,startpos,nread);
|
||||||
|
if (ret < mincount)
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((nread-predict) > 0) {
|
_smb_setlen(header,ret);
|
||||||
if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
|
if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
|
||||||
DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
|
fail_readraw();
|
||||||
ret = 0;
|
|
||||||
seek_fail = True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!seek_fail)
|
DEBUG(5,("readbraw finished\n"));
|
||||||
ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
|
END_PROFILE(SMBreadbraw);
|
||||||
(SMB_OFF_T)(nread-predict),header,4+predict,
|
return -1;
|
||||||
startpos+predict);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != nread+4)
|
|
||||||
DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
|
|
||||||
fsp->fsp_name,startpos,nread,ret));
|
|
||||||
|
|
||||||
#else /* UNSAFE_READRAW */
|
|
||||||
ret = read_file(fsp,header+4,startpos,nread);
|
|
||||||
if (ret < mincount) ret = 0;
|
|
||||||
|
|
||||||
_smb_setlen(header,ret);
|
|
||||||
transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
|
|
||||||
#endif /* UNSAFE_READRAW */
|
|
||||||
|
|
||||||
DEBUG(5,("readbraw finished\n"));
|
|
||||||
END_PROFILE(SMBreadbraw);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
reply to a lockread (core+ protocol)
|
reply to a lockread (core+ protocol)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -2231,114 +2221,126 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
|
|||||||
|
|
||||||
int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
|
int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
|
||||||
{
|
{
|
||||||
ssize_t nwritten=0;
|
ssize_t nwritten=0;
|
||||||
ssize_t total_written=0;
|
ssize_t total_written=0;
|
||||||
size_t numtowrite=0;
|
size_t numtowrite=0;
|
||||||
size_t tcount;
|
size_t tcount;
|
||||||
SMB_OFF_T startpos;
|
SMB_OFF_T startpos;
|
||||||
char *data=NULL;
|
char *data=NULL;
|
||||||
BOOL write_through;
|
BOOL write_through;
|
||||||
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
|
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
|
||||||
int outsize = 0;
|
int outsize = 0;
|
||||||
START_PROFILE(SMBwritebraw);
|
START_PROFILE(SMBwritebraw);
|
||||||
|
|
||||||
CHECK_FSP(fsp,conn);
|
CHECK_FSP(fsp,conn);
|
||||||
CHECK_WRITE(fsp);
|
CHECK_WRITE(fsp);
|
||||||
|
|
||||||
tcount = IVAL(inbuf,smb_vwv1);
|
tcount = IVAL(inbuf,smb_vwv1);
|
||||||
startpos = IVAL(inbuf,smb_vwv3);
|
startpos = IVAL(inbuf,smb_vwv3);
|
||||||
write_through = BITSETW(inbuf+smb_vwv7,0);
|
write_through = BITSETW(inbuf+smb_vwv7,0);
|
||||||
|
|
||||||
/* We have to deal with slightly different formats depending
|
/* We have to deal with slightly different formats depending
|
||||||
on whether we are using the core+ or lanman1.0 protocol */
|
on whether we are using the core+ or lanman1.0 protocol */
|
||||||
if(Protocol <= PROTOCOL_COREPLUS) {
|
|
||||||
numtowrite = SVAL(smb_buf(inbuf),-2);
|
|
||||||
data = smb_buf(inbuf);
|
|
||||||
} else {
|
|
||||||
numtowrite = SVAL(inbuf,smb_vwv10);
|
|
||||||
data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* force the error type */
|
if(Protocol <= PROTOCOL_COREPLUS) {
|
||||||
CVAL(inbuf,smb_com) = SMBwritec;
|
numtowrite = SVAL(smb_buf(inbuf),-2);
|
||||||
CVAL(outbuf,smb_com) = SMBwritec;
|
data = smb_buf(inbuf);
|
||||||
|
} else {
|
||||||
|
numtowrite = SVAL(inbuf,smb_vwv10);
|
||||||
|
data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
|
/* force the error type */
|
||||||
END_PROFILE(SMBwritebraw);
|
CVAL(inbuf,smb_com) = SMBwritec;
|
||||||
return ERROR_DOS(ERRDOS,ERRlock);
|
CVAL(outbuf,smb_com) = SMBwritec;
|
||||||
}
|
|
||||||
|
|
||||||
if (numtowrite>0)
|
if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
|
||||||
nwritten = write_file(fsp,data,startpos,numtowrite);
|
END_PROFILE(SMBwritebraw);
|
||||||
|
return(ERROR_DOS(ERRDOS,ERRlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numtowrite>0)
|
||||||
|
nwritten = write_file(fsp,data,startpos,numtowrite);
|
||||||
|
|
||||||
DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
|
DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
|
||||||
fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
|
fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
|
||||||
|
|
||||||
if (nwritten < numtowrite) {
|
if (nwritten < numtowrite) {
|
||||||
END_PROFILE(SMBwritebraw);
|
END_PROFILE(SMBwritebraw);
|
||||||
return(UNIXERROR(ERRHRD,ERRdiskfull));
|
return(UNIXERROR(ERRHRD,ERRdiskfull));
|
||||||
}
|
}
|
||||||
|
|
||||||
total_written = nwritten;
|
total_written = nwritten;
|
||||||
|
|
||||||
/* Return a message to the redirector to tell it
|
/* Return a message to the redirector to tell it to send more bytes */
|
||||||
to send more bytes */
|
CVAL(outbuf,smb_com) = SMBwritebraw;
|
||||||
CVAL(outbuf,smb_com) = SMBwritebraw;
|
SSVALS(outbuf,smb_vwv0,-1);
|
||||||
SSVALS(outbuf,smb_vwv0,-1);
|
outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
|
||||||
outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
|
if (!send_smb(smbd_server_fd(),outbuf))
|
||||||
if (!send_smb(smbd_server_fd(),outbuf))
|
exit_server("reply_writebraw: send_smb failed.\n");
|
||||||
exit_server("reply_writebraw: send_smb failed.\n");
|
|
||||||
|
|
||||||
/* Now read the raw data into the buffer and write it */
|
/* Now read the raw data into the buffer and write it */
|
||||||
if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
|
if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
|
||||||
exit_server("secondary writebraw failed");
|
exit_server("secondary writebraw failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Even though this is not an smb message, smb_len
|
/* Even though this is not an smb message, smb_len returns the generic length of an smb message */
|
||||||
returns the generic length of an smb message */
|
numtowrite = smb_len(inbuf);
|
||||||
numtowrite = smb_len(inbuf);
|
|
||||||
|
|
||||||
if (tcount > nwritten+numtowrite) {
|
/* Set up outbuf to return the correct return */
|
||||||
DEBUG(3,("Client overestimated the write %d %d %d\n",
|
outsize = set_message(outbuf,1,0,True);
|
||||||
(int)tcount,(int)nwritten,(int)numtowrite));
|
CVAL(outbuf,smb_com) = SMBwritec;
|
||||||
}
|
SSVAL(outbuf,smb_vwv0,total_written);
|
||||||
|
|
||||||
nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
|
if (numtowrite != 0) {
|
||||||
(SMB_OFF_T)numtowrite,NULL,0,
|
|
||||||
startpos+nwritten);
|
|
||||||
total_written += nwritten;
|
|
||||||
|
|
||||||
/* Set up outbuf to return the correct return */
|
|
||||||
outsize = set_message(outbuf,1,0,True);
|
|
||||||
CVAL(outbuf,smb_com) = SMBwritec;
|
|
||||||
SSVAL(outbuf,smb_vwv0,total_written);
|
|
||||||
|
|
||||||
if (nwritten < (ssize_t)numtowrite) {
|
if (numtowrite > BUFFER_SIZE) {
|
||||||
CVAL(outbuf,smb_rcls) = ERRHRD;
|
DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
|
||||||
SSVAL(outbuf,smb_err,ERRdiskfull);
|
(unsigned int)numtowrite ));
|
||||||
}
|
exit_server("secondary writebraw failed");
|
||||||
|
}
|
||||||
|
|
||||||
if ((lp_syncalways(SNUM(conn)) || write_through) &&
|
if (tcount > nwritten+numtowrite) {
|
||||||
lp_strict_sync(SNUM(conn)))
|
DEBUG(3,("Client overestimated the write %d %d %d\n",
|
||||||
sync_file(conn,fsp);
|
(int)tcount,(int)nwritten,(int)numtowrite));
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
|
if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
|
||||||
fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
|
DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
|
||||||
|
strerror(errno) ));
|
||||||
|
exit_server("secondary writebraw failed");
|
||||||
|
}
|
||||||
|
|
||||||
/* we won't return a status if write through is not selected - this
|
nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
|
||||||
follows what WfWg does */
|
|
||||||
END_PROFILE(SMBwritebraw);
|
|
||||||
if (!write_through && total_written==tcount) {
|
|
||||||
/*
|
|
||||||
* Fix for "rabbit pellet" mode, trigger an early TCP ack by
|
|
||||||
* sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
|
|
||||||
*/
|
|
||||||
if (!send_keepalive(smbd_server_fd()))
|
|
||||||
exit_server("reply_writebraw: send of keepalive failed");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(outsize);
|
if (nwritten < (ssize_t)numtowrite) {
|
||||||
|
CVAL(outbuf,smb_rcls) = ERRHRD;
|
||||||
|
SSVAL(outbuf,smb_err,ERRdiskfull);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nwritten > 0)
|
||||||
|
total_written += nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
|
||||||
|
sync_file(conn,fsp);
|
||||||
|
|
||||||
|
DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
|
||||||
|
fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
|
||||||
|
|
||||||
|
/* we won't return a status if write through is not selected - this follows what WfWg does */
|
||||||
|
END_PROFILE(SMBwritebraw);
|
||||||
|
if (!write_through && total_written==tcount) {
|
||||||
|
/*
|
||||||
|
* Fix for "rabbit pellet" mode, trigger an early TCP ack by
|
||||||
|
* sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
|
||||||
|
*/
|
||||||
|
if (!send_keepalive(smbd_server_fd()))
|
||||||
|
exit_server("reply_writebraw: send of keepalive failed");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(outsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -3709,82 +3711,80 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
copy a file as part of a reply_copy
|
Copy a file as part of a reply_copy.
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
|
static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
|
||||||
int count,BOOL target_is_directory, int *err_ret)
|
int count,BOOL target_is_directory, int *err_ret)
|
||||||
{
|
{
|
||||||
int Access,action;
|
int Access,action;
|
||||||
SMB_STRUCT_STAT src_sbuf, sbuf2;
|
SMB_STRUCT_STAT src_sbuf, sbuf2;
|
||||||
SMB_OFF_T ret=-1;
|
SMB_OFF_T ret=-1;
|
||||||
files_struct *fsp1,*fsp2;
|
files_struct *fsp1,*fsp2;
|
||||||
pstring dest;
|
pstring dest;
|
||||||
|
|
||||||
*err_ret = 0;
|
*err_ret = 0;
|
||||||
|
|
||||||
pstrcpy(dest,dest1);
|
pstrcpy(dest,dest1);
|
||||||
if (target_is_directory) {
|
if (target_is_directory) {
|
||||||
char *p = strrchr_m(src,'/');
|
char *p = strrchr_m(src,'/');
|
||||||
if (p)
|
if (p)
|
||||||
p++;
|
p++;
|
||||||
else
|
else
|
||||||
p = src;
|
p = src;
|
||||||
pstrcat(dest,"/");
|
pstrcat(dest,"/");
|
||||||
pstrcat(dest,p);
|
pstrcat(dest,p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs_file_exist(conn,src,&src_sbuf))
|
if (!vfs_file_exist(conn,src,&src_sbuf))
|
||||||
return(False);
|
return(False);
|
||||||
|
|
||||||
fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
|
fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
|
||||||
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
|
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
|
||||||
|
|
||||||
if (!fsp1) {
|
if (!fsp1)
|
||||||
return(False);
|
return(False);
|
||||||
}
|
|
||||||
|
|
||||||
if (!target_is_directory && count)
|
if (!target_is_directory && count)
|
||||||
ofun = FILE_EXISTS_OPEN;
|
ofun = FILE_EXISTS_OPEN;
|
||||||
|
|
||||||
vfs_stat(conn,dest,&sbuf2);
|
if (vfs_stat(conn,dest,&sbuf2) == -1)
|
||||||
fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
|
ZERO_STRUCTP(&sbuf2);
|
||||||
ofun,src_sbuf.st_mode,0,&Access,&action);
|
|
||||||
|
|
||||||
if (!fsp2) {
|
fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
|
||||||
close_file(fsp1,False);
|
ofun,src_sbuf.st_mode,0,&Access,&action);
|
||||||
return(False);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ofun&3) == 1) {
|
if (!fsp2) {
|
||||||
if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
|
close_file(fsp1,False);
|
||||||
DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
|
return(False);
|
||||||
strerror(errno) ));
|
}
|
||||||
/*
|
|
||||||
* Stop the copy from occurring.
|
if ((ofun&3) == 1) {
|
||||||
*/
|
if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
|
||||||
ret = -1;
|
DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
|
||||||
src_sbuf.st_size = 0;
|
/*
|
||||||
}
|
* Stop the copy from occurring.
|
||||||
}
|
*/
|
||||||
|
ret = -1;
|
||||||
|
src_sbuf.st_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (src_sbuf.st_size)
|
if (src_sbuf.st_size)
|
||||||
ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
|
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
|
||||||
|
|
||||||
close_file(fsp1,False);
|
close_file(fsp1,False);
|
||||||
/*
|
/*
|
||||||
* As we are opening fsp1 read-only we only expect
|
* As we are opening fsp1 read-only we only expect
|
||||||
* an error on close on fsp2 if we are out of space.
|
* an error on close on fsp2 if we are out of space.
|
||||||
* Thus we don't look at the error return from the
|
* Thus we don't look at the error return from the
|
||||||
* close of fsp1.
|
* close of fsp1.
|
||||||
*/
|
*/
|
||||||
*err_ret = close_file(fsp2,False);
|
*err_ret = close_file(fsp2,False);
|
||||||
|
|
||||||
return(ret == (SMB_OFF_T)src_sbuf.st_size);
|
return(ret == (SMB_OFF_T)src_sbuf.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
reply to a file copy.
|
reply to a file copy.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -190,7 +190,7 @@ int vfswrap_close(files_struct *fsp, int fd)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n)
|
ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
|
||||||
{
|
{
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t vfswrap_write(files_struct *fsp, int fd, const char *data, size_t n)
|
ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
|
||||||
{
|
{
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
|
|
||||||
|
@ -395,92 +395,28 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Transfer some data between two file_struct's.
|
Transfer some data (n bytes) between two file_struct's.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
|
static files_struct *in_fsp;
|
||||||
int out_fd, files_struct *out_fsp,
|
static files_struct *out_fsp;
|
||||||
SMB_OFF_T n, char *header, int headlen, int align)
|
|
||||||
|
static ssize_t read_fn(int fd, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
static char *buf=NULL;
|
return in_fsp->conn->vfs_ops.read(in_fsp, fd, buf, len);
|
||||||
static int size=0;
|
}
|
||||||
char *buf1,*abuf;
|
|
||||||
SMB_OFF_T total = 0;
|
|
||||||
|
|
||||||
DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
|
static ssize_t write_fn(int fd, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
return out_fsp->conn->vfs_ops.write(out_fsp, fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check we have at least somewhere to read from */
|
SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
|
||||||
|
{
|
||||||
|
in_fsp = in;
|
||||||
|
out_fsp = out;
|
||||||
|
|
||||||
SMB_ASSERT((in_fd != -1) || (in_fsp != NULL));
|
return transfer_file_internal(in_fsp->fd, out_fsp->fd, n, read_fn, write_fn);
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
size = lp_readsize();
|
|
||||||
size = MAX(size,1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!buf && size>0) {
|
|
||||||
buf = (char *)Realloc(buf,size+8);
|
|
||||||
if (!buf) size /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buf) {
|
|
||||||
DEBUG(0,("Can't allocate transfer buffer!\n"));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
abuf = buf + (align%8);
|
|
||||||
|
|
||||||
if (header)
|
|
||||||
n += headlen;
|
|
||||||
|
|
||||||
while (n > 0)
|
|
||||||
{
|
|
||||||
int s = (int)MIN(n,(SMB_OFF_T)size);
|
|
||||||
int ret,ret2=0;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
if (header && (headlen >= MIN(s,1024))) {
|
|
||||||
buf1 = header;
|
|
||||||
s = headlen;
|
|
||||||
ret = headlen;
|
|
||||||
headlen = 0;
|
|
||||||
header = NULL;
|
|
||||||
} else {
|
|
||||||
buf1 = abuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header && headlen > 0)
|
|
||||||
{
|
|
||||||
ret = MIN(headlen,size);
|
|
||||||
memcpy(buf1,header,ret);
|
|
||||||
headlen -= ret;
|
|
||||||
header += ret;
|
|
||||||
if (headlen <= 0) header = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s > ret) {
|
|
||||||
ret += in_fsp ?
|
|
||||||
in_fsp->conn->vfs_ops.read(in_fsp,in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret > 0) {
|
|
||||||
if (out_fsp)
|
|
||||||
ret2 = out_fsp->conn->vfs_ops.write(out_fsp,out_fsp->fd,buf1,ret);
|
|
||||||
else
|
|
||||||
ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret2 > 0) total += ret2;
|
|
||||||
/* if we can't write then dump excess data */
|
|
||||||
if (ret2 != ret)
|
|
||||||
vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0);
|
|
||||||
|
|
||||||
if (ret <= 0 || ret2 != ret)
|
|
||||||
return(total);
|
|
||||||
n -= ret;
|
|
||||||
}
|
|
||||||
return(total);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
Reference in New Issue
Block a user