r23538: Fix for wild-card rename: We can't return directly on error, we need to
[sfrench/samba-autobuild/.git] / source / smbd / reply.c
index 3d0f8a3ca84c7b514ce99a1ed7648ea8574236aa..41665e1676209cddc4dee47ccbe67e2c4cb22d77 100644 (file)
@@ -47,13 +47,12 @@ extern BOOL global_encrypted_passwords_negotiated;
 /* Custom version for processing POSIX paths. */
 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
 
-NTSTATUS check_path_syntax_internal(pstring destname,
-                                   const pstring srcname,
-                                   BOOL posix_path,
-                                   BOOL *p_last_component_contains_wcard)
+static NTSTATUS check_path_syntax_internal(char *path,
+                                          BOOL posix_path,
+                                          BOOL *p_last_component_contains_wcard)
 {
-       char *d = destname;
-       const char *s = srcname;
+       char *d = path;
+       const char *s = path;
        NTSTATUS ret = NT_STATUS_OK;
        BOOL start_of_name_component = True;
 
@@ -69,7 +68,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                        while (IS_PATH_SEP(*s,posix_path)) {
                                s++;
                        }
-                       if ((d != destname) && (*s != '\0')) {
+                       if ((d != path) && (*s != '\0')) {
                                /* We only care about non-leading or trailing '/' or '\\' */
                                *d++ = '/';
                        }
@@ -89,13 +88,13 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                                 */
 
                                /* If  we just added a '/' - delete it */
-                               if ((d > destname) && (*(d-1) == '/')) {
+                               if ((d > path) && (*(d-1) == '/')) {
                                        *(d-1) = '\0';
                                        d--;
                                }
 
                                /* Are we at the start ? Can't go back further if so. */
-                               if (d <= destname) {
+                               if (d <= path) {
                                        ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                                        break;
                                }
@@ -103,7 +102,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                                /* We know this is safe as '/' cannot be part of a mb sequence. */
                                /* NOTE - if this assumption is invalid we are not in good shape... */
                                /* Decrement d first as d points to the *next* char to write into. */
-                               for (d--; d > destname; d--) {
+                               for (d--; d > path; d--) {
                                        if (*d == '/')
                                                break;
                                }
@@ -177,10 +176,10 @@ NTSTATUS check_path_syntax_internal(pstring destname,
  No wildcards allowed.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(char *path)
 {
        BOOL ignore;
-       return check_path_syntax_internal(destname, srcname, False, &ignore);
+       return check_path_syntax_internal(path, False, &ignore);
 }
 
 /****************************************************************************
@@ -189,9 +188,9 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
  a wildcard.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
 {
-       return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
+       return check_path_syntax_internal(path, False, p_contains_wcard);
 }
 
 /****************************************************************************
@@ -200,10 +199,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
  set (a safe assumption).
 ****************************************************************************/
 
-NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax_posix(char *path)
 {
        BOOL ignore;
-       return check_path_syntax_internal(destname, srcname, True, &ignore);
+       return check_path_syntax_internal(path, True, &ignore);
 }
 
 /****************************************************************************
@@ -213,17 +212,15 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
                                NTSTATUS *err, BOOL *contains_wcard)
 {
-       pstring tmppath;
-       char *tmppath_ptr = tmppath;
        size_t ret;
 #ifdef DEVELOPER
        SMB_ASSERT(dest_len == sizeof(pstring));
 #endif
 
        if (src_len == 0) {
-               ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
+               ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
        } else {
-               ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+               ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
        }
 
        *contains_wcard = False;
@@ -233,15 +230,14 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
                 * For a DFS path the function parse_dfs_path()
                 * will do the path processing, just make a copy.
                 */
-               pstrcpy(dest, tmppath);
                *err = NT_STATUS_OK;
                return ret;
        }
 
        if (lp_posix_pathnames()) {
-               *err = check_path_syntax_posix(dest, tmppath);
+               *err = check_path_syntax_posix(dest);
        } else {
-               *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
+               *err = check_path_syntax_wcard(dest, contains_wcard);
        }
 
        return ret;
@@ -253,17 +249,15 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
 
 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
 {
-       pstring tmppath;
-       char *tmppath_ptr = tmppath;
        size_t ret;
 #ifdef DEVELOPER
        SMB_ASSERT(dest_len == sizeof(pstring));
 #endif
 
        if (src_len == 0) {
-               ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
+               ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
        } else {
-               ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+               ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
        }
 
        if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
@@ -271,15 +265,14 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
                 * For a DFS path the function parse_dfs_path()
                 * will do the path processing, just make a copy.
                 */
-               pstrcpy(dest, tmppath);
                *err = NT_STATUS_OK;
                return ret;
        }
 
        if (lp_posix_pathnames()) {
-               *err = check_path_syntax_posix(dest, tmppath);
+               *err = check_path_syntax_posix(dest);
        } else {
-               *err = check_path_syntax(dest, tmppath);
+               *err = check_path_syntax(dest);
        }
 
        return ret;
@@ -303,7 +296,7 @@ int reply_special(char *inbuf,char *outbuf)
        
        memset(outbuf,'\0',smb_size);
 
-       smb_setlen(outbuf,0);
+       smb_setlen(inbuf,outbuf,0);
        
        switch (msg_type) {
        case 0x81: /* session request */
@@ -421,7 +414,7 @@ int reply_tcon(connection_struct *conn,
                return ERROR_NT(nt_status);
        }
   
-       outsize = set_message(outbuf,2,0,True);
+       outsize = set_message(inbuf,outbuf,2,0,True);
        SSVAL(outbuf,smb_vwv0,max_recv);
        SSVAL(outbuf,smb_vwv1,conn->cnum);
        SSVAL(outbuf,smb_tid,conn->cnum);
@@ -523,11 +516,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                server_devicetype = "A:";
 
        if (Protocol < PROTOCOL_NT1) {
-               set_message(outbuf,2,0,True);
+               set_message(inbuf,outbuf,2,0,True);
                p = smb_buf(outbuf);
                p += srvstr_push(outbuf, p, server_devicetype, -1, 
                                 STR_TERMINATE|STR_ASCII);
-               set_message_end(outbuf,p);
+               set_message_end(inbuf,outbuf,p);
        } else {
                /* NT sets the fstype of IPC$ to the null string */
                const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
@@ -537,7 +530,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                        uint32 perm1 = 0;
                        uint32 perm2 = 0;
 
-                       set_message(outbuf,7,0,True);
+                       set_message(inbuf,outbuf,7,0,True);
 
                        if (IS_IPC(conn)) {
                                perm1 = FILE_ALL_ACCESS;
@@ -551,7 +544,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                        SIVAL(outbuf, smb_vwv3, perm1);
                        SIVAL(outbuf, smb_vwv5, perm2);
                } else {
-                       set_message(outbuf,3,0,True);
+                       set_message(inbuf,outbuf,3,0,True);
                }
 
                p = smb_buf(outbuf);
@@ -560,7 +553,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                p += srvstr_push(outbuf, p, fstype, -1, 
                                 STR_TERMINATE);
                
-               set_message_end(outbuf,p);
+               set_message_end(inbuf,outbuf,p);
                
                /* what does setting this bit do? It is set by NT4 and
                   may affect the ability to autorun mounted cdroms */
@@ -623,7 +616,7 @@ int reply_ioctl(connection_struct *conn,
                return(ERROR_DOS(ERRSRV,ERRnosupport));
        }
 
-       outsize = set_message(outbuf,8,replysize+1,True);
+       outsize = set_message(inbuf,outbuf,8,replysize+1,True);
        SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
        SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
        SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
@@ -719,7 +712,7 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
                return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
        }
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
 
        END_PROFILE(SMBcheckpath);
        return outsize;
@@ -815,7 +808,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                }
        }
   
-       outsize = set_message(outbuf,10,0,True);
+       outsize = set_message(inbuf,outbuf,10,0,True);
 
        SSVAL(outbuf,smb_vwv0,mode);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -908,7 +901,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return UNIXERROR(ERRDOS, ERRnoaccess);
        }
  
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
   
        DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
   
@@ -931,7 +924,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
                return(UNIXERROR(ERRHRD,ERRgeneral));
        }
   
-       outsize = set_message(outbuf,5,0,True);
+       outsize = set_message(inbuf,outbuf,5,0,True);
        
        if (Protocol <= PROTOCOL_LANMAN2) {
                double total_space, free_space;
@@ -1010,7 +1003,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                expect_close = True;
        }
   
-       outsize = set_message(outbuf,1,3,True);
+       outsize = set_message(inbuf,outbuf,1,3,True);
        maxentries = SVAL(inbuf,smb_vwv0); 
        dirtype = SVAL(inbuf,smb_vwv1);
        p = smb_buf(inbuf) + 1;
@@ -1182,7 +1175,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
          
        outsize += DIR_STRUCT_SIZE*numentries;
-       smb_setlen(outbuf,outsize - 4);
+       smb_setlen(inbuf,outbuf,outsize - 4);
   
        if ((! *directory) && dptr_path(dptr_num))
                slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -1217,7 +1210,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return reply_unknown(inbuf, outbuf);
        }
 
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        p = smb_buf(inbuf) + 1;
        p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(err)) {
@@ -1336,7 +1329,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
   
-       outsize = set_message(outbuf,7,0,True);
+       outsize = set_message(inbuf,outbuf,7,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
        SSVAL(outbuf,smb_vwv1,fattr);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -1512,9 +1505,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
-               set_message(outbuf,19,0,True);
+               set_message(inbuf,outbuf,19,0,True);
        } else {
-               set_message(outbuf,15,0,True);
+               set_message(inbuf,outbuf,15,0,True);
        }
        SSVAL(outbuf,smb_vwv2,fsp->fnum);
        SSVAL(outbuf,smb_vwv3,fattr);
@@ -1556,7 +1549,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
 
        invalidate_vuid(vuid);
 
-       set_message(outbuf,2,0,True);
+       set_message(inbuf,outbuf,2,0,True);
 
        DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
 
@@ -1651,7 +1644,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        ts[0] = get_atimespec(&sbuf); /* atime. */
        file_ntimes(conn, fname, ts);
 
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -1750,7 +1743,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
 
        /* the returned filename is relative to the directory */
@@ -1769,7 +1762,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 #endif
        namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
        p += namelen;
-       outsize = set_message_end(outbuf, p);
+       outsize = set_message_end(inbuf,outbuf, p);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
@@ -1791,17 +1784,16 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  Check if a user is allowed to rename a file.
 ********************************************************************/
 
-static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
+                          uint16 dirtype, SMB_STRUCT_STAT *pst)
 {
-       files_struct *fsp;
        uint32 fmode;
-       NTSTATUS status;
 
        if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
        }
 
