diff options
-rw-r--r-- | source3/include/vfs.h | 4 | ||||
-rw-r--r-- | source3/lib/util.c | 105 | ||||
-rw-r--r-- | source3/smbd/close.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 534 | ||||
-rw-r--r-- | source3/smbd/vfs-wrap.c | 4 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 96 |
6 files changed, 327 insertions, 418 deletions
diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 5b1d804e4d..5a8451fb14 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -68,8 +68,8 @@ struct vfs_ops { int (*open)(struct connection_struct *conn, const char *fname, int flags, mode_t mode); int (*close)(struct files_struct *fsp, int fd); - ssize_t (*read)(struct files_struct *fsp, int fd, char *data, size_t n); - ssize_t (*write)(struct files_struct *fsp, int fd, const 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 void *data, size_t n); 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 (*fsync)(struct files_struct *fsp, int fd); diff --git a/source3/lib/util.c b/source3/lib/util.c index 1a2f8fd84a..9b92e412d0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -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) -{ - static char *buf=NULL; - static int size=0; - char *buf1,*abuf; - SMB_OFF_T total = 0; - - DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); - - if (size == 0) { - size = lp_readsize(); - size = MAX(size,1024); - } - - while (!buf && size>0) { - buf = (char *)malloc(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; +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[16384]; + size_t total = 0; + ssize_t read_ret; + size_t write_total = 0; + ssize_t write_ret; - ret = 0; + while (total < n) { + size_t num_to_read_thistime = MIN((n - total), sizeof(buf)); - if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; - } else { - buf1 = abuf; - } + read_ret = (*read_fn)(infd, buf + total, num_to_read_thistime); + if (read_ret == -1) { + DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (read_ret == 0) + break; - if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } + write_total = 0; + + 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 (s > ret) - ret += read(infd,buf1+ret,s-ret); + total += (size_t)read_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); + return (ssize_t)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 diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1a98a8bca5..f790778676 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -78,7 +78,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) return; } - transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0); + transfer_file(tmp_fd,outfd,st.st_size); close(tmp_fd); close(outfd); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 73cfd5ac85..2af1f62356 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1880,157 +1880,147 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size 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) { - size_t maxcount,mincount; - size_t nread = 0; - SMB_OFF_T startpos; - char *header = outbuf; - ssize_t ret=0; - files_struct *fsp; - START_PROFILE(SMBreadbraw); + size_t maxcount,mincount; + size_t nread = 0; + SMB_OFF_T startpos; + char *header = outbuf; + ssize_t ret=0; + files_struct *fsp; + START_PROFILE(SMBreadbraw); - /* - * Special check if an oplock break has been issued - * and the readraw request croses on the wire, we must - * return a zero length response here. - */ + /* + * Special check if an oplock break has been issued + * and the readraw request croses on the wire, we must + * return a zero length response here. + */ - if(global_oplock_break) - { - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - DEBUG(5,("readbraw - oplock break finished\n")); - END_PROFILE(SMBreadbraw); - return -1; - } + if(global_oplock_break) { + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + DEBUG(5,("readbraw - oplock break finished\n")); + END_PROFILE(SMBreadbraw); + return -1; + } - fsp = file_fsp(inbuf,smb_vwv0); - - if (!FNUM_OK(fsp,conn) || !fsp->can_read) { - /* - * 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))); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } + fsp = file_fsp(inbuf,smb_vwv0); - CHECK_FSP(fsp,conn); + if (!FNUM_OK(fsp,conn) || !fsp->can_read) { + /* + * 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))); + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } - flush_write_cache(fsp, READRAW_FLUSH); + CHECK_FSP(fsp,conn); - startpos = IVAL(inbuf,smb_vwv1); - if(CVAL(inbuf,smb_wct) == 10) { - /* - * This is a large offset (64 bit) read. - */ + flush_write_cache(fsp, READRAW_FLUSH); + + startpos = IVAL(inbuf,smb_vwv1); + if(CVAL(inbuf,smb_wct) == 10) { + /* + * This is a large offset (64 bit) read. + */ #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 */ - /* - * 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) { - DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ + if(IVAL(inbuf,smb_vwv8) != 0) { + DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } #endif /* LARGE_SMB_OFF_T */ - if(startpos < 0) { - DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", - (double)startpos )); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } - } - maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); - mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); + if(startpos < 0) { + DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } + } + maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); + mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); - /* ensure we don't overrun the packet size */ - maxcount = MIN(65535,maxcount); - maxcount = MAX(mincount,maxcount); + /* ensure we don't overrun the packet size */ + maxcount = MIN(65535,maxcount); + maxcount = MAX(mincount,maxcount); - 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 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; - } + 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 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 (startpos >= size) + nread = 0; + else + nread = MIN(maxcount,(size - startpos)); + } - if (nread < mincount) - nread = 0; + if (nread < mincount) + nread = 0; - DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", - fsp->fnum, (double)startpos, - (int)maxcount, (int)mincount, (int)nread ) ); + DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, + (int)maxcount, (int)mincount, (int)nread ) ); -#if UNSAFE_READRAW - { - BOOL seek_fail = False; - int predict=0; - _smb_setlen(header,nread); - - if ((nread-predict) > 0) { - if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) { - DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); - ret = 0; - seek_fail = True; - } - } - - if(!seek_fail) - ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL, - (SMB_OFF_T)(nread-predict),header,4+predict, - 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; + if (nread > 0) { + 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 */ + _smb_setlen(header,ret); + if (write_data(smbd_server_fd(),header,4+ret) != 4+ret) + fail_readraw(); - DEBUG(5,("readbraw finished\n")); - END_PROFILE(SMBreadbraw); - return -1; + DEBUG(5,("readbraw finished\n")); + END_PROFILE(SMBreadbraw); + return -1; } - /**************************************************************************** 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) { - ssize_t nwritten=0; - ssize_t total_written=0; - size_t numtowrite=0; - size_t tcount; - SMB_OFF_T startpos; - char *data=NULL; - BOOL write_through; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - int outsize = 0; - START_PROFILE(SMBwritebraw); + ssize_t nwritten=0; + ssize_t total_written=0; + size_t numtowrite=0; + size_t tcount; + SMB_OFF_T startpos; + char *data=NULL; + BOOL write_through; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; + START_PROFILE(SMBwritebraw); - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); - tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - - /* We have to deal with slightly different formats depending - 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); - } + tcount = IVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv3); + write_through = BITSETW(inbuf+smb_vwv7,0); - /* force the error type */ - CVAL(inbuf,smb_com) = SMBwritec; - CVAL(outbuf,smb_com) = SMBwritec; + /* We have to deal with slightly different formats depending + on whether we are using the core+ or lanman1.0 protocol */ - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { - END_PROFILE(SMBwritebraw); - return ERROR_DOS(ERRDOS,ERRlock); - } + 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); + } - if (numtowrite>0) - nwritten = write_file(fsp,data,startpos,numtowrite); + /* force the error type */ + CVAL(inbuf,smb_com) = SMBwritec; + CVAL(outbuf,smb_com) = SMBwritec; + + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + 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", - fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); + 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)); - if (nwritten < numtowrite) { - END_PROFILE(SMBwritebraw); - return(UNIXERROR(ERRHRD,ERRdiskfull)); - } + if (nwritten < numtowrite) { + END_PROFILE(SMBwritebraw); + return(UNIXERROR(ERRHRD,ERRdiskfull)); + } - total_written = nwritten; + total_written = nwritten; - /* Return a message to the redirector to tell it - to send more bytes */ - CVAL(outbuf,smb_com) = SMBwritebraw; - SSVALS(outbuf,smb_vwv0,-1); - outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebraw: send_smb failed.\n"); + /* Return a message to the redirector to tell it to send more bytes */ + CVAL(outbuf,smb_com) = SMBwritebraw; + SSVALS(outbuf,smb_vwv0,-1); + outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_writebraw: send_smb failed.\n"); - /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { - exit_server("secondary writebraw failed"); - } + /* Now read the raw data into the buffer and write it */ + if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { + exit_server("secondary writebraw failed"); + } - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - numtowrite = smb_len(inbuf); + /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ + numtowrite = smb_len(inbuf); - if (tcount > nwritten+numtowrite) { - DEBUG(3,("Client overestimated the write %d %d %d\n", - (int)tcount,(int)nwritten,(int)numtowrite)); - } + /* 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); - nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp, - (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 (numtowrite != 0) { - if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } + if (numtowrite > BUFFER_SIZE) { + DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n", + (unsigned int)numtowrite )); + exit_server("secondary writebraw failed"); + } - if ((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - sync_file(conn,fsp); + if (tcount > nwritten+numtowrite) { + DEBUG(3,("Client overestimated the write %d %d %d\n", + (int)tcount,(int)nwritten,(int)numtowrite)); + } - DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", - fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); + if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) { + 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 - 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); - } + nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); - 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, int count,BOOL target_is_directory, int *err_ret) { - int Access,action; - SMB_STRUCT_STAT src_sbuf, sbuf2; - SMB_OFF_T ret=-1; - files_struct *fsp1,*fsp2; - pstring dest; + int Access,action; + SMB_STRUCT_STAT src_sbuf, sbuf2; + SMB_OFF_T ret=-1; + files_struct *fsp1,*fsp2; + pstring dest; - *err_ret = 0; + *err_ret = 0; - pstrcpy(dest,dest1); - if (target_is_directory) { - char *p = strrchr_m(src,'/'); - if (p) - p++; - else - p = src; - pstrcat(dest,"/"); - pstrcat(dest,p); - } + pstrcpy(dest,dest1); + if (target_is_directory) { + char *p = strrchr_m(src,'/'); + if (p) + p++; + else + p = src; + pstrcat(dest,"/"); + pstrcat(dest,p); + } - if (!vfs_file_exist(conn,src,&src_sbuf)) - return(False); + if (!vfs_file_exist(conn,src,&src_sbuf)) + return(False); - 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); + 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); - if (!fsp1) { - return(False); - } + if (!fsp1) + return(False); - if (!target_is_directory && count) - ofun = FILE_EXISTS_OPEN; + if (!target_is_directory && count) + ofun = FILE_EXISTS_OPEN; - vfs_stat(conn,dest,&sbuf2); - fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,src_sbuf.st_mode,0,&Access,&action); + if (vfs_stat(conn,dest,&sbuf2) == -1) + ZERO_STRUCTP(&sbuf2); - if (!fsp2) { - close_file(fsp1,False); - return(False); - } + fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun,src_sbuf.st_mode,0,&Access,&action); - if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { - DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", - strerror(errno) )); - /* - * Stop the copy from occurring. - */ - ret = -1; - src_sbuf.st_size = 0; - } - } + if (!fsp2) { + close_file(fsp1,False); + return(False); + } + + if ((ofun&3) == 1) { + if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { + DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); + /* + * Stop the copy from occurring. + */ + ret = -1; + src_sbuf.st_size = 0; + } + } - if (src_sbuf.st_size) - ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0); + if (src_sbuf.st_size) + ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); - close_file(fsp1,False); - /* - * As we are opening fsp1 read-only we only expect - * an error on close on fsp2 if we are out of space. - * Thus we don't look at the error return from the - * close of fsp1. - */ - *err_ret = close_file(fsp2,False); + close_file(fsp1,False); + /* + * As we are opening fsp1 read-only we only expect + * an error on close on fsp2 if we are out of space. + * Thus we don't look at the error return from the + * close of fsp1. + */ + *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. ****************************************************************************/ diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 2b465dbe15..11ba30f909 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -190,7 +190,7 @@ int vfswrap_close(files_struct *fsp, int fd) 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; @@ -207,7 +207,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) 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; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f5870a3119..fce13bf13d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -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, - int out_fd, files_struct *out_fsp, - SMB_OFF_T n, char *header, int headlen, int align) -{ - static char *buf=NULL; - 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)); - - /* Check we have at least somewhere to read from */ - - SMB_ASSERT((in_fd != -1) || (in_fsp != NULL)); - - 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; - } +static files_struct *in_fsp; +static files_struct *out_fsp; - 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); - } +static ssize_t read_fn(int fd, void *buf, size_t len) +{ + return in_fsp->conn->vfs_ops.read(in_fsp, fd, buf, len); +} - 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; - } +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); +} - 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); +SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) +{ + in_fsp = in; + out_fsp = out; - if (ret <= 0 || ret2 != ret) - return(total); - n -= ret; - } - return(total); + return transfer_file_internal(in_fsp->fd, out_fsp->fd, n, read_fn, write_fn); } /******************************************************************* |