r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[abartlet/samba.git/.git] / source3 / smbd / reply.c
index 205374cff74d957d9a00fcbbb3ca309fa1e1c7ee..9a2dc19fa10bec89163739bf246015acc6fbf883 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 /*
    This file handles most of the reply_ calls that the server
@@ -47,13 +46,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 +67,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 +87,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 +101,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 +175,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 +187,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,48 +198,48 @@ 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);
 }
 
 /****************************************************************************
  Pull a string and check the path allowing a wilcard - provide for error return.
 ****************************************************************************/
 
-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)
+size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, 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, smb_flags2, dest, src,
+                                     dest_len, flags);
        } else {
-               ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+               ret = srvstr_pull(inbuf, smb_flags2, dest, src,
+                                 dest_len, src_len, flags);
        }
 
        *contains_wcard = False;
 
-       if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+       if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
                /* 
                 * 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;
@@ -251,35 +249,36 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
+size_t srvstr_get_path(char *inbuf, uint16 smb_flags2, 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, smb_flags2, dest, src,
+                                     dest_len, flags);
        } else {
-               ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+               ret = srvstr_pull(inbuf, smb_flags2, dest, src,
+                                 dest_len, src_len, flags);
        }
 
-       if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+       if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
                /* 
                 * 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;
@@ -398,10 +397,13 @@ int reply_tcon(connection_struct *conn,
        *service_buf = *password = *dev = 0;
 
        p = smb_buf(inbuf)+1;
-       p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
-       pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
+       p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p,
+                            sizeof(service_buf), STR_TERMINATE) + 1;
+       pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p,
+                               sizeof(password), STR_TERMINATE) + 1;
        p += pwlen;
-       p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
+       p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev),
+                            STR_TERMINATE) + 1;
 
        p = strrchr_m(service_buf,'\\');
        if (p) {
@@ -485,7 +487,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                p = smb_buf(inbuf) + passlen + 1;
        }
 
-       p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
+       p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p,
+                            sizeof(path), STR_TERMINATE);
 
        /*
         * the service name can be either: \\server\share
@@ -502,7 +505,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        else
                fstrcpy(service,path);
                
-       p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
+       p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p,
+                        sizeof(client_devicetype), 6, STR_ASCII);
 
        DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
 
@@ -679,7 +683,8 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
 
        START_PROFILE(SMBcheckpath);
 
-       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1,
+                       sizeof(name), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcheckpath);
                status = map_checkpath_error(inbuf, status);
@@ -766,7 +771,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBgetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
+                            sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBgetatr);
                return ERROR_NT(status);
@@ -852,7 +858,8 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBsetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+       p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
+                            sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsetatr);
                return ERROR_NT(status);
@@ -1014,7 +1021,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        maxentries = SVAL(inbuf,smb_vwv0); 
        dirtype = SVAL(inbuf,smb_vwv1);
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
+                                  sizeof(path), 0, STR_TERMINATE, &nt_status,
+                                  &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(nt_status)) {
                END_PROFILE(SMBsearch);
                return ERROR_NT(nt_status);
@@ -1219,7 +1228,9 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 
        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);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
+                                  sizeof(path), 0, STR_TERMINATE, &err,
+                                  &path_contains_wcard);
        if (!NT_STATUS_IS_OK(err)) {
                END_PROFILE(SMBfclose);
                return ERROR_NT(err);
@@ -1270,11 +1281,16 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        uint32 create_disposition;
        uint32 create_options = 0;
        NTSTATUS status;
+       struct smb_request req;
+
        START_PROFILE(SMBopen);
+
+       init_smb_request(&req, (uint8 *)inbuf);
  
        deny_mode = SVAL(inbuf,smb_vwv0);
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
+                       sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopen);
                return ERROR_NT(status);
@@ -1307,7 +1323,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
        }
 
-       status = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn, &req, fname, &sbuf,
                        access_mask,
                        share_mode,
                        create_disposition,
@@ -1390,9 +1406,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        uint32 share_mode;
        uint32 create_disposition;
        uint32 create_options = 0;
+       struct smb_request req;
 
        START_PROFILE(SMBopenX);
 
+       init_smb_request(&req, (uint8 *)inbuf);
+
        /* If it's an IPC, pass off the pipe handler. */
        if (IS_IPC(conn)) {
                if (lp_nt_pipe_support()) {
@@ -1405,7 +1424,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        /* XXXX we need to handle passed times, sattr and flags */
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf),
+                       sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                return ERROR_NT(status);
@@ -1441,7 +1461,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
        }
 
-       status = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn, &req, fname, &sbuf,
                        access_mask,
                        share_mode,
                        create_disposition,
@@ -1583,14 +1603,18 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
        uint32 create_disposition;
        uint32 create_options = 0;
+       struct smb_request req;
 
        START_PROFILE(SMBcreate);
+
+       init_smb_request(&req, (uint8 *)inbuf);
  
        com = SVAL(inbuf,smb_com);
 
        ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
+                       sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
                return ERROR_NT(status);
@@ -1630,7 +1654,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        }
 
        /* Open file using ntcreate. */