-       fmode = dos_mode(conn,fname,pst);
+       fmode = dos_mode(conn, fsp->fsp_name, pst);
        if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
                return NT_STATUS_NO_SUCH_FILE;
        }
@@ -1810,28 +1802,19 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
                return NT_STATUS_OK;
        }
 
-       status = open_file_ntcreate(conn, fname, pst,
-                               DELETE_ACCESS,
-                               FILE_SHARE_READ|FILE_SHARE_WRITE,
-                               FILE_OPEN,
-                               0,
-                               FILE_ATTRIBUTE_NORMAL,
-                               0,
-                               NULL, &fsp);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       if (fsp->access_mask & DELETE_ACCESS) {
+               return NT_STATUS_OK;
        }
-       close_file(fsp,NORMAL_CLOSE);
-       return NT_STATUS_OK;
+
+       return NT_STATUS_ACCESS_DENIED;
 }
 
 /*******************************************************************
- Check if a user is allowed to delete a file.
-********************************************************************/
+ * unlink a file with all relevant access checks
+ *******************************************************************/
 
-static NTSTATUS can_delete(connection_struct *conn, char *fname,
-                          uint32 dirtype, BOOL can_defer)
+static NTSTATUS do_unlink(connection_struct *conn, char *fname,
+                         uint32 dirtype, BOOL can_defer)
 {
        SMB_STRUCT_STAT sbuf;
        uint32 fattr;
@@ -1839,7 +1822,7 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname,
        uint32 dirtype_orig = dirtype;
        NTSTATUS status;
 
-       DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
+       DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
 
        if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -1932,10 +1915,19 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname,
                                    can_defer ? 0 : INTERNAL_OPEN_ONLY,
                                    NULL, &fsp);
 
-       if (NT_STATUS_IS_OK(status)) {
-               close_file(fsp,NORMAL_CLOSE);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("open_file_ntcreate failed: %s\n",
+                          nt_errstr(status)));
+               return status;
        }
