X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Freply.c;h=9a2dc19fa10bec89163739bf246015acc6fbf883;hb=5e54558c6dea67b56bbfaba5698f3a434d3dffb6;hp=3a80d9eaa6e865e9c09364000ba0566a3c50d73b;hpb=7d48db6a622af587d2f3fa2541b77fa1179ca042;p=abartlet%2Fsamba.git%2F.git diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3a80d9eaa6e..9a2dc19fa10 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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 . */ /* 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; } /******************************************************************* - 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, struct smb_request *req, + char *fname, uint32 dirtype) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1842,7 +1857,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; @@ -1926,19 +1941,28 @@ static NTSTATUS can_delete(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)) { - 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, ¤t_user.ut)) { + close_file(fsp, NORMAL_CLOSE); + return NT_STATUS_ACCESS_DENIED; + } + + return close_file(fsp,NORMAL_CLOSE); } /**************************************************************************** @@ -1946,8 +1970,8 @@ static NTSTATUS can_delete(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; @@ -1997,17 +2021,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = can_delete(conn,directory,dirtype,can_defer); + status = do_unlink(conn, req, directory, dirtype); 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; @@ -2066,19 +2085,14 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = can_delete(conn, fname, dirtype, can_defer); + status = do_unlink(conn, req, fname, dirtype); 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); } @@ -2102,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); @@ -2124,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. */ @@ -2570,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); } @@ -2788,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()) { @@ -2892,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)); @@ -2957,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); @@ -3004,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. */ @@ -3014,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)); } @@ -3049,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); @@ -3086,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. */ @@ -3176,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); @@ -3273,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")); @@ -3796,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); @@ -4037,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); @@ -4169,13 +4224,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2) asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - struct file_id id, 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(id); 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 @@ -4192,7 +4249,7 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l if (!did_rename) { DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", - file_id_static_string(&id), newname )); + file_id_static_string(&lck->id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4229,17 +4286,59 @@ 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); @@ -4307,14 +4406,22 @@ 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; } + 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) { @@ -4326,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", @@ -4342,13 +4449,22 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin 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->file_id, 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 @@ -4388,54 +4504,12 @@ 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. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, +NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, pstring name, pstring newname, uint32 attrs, @@ -4451,12 +4525,10 @@ 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; pstring destname; - struct file_id id; *directory = *mask = 0; @@ -4507,6 +4579,8 @@ NTSTATUS rename_internals(connection_struct *conn, } if (!src_has_wild) { + files_struct *fsp; + /* * No wildcards - just process the one file. */ @@ -4533,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)) { @@ -4548,134 +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; + 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); - /* - * 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)) { + DEBUG(3, ("Could not open rename source %s: %s\n", + directory, nt_errstr(status))); return status; } - /* - * The source object must exist. - */ + status = rename_internals_fsp(conn, fsp, newname, attrs, + replace_if_exists); - if (!vfs_object_exist(conn, directory, &sbuf1)) { - DEBUG(3, ("rename_internals: source doesn't exist " - "doing rename %s -> %s\n", - directory,newname)); + close_file(fsp, NORMAL_CLOSE); - 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,False); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3,("rename_internals: Error %s rename %s -> " - "%s\n", nt_errstr(status), directory, - newname)); - return status; - } - - /* - * If the src and dest names are identical - including case, - * don't do the rename, just return success. - */ - - id = file_id_sbuf(&sbuf1); - - if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, id, 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; - } - - lck = get_share_mode_lock(NULL, id, NULL, NULL); - - 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, id, 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; } @@ -4704,6 +4672,7 @@ NTSTATUS rename_internals(connection_struct *conn, */ while ((dname = ReadDirName(dir_hnd, &offset))) { + files_struct *fsp; pstring fname; BOOL sysdir_entry = False; @@ -4733,26 +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; - } - - 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,False); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(6, ("rename %s refused\n", fname)); - continue; - } pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) { @@ -4761,42 +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; } - id = file_id_sbuf(&sbuf1); + status = rename_internals_fsp(conn, fsp, destname, attrs, + replace_if_exists); - if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, id, newname); - DEBUG(3,("rename_internals: identical names " - "in wildcard rename %s - success\n", - fname)); - count++; - status = NT_STATUS_OK; - continue; - } + close_file(fsp, NORMAL_CLOSE); - 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; + 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, id, NULL, NULL); + count++; - if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, id, 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)