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,
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
/* 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;
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++ = '/';
}
*/
/* 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;
}
/* 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;
}
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);
}
/****************************************************************************
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);
}
/****************************************************************************
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;
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;
*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) {
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
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));
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);
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);
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);
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);
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);
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);
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,
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()) {
}
/* 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);
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,
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);
}
/* 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,
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);
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,
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;
}
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;
/* 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)) {
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;
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;
}
return status;
}
- status = do_unlink(conn, fname, dirtype, can_defer);
+ status = do_unlink(conn, req, fname, dirtype);
if (!NT_STATUS_IS_OK(status)) {
continue;
}
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);
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. */
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);
}
BOOL write_through;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
int outsize = 0;
+ NTSTATUS status;
START_PROFILE(SMBwritebraw);
if (srv_is_signing_active()) {
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));
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);
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. */
CHECK_FSP(fsp,conn);
if (!CHECK_WRITE(fsp)) {
+ END_PROFILE(SMBwrite);
return(ERROR_DOS(ERRDOS,ERRbadaccess));
}
} 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);
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. */
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);
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"));
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);
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);
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;
}
}
}
- 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",
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn,
+NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
pstring name,
pstring newname,
uint32 attrs,
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;
}
if (!src_has_wild) {
+ files_struct *fsp;
+
/*
* No wildcards - just process the one file.
*/
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)) {
}
}
- /*
- * 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;
}
*/
while ((dname = ReadDirName(dir_hnd, &offset))) {
+ files_struct *fsp;
pstring fname;
BOOL sysdir_entry = False;
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)) {
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));
}
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);
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))) {
}
}
- 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,
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,
*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);
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);
int smb_doff;
char *data;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ NTSTATUS status;
START_PROFILE(SMBwriteBmpx);
CHECK_FSP(fsp,conn);
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);
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);
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)