-       return status;
+
+       /* The set is across all open files on this dev/inode pair. */
+       if (!set_delete_on_close(fsp, True, &current_user.ut)) {
+               close_file(fsp, NORMAL_CLOSE);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return close_file(fsp,NORMAL_CLOSE);
 }
 
 /****************************************************************************
@@ -1994,17 +1986,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                        return status;
                }
 
-               status = can_delete(conn,directory,dirtype,can_defer);
+               status = do_unlink(conn,directory,dirtype,can_defer);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
 
-               if (SMB_VFS_UNLINK(conn,directory) == 0) {
-                       count++;
-                       notify_fname(conn, NOTIFY_ACTION_REMOVED,
-                                    FILE_NOTIFY_CHANGE_FILE_NAME,
-                                    directory);
-               }
+               count++;
        } else {
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
@@ -2063,19 +2050,14 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                                return status;
                        }
 
-                       status = can_delete(conn, fname, dirtype, can_defer);
+                       status = do_unlink(conn, fname, dirtype, can_defer);
                        if (!NT_STATUS_IS_OK(status)) {
                                continue;
                        }
-                       if (SMB_VFS_UNLINK(conn,fname) == 0) {
-                               count++;
-                               DEBUG(3,("unlink_internals: succesful unlink "
-                                        "[%s]\n",fname));
-                               notify_fname(conn, NOTIFY_ACTION_REMOVED,
-                                            FILE_NOTIFY_CHANGE_FILE_NAME,
-                                            fname);
-                       }
-                               
+
+                       count++;
+                       DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
+                                fname));
                }
                CloseDir(dir_hnd);
        }
@@ -2131,7 +2113,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
   
        END_PROFILE(SMBunlink);
        return outsize;
@@ -2149,39 +2131,42 @@ static void fail_readraw(void)
        exit_server_cleanly(errstr);
 }
 
-#if defined(WITH_SENDFILE)
 /****************************************************************************
  Fake (read/write) sendfile. Returns -1 on read or write fail.
 ****************************************************************************/
 
-static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
 {
-       ssize_t ret=0;
+       size_t tosend = nread;
 
-       /* Paranioa check... */
-       if (nread > bufsize) {
-               fail_readraw();
-       }
+       while (tosend > 0) {
+               ssize_t ret;
+               size_t cur_read;
 
-       if (nread > 0) {
-               ret = read_file(fsp,buf,startpos,nread);
+               if (tosend > bufsize) {
+                       cur_read = bufsize;
+               } else {
+                       cur_read = tosend;
+               }
+               ret = read_file(fsp,buf,startpos,cur_read);
                if (ret == -1) {
                        return -1;
                }
-       }
 
-       /* If we had a short read, fill with zeros. */
-       if (ret < nread) {
-               memset(buf, '\0', nread - ret);
-       }
+               /* If we had a short read, fill with zeros. */
+               if (ret < cur_read) {
+                       memset(buf, '\0', cur_read - ret);
+               }
 
-       if (write_data(smbd_server_fd(),buf,nread) != nread) {
-               return -1;
-       }       
+               if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
+                       return -1;
+               }
+               tosend -= cur_read;
+               startpos += cur_read;
+       }
 
        return (ssize_t)nread;
 }
-#endif
 
 /****************************************************************************
  Use sendfile in readbraw.
@@ -2238,12 +2223,12 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
                        exit_server_cleanly("send_file_readbraw sendfile failed");
                }
 
+               return;
        }
-
-  normal_readbraw:
-
 #endif
 
+normal_readbraw:
+
        if (nread > 0) {
                ret = read_file(fsp,outbuf+4,startpos,nread);
 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
@@ -2402,7 +2387,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        numtoread = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
   
-       outsize = set_message(outbuf,5,3,True);
+       outsize = set_message(inbuf,outbuf,5,3,True);
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
        data = smb_buf(outbuf) + 3;
        
@@ -2414,14 +2399,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
         * Note that the requested lock size is unaffected by max_recv.
         */
        
-       br_lck = do_lock(fsp,
+       br_lck = do_lock(smbd_messaging_context(),
+                       fsp,
                        (uint32)SVAL(inbuf,smb_pid), 
                        (SMB_BIG_UINT)numtoread,
                        (SMB_BIG_UINT)startpos,
                        WRITE_LOCK,
                        WINDOWS_LOCK,
                        False, /* Non-blocking lock. */
-                       &status);
+                       &status,
+                       NULL);
        TALLOC_FREE(br_lck);
 
        if (NT_STATUS_V(status)) {
@@ -2483,7 +2470,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        numtoread = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
 
-       outsize = set_message(outbuf,5,3,True);
+       outsize = set_message(inbuf,outbuf,5,3,True);
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
        /*
         * The requested read size cannot be greater than max_recv. JRA.
@@ -2523,6 +2510,27 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
        return(outsize);
 }
 
+/****************************************************************************
+ Setup readX header.
+****************************************************************************/
+
+static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
+{
+       int outsize;
+       char *data = smb_buf(outbuf);
+
+       SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
+       SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+       SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
+       SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+       SCVAL(outbuf,smb_vwv0,0xFF);
+       outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
+       /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
+       _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
+       return outsize;
+}
+
 /****************************************************************************
  Reply to a read and X - possibly using sendfile.
 ****************************************************************************/
@@ -2530,10 +2538,27 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
                files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
 {
+       SMB_STRUCT_STAT sbuf;
        int outsize = 0;
        ssize_t nread = -1;
        char *data = smb_buf(outbuf);
 
+       if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
+
+       if (startpos > sbuf.st_size) {
+               smb_maxcnt = 0;
+       }
+
+       if (smb_maxcnt > (sbuf.st_size - startpos)) {
+               smb_maxcnt = (sbuf.st_size - startpos);
+       }
+
+       if (smb_maxcnt == 0) {
+               goto normal_read;
+       }
+
 #if defined(WITH_SENDFILE)
        /*
         * We can only use sendfile on a non-chained packet 
@@ -2543,34 +2568,16 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
 
        if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
            lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
-               SMB_STRUCT_STAT sbuf;
                DATA_BLOB header;
 
-               if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
-                       return(UNIXERROR(ERRDOS,ERRnoaccess));
-
-               if (startpos > sbuf.st_size)
-                       goto normal_read;
-
-               if (smb_maxcnt > (sbuf.st_size - startpos))
-                       smb_maxcnt = (sbuf.st_size - startpos);
-
-               if (smb_maxcnt == 0)
-                       goto normal_read;
-
                /* 
                 * Set up the packet header before send. We
                 * assume here the sendfile will work (get the
                 * correct amount of data).
                 */
 
-               SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
-               SSVAL(outbuf,smb_vwv5,smb_maxcnt);
-               SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
-               SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
-               SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
-               SCVAL(outbuf,smb_vwv0,0xFF);
-               set_message(outbuf,12,smb_maxcnt,False);
+               setup_readX_header(inbuf,outbuf,smb_maxcnt);
+               set_message(inbuf,outbuf,12,smb_maxcnt,False);
                header.data = (uint8 *)outbuf;
                header.length = data - outbuf;
                header.free = NULL;
@@ -2615,28 +2622,40 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                return -1;
        }
 
-  normal_read:
-
 #endif
 
-       nread = read_file(fsp,data,startpos,smb_maxcnt);
-  
-       if (nread < 0) {
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
-       }
+normal_read:
 
-       outsize = set_message(outbuf,12,nread,False);
-       SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
-       SSVAL(outbuf,smb_vwv5,nread);
-       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
-       SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
-       SSVAL(smb_buf(outbuf),-2,nread);
-  
-       DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
-               fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+       if ((smb_maxcnt & 0xFF0000) > 0x10000) {
+               int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
+               /* Send out the header. */
+               if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
+                       DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server_cleanly("send_file_readX sendfile failed");
+               }
+               if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
+                                       len_outbuf - (data-outbuf))) == -1) {
+                       DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server_cleanly("send_file_readX: fake_sendfile failed");
+               }
+               return -1;
+       } else {
+               nread = read_file(fsp,data,startpos,smb_maxcnt);
 
-       /* Returning the number of bytes we want to send back - including header. */
-       return outsize;
+               if (nread < 0) {
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+               }
+
+               outsize = setup_readX_header(inbuf, outbuf,nread);
+
+               DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+                       fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+
+               /* Returning the number of bytes we want to send back - including header. */
+               return outsize;
+       }
 }
 
 /****************************************************************************
@@ -2649,6 +2668,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
        ssize_t nread = -1;
        size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+       BOOL big_readX = False;
 #if 0
        size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
 #endif
@@ -2666,17 +2686,25 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return(ERROR_DOS(ERRDOS,ERRbadaccess));
        }
 
-       set_message(outbuf,12,0,True);
+       set_message(inbuf,outbuf,12,0,True);
 
        if (global_client_caps & CAP_LARGE_READX) {
-               if (SVAL(inbuf,smb_vwv7) == 1) {
-                       smb_maxcnt |= (1<<16);
-               }
-               if (smb_maxcnt > BUFFER_SIZE) {
-                       DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
-                               (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
-                       END_PROFILE(SMBreadX);
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               size_t upper_size = SVAL(inbuf,smb_vwv7);
+               smb_maxcnt |= (upper_size<<16);
+               if (upper_size > 1) {
+                       /* Can't do this on a chained packet. */
+                       if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
+                               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+                       }
+                       /* We currently don't do this on signed or sealed data. */
+                       if (srv_is_signing_active() || srv_encryption_on()) {
+                               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+                       }
+                       /* Is there room in the reply for this data ? */
+                       if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
+                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       }
+                       big_readX = True;
                }
        }
 
