Merge of transfer file code from 2.2, fix for readbraw.
authorJeremy Allison <jra@samba.org>
Tue, 4 Sep 2001 19:10:30 +0000 (19:10 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 4 Sep 2001 19:10:30 +0000 (19:10 +0000)
Jeremy.

source/include/vfs.h
source/lib/util.c
source/smbd/close.c
source/smbd/reply.c
source/smbd/vfs-wrap.c
source/smbd/vfs.c

index 5b1d804e4da2730f52c0fd96f161fe46ab4f65f6..5a8451fb1489db3c89c1f1d9823bd47169fc5f56 100644 (file)
@@ -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);
index 1a2f8fd84a845e164271c13a5c9f89e8edc58d1a..9b92e412d00a7109a6c653063f24c3ae270bc97a 100644 (file)
@@ -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
index 1a98a8bca509b647303f50ea8af1b6ece72625d5..f790778676c0e93cc6e95ddbe34d68cc4edebee4 100644 (file)
@@ -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);
   }
index 73cfd5ac85ed59d7945f328ea405590cfb39f22e..2af1f62356fc56204d8d8380024a32feded4e2d2 100644 (file)
@@ -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.
   ****************************************************************************/
index 2b465dbe15087cf5434734b533eb60466302b14d..11ba30f909824b482aabfc2b2e85540e37827d61 100644 (file)
@@ -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;
 
index f5870a311903273324ebfd69dcc7ed43dfcb288a..fce13bf13d96c863c493b39f380bea0cf5f85ef8 100644 (file)
@@ -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);
 }
 
 /*******************************************************************