-       status = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn, &req, fname, &sbuf,
                                access_mask,
                                share_mode,
                                create_disposition,
@@ -1685,10 +1709,14 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        char *p, *s;
        NTSTATUS status;
        unsigned int namelen;
+       struct smb_request req;
 
        START_PROFILE(SMBctemp);
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+       init_smb_request(&req, (uint8 *)inbuf);
+
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
+                       sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                return ERROR_NT(status);
@@ -1729,7 +1757,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        SMB_VFS_STAT(conn,fname,&sbuf);
 
        /* We should fail if file does not exist. */
-       status = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn, &req, fname, &sbuf,
                                FILE_GENERIC_READ | FILE_GENERIC_WRITE,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
@@ -1791,17 +1819,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, BOOL self_open)
+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,31 +1837,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,
-                               /* If we're checking our fsp don't deny for delete. */
-                               self_open ?
-                                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
-                                       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;
 }
 
 /*******************************************************************
  * unlink a file with all relevant access checks
  *******************************************************************/
 
-static NTSTATUS do_unlink(connection_struct *conn, char *fname,
-                         uint32 dirtype, BOOL can_defer)
+static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
+                         char *fname, uint32 dirtype)
 {
        SMB_STRUCT_STAT sbuf;
        uint32 fattr;
@@ -1926,13 +1941,13 @@ static NTSTATUS do_unlink(connection_struct *conn, char *fname,
        /* On open checks the open itself will check the share mode, so
           don't do it here as we'll get it wrong. */
 
-       status = open_file_ntcreate(conn, fname, &sbuf,
+       status = open_file_ntcreate(conn, req, fname, &sbuf,
                                    DELETE_ACCESS,
                                    FILE_SHARE_NONE,
                                    FILE_OPEN,
                                    0,
                                    FILE_ATTRIBUTE_NORMAL,
-                                   can_defer ? 0 : INTERNAL_OPEN_ONLY,
+                                   req != NULL ? 0 : INTERNAL_OPEN_ONLY,
                                    NULL, &fsp);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -1955,8 +1970,8 @@ static NTSTATUS do_unlink(connection_struct *conn, char *fname,
  code.
 ****************************************************************************/
 
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
-                         char *name, BOOL has_wild, BOOL can_defer)
+NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
+                         uint32 dirtype, char *name, BOOL has_wild)
 {
        pstring directory;
        pstring mask;
@@ -2006,7 +2021,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                        return status;
                }
 
-               status = do_unlink(conn,directory,dirtype,can_defer);
+               status = do_unlink(conn, req, directory, dirtype);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -2070,7 +2085,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                                return status;
                        }
 
-                       status = do_unlink(conn, fname, dirtype, can_defer);
+                       status = do_unlink(conn, req, fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
                                continue;
                        }
@@ -2101,12 +2116,17 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        uint32 dirtype;
        NTSTATUS status;
        BOOL path_contains_wcard = False;
+       struct smb_request req;
 
        START_PROFILE(SMBunlink);
 
+       init_smb_request(&req, (uint8 *)inbuf);
+
        dirtype = SVAL(inbuf,smb_vwv0);
        
-       srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
+       srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
+                             smb_buf(inbuf) + 1, sizeof(name), 0,
+                             STR_TERMINATE, &status, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBunlink);
                return ERROR_NT(status);
@@ -2123,8 +2143,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        
        DEBUG(3,("reply_unlink : %s\n",name));
        
-       status = unlink_internals(conn, dirtype, name, path_contains_wcard,
-                                 True);
+       status = unlink_internals(conn, &req, dirtype, name,
+                                 path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
@@ -2569,9 +2589,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
 
        if (startpos > sbuf.st_size) {
                smb_maxcnt = 0;
-       }
-
-       if (smb_maxcnt > (sbuf.st_size - startpos)) {
+       } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
                smb_maxcnt = (sbuf.st_size - startpos);
        }
 
@@ -2787,6 +2805,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()) {
@@ -2891,7 +2910,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));
@@ -2956,7 +2981,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);
@@ -3003,6 +3034,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. */
@@ -3013,6 +3045,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));
        }
 
@@ -3048,7 +3081,13 @@ 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);
@@ -3085,6 +3124,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. */
@@ -3175,7 +3215,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);
@@ -3272,7 +3318,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"));
@@ -3795,7 +3847,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        START_PROFILE(SMBmkdir);
  
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
+                       smb_buf(inbuf) + 1, sizeof(directory), 0,
+                       STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmkdir);
                return ERROR_NT(status);
@@ -4036,7 +4090,9 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        NTSTATUS status;
        START_PROFILE(SMBrmdir);
 
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
+                       smb_buf(inbuf) + 1, sizeof(directory), 0,
+                       STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBrmdir);
                return ERROR_NT(status);
@@ -4361,7 +4417,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       if (file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
+       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;
        }
@@ -4377,7 +4433,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                }
        }
 
-       status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
+       status = can_rename(conn, fsp, attrs, &sbuf);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
@@ -4453,7 +4509,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
  code. 
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn,
+NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                                pstring name,
                                pstring newname,
                                uint32 attrs,