@@ -2709,7 +2737,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_DOS(ERRDOS,ERRlock);
        }
 
-       if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+       if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
                END_PROFILE(SMBreadX);
                return -1;
        }
@@ -2739,6 +2767,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        BOOL write_through;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        int outsize = 0;
+       NTSTATUS status;
        START_PROFILE(SMBwritebraw);
 
        if (srv_is_signing_active()) {
@@ -2790,7 +2819,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        /* Return a message to the redirector to tell it to send more bytes */
        SCVAL(outbuf,smb_com,SMBwritebraw);
        SSVALS(outbuf,smb_vwv0,-1);
-       outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
        show_msg(outbuf);
        if (!send_smb(smbd_server_fd(),outbuf))
                exit_server_cleanly("reply_writebraw: send_smb failed.");
@@ -2804,7 +2833,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        numtowrite = smb_len(inbuf);
 
        /* Set up outbuf to return the correct return */
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        SCVAL(outbuf,smb_com,SMBwritec);
 
        if (numtowrite != 0) {
@@ -2843,7 +2872,13 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
  
        SSVAL(outbuf,smb_vwv0,total_written);
 
-       sync_file(conn, fsp, write_through);
+       status = sync_file(conn, fsp, write_through);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
+                       fsp->fsp_name, nt_errstr(status) ));
+               END_PROFILE(SMBwritebraw);
+               return ERROR_NT(status);
+       }
 
        DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
                fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
@@ -2908,7 +2943,13 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
                nwritten = write_file(fsp,data,startpos,numtowrite);
        }
   
-       sync_file(conn, fsp, False /* write through */);
+       status = sync_file(conn, fsp, False /* write through */);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBwriteunlock);
+               DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
+                       fsp->fsp_name, nt_errstr(status) ));
+               return ERROR_NT(status);
+       }
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwriteunlock);
@@ -2916,7 +2957,8 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        }
 
        if (numtowrite) {
-               status = do_unlock(fsp,
+               status = do_unlock(smbd_messaging_context(),
+                               fsp,
                                (uint32)SVAL(inbuf,smb_pid),
                                (SMB_BIG_UINT)numtowrite, 
                                (SMB_BIG_UINT)startpos,
@@ -2928,7 +2970,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
                }
        }
        
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        
        SSVAL(outbuf,smb_vwv0,nwritten);
        
@@ -2954,6 +2996,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        char *data;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        int outsize = 0;
+       NTSTATUS status;
        START_PROFILE(SMBwrite);
 
        /* If it's an IPC, pass off the pipe handler. */
@@ -2964,6 +3007,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
 
        CHECK_FSP(fsp,conn);
        if (!CHECK_WRITE(fsp)) {
+               END_PROFILE(SMBwrite);
                return(ERROR_DOS(ERRDOS,ERRbadaccess));
        }
 
@@ -2999,14 +3043,20 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        } else
                nwritten = write_file(fsp,data,startpos,numtowrite);
   
-       sync_file(conn, fsp, False);
+       status = sync_file(conn, fsp, False);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBwrite);
+               DEBUG(5,("reply_write: sync_file for %s returned %s\n",
+                       fsp->fsp_name, nt_errstr(status) ));
+               return ERROR_NT(status);
+       }
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwrite);
                return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
 
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
   
        SSVAL(outbuf,smb_vwv0,nwritten);
 
@@ -3036,6 +3086,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        unsigned int smblen = smb_len(inbuf);
        char *data;
        BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
+       NTSTATUS status;
        START_PROFILE(SMBwriteX);
 
        /* If it's an IPC, pass off the pipe handler. */
@@ -3049,7 +3100,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
                return(ERROR_DOS(ERRDOS,ERRbadaccess));
        }
 
-       set_message(outbuf,6,0,True);
+       set_message(inbuf,outbuf,6,0,True);
   
        /* Deal with possible LARGE_WRITEX */
        if (large_writeX) {
@@ -3126,7 +3177,13 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
                fsp->fnum, (int)numtowrite, (int)nwritten));
 
-       sync_file(conn, fsp, write_through);
+       status = sync_file(conn, fsp, write_through);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBwriteX);
+               DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
+                       fsp->fsp_name, nt_errstr(status) ));
+               return ERROR_NT(status);
+       }
 
        END_PROFILE(SMBwriteX);
        return chain_reply(inbuf,outbuf,length,bufsize);
@@ -3196,7 +3253,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
        fsp->fh->pos = res;
   
-       outsize = set_message(outbuf,2,0,True);
+       outsize = set_message(inbuf,outbuf,2,0,True);
        SIVAL(outbuf,smb_vwv0,res);
   
        DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
@@ -3212,7 +3269,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        uint16 fnum = SVAL(inbuf,smb_vwv0);
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBflush);
@@ -3223,7 +3280,13 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        if (!fsp) {
                file_sync_all(conn);
        } else {
-               sync_file(conn,fsp, True);
+               NTSTATUS status = sync_file(conn, fsp, True);
+               if (!NT_STATUS_IS_OK(status)) {
+                       END_PROFILE(SMBflush);
+                       DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
+                               fsp->fsp_name, nt_errstr(status) ));
+                       return ERROR_NT(status);
+               }
        }
        
        DEBUG(3,("flush\n"));
@@ -3244,7 +3307,7 @@ int reply_exit(connection_struct *conn,
 
        file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
 
        DEBUG(3,("exit\n"));
 
@@ -3264,7 +3327,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
        files_struct *fsp = NULL;
        START_PROFILE(SMBclose);
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
 
        /* If it's an IPC, pass off to the pipe handler. */
        if (IS_IPC(conn)) {
@@ -3384,7 +3447,7 @@ int reply_writeclose(connection_struct *conn,
                return ERROR_NT(close_status);
        }
  
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
   
        SSVAL(outbuf,smb_vwv0,nwritten);
        END_PROFILE(SMBwriteclose);
@@ -3401,7 +3464,7 @@ int reply_writeclose(connection_struct *conn,
 int reply_lock(connection_struct *conn,
               char *inbuf,char *outbuf, int length, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3419,14 +3482,16 @@ int reply_lock(connection_struct *conn,
        DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
                 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
 
-       br_lck = do_lock(fsp,
+       br_lck = do_lock(smbd_messaging_context(),
+                       fsp,
                        (uint32)SVAL(inbuf,smb_pid),
                        count,
                        offset,
                        WRITE_LOCK,
                        WINDOWS_LOCK,
                        False, /* Non-blocking lock. */
-                       &status);
+                       &status,
+                       NULL);
 
        TALLOC_FREE(br_lck);
 
@@ -3446,7 +3511,7 @@ int reply_lock(connection_struct *conn,
 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
                 int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3457,7 +3522,8 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
        count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
        offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
        
-       status = do_unlock(fsp,
+       status = do_unlock(smbd_messaging_context(),
+                       fsp,
                        (uint32)SVAL(inbuf,smb_pid),
                        count,
                        offset,
@@ -3486,7 +3552,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
 int reply_tdis(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        uint16 vuid;
        START_PROFILE(SMBtdis);
 
@@ -3517,7 +3583,7 @@ int reply_echo(connection_struct *conn,
        int smb_reverb = SVAL(inbuf,smb_vwv0);
        int seq_num;
        unsigned int data_len = smb_buflen(inbuf);
-       int outsize = set_message(outbuf,1,data_len,True);
+       int outsize = set_message(inbuf,outbuf,1,data_len,True);
        START_PROFILE(SMBecho);
 
        if (data_len > BUFFER_SIZE) {
@@ -3538,7 +3604,7 @@ int reply_echo(connection_struct *conn,
        for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
                SSVAL(outbuf,smb_vwv0,seq_num);
 
-               smb_setlen(outbuf,outsize - 4);
+               smb_setlen(inbuf,outbuf,outsize - 4);
 
                show_msg(outbuf);
                if (!send_smb(smbd_server_fd(),outbuf))
@@ -3579,7 +3645,7 @@ int reply_printopen(connection_struct *conn,
                return(ERROR_NT(status));
        }
 
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
   
        DEBUG(3,("openprint fd=%d fnum=%d\n",
@@ -3596,7 +3662,7 @@ int reply_printopen(connection_struct *conn,
 int reply_printclose(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        NTSTATUS status;
        START_PROFILE(SMBsplclose);
@@ -3629,7 +3695,7 @@ int reply_printclose(connection_struct *conn,
 int reply_printqueue(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,2,3,True);
+       int outsize = set_message(inbuf,outbuf,2,3,True);
        int max_count = SVAL(inbuf,smb_vwv0);
        int start_index = SVAL(inbuf,smb_vwv1);
        START_PROFILE(SMBsplretq);
@@ -3677,7 +3743,7 @@ int reply_printqueue(connection_struct *conn,
                }
 
                if (count > 0) {
-                       outsize = set_message(outbuf,2,28*count+3,False); 
+                       outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
                        SSVAL(outbuf,smb_vwv0,count);
                        SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
                        SCVAL(smb_buf(outbuf),0,1);
@@ -3700,7 +3766,7 @@ int reply_printqueue(connection_struct *conn,
 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
        int numtowrite;
-       int outsize = set_message(outbuf,0,0,False);
+       int outsize = set_message(inbuf,outbuf,0,0,False);
        char *data;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
@@ -3791,7 +3857,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
 
        DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
 
@@ -3867,7 +3933,23 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
        int ret;
        SMB_STRUCT_STAT st;
 
-       ret = SMB_VFS_RMDIR(conn,directory);
+       /* Might be a symlink. */
+       if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+               return map_nt_error_from_unix(errno);
+       }
+
+       if (S_ISLNK(st.st_mode)) {
+               /* Is what it points to a directory ? */
+               if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+                       return map_nt_error_from_unix(errno);
+               }
+               if (!(S_ISDIR(st.st_mode))) {
+                       return NT_STATUS_NOT_A_DIRECTORY;
+               }
+               ret = SMB_VFS_UNLINK(conn,directory);
+       } else {
+               ret = SMB_VFS_RMDIR(conn,directory);
+       }
        if (ret == 0) {
                notify_fname(conn, NOTIFY_ACTION_REMOVED,
                             FILE_NOTIFY_CHANGE_DIR_NAME,
@@ -4002,7 +4084,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
  
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
   
        DEBUG( 3, ( "rmdir %s\n", directory ) );
   
@@ -4100,13 +4182,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
  asynchronously.
 ****************************************************************************/
 
-static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
-                               SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
+static void rename_open_files(connection_struct *conn,
+                             struct share_mode_lock *lck,
+                             const char *newname)
 {
        files_struct *fsp;
        BOOL did_rename = False;
 
-       for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+       for(fsp = file_find_di_first(lck->id); fsp;
+           fsp = file_find_di_next(fsp)) {
                /* fsp_name is a relative path under the fsp. To change this for other
                   sharepaths we need to manipulate relative paths. */
                /* TODO - create the absolute path and manipulate the newname
@@ -4114,20 +4198,21 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l
                if (fsp->conn != conn) {
                        continue;
                }
-               DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
-                       fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
+               DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
+                         fsp->fnum, file_id_static_string(&fsp->file_id),
                        fsp->fsp_name, newname ));
                string_set(&fsp->fsp_name, newname);
                did_rename = True;
        }
 
        if (!did_rename) {
-               DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
-                       (unsigned int)dev, (double)inode, newname ));
+               DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
+                         file_id_static_string(&lck->id), newname ));
        }
 
        /* Send messages to all smbd's (not ourself) that the name has changed. */
-       rename_share_filename(lck, conn->connectpath, newname);
+       rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
+                             newname);
 }
 
 /****************************************************************************
@@ -4159,22 +4244,67 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest)
        return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
 }
 
+/*
+ * Do the notify calls from a rename
+ */
+
+static void notify_rename(connection_struct *conn, BOOL is_dir,
+                         const char *oldpath, const char *newpath)
+{
+       char *olddir, *newdir;
+       const char *oldname, *newname;
+       uint32 mask;
+
+       mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
+               : FILE_NOTIFY_CHANGE_FILE_NAME;
+
+       if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
+           || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
+               TALLOC_FREE(olddir);
+               return;
+       }
+
+       if (strcmp(olddir, newdir) == 0) {
+               notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
+               notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
+       }
+       else {
+               notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
+               notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
+       }
+       TALLOC_FREE(olddir);
+       TALLOC_FREE(newdir);
+
+       /* this is a strange one. w2k3 gives an additional event for
+          CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
+          files, but not directories */
+       if (!is_dir) {
+               notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+                            FILE_NOTIFY_CHANGE_ATTRIBUTES
+                            |FILE_NOTIFY_CHANGE_CREATION,
+                            newpath);
+       }
+}
+
 /****************************************************************************
  Rename an open file - given an fsp.
 ****************************************************************************/
 
 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
 {
-       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_STAT sbuf, sbuf1;
        pstring newname_last_component;
        NTSTATUS status = NT_STATUS_OK;
-       BOOL dest_exists;
        struct share_mode_lock *lck = NULL;
+       BOOL dst_exists;
 
        ZERO_STRUCT(sbuf);
 
        status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
+
+       /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
+
+       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
                return status;
        }
 
@@ -4234,18 +4364,37 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                return NT_STATUS_OK;
        }
 
-       dest_exists = vfs_object_exist(conn,newname,NULL);
+       /*
+        * Have vfs_object_exist also fill sbuf1
+        */
+       dst_exists = vfs_object_exist(conn, newname, &sbuf1);
 
-       if(!replace_if_exists && dest_exists) {
+       if(!replace_if_exists && dst_exists) {
                DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
                        fsp->fsp_name,newname));
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       status = can_rename(conn,newname,attrs,&sbuf);
+       if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
+               DEBUG(3, ("rename_internals_fsp: Target file open\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* Ensure we have a valid stat struct for the source. */
+       if (fsp->fh->fd != -1) {
+               if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       } else {
+               if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       }
+
+       status = can_rename(conn, fsp, attrs, &sbuf);
 
-       if (dest_exists && !NT_STATUS_IS_OK(status)) {
-               DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
                        nt_errstr(status), fsp->fsp_name,newname));
                if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
                        status = NT_STATUS_ACCESS_DENIED;
@@ -4256,12 +4405,45 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+       lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+
+       /*
+        * We have the file open ourselves, so not being able to get the
+        * corresponding share mode lock is a fatal error.
+        */
+
+       SMB_ASSERT(lck != NULL);
 
        if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
+               uint32 create_options = fsp->fh->private_options;
+
                DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
                        fsp->fsp_name,newname));
-               rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
+
+               rename_open_files(conn, lck, newname);
+
+               notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
+
+               /*
+                * A rename acts as a new file create w.r.t. allowing an initial delete
+                * on close, probably because in Windows there is a new handle to the
+                * new file. If initial delete on close was requested but not
+                * originally set, we need to set it here. This is probably not 100% correct,
+                * but will work for the CIFSFS client which in non-posix mode
+                * depends on these semantics. JRA.
+                */
+
+               set_allow_initial_delete_on_close(lck, fsp, True);
+
+               if (create_options & FILE_DELETE_ON_CLOSE) {
+                       status = can_set_delete_on_close(fsp, True, 0);
+
+                       if (NT_STATUS_IS_OK(status)) {
+                               /* Note that here we set the *inital* delete on close flag,
+                                * not the regular one. The magic gets handled in close. */
+                               fsp->initial_delete_on_close = True;
+                       }
+               }
                TALLOC_FREE(lck);
                return NT_STATUS_OK;    
        }
@@ -4280,48 +4462,6 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
        return status;
 }
 
-/*
- * Do the notify calls from a rename
- */
-
-static void notify_rename(connection_struct *conn, BOOL is_dir,
-                         const char *oldpath, const char *newpath)
-{
-       char *olddir, *newdir;
-       const char *oldname, *newname;
-       uint32 mask;
-
-       mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
-               : FILE_NOTIFY_CHANGE_FILE_NAME;
-
-       if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
-           || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
-               TALLOC_FREE(olddir);
-               return;
-       }
-
-       if (strcmp(olddir, newdir) == 0) {
-               notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
-               notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
-       }
-       else {
-               notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
-               notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
-       }
-       TALLOC_FREE(olddir);
-       TALLOC_FREE(newdir);
-
-       /* this is a strange one. w2k3 gives an additional event for
-          CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
-          files, but not directories */
-       if (!is_dir) {
-               notify_fname(conn, NOTIFY_ACTION_MODIFIED,
-                            FILE_NOTIFY_CHANGE_ATTRIBUTES
-                            |FILE_NOTIFY_CHANGE_CREATION,
-                            newpath);
-       }
-}
-
 /****************************************************************************
  The guts of the rename command, split out so it may be called by the NT SMB
  code. 
@@ -4343,7 +4483,6 @@ NTSTATUS rename_internals(connection_struct *conn,
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        SMB_STRUCT_STAT sbuf1, sbuf2;
-       struct share_mode_lock *lck = NULL;
        struct smb_Dir *dir_hnd = NULL;
        const char *dname;
        long offset = 0;
@@ -4398,6 +4537,8 @@ NTSTATUS rename_internals(connection_struct *conn,
        }
 
        if (!src_has_wild) {
+               files_struct *fsp;
+
                /*
                 * No wildcards - just process the one file.
                 */
@@ -4424,12 +4565,6 @@ NTSTATUS rename_internals(connection_struct *conn,
                          conn->short_case_preserve, directory, 
                          newname, last_component_dest, is_short_name));
 
-               /* Ensure the source name is valid for us to access. */
-               status = check_name(conn, directory);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-
                /* The dest name still may have wildcards. */
                if (dest_has_wild) {
                        if (!resolve_wildcards(directory,newname)) {
@@ -4439,135 +4574,34 @@ NTSTATUS rename_internals(connection_struct *conn,
                        }
                }
                                
-               /*
-                * Check for special case with case preserving and not
-                * case sensitive, if directory and newname are identical,
-                * and the old last component differs from the original
-                * last component only by case, then we should allow
-                * the rename (user is trying to change the case of the
-                * filename).
-                */
-               if((conn->case_sensitive == False) && 
-                  (((conn->case_preserve == True) && 
-                    (is_short_name == False)) || 
-                   ((conn->short_case_preserve == True) && 
-                    (is_short_name == True))) &&
-                  strcsequal(directory, newname)) {
-                       pstring modified_last_component;
-
-                       /*
-                        * Get the last component of the modified name.
-                        * Note that we guarantee that newname contains a '/'
-                        * character above.
-                        */
-                       p = strrchr_m(newname,'/');
-                       pstrcpy(modified_last_component,p+1);
-                       
-                       if(strcsequal(modified_last_component, 
-                                     last_component_dest) == False) {
-                               /*
-                                * Replace the modified last component with
-                                * the original.
-                                */
-                               pstrcpy(p+1, last_component_dest);
-                       }
-               }
-       
-               /* Ensure the dest name is valid for us to access. */
-               status = check_name(conn, newname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-
-               /*
-                * The source object must exist.
-                */
-
-               if (!vfs_object_exist(conn, directory, &sbuf1)) {
-                       DEBUG(3, ("rename_internals: source doesn't exist "
-                                 "doing rename %s -> %s\n",
-                               directory,newname));
-
-                       if (errno == ENOTDIR || errno == EISDIR
-                           || errno == ENOENT) {
-                               /*
-                                * Must return different errors depending on
-                                * whether the parent directory existed or
-                                * not.
-                                */
-
-                               p = strrchr_m(directory, '/');
-                               if (!p)
-                                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                               *p = '\0';
-                               if (vfs_object_exist(conn, directory, NULL))
-                                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       }
-                       status = map_nt_error_from_unix(errno);
-                       DEBUG(3, ("rename_internals: Error %s rename %s -> "
-                                 "%s\n", nt_errstr(status), directory,
-                                 newname));
-
-                       return status;
-               }
-
-               status = can_rename(conn,directory,attrs,&sbuf1);
+               ZERO_STRUCT(sbuf1);
+               SMB_VFS_STAT(conn, directory, &sbuf1);
+
+               status = S_ISDIR(sbuf1.st_mode) ?
+                       open_directory(conn, directory, &sbuf1,
+                                      DELETE_ACCESS,
+                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                      FILE_OPEN, 0, 0, NULL,
+                                      &fsp)
+                       : open_file_ntcreate(conn, directory, &sbuf1,
+                                            DELETE_ACCESS,
+                                            FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                            FILE_OPEN, 0, 0, 0, NULL,
+                                            &fsp);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(3,("rename_internals: Error %s rename %s -> "
-                                "%s\n", nt_errstr(status), directory,
-                                newname));
+                       DEBUG(3, ("Could not open rename source %s: %s\n",
+                                 directory, nt_errstr(status)));
                        return status;
                }
 
-               /*
-                * If the src and dest names are identical - including case,
-                * don't do the rename, just return success.
-                */
-
-               if (strcsequal(directory, newname)) {
-                       rename_open_files(conn, NULL, sbuf1.st_dev,
-                                         sbuf1.st_ino, newname);
-                       DEBUG(3, ("rename_internals: identical names in "
-                                 "rename %s - returning success\n",
-                                 directory));
-                       return NT_STATUS_OK;
-               }
-
-               if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
-                       DEBUG(3,("rename_internals: dest exists doing "
-                                "rename %s -> %s\n", directory, newname));
-                       return NT_STATUS_OBJECT_NAME_COLLISION;
-               }
-
-               if (rename_path_prefix_equal(directory, newname)) {
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+               status = rename_internals_fsp(conn, fsp, newname, attrs,
+                                             replace_if_exists);
 
-               lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
-                                         NULL, NULL);
+               close_file(fsp, NORMAL_CLOSE);
 
-               if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
-                       DEBUG(3,("rename_internals: succeeded doing rename "
-                                "on %s -> %s\n", directory, newname));
-                       rename_open_files(conn, lck, sbuf1.st_dev,
-                                         sbuf1.st_ino, newname);
-                       TALLOC_FREE(lck);
-                       notify_rename(conn, S_ISDIR(sbuf1.st_mode),
-                                     directory, newname);
-                       return NT_STATUS_OK;    
-               }
-
-               TALLOC_FREE(lck);
-               if (errno == ENOTDIR || errno == EISDIR) {
-                       status = NT_STATUS_OBJECT_NAME_COLLISION;
-               } else {
-                       status = map_nt_error_from_unix(errno);
-               }
-               
-               DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
-                       nt_errstr(status), directory,newname));
+               DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
+                         nt_errstr(status), directory,newname));
 
                return status;
        }
@@ -4596,6 +4630,7 @@ NTSTATUS rename_internals(connection_struct *conn,
         */
                        
        while ((dname = ReadDirName(dir_hnd, &offset))) {
+               files_struct *fsp;
                pstring fname;
                BOOL sysdir_entry = False;
 
@@ -4625,26 +4660,8 @@ NTSTATUS rename_internals(connection_struct *conn,
                        break;
                }
 
-               status = NT_STATUS_ACCESS_DENIED;
                slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
 
-               /* Ensure the source name is valid for us to access. */
-               status = check_name(conn, fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-
-               if (!vfs_object_exist(conn, fname, &sbuf1)) {
-                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                       DEBUG(6, ("rename %s failed. Error %s\n",
-                                 fname, nt_errstr(status)));
-                       continue;
-               }
-               status = can_rename(conn,fname,attrs,&sbuf1);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(6, ("rename %s refused\n", fname));
-                       continue;
-               }
                pstrcpy(destname,newname);
                        
                if (!resolve_wildcards(fname,destname)) {
@@ -4653,43 +4670,42 @@ NTSTATUS rename_internals(connection_struct *conn,
                        continue;
                }
                                
-               /* Ensure the dest name is valid for us to access. */
-               status = check_name(conn, destname);
+               ZERO_STRUCT(sbuf1);
+               SMB_VFS_STAT(conn, fname, &sbuf1);
+
+               status = S_ISDIR(sbuf1.st_mode) ?
+                       open_directory(conn, fname, &sbuf1,
+                                      DELETE_ACCESS,
+                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                      FILE_OPEN, 0, 0, NULL,
+                                      &fsp)
+                       : open_file_ntcreate(conn, fname, &sbuf1,
+                                            DELETE_ACCESS,
+                                            FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                            FILE_OPEN, 0, 0, 0, NULL,
+                                            &fsp);
+
                if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+                       DEBUG(3,("rename_internals: open_file_ntcreate "
+                                "returned %s rename %s -> %s\n",
+                                nt_errstr(status), directory, newname));
+                       break;
                }
 
-               if (strcsequal(fname,destname)) {
-                       rename_open_files(conn, NULL, sbuf1.st_dev,
-                                         sbuf1.st_ino, newname);
-                       DEBUG(3,("rename_internals: identical names "
-                                "in wildcard rename %s - success\n",
-                                fname));
-                       count++;
-                       status = NT_STATUS_OK;
-                       continue;
-               }
+               status = rename_internals_fsp(conn, fsp, destname, attrs,
+                                             replace_if_exists);
 
-               if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
-                       DEBUG(6,("file_exist %s\n", destname));
-                       status = NT_STATUS_OBJECT_NAME_COLLISION;
-                       continue;
-               }
-                               
-               if (rename_path_prefix_equal(fname, destname)) {
-                       return NT_STATUS_SHARING_VIOLATION;
+               close_file(fsp, NORMAL_CLOSE);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("rename_internals_fsp returned %s for "
+                                 "rename %s -> %s\n", nt_errstr(status),
+                                 directory, newname));
+                       break;
                }
 
-               lck = get_share_mode_lock(NULL, sbuf1.st_dev,
-                                         sbuf1.st_ino, NULL, NULL);
+               count++;
 
-               if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                       rename_open_files(conn, lck, sbuf1.st_dev,
-                                         sbuf1.st_ino, newname);
-                       count++;
-                       status = NT_STATUS_OK;
-               }
-               TALLOC_FREE(lck);
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n",fname,destname));
        }
@@ -4763,7 +4779,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
   
        END_PROFILE(SMBmv);
        return(outsize);
@@ -5110,7 +5126,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_DOS(ERRDOS,error);
        }
   
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,count);
 
        END_PROFILE(SMBcopy);
@@ -5159,7 +5175,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                set_conn_connectpath(conn,newdir);
        }
   
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
        SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
   
        DEBUG(3,("setdir %s\n", newdir));
@@ -5436,7 +5452,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                          "pid %u, file %s\n", (double)offset, (double)count,
                          (unsigned int)lock_pid, fsp->fsp_name ));
                
-               status = do_unlock(fsp,
+               status = do_unlock(smbd_messaging_context(),
+                               fsp,
                                lock_pid,
                                count,
                                offset,
@@ -5508,15 +5525,18 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                        BOOL blocking_lock = lock_timeout ? True : False;
                        BOOL defer_lock = False;
                        struct byte_range_lock *br_lck;
+                       uint32 block_smbpid;
 
-                       br_lck = do_lock(fsp,
+                       br_lck = do_lock(smbd_messaging_context(),
+                                       fsp,
                                        lock_pid,
                                        count,
                                        offset, 
                                        lock_type,
                                        WINDOWS_LOCK,
                                        blocking_lock,
-                                       &status);
+                                       &status,
+                                       &block_smbpid);
 
                        if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
                                /* Windows internal resolution for blocking locks seems
@@ -5553,7 +5573,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                                        lock_type,
                                                        WINDOWS_LOCK,
                                                        offset,
-                                                       count)) {
+                                                       count,
+                                                       block_smbpid)) {
                                        TALLOC_FREE(br_lck);
                                        END_PROFILE(SMBlockingX);
                                        return -1;
@@ -5595,7 +5616,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                return ERROR_DOS(ERRDOS,ERRnoaccess);
                        }
                        
-                       do_unlock(fsp,
+                       do_unlock(smbd_messaging_context(),
+                               fsp,
                                lock_pid,
                                count,
                                offset,
@@ -5605,7 +5627,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(status);
        }
 
-       set_message(outbuf,2,0,True);
+       set_message(inbuf,outbuf,2,0,True);
        
        DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
                  fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
@@ -5641,7 +5663,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
                return ERROR_DOS(ERRSRV,ERRuseSTD);
        }
 
-       outsize = set_message(outbuf,8,0,True);
+       outsize = set_message(inbuf,outbuf,8,0,True);
 
        CHECK_FSP(fsp,conn);
        if (!CHECK_READ(fsp,inbuf)) {
@@ -5677,7 +5699,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
                if (nread < (ssize_t)N)
                        tcount = total_read + nread;
 
-               set_message(outbuf,8,nread+pad,False);
+               set_message(inbuf,outbuf,8,nread+pad,False);
                SIVAL(outbuf,smb_vwv0,startpos);
                SSVAL(outbuf,smb_vwv2,tcount);
                SSVAL(outbuf,smb_vwv6,nread);
@@ -5706,7 +5728,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBsetattrE);
 
-       outsize = set_message(outbuf,0,0,False);
+       outsize = set_message(inbuf,outbuf,0,0,False);
 
        if(!fsp || (fsp->conn != conn)) {
                END_PROFILE(SMBsetattrE);
@@ -5773,6 +5795,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
        int smb_doff;
        char *data;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       NTSTATUS status;
        START_PROFILE(SMBwriteBmpx);
 
        CHECK_FSP(fsp,conn);
@@ -5802,7 +5825,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
 
        nwritten = write_file(fsp,data,startpos,numtowrite);
 
-       sync_file(conn, fsp, write_through);
+       status = sync_file(conn, fsp, write_through);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBwriteBmpx);
+               DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
+                       fsp->fsp_name, nt_errstr(status) ));
+               return ERROR_NT(status);
+       }
   
        if(nwritten < (ssize_t)numtowrite) {
                END_PROFILE(SMBwriteBmpx);
@@ -5837,7 +5866,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
                SMBwritebmpx */
        SCVAL(outbuf,smb_com,SMBwriteBmpx);
   
-       outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(inbuf,outbuf,1,0,True);
   
        SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
   
@@ -5846,13 +5875,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
 
        if (write_through && tcount==nwritten) {
                /* We need to send both a primary and a secondary response */
-               smb_setlen(outbuf,outsize - 4);
+               smb_setlen(inbuf,outbuf,outsize - 4);
                show_msg(outbuf);
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server_cleanly("reply_writebmpx: send_smb failed.");
 
                /* Now the secondary */
-               outsize = set_message(outbuf,1,0,True);
+               outsize = set_message(inbuf,outbuf,1,0,True);
                SCVAL(outbuf,smb_com,SMBwritec);
                SSVAL(outbuf,smb_vwv0,nwritten);
        }
@@ -5878,6 +5907,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        write_bmpx_struct *wbms;
        BOOL send_response = False; 
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       NTSTATUS status;
        START_PROFILE(SMBwriteBs);
 
        CHECK_FSP(fsp,conn);
@@ -5914,9 +5944,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
 
        nwritten = write_file(fsp,data,startpos,numtowrite);
 
-       sync_file(conn, fsp, write_through);
+       status = sync_file(conn, fsp, write_through);
   
-       if (nwritten < (ssize_t)numtowrite) {
+       if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
                if(write_through) {
                        /* We are returning an error - we can delete the aux struct */
                        if (wbms)
@@ -5938,7 +5968,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        wbms->wr_total_written += nwritten;
        if(wbms->wr_total_written >= tcount) {
                if (write_through) {
-                       outsize = set_message(outbuf,1,0,True);
+                       outsize = set_message(inbuf,outbuf,1,0,True);
                        SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
                        send_response = True;
                }
@@ -5968,7 +5998,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBgetattrE);
 
-       outsize = set_message(outbuf,11,0,True);
+       outsize = set_message(inbuf,outbuf,11,0,True);
 
        if(!fsp || (fsp->conn != conn)) {
                END_PROFILE(SMBgetattrE);