@@ -4469,7 +4525,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;
@@ -4524,6 +4579,8 @@ NTSTATUS rename_internals(connection_struct *conn,
        }
 
        if (!src_has_wild) {
+               files_struct *fsp;
+
                /*
                 * No wildcards - just process the one file.
                 */
@@ -4550,12 +4607,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)) {
@@ -4565,109 +4616,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, and it may not have a
-                * conflicting share mode.
-                */
-               status = can_rename(conn,directory,attrs,&sbuf1,False);
+               ZERO_STRUCT(sbuf1);
+               SMB_VFS_STAT(conn, directory, &sbuf1);
+
+               status = S_ISDIR(sbuf1.st_mode) ?
+                       open_directory(conn, req, directory, &sbuf1,
+                                      DELETE_ACCESS,
+                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                      FILE_OPEN, 0, 0, NULL,
+                                      &fsp)
+                       : open_file_ntcreate(conn, req, 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)) {
-                       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, file_id_sbuf(&sbuf1),
-                                         NULL, NULL);
-
-               if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
-                       DEBUG(3,("rename_internals: succeeded doing rename "
-                                "on %s -> %s\n", directory, newname));
-                       if (lck != NULL) {
-                               /*
-                                * Only in this case there are open files at
-                                * all.
-                                */
-                               rename_open_files(conn, lck, newname);
-                       }
-                       TALLOC_FREE(lck);
-                       notify_rename(conn, S_ISDIR(sbuf1.st_mode),
-                                     directory, newname);
-                       return NT_STATUS_OK;    
-               }
+               close_file(fsp, NORMAL_CLOSE);
 
-               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;
        }
@@ -4696,6 +4672,7 @@ NTSTATUS rename_internals(connection_struct *conn,
         */
                        
        while ((dname = ReadDirName(dir_hnd, &offset))) {
+               files_struct *fsp;
                pstring fname;
                BOOL sysdir_entry = False;
 
@@ -4725,30 +4702,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;
-               }
-
-               /*
-                * can_rename does an open_file_ntcreate which needs a valid
-                * stat in case the file exists
-                */
-
-               ZERO_STRUCT(sbuf1);
-               SMB_VFS_STAT(conn, fname, &sbuf1);
-
-               status = can_rename(conn,fname,attrs,&sbuf1,False);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(6, ("rename %s refused: %s\n", fname,
-                                 nt_errstr(status)));
-                       continue;
-               }
                pstrcpy(destname,newname);
                        
                if (!resolve_wildcards(fname,destname)) {
@@ -4757,46 +4712,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, req, fname, &sbuf1,
+                                      DELETE_ACCESS,
+                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                      FILE_OPEN, 0, 0, NULL,
+                                      &fsp)
+                       : open_file_ntcreate(conn, req, 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)) {
-                       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, file_id_sbuf(&sbuf1), NULL,
-                                         NULL);
+               count++;
 
-               if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                       if (lck != NULL) {
-                               /*
-                                * Only in this case there are open files at
-                                * all.
-                                */
-                               rename_open_files(conn, lck, newname);
-                       }
-                       count++;
-                       status = NT_STATUS_OK;
-               }
-               TALLOC_FREE(lck);
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n",fname,destname));
        }
@@ -4824,17 +4775,24 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        NTSTATUS status;
        BOOL src_has_wcard = False;
        BOOL dest_has_wcard = False;
+       struct smb_request req;
 
        START_PROFILE(SMBmv);
 
+       init_smb_request(&req, (uint8 *)inbuf);
+
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
+                                  sizeof(name), 0, STR_TERMINATE, &status,
+                                  &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        p++;
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
+                                  sizeof(newname), 0, STR_TERMINATE, &status,
+                                  &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
@@ -4860,7 +4818,8 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
        
-       status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
+       status = rename_internals(conn, &req, name, newname, attrs, False,
+                                 src_has_wcard, dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4924,7 +4883,7 @@ NTSTATUS copy_file(connection_struct *conn,
                }
        }
 
-       status = open_file_ntcreate(conn,src,&src_sbuf,
+       status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
                        FILE_GENERIC_READ,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        FILE_OPEN,
@@ -4942,7 +4901,7 @@ NTSTATUS copy_file(connection_struct *conn,
                ZERO_STRUCTP(&sbuf2);
        }
 
-       status = open_file_ntcreate(conn,dest,&sbuf2,
+       status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
                        FILE_GENERIC_WRITE,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        new_create_disposition,
@@ -5022,12 +4981,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        *directory = *mask = 0;
 
        p = smb_buf(inbuf);
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
+                                  sizeof(name), 0, STR_TERMINATE, &status,
+                                  &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
+       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
+                                  sizeof(newname), 0, STR_TERMINATE, &status,
+                                  &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -5243,7 +5206,9 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
-       srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
+       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
+                       smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
+                       &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(pathworks_setdir);
                return ERROR_NT(status);
@@ -5886,6 +5851,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);
@@ -5915,7 +5881,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);
@@ -5991,6 +5963,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);
@@ -6027,9 +6000,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)