Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Andrew Bartlett 2001
- Copyright (C) Jeremy Allison 1992-2004.
+ Copyright (C) Jeremy Allison 1992-2007.
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
extern struct current_user current_user;
extern BOOL global_encrypted_passwords_negotiated;
-/****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption). '\\' *may* be the second byte in a multibyte char
- set.
-****************************************************************************/
-
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
-{
- char *d = destname;
- const char *s = srcname;
- NTSTATUS ret = NT_STATUS_OK;
- BOOL start_of_name_component = True;
- unsigned int num_bad_components = 0;
-
- while (*s) {
- if (IS_DIRECTORY_SEP(*s)) {
- /*
- * Safe to assume is not the second part of a mb char as this is handled below.
- */
- /* Eat multiple '/' or '\\' */
- while (IS_DIRECTORY_SEP(*s)) {
- s++;
- }
- if ((d != destname) && (*s != '\0')) {
- /* We only care about non-leading or trailing '/' or '\\' */
- *d++ = '/';
- }
-
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
- /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
-
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
-
- /* If we just added a '/' - delete it */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- d--;
- }
-
- /* Are we at the start ? Can't go back further if so. */
- if (d <= destname) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
- }
- /* Go back one level... */
- /* 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--) {
- if (*d == '/')
- break;
- }
- s += 2; /* Else go past the .. */
- /* We're still at the start of a name component, just the previous one. */
-
- if (num_bad_components) {
- /* Hmmm. Should we only decrement the bad_components if
- we're removing a bad component ? Need to check this. JRA. */
- num_bad_components--;
- }
-
- continue;
-
- } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- /* Component of pathname can't be "." only. */
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- num_bad_components++;
- *d++ = *s++;
- continue;
- }
- }
-
- if (!(*s & 0x80)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- switch (*s) {
- case '*':
- case '?':
- case '<':
- case '>':
- case '"':
- return NT_STATUS_OBJECT_NAME_INVALID;
- default:
- *d++ = *s++;
- break;
- }
- } else {
- size_t siz;
- /* Get the size of the next MB character. */
- next_codepoint(s,&siz);
- switch(siz) {
- case 5:
- *d++ = *s++;
- /*fall through*/
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- if (start_of_name_component && num_bad_components) {
- num_bad_components++;
- }
- start_of_name_component = False;
- }
-
- if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
- if (num_bad_components > 1) {
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- }
-
- *d = '\0';
- return ret;
-}
-
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
path or anything including wildcards.
set.
****************************************************************************/
-NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+/* 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)
{
char *d = destname;
const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
BOOL start_of_name_component = True;
- unsigned int num_bad_components = 0;
- *p_contains_wcard = False;
+ *p_last_component_contains_wcard = False;
while (*s) {
- if (IS_DIRECTORY_SEP(*s)) {
+ if (IS_PATH_SEP(*s,posix_path)) {
/*
- * Safe to assume is not the second part of a mb char as this is handled below.
+ * Safe to assume is not the second part of a mb char
+ * as this is handled below.
*/
/* Eat multiple '/' or '\\' */
- while (IS_DIRECTORY_SEP(*s)) {
+ while (IS_PATH_SEP(*s,posix_path)) {
s++;
}
if ((d != destname) && (*s != '\0')) {
}
start_of_name_component = True;
+ /* New component. */
+ *p_last_component_contains_wcard = False;
continue;
}
if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+ if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
/* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
/*
}
s += 2; /* Else go past the .. */
/* We're still at the start of a name component, just the previous one. */
-
- if (num_bad_components) {
- /* Hmmm. Should we only decrement the bad_components if
- we're removing a bad component ? Need to check this. JRA. */
- num_bad_components--;
- }
-
continue;
- } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- /* Component of pathname can't be "." only. */
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- num_bad_components++;
- *d++ = *s++;
- continue;
+ } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
+ if (posix_path) {
+ /* Eat the '.' */
+ s++;
+ continue;
+ }
}
+
}
if (!(*s & 0x80)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- if (!*p_contains_wcard) {
+ if (!posix_path) {
+ if (*s <= 0x1f) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
switch (*s) {
case '*':
case '?':
case '<':
case '>':
case '"':
- *p_contains_wcard = True;
+ *p_last_component_contains_wcard = True;
break;
default:
break;
*d++ = *s++;
break;
default:
- DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
+ DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
*d = '\0';
return NT_STATUS_INVALID_PARAMETER;
}
}
- if (start_of_name_component && num_bad_components) {
- num_bad_components++;
- }
start_of_name_component = False;
}
- if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
- /* For some strange reason being called from findfirst changes
- the num_components number to cause the error return to change. JRA. */
- if (num_bad_components > 2) {
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- }
-
*d = '\0';
return ret;
}
/****************************************************************************
- Check the path for a POSIX client.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption).
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ No wildcards allowed.
****************************************************************************/
-NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
- char *d = destname;
- const char *s = srcname;
- NTSTATUS ret = NT_STATUS_OK;
- BOOL start_of_name_component = True;
-
- while (*s) {
- if (*s == '/') {
- /*
- * Safe to assume is not the second part of a mb char as this is handled below.
- */
- /* Eat multiple '/' or '\\' */
- while (*s == '/') {
- s++;
- }
- if ((d != destname) && (*s != '\0')) {
- /* We only care about non-leading or trailing '/' */
- *d++ = '/';
- }
-
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
- /* Uh oh - "/../" or "/..\0" ! */
-
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
-
- /* If we just added a '/' - delete it */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- d--;
- }
+ BOOL ignore;
+ return check_path_syntax_internal(destname, srcname, False, &ignore);
+}
- /* Are we at the start ? Can't go back further if so. */
- if (d <= destname) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
- }
- /* Go back one level... */
- /* 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--) {
- if (*d == '/')
- break;
- }
- s += 2; /* Else go past the .. */
- continue;
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ Wildcards allowed - p_contains_wcard returns true if the last component contained
+ a wildcard.
+****************************************************************************/
- } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
- /* Eat the '.' */
- s++;
- continue;
- }
- }
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+{
+ return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
+}
- if (!(*s & 0x80)) {
- *d++ = *s++;
- } else {
- size_t siz;
- /* Get the size of the next MB character. */
- next_codepoint(s,&siz);
- switch(siz) {
- case 5:
- *d++ = *s++;
- /*fall through*/
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- start_of_name_component = False;
- }
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
- *d = '\0';
- return ret;
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+{
+ BOOL ignore;
+ return check_path_syntax_internal(destname, srcname, True, &ignore);
}
/****************************************************************************
*contains_wcard = False;
+ if (SVAL(inbuf,smb_flg2) & 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);
} else {
} else {
ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
+
+ if (SVAL(inbuf,smb_flg2) & 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);
} else {
memset(outbuf,'\0',smb_size);
- smb_setlen(outbuf,0);
+ smb_setlen(inbuf,outbuf,0);
switch (msg_type) {
case 0x81: /* session request */
return ERROR_NT(nt_status);
}
- outsize = set_message(outbuf,2,0,True);
+ outsize = set_message(inbuf,outbuf,2,0,True);
SSVAL(outbuf,smb_vwv0,max_recv);
SSVAL(outbuf,smb_vwv1,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *p, *q;
+ uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
START_PROFILE(SMBtconX);
if (global_encrypted_passwords_negotiated) {
password = data_blob(smb_buf(inbuf),passlen);
+ if (lp_security() == SEC_SHARE) {
+ /*
+ * Security = share always has a pad byte
+ * after the password.
+ */
+ p = smb_buf(inbuf) + passlen + 1;
+ } else {
+ p = smb_buf(inbuf) + passlen;
+ }
} else {
password = data_blob(smb_buf(inbuf),passlen+1);
/* Ensure correct termination */
- password.data[passlen]=0;
+ password.data[passlen]=0;
+ p = smb_buf(inbuf) + passlen + 1;
}
- p = smb_buf(inbuf) + passlen;
p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
/*
server_devicetype = "A:";
if (Protocol < PROTOCOL_NT1) {
- set_message(outbuf,2,0,True);
+ set_message(inbuf,outbuf,2,0,True);
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
STR_TERMINATE|STR_ASCII);
- set_message_end(outbuf,p);
+ set_message_end(inbuf,outbuf,p);
} else {
/* NT sets the fstype of IPC$ to the null string */
const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
- set_message(outbuf,3,0,True);
+ if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
+ /* Return permissions. */
+ uint32 perm1 = 0;
+ uint32 perm2 = 0;
+
+ set_message(inbuf,outbuf,7,0,True);
+
+ if (IS_IPC(conn)) {
+ perm1 = FILE_ALL_ACCESS;
+ perm2 = FILE_ALL_ACCESS;
+ } else {
+ perm1 = CAN_WRITE(conn) ?
+ SHARE_ALL_ACCESS :
+ SHARE_READ_ONLY;
+ }
+
+ SIVAL(outbuf, smb_vwv3, perm1);
+ SIVAL(outbuf, smb_vwv5, perm2);
+ } else {
+ set_message(inbuf,outbuf,3,0,True);
+ }
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
p += srvstr_push(outbuf, p, fstype, -1,
STR_TERMINATE);
- set_message_end(outbuf,p);
+ set_message_end(inbuf,outbuf,p);
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
return(ERROR_DOS(ERRSRV,ERRnosupport));
}
- outsize = set_message(outbuf,8,replysize+1,True);
+ outsize = set_message(inbuf,outbuf,8,replysize+1,True);
SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
}
/****************************************************************************
- Reply to a chkpth.
+ Strange checkpath NTSTATUS mapping.
+****************************************************************************/
+
+static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
+{
+ /* Strange DOS error code semantics only for checkpath... */
+ if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
+ if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
+ /* We need to map to ERRbadpath */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+ return status;
+}
+
+/****************************************************************************
+ Reply to a checkpath.
****************************************************************************/
-int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
pstring name;
- BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
- START_PROFILE(SMBchkpth);
+ START_PROFILE(SMBcheckpath);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBchkpth);
+ END_PROFILE(SMBcheckpath);
+ status = map_checkpath_error(inbuf, status);
+ return ERROR_NT(status);
+ }
- /* Strange DOS error code semantics only for chkpth... */
- if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
- if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
- /* We need to map to ERRbadpath */
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ END_PROFILE(SMBcheckpath);
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
}
- return ERROR_NT(status);
+ goto path_err;
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
- unix_convert(name,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, name, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto path_err;
}
- if (check_name(name,conn)) {
- if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
- if (!(ok = S_ISDIR(sbuf.st_mode))) {
- END_PROFILE(SMBchkpth);
- return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
- }
+ status = check_name(conn, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
+ goto path_err;
}
- if (!ok) {
- /* We special case this - as when a Windows machine
- is parsing a path is steps through the components
- one at a time - if a component fails it expects
- ERRbadpath, not ERRbadfile.
- */
- if(errno == ENOENT) {
- /*
- * Windows returns different error codes if
- * the parent directory is valid but not the
- * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
- * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
- * if the path is invalid. This is different from set_bad_path_error()
- * in the non-NT error case.
- */
- END_PROFILE(SMBchkpth);
- return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
- }
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
+ DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ goto path_err;
+ }
- END_PROFILE(SMBchkpth);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ if (!S_ISDIR(sbuf.st_mode)) {
+ END_PROFILE(SMBcheckpath);
+ return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
}
- outsize = set_message(outbuf,0,0,False);
- DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
+ outsize = set_message(inbuf,outbuf,0,0,False);
- END_PROFILE(SMBchkpth);
- return(outsize);
+ END_PROFILE(SMBcheckpath);
+ return outsize;
+
+ path_err:
+
+ END_PROFILE(SMBcheckpath);
+
+ /* We special case this - as when a Windows machine
+ is parsing a path is steps through the components
+ one at a time - if a component fails it expects
+ ERRbadpath, not ERRbadfile.
+ */
+ status = map_checkpath_error(inbuf, status);
+ if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ /*
+ * Windows returns different error codes if
+ * the parent directory is valid but not the
+ * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
+ * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
+ * if the path is invalid.
+ */
+ return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
+ }
+
+ return ERROR_NT(status);
}
/****************************************************************************
pstring fname;
int outsize = 0;
SMB_STRUCT_STAT sbuf;
- BOOL ok = False;
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBgetatr);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
- if (! (*fname)) {
+ if (*fname == '\0') {
mode = aHIDDEN | aDIR;
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
mode |= aRONLY;
+ }
size = 0;
mtime = 0;
- ok = True;
} else {
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
- if (check_name(fname,conn)) {
- if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
- mode = dos_mode(conn,fname,&sbuf);
- size = sbuf.st_size;
- mtime = sbuf.st_mtime;
- if (mode & aDIR)
- size = 0;
- ok = True;
- } else {
- DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
- }
+ return ERROR_NT(status);
+ }
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
+ END_PROFILE(SMBgetatr);
+ return ERROR_NT(status);
+ }
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
+ DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+ return UNIXERROR(ERRDOS,ERRbadfile);
+ }
+
+ mode = dos_mode(conn,fname,&sbuf);
+ size = sbuf.st_size;
+ mtime = sbuf.st_mtime;
+ if (mode & aDIR) {
+ size = 0;
}
}
- if (!ok) {
- END_PROFILE(SMBgetatr);
- return UNIXERROR(ERRDOS, ERRbadfile);
- }
-
- outsize = set_message(outbuf,10,0,True);
+ outsize = set_message(inbuf,outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
if(lp_dos_filetime_resolution(SNUM(conn)) ) {
SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
- DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
+ DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
END_PROFILE(SMBgetatr);
return(outsize);
int mode;
time_t mtime;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path || !check_name(fname, conn)) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(status);
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (fname[0] == '.' && fname[1] == '\0') {
}
}
- if (!set_filetime(conn,fname,mtime)) {
+ if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
END_PROFILE(SMBsetatr);
return UNIXERROR(ERRDOS, ERRnoaccess);
}
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
return(UNIXERROR(ERRHRD,ERRgeneral));
}
- outsize = set_message(outbuf,5,0,True);
+ outsize = set_message(inbuf,outbuf,5,0,True);
if (Protocol <= PROTOCOL_LANMAN2) {
double total_space, free_space;
unsigned int maxentries = 0;
BOOL finished = False;
char *p;
- BOOL ok = False;
int status_len;
pstring path;
char status[21];
int dptr_num= -1;
BOOL check_descend = False;
BOOL expect_close = False;
- BOOL can_open = True;
- BOOL bad_path = False;
NTSTATUS nt_status;
BOOL mask_contains_wcard = False;
BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
*mask = *directory = *fname = 0;
/* If we were called as SMBffirst then we must expect close. */
- if(CVAL(inbuf,smb_com) == SMBffirst)
+ if(CVAL(inbuf,smb_com) == SMBffirst) {
expect_close = True;
+ }
- outsize = set_message(outbuf,1,3,True);
+ outsize = set_message(inbuf,outbuf,1,3,True);
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
return ERROR_NT(nt_status);
}
- RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
+ nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(nt_status);
+ }
p++;
status_len = SVAL(p, 0);
if (status_len == 0) {
SMB_STRUCT_STAT sbuf;
- pstring dir2;
pstrcpy(directory,path);
- pstrcpy(dir2,path);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- unix_format(dir2);
+ nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_NT(nt_status);
+ }
- if (!check_name(directory,conn))
- can_open = False;
+ nt_status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_NT(nt_status);
+ }
- p = strrchr_m(dir2,'/');
- if (p == NULL) {
- pstrcpy(mask,dir2);
- *dir2 = 0;
+ p = strrchr_m(directory,'/');
+ if (!p) {
+ pstrcpy(mask,directory);
+ pstrcpy(directory,".");
} else {
*p = 0;
pstrcpy(mask,p+1);
}
- p = strrchr_m(directory,'/');
- if (!p)
- *directory = 0;
- else
- *p = 0;
-
- if (strlen(directory) == 0)
+ if (*directory == '\0') {
pstrcpy(directory,".");
+ }
memset((char *)status,'\0',21);
SCVAL(status,0,(dirtype & 0x1F));
} else {
memcpy(status,p,21);
status_dirtype = CVAL(status,0) & 0x1F;
- if (status_dirtype != (dirtype & 0x1F))
+ if (status_dirtype != (dirtype & 0x1F)) {
dirtype = status_dirtype;
+ }
conn->dirptr = dptr_fetch(status+12,&dptr_num);
- if (!conn->dirptr)
+ if (!conn->dirptr) {
goto SearchEmpty;
+ }
string_set(&conn->dirpath,dptr_path(dptr_num));
pstrcpy(mask, dptr_wcard(dptr_num));
+ /*
+ * For a 'continue' search we have no string. So
+ * check from the initial saved string.
+ */
+ mask_contains_wcard = ms_has_wild(mask);
}
- if (can_open) {
- p = smb_buf(outbuf) + 3;
- ok = True;
+ p = smb_buf(outbuf) + 3;
- if (status_len == 0) {
- dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
- if (dptr_num < 0) {
- if(dptr_num == -2) {
- END_PROFILE(SMBsearch);
- if ((errno == ENOENT) && bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
- return UNIXERROR(ERRDOS, ERRnofids);
- }
- END_PROFILE(SMBsearch);
- return ERROR_DOS(ERRDOS,ERRnofids);
- }
+ if (status_len == 0) {
+ nt_status = dptr_create(conn,
+ directory,
+ True,
+ expect_close,
+ SVAL(inbuf,smb_pid),
+ mask,
+ mask_contains_wcard,
+ dirtype,
+ &conn->dirptr);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return ERROR_NT(nt_status);
+ }
+ dptr_num = dptr_dnum(conn->dirptr);
+ } else {
+ dirtype = dptr_attr(dptr_num);
+ }
+
+ DEBUG(4,("dptr_num is %d\n",dptr_num));
+
+ if ((dirtype&0x1F) == aVOLID) {
+ memcpy(p,status,21);
+ make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
+ 0,aVOLID,0,!allow_long_path_components);
+ dptr_fill(p+12,dptr_num);
+ if (dptr_zero(p+12) && (status_len==0)) {
+ numentries = 1;
} else {
- dirtype = dptr_attr(dptr_num);
+ numentries = 0;
}
+ p += DIR_STRUCT_SIZE;
+ } else {
+ unsigned int i;
+ maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
- DEBUG(4,("dptr_num is %d\n",dptr_num));
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
+ conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
+ check_descend = True;
+ }
- if (ok) {
- if ((dirtype&0x1F) == aVOLID) {
+ for (i=numentries;(i<maxentries) && !finished;i++) {
+ finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
+ if (!finished) {
memcpy(p,status,21);
- make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
- 0,aVOLID,0,!allow_long_path_components);
- dptr_fill(p+12,dptr_num);
- if (dptr_zero(p+12) && (status_len==0))
- numentries = 1;
- else
- numentries = 0;
- p += DIR_STRUCT_SIZE;
- } else {
- unsigned int i;
- maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
-
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- conn->dirpath,lp_dontdescend(SNUM(conn))));
- if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
- check_descend = True;
-
- for (i=numentries;(i<maxentries) && !finished;i++) {
- finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
- if (!finished) {
- memcpy(p,status,21);
- make_dir_struct(p,mask,fname,size, mode,date,
- !allow_long_path_components);
- if (!dptr_fill(p+12,dptr_num)) {
- break;
- }
- numentries++;
- p += DIR_STRUCT_SIZE;
- }
+ make_dir_struct(p,mask,fname,size, mode,date,
+ !allow_long_path_components);
+ if (!dptr_fill(p+12,dptr_num)) {
+ break;
}
+ numentries++;
+ p += DIR_STRUCT_SIZE;
}
- } /* if (ok ) */
+ }
}
-
SearchEmpty:
/* If we were called as SMBffirst with smb_search_id == NULL
and no entries were found then return error and close dirptr
(X/Open spec) */
- if (numentries == 0 || !ok) {
+ if (numentries == 0) {
dptr_close(&dptr_num);
- } else if(ok && expect_close && status_len == 0) {
+ } else if(expect_close && status_len == 0) {
/* Close the dptr - we know it's gone */
dptr_close(&dptr_num);
}
SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
outsize += DIR_STRUCT_SIZE*numentries;
- smb_setlen(outbuf,outsize - 4);
+ smb_setlen(inbuf,outbuf,outsize - 4);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
return reply_unknown(inbuf, outbuf);
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
if (!NT_STATUS_IS_OK(err)) {
time_t mtime=0;
int info;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int deny_mode;
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopen);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopen);
+ return ERROR_NT(status);
+ }
+
if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
&access_mask, &share_mode, &create_disposition, &create_options)) {
END_PROFILE(SMBopen);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- outsize = set_message(outbuf,7,0,True);
+ outsize = set_message(inbuf,outbuf,7,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
SSVAL(outbuf,smb_vwv1,fattr);
if(lp_dos_filetime_resolution(SNUM(conn)) ) {
int mtime=0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
- BOOL bad_path = False;
files_struct *fsp;
NTSTATUS status;
SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
+ return ERROR_NT(status);
+ }
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
}
if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
- set_message(outbuf,19,0,True);
+ set_message(inbuf,outbuf,19,0,True);
} else {
- set_message(outbuf,15,0,True);
+ set_message(inbuf,outbuf,15,0,True);
}
SSVAL(outbuf,smb_vwv2,fsp->fnum);
SSVAL(outbuf,smb_vwv3,fattr);
invalidate_vuid(vuid);
- set_message(outbuf,2,0,True);
+ set_message(inbuf,outbuf,2,0,True);
DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
int com;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- struct utimbuf times;
- BOOL bad_path = False;
+ struct timespec ts[2];
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
com = SVAL(inbuf,smb_com);
- times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
+ 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);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ return ERROR_NT(status);
+ }
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (fattr & aVOLID) {
return ERROR_NT(status);
}
- times.actime = sbuf.st_atime;
- file_utime(conn, fname, ×);
+ ts[0] = get_atimespec(&sbuf); /* atime. */
+ file_ntimes(conn, fname, ts);
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
pstring fname;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int tmpfd;
pstrcat(fname,"TMXXXXXX");
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBctemp);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBctemp);
+ return ERROR_NT(status);
+ }
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
tmpfd = smb_mkstemp(fname);
return ERROR_NT(status);
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
/* the returned filename is relative to the directory */
#endif
namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
p += namelen;
- outsize = set_message_end(outbuf, p);
+ outsize = set_message_end(inbuf,outbuf, p);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
********************************************************************/
static NTSTATUS can_delete(connection_struct *conn, char *fname,
- uint32 dirtype)
+ uint32 dirtype, BOOL can_defer)
{
SMB_STRUCT_STAT sbuf;
uint32 fattr;
files_struct *fsp;
+ uint32 dirtype_orig = dirtype;
NTSTATUS status;
DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
fattr = dos_mode(conn,fname,&sbuf);
+ if (dirtype & FILE_ATTRIBUTE_NORMAL) {
+ dirtype = aDIR|aARCH|aRONLY;
+ }
+
+ dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!dir_check_ftype(conn, fattr, dirtype)) {
+ if (fattr & aDIR) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype_orig & 0x8000) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+#if 0
+ if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype & 0xFF00) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ dirtype &= 0xFF;
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
/* Can't delete a directory. */
if (fattr & aDIR) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
+#endif
#if 0 /* JRATEST */
else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
return NT_STATUS_CANNOT_DELETE;
}
}
- if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
- return NT_STATUS_NO_SUCH_FILE;
- }
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
- 0,
+ can_defer ? 0 : INTERNAL_OPEN_ONLY,
NULL, &fsp);
if (NT_STATUS_IS_OK(status)) {
****************************************************************************/
NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
- char *name, BOOL has_wild)
+ char *name, BOOL has_wild, BOOL can_defer)
{
pstring directory;
pstring mask;
- pstring orig_name;
char *p;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL bad_path = False;
- BOOL rc = True;
+ NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf;
*directory = *mask = 0;
- rc = unix_convert(name,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return has_wild
- ? NT_STATUS_INVALID_PARAMETER
- : NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
-
- /*
- * Feel my pain, this code needs rewriting *very* badly! -- vl
- */
- pstrcpy(orig_name, name);
p = strrchr_m(name,'/');
if (!p) {
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask,conn->params))
+ if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- error = can_delete(conn,directory,dirtype);
- if (!NT_STATUS_IS_OK(error))
- return error;
+ if (dirtype == 0) {
+ dirtype = FILE_ATTRIBUTE_NORMAL;
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = can_delete(conn,directory,dirtype,can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (SMB_VFS_UNLINK(conn,directory) == 0) {
count++;
- notify_fname(conn, orig_name, -1,
- NOTIFY_ACTION_REMOVED);
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ directory);
}
-
} else {
struct smb_Dir *dir_hnd = NULL;
+ long offset = 0;
const char *dname;
- if (strequal(mask,"????????.???"))
+ if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+
+ if (strequal(mask,"????????.???")) {
pstrcpy(mask,"*");
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, dirtype);
+ dir_hnd = OpenDir(conn, directory, mask, dirtype);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name, otherwise the short name
We don't implement this yet XXXX
*/
- if (dir_hnd) {
- long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
+ status = NT_STATUS_NO_SUCH_FILE;
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- SMB_STRUCT_STAT st;
- pstring fname;
- BOOL sys_direntry = False;
- pstrcpy(fname,dname);
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ SMB_STRUCT_STAT st;
+ pstring fname;
+ pstrcpy(fname,dname);
- if (!is_visible_file(conn, directory, dname, &st, True)) {
- continue;
- }
+ if (!is_visible_file(conn, directory, dname, &st, True)) {
+ continue;
+ }
- /* Quick check for "." and ".." */
- if (fname[0] == '.') {
- if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if (dirtype & FILE_ATTRIBUTE_DIRECTORY) {
- sys_direntry = True;
- } else {
- continue;
- }
- }
+ /* Quick check for "." and ".." */
+ if (fname[0] == '.') {
+ if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+ continue;
}
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
- continue;
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
- if (sys_direntry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
- DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
- fname, mask));
- break;
- }
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- error = can_delete(conn, fname, dirtype);
- if (!NT_STATUS_IS_OK(error)) {
- continue;
- }
- if (SMB_VFS_UNLINK(conn,fname) == 0) {
- count++;
- notify_action(
- conn, directory, dname,
- -1, NOTIFY_ACTION_REMOVED);
- }
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ CloseDir(dir_hnd);
+ return status;
+ }
+
+ status = can_delete(conn, fname, dirtype, can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ continue;
}
- CloseDir(dir_hnd);
+ 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);
+ }
+
}
+ CloseDir(dir_hnd);
}
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- return error;
+ return status;
}
/****************************************************************************
END_PROFILE(SMBunlink);
return ERROR_NT(status);
}
-
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBunlink);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
DEBUG(3,("reply_unlink : %s\n",name));
- status = unlink_internals(conn, dirtype, name, path_contains_wcard);
+ status = unlink_internals(conn, dirtype, name, path_contains_wcard,
+ True);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return ERROR_NT(status);
}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
- process_pending_change_notify_queue((time_t)0);
-
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
END_PROFILE(SMBunlink);
return outsize;
exit_server_cleanly(errstr);
}
-#if defined(WITH_SENDFILE)
/****************************************************************************
Fake (read/write) sendfile. Returns -1 on read or write fail.
****************************************************************************/
-static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
{
- ssize_t ret=0;
+ size_t tosend = nread;
- /* Paranioa check... */
- if (nread > bufsize) {
- fail_readraw();
- }
+ while (tosend > 0) {
+ ssize_t ret;
+ size_t cur_read;
- if (nread > 0) {
- ret = read_file(fsp,buf,startpos,nread);
+ if (tosend > bufsize) {
+ cur_read = bufsize;
+ } else {
+ cur_read = tosend;
+ }
+ ret = read_file(fsp,buf,startpos,cur_read);
if (ret == -1) {
return -1;
}
- }
- /* If we had a short read, fill with zeros. */
- if (ret < nread) {
- memset(buf, '\0', nread - ret);
- }
+ /* If we had a short read, fill with zeros. */
+ if (ret < cur_read) {
+ memset(buf, '\0', cur_read - ret);
+ }
- if (write_data(smbd_server_fd(),buf,nread) != nread) {
- return -1;
- }
+ if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
+ return -1;
+ }
+ tosend -= cur_read;
+ startpos += cur_read;
+ }
return (ssize_t)nread;
}
-#endif
/****************************************************************************
Use sendfile in readbraw.
exit_server_cleanly("send_file_readbraw sendfile failed");
}
+ return;
}
normal_readbraw:
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- outsize = set_message(outbuf,5,3,True);
+ outsize = set_message(inbuf,outbuf,5,3,True);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
data = smb_buf(outbuf) + 3;
* Note that the requested lock size is unaffected by max_recv.
*/
- br_lck = do_lock(fsp,
+ br_lck = do_lock(smbd_messaging_context(),
+ fsp,
(uint32)SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtoread,
(SMB_BIG_UINT)startpos,
WRITE_LOCK,
WINDOWS_LOCK,
False, /* Non-blocking lock. */
- &status);
+ &status,
+ NULL);
TALLOC_FREE(br_lck);
if (NT_STATUS_V(status)) {
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- outsize = set_message(outbuf,5,3,True);
+ outsize = set_message(inbuf,outbuf,5,3,True);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
/*
* The requested read size cannot be greater than max_recv. JRA.
return(outsize);
}
+/****************************************************************************
+ Setup readX header.
+****************************************************************************/
+
+static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
+{
+ int outsize;
+ char *data = smb_buf(outbuf);
+
+ SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
+ SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+ SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
+ SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+ SCVAL(outbuf,smb_vwv0,0xFF);
+ outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
+ /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
+ _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
+ return outsize;
+}
+
/****************************************************************************
Reply to a read and X - possibly using sendfile.
****************************************************************************/
int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
{
+ SMB_STRUCT_STAT sbuf;
int outsize = 0;
ssize_t nread = -1;
char *data = smb_buf(outbuf);
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ if (startpos > sbuf.st_size) {
+ smb_maxcnt = 0;
+ }
+
+ if (smb_maxcnt > (sbuf.st_size - startpos)) {
+ smb_maxcnt = (sbuf.st_size - startpos);
+ }
+
+ if (smb_maxcnt == 0) {
+ goto normal_read;
+ }
+
#if defined(WITH_SENDFILE)
/*
* We can only use sendfile on a non-chained packet
if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
- SMB_STRUCT_STAT sbuf;
DATA_BLOB header;
- if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
-
- if (startpos > sbuf.st_size)
- goto normal_read;
-
- if (smb_maxcnt > (sbuf.st_size - startpos))
- smb_maxcnt = (sbuf.st_size - startpos);
-
- if (smb_maxcnt == 0)
- goto normal_read;
-
/*
* Set up the packet header before send. We
* assume here the sendfile will work (get the
* correct amount of data).
*/
- SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
- SSVAL(outbuf,smb_vwv5,smb_maxcnt);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
- SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
- SCVAL(outbuf,smb_vwv0,0xFF);
- set_message(outbuf,12,smb_maxcnt,False);
+ setup_readX_header(inbuf,outbuf,smb_maxcnt);
+ set_message(inbuf,outbuf,12,smb_maxcnt,False);
header.data = (uint8 *)outbuf;
header.length = data - outbuf;
header.free = NULL;
return -1;
}
+#endif
+
normal_read:
-#endif
+ if ((smb_maxcnt && 0xFF0000) > 0x10000) {
+ int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
+ /* Send out the header. */
+ if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
+ DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server_cleanly("send_file_readX sendfile failed");
+ }
+ if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
+ len_outbuf - (data-outbuf))) == -1) {
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server_cleanly("send_file_readX: fake_sendfile failed");
+ }
+ return -1;
+ } else {
+ nread = read_file(fsp,data,startpos,smb_maxcnt);
- nread = read_file(fsp,data,startpos,smb_maxcnt);
-
- if (nread < 0) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if (nread < 0) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- outsize = set_message(outbuf,12,nread,False);
- SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
- SSVAL(outbuf,smb_vwv5,nread);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
- SSVAL(smb_buf(outbuf),-2,nread);
-
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ outsize = setup_readX_header(inbuf, outbuf,nread);
- /* Returning the number of bytes we want to send back - including header. */
- return outsize;
+ DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+
+ /* Returning the number of bytes we want to send back - including header. */
+ return outsize;
+ }
}
/****************************************************************************
SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
ssize_t nread = -1;
size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+ BOOL big_readX = False;
#if 0
size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
#endif
return(ERROR_DOS(ERRDOS,ERRbadaccess));
}
- set_message(outbuf,12,0,True);
+ set_message(inbuf,outbuf,12,0,True);
if (global_client_caps & CAP_LARGE_READX) {
- if (SVAL(inbuf,smb_vwv7) == 1) {
- smb_maxcnt |= (1<<16);
- }
- if (smb_maxcnt > BUFFER_SIZE) {
- DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
- (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
- END_PROFILE(SMBreadX);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ size_t upper_size = SVAL(inbuf,smb_vwv7);
+ smb_maxcnt |= (upper_size<<16);
+ if (upper_size > 1) {
+ /* Can't do this on a chained packet. */
+ if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ }
+ /* We currently don't do this on signed or sealed data. */
+ if (srv_is_signing_active() || srv_encryption_on()) {
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ }
+ /* Is there room in the reply for this data ? */
+ if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ big_readX = True;
}
}
return ERROR_DOS(ERRDOS,ERRlock);
}
- if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+ if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
END_PROFILE(SMBreadX);
return -1;
}
nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
- if (nread != -1)
+ /* Only call chain_reply if not an error. */
+ if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
nread = chain_reply(inbuf,outbuf,length,bufsize);
+ }
END_PROFILE(SMBreadX);
return nread;
/* Return a message to the redirector to tell it to send more bytes */
SCVAL(outbuf,smb_com,SMBwritebraw);
SSVALS(outbuf,smb_vwv0,-1);
- outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+ outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server_cleanly("reply_writebraw: send_smb failed.");
numtowrite = smb_len(inbuf);
/* Set up outbuf to return the correct return */
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SCVAL(outbuf,smb_com,SMBwritec);
if (numtowrite != 0) {
}
if (numtowrite) {
- status = do_unlock(fsp,
+ status = do_unlock(smbd_messaging_context(),
+ fsp,
(uint32)SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtowrite,
(SMB_BIG_UINT)startpos,
}
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
return(UNIXERROR(ERRHRD,ERRdiskfull));
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
return(ERROR_DOS(ERRDOS,ERRbadaccess));
}
- set_message(outbuf,6,0,True);
+ set_message(inbuf,outbuf,6,0,True);
/* Deal with possible LARGE_WRITEX */
if (large_writeX) {
fsp->fh->pos = res;
- outsize = set_message(outbuf,2,0,True);
+ outsize = set_message(inbuf,outbuf,2,0,True);
SIVAL(outbuf,smb_vwv0,res);
DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
uint16 fnum = SVAL(inbuf,smb_vwv0);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBflush);
file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
DEBUG(3,("exit\n"));
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
+ NTSTATUS status = NT_STATUS_OK;
int outsize = 0;
- time_t mtime;
- int32 eclass = 0, err = 0;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
/* If it's an IPC, pass off to the pipe handler. */
if (IS_IPC(conn)) {
* Special case - close NT SMB directory handle.
*/
DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
- close_file(fsp,NORMAL_CLOSE);
+ status = close_file(fsp,NORMAL_CLOSE);
} else {
/*
* Close ordinary file.
*/
- int close_err;
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
fsp->fh->fd, fsp->fnum,
* Take care of any time sent in the close.
*/
- mtime = srv_make_unix_date3(inbuf+smb_vwv1);
- fsp_set_pending_modtime(fsp, mtime);
+ fsp_set_pending_modtime(fsp,
+ convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
/*
* close_file() returns the unix errno if an error
* a disk full error. If not then it was probably an I/O error.
*/
- if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
- errno = close_err;
- END_PROFILE(SMBclose);
- return (UNIXERROR(ERRHRD,ERRgeneral));
- }
+ status = close_file(fsp,NORMAL_CLOSE);
}
- /* We have a cached error */
- if(eclass || err) {
+ if(!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBclose);
- return ERROR_DOS(eclass,err);
+ return ERROR_NT(status);
}
END_PROFILE(SMBclose);
size_t numtowrite;
ssize_t nwritten = -1;
int outsize = 0;
- int close_err = 0;
+ NTSTATUS close_status = NT_STATUS_OK;
SMB_OFF_T startpos;
char *data;
- time_t mtime;
+ struct timespec mtime;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBwriteclose);
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- mtime = srv_make_unix_date3(inbuf+smb_vwv4);
+ mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
data = smb_buf(inbuf) + 1;
if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
nwritten = write_file(fsp,data,startpos,numtowrite);
- set_filetime(conn, fsp->fsp_name,mtime);
+ set_filetime(conn, fsp->fsp_name, mtime);
/*
* More insanity. W2K only closes the file if writelen > 0.
if (numtowrite) {
DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
fsp->fsp_name ));
- close_err = close_file(fsp,NORMAL_CLOSE);
+ close_status = close_file(fsp,NORMAL_CLOSE);
}
DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
return(UNIXERROR(ERRHRD,ERRdiskfull));
}
- if(close_err != 0) {
- errno = close_err;
+ if(!NT_STATUS_IS_OK(close_status)) {
END_PROFILE(SMBwriteclose);
- return(UNIXERROR(ERRHRD,ERRgeneral));
+ return ERROR_NT(close_status);
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
END_PROFILE(SMBwriteclose);
int reply_lock(connection_struct *conn,
char *inbuf,char *outbuf, int length, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
- br_lck = do_lock(fsp,
+ br_lck = do_lock(smbd_messaging_context(),
+ fsp,
(uint32)SVAL(inbuf,smb_pid),
count,
offset,
WRITE_LOCK,
WINDOWS_LOCK,
False, /* Non-blocking lock. */
- &status);
+ &status,
+ NULL);
TALLOC_FREE(br_lck);
int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
- status = do_unlock(fsp,
+ status = do_unlock(smbd_messaging_context(),
+ fsp,
(uint32)SVAL(inbuf,smb_pid),
count,
offset,
int reply_tdis(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
uint16 vuid;
START_PROFILE(SMBtdis);
int smb_reverb = SVAL(inbuf,smb_vwv0);
int seq_num;
unsigned int data_len = smb_buflen(inbuf);
- int outsize = set_message(outbuf,1,data_len,True);
+ int outsize = set_message(inbuf,outbuf,1,data_len,True);
START_PROFILE(SMBecho);
if (data_len > BUFFER_SIZE) {
for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
SSVAL(outbuf,smb_vwv0,seq_num);
- smb_setlen(outbuf,outsize - 4);
+ smb_setlen(inbuf,outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
return(ERROR_NT(status));
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
DEBUG(3,("openprint fd=%d fnum=%d\n",
int reply_printclose(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int close_err = 0;
+ NTSTATUS status;
START_PROFILE(SMBsplclose);
CHECK_FSP(fsp,conn);
DEBUG(3,("printclose fd=%d fnum=%d\n",
fsp->fh->fd,fsp->fnum));
- close_err = close_file(fsp,NORMAL_CLOSE);
+ status = close_file(fsp,NORMAL_CLOSE);
- if(close_err != 0) {
- errno = close_err;
+ if(!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsplclose);
- return(UNIXERROR(ERRHRD,ERRgeneral));
+ return ERROR_NT(status);
}
END_PROFILE(SMBsplclose);
int reply_printqueue(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(outbuf,2,3,True);
+ int outsize = set_message(inbuf,outbuf,2,3,True);
int max_count = SVAL(inbuf,smb_vwv0);
int start_index = SVAL(inbuf,smb_vwv1);
START_PROFILE(SMBsplretq);
}
if (count > 0) {
- outsize = set_message(outbuf,2,28*count+3,False);
+ outsize = set_message(inbuf,outbuf,2,28*count+3,False);
SSVAL(outbuf,smb_vwv0,count);
SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
SCVAL(smb_buf(outbuf),0,1);
int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int numtowrite;
- int outsize = set_message(outbuf,0,0,False);
+ int outsize = set_message(inbuf,outbuf,0,0,False);
char *data;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
pstring directory;
int outsize;
NTSTATUS status;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBmkdir);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmkdir);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmkdir);
+ return ERROR_NT(status);
+ }
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
-
+
status = create_directory(conn, directory);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
return ERROR_NT(status);
}
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
The internals of the rmdir code - called elsewhere.
****************************************************************************/
-BOOL rmdir_internals(connection_struct *conn, const char *directory)
+NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
{
- BOOL ok;
+ int ret;
SMB_STRUCT_STAT st;
- ok = (SMB_VFS_RMDIR(conn,directory) == 0);
- if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
+ /* Might be a symlink. */
+ if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (S_ISLNK(st.st_mode)) {
+ /* Is what it points to a directory ? */
+ if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ if (!(S_ISDIR(st.st_mode))) {
+ return NT_STATUS_NOT_A_DIRECTORY;
+ }
+ ret = SMB_VFS_UNLINK(conn,directory);
+ } else {
+ ret = SMB_VFS_RMDIR(conn,directory);
+ }
+ if (ret == 0) {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+ return NT_STATUS_OK;
+ }
+
+ if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
/*
* Check to see if the only thing in this directory are
* vetoed files/directories. If so then delete them and
pstrcpy(fullname, directory);
pstrcat(fullname, "/");
pstrcat(fullname, dname);
-
+
if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
break;
if(st.st_mode & S_IFDIR) {
}
CloseDir(dir_hnd);
/* Retry the rmdir */
- ok = (SMB_VFS_RMDIR(conn,directory) == 0);
+ ret = SMB_VFS_RMDIR(conn,directory);
}
err:
- if (!ok) {
+ if (ret != 0) {
DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
"%s\n", directory,strerror(errno)));
- return False;
+ return map_nt_error_from_unix(errno);
}
- {
- char *parent_dir;
- const char *dirname;
-
- if (parent_dirname_talloc(tmp_talloc_ctx(), directory,
- &parent_dir, &dirname)) {
- notify_action(conn, parent_dir, dirname, -1,
- NOTIFY_ACTION_REMOVED);
- TALLOC_FREE(parent_dir); /* Not strictly necessary */
- }
- }
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
{
pstring directory;
int outsize = 0;
- BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBrmdir);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBrmdir);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
- unix_convert(directory,conn, NULL,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
- if (check_name(directory,conn)) {
- dptr_closepath(directory,SVAL(inbuf,smb_pid));
- ok = rmdir_internals(conn, directory);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBrmdir);
+ return ERROR_NT(status);
}
-
- if (!ok) {
+
+ dptr_closepath(directory,SVAL(inbuf,smb_pid));
+ status = rmdir_internals(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
- return UNIXERROR(ERRDOS, ERRbadpath);
+ return ERROR_NT(status);
}
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
DEBUG( 3, ( "rmdir %s\n", directory ) );
char *p,*p2, *pname1, *pname2;
int available_space, actual_space;
-
pname1 = strrchr_m(name1,'/');
pname2 = strrchr_m(name2,'/');
}
/* Send messages to all smbd's (not ourself) that the name has changed. */
- rename_share_filename(lck, conn->connectpath, newname);
+ rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
+ newname);
}
/****************************************************************************
Rename an open file - given an fsp.
****************************************************************************/
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
{
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
pstring newname_last_component;
- NTSTATUS error = NT_STATUS_OK;
+ NTSTATUS status = NT_STATUS_OK;
BOOL dest_exists;
- BOOL rcdest = True;
struct share_mode_lock *lck = NULL;
ZERO_STRUCT(sbuf);
- rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
- /* Quick check for "." and ".." */
- if (!bad_path && newname_last_component[0] == '.') {
- if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
- return NT_STATUS_ACCESS_DENIED;
- }
- }
- if (!rcdest && bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* Ensure newname contains a '/' */
if(strrchr_m(newname,'/') == 0) {
pstring tmpstr;
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- error = can_rename(conn,newname,attrs,&sbuf);
+ status = can_rename(conn,newname,attrs,&sbuf);
- if (dest_exists && !NT_STATUS_IS_OK(error)) {
+ if (dest_exists && !NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
- if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
- error = NT_STATUS_ACCESS_DENIED;
- return error;
+ nt_errstr(status), fsp->fsp_name,newname));
+ if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
+ status = NT_STATUS_ACCESS_DENIED;
+ return status;
}
if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
TALLOC_FREE(lck);
if (errno == ENOTDIR || errno == EISDIR) {
- error = NT_STATUS_OBJECT_NAME_COLLISION;
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
} else {
- error = map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
}
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
+ nt_errstr(status), fsp->fsp_name,newname));
+
+ 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);
- return error;
+ /* 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);
+ }
}
/****************************************************************************
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
+NTSTATUS rename_internals(connection_struct *conn,
+ pstring name,
+ pstring newname,
+ uint32 attrs,
+ BOOL replace_if_exists,
+ BOOL src_has_wild,
+ BOOL dest_has_wild)
{
pstring directory;
pstring mask;
pstring last_component_src;
pstring last_component_dest;
char *p;
- BOOL bad_path_src = False;
- BOOL bad_path_dest = False;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL rc = True;
- BOOL rcdest = True;
+ 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;
*directory = *mask = 0;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
- if (!rc && bad_path_src) {
- if (ms_has_wild(last_component_src))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_src[0] == '.') {
- if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
-
- /* Quick check for "." and ".." */
- if (last_component_dest[0] == '.') {
- if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask, conn->params))
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ }
- if (!has_wild) {
+ if (!src_has_wild) {
/*
* No wildcards - just process the one file.
*/
pstrcpy(newname, tmpstr);
}
- DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
-directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
- conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
- newname, last_component_dest, is_short_name));
+ DEBUG(3, ("rename_internals: case_sensitive = %d, "
+ "case_preserve = %d, short case preserve = %d, "
+ "directory = %s, newname = %s, "
+ "last_component_dest = %s, is_8_3 = %d\n",
+ conn->case_sensitive, conn->case_preserve,
+ 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)) {
+ DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
+ directory,newname));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
/*
* Check for special case with case preserving and not
* case sensitive, if directory and newname are identical,
}
}
- resolve_wildcards(directory,newname);
-
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/*
* The source object must exist.
*/
if (!vfs_object_exist(conn, directory, &sbuf1)) {
- DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
+ DEBUG(3, ("rename_internals: source doesn't exist "
+ "doing rename %s -> %s\n",
directory,newname));
- if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
+ if (errno == ENOTDIR || errno == EISDIR
+ || errno == ENOENT) {
/*
- * Must return different errors depending on whether the parent
- * directory existed or not.
+ * Must return different errors depending on
+ * whether the parent directory existed or
+ * not.
*/
p = strrchr_m(directory, '/');
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- error = map_nt_error_from_unix(errno);
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
-
- return error;
- }
+ status = map_nt_error_from_unix(errno);
+ DEBUG(3, ("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
- if (!rcdest && bad_path_dest) {
- if (ms_has_wild(last_component_dest))
- return NT_STATUS_OBJECT_NAME_INVALID;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ return status;
}
- error = can_rename(conn,directory,attrs,&sbuf1);
+ status = can_rename(conn,directory,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
- return error;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
+ return status;
}
/*
*/
if (strcsequal(directory, newname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
+ rename_open_files(conn, NULL, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ DEBUG(3, ("rename_internals: identical names in "
+ "rename %s - returning success\n",
+ directory));
return NT_STATUS_OK;
}
if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
- DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
- directory,newname));
+ DEBUG(3,("rename_internals: dest exists doing "
+ "rename %s -> %s\n", directory, newname));
return NT_STATUS_OBJECT_NAME_COLLISION;
}
return NT_STATUS_SHARING_VIOLATION;
}
- lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
+ 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, sbuf1.st_dev, sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: succeeded doing rename "
+ "on %s -> %s\n", directory, newname));
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
TALLOC_FREE(lck);
+ notify_rename(conn, S_ISDIR(sbuf1.st_mode),
+ directory, newname);
return NT_STATUS_OK;
}
TALLOC_FREE(lck);
- if (errno == ENOTDIR || errno == EISDIR)
- error = NT_STATUS_OBJECT_NAME_COLLISION;
- else
- error = map_nt_error_from_unix(errno);
+ 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(error), directory,newname));
+ nt_errstr(status), directory,newname));
- return error;
- } else {
- /*
- * Wildcards - process each file that matches.
- */
- struct smb_Dir *dir_hnd = NULL;
- const char *dname;
- pstring destname;
-
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
+ return status;
+ }
+
+ /*
+ * Wildcards - process each file that matches.
+ */
+ if (strequal(mask,"????????.???")) {
+ pstrcpy(mask,"*");
+ }
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, attrs);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ dir_hnd = OpenDir(conn, directory, mask, attrs);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
- if (dir_hnd) {
- long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
-/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
+ status = NT_STATUS_NO_SUCH_FILE;
+ /*
+ * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ * - gentest fix. JRA
+ */
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- pstring fname;
- BOOL sysdir_entry = False;
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ pstring fname;
+ BOOL sysdir_entry = False;
- pstrcpy(fname,dname);
+ pstrcpy(fname,dname);
- /* Quick check for "." and ".." */
- if (fname[0] == '.') {
- if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if (attrs & aDIR) {
- sysdir_entry = True;
- } else {
- continue;
- }
- }
+ /* Quick check for "." and ".." */
+ if (fname[0] == '.') {
+ if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+ if (attrs & aDIR) {
+ sysdir_entry = True;
+ } else {
+ continue;
}
+ }
+ }
- if (!is_visible_file(conn, directory, dname, &sbuf1, False))
- continue;
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
- continue;
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
- if (sysdir_entry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- }
+ if (sysdir_entry) {
+ status = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
+ }
- error = NT_STATUS_ACCESS_DENIED;
- slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
- if (!vfs_object_exist(conn, fname, &sbuf1)) {
- error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
- continue;
- }
- error = can_rename(conn,fname,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
- DEBUG(6,("rename %s refused\n", fname));
- continue;
- }
- pstrcpy(destname,newname);
-
- if (!resolve_wildcards(fname,destname)) {
- DEBUG(6,("resolve_wildcards %s %s failed\n",
- fname, destname));
- continue;
- }
-
- if (strcsequal(fname,destname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
- count++;
- error = NT_STATUS_OK;
- continue;
- }
+ status = NT_STATUS_ACCESS_DENIED;
+ slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
- if (!replace_if_exists &&
- vfs_file_exist(conn,destname, NULL)) {
- DEBUG(6,("file_exist %s\n", destname));
- error = NT_STATUS_OBJECT_NAME_COLLISION;
- continue;
- }
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!vfs_object_exist(conn, fname, &sbuf1)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6, ("rename %s failed. Error %s\n",
+ fname, nt_errstr(status)));
+ continue;
+ }
+ status = can_rename(conn,fname,attrs,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused\n", fname));
+ continue;
+ }
+ pstrcpy(destname,newname);
+
+ if (!resolve_wildcards(fname,destname)) {
+ DEBUG(6, ("resolve_wildcards %s %s failed\n",
+ fname, destname));
+ continue;
+ }
- if (rename_path_prefix_equal(fname, destname)) {
- return NT_STATUS_SHARING_VIOLATION;
- }
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, destname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+ if (strcsequal(fname,destname)) {
+ rename_open_files(conn, NULL, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: identical names "
+ "in wildcard rename %s - success\n",
+ fname));
+ count++;
+ status = NT_STATUS_OK;
+ continue;
+ }
- if (!SMB_VFS_RENAME(conn,fname,destname)) {
- rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
- count++;
- error = NT_STATUS_OK;
- }
- TALLOC_FREE(lck);
- DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
- }
- CloseDir(dir_hnd);
+ 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_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
- if (!rcdest && bad_path_dest) {
- if (ms_has_wild(last_component_dest))
- return NT_STATUS_OBJECT_NAME_INVALID;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+ sbuf1.st_ino, NULL, NULL);
+
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ count++;
+ status = NT_STATUS_OK;
}
+ TALLOC_FREE(lck);
+ DEBUG(3,("rename_internals: doing rename on %s -> "
+ "%s\n",fname,destname));
}
-
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
+ CloseDir(dir_hnd);
+
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- return error;
+ return status;
}
/****************************************************************************
char *p;
uint32 attrs = SVAL(inbuf,smb_vwv0);
NTSTATUS status;
- BOOL path1_contains_wcard = False;
- BOOL path2_contains_wcard = False;
+ BOOL src_has_wcard = False;
+ BOOL dest_has_wcard = False;
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, 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, &path2_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmv);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmv);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
+ status = rename_internals(conn, 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))) {
return ERROR_NT(status);
}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
- process_pending_change_notify_queue((time_t)0);
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
END_PROFILE(SMBmv);
return(outsize);
* TODO: check error codes on all callers
*/
-NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
- int count, BOOL target_is_directory)
+NTSTATUS copy_file(connection_struct *conn,
+ char *src,
+ char *dest1,
+ int ofun,
+ int count,
+ BOOL target_is_directory)
{
SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
uint32 dosattrs;
uint32 new_create_disposition;
NTSTATUS status;
- int close_err;
pstrcpy(dest,dest1);
if (target_is_directory) {
close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
+ fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
/*
* As we are opening fsp1 read-only we only expect
* Thus we don't look at the error return from the
* close of fsp1.
*/
- close_err = close_file(fsp2,NORMAL_CLOSE);
+ status = close_file(fsp2,NORMAL_CLOSE);
- if (close_err != 0) {
- return map_nt_error_from_unix(close_err);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
if (ret != (SMB_OFF_T)src_sbuf.st_size) {
int count=0;
int error = ERRnoaccess;
int err = 0;
- BOOL has_wild;
- BOOL exists=False;
int tid2 = SVAL(inbuf,smb_vwv0);
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
- BOOL bad_path1 = False;
- BOOL bad_path2 = False;
- BOOL path_contains_wcard1 = False;
- BOOL path_contains_wcard2 = False;
- BOOL rc = True;
+ BOOL source_has_wild = False;
+ BOOL dest_has_wild = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
START_PROFILE(SMBcopy);
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
+ p += srvstr_get_path_wcard(inbuf, 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, &path_contains_wcard2);
+ p += srvstr_get_path_wcard(inbuf, 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(ERRSRV,ERRinvdevice);
}
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
- rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
- unix_convert(newname,conn,0,&bad_path2,&sbuf2);
+ status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
target_is_directory = VALID_STAT_OF_DIR(sbuf2);
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask, conn->params))
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ }
- has_wild = path_contains_wcard1;
-
- if (!has_wild) {
+ if (!source_has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- if (resolve_wildcards(directory,newname)
- && NT_STATUS_IS_OK(status = copy_file(
- directory,newname,conn,ofun,
- count,target_is_directory)))
- count++;
- if(!count && !NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBcopy);
+ if (dest_has_wild) {
+ if (!resolve_wildcards(directory,newname)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- if (!count) {
- exists = vfs_file_exist(conn,directory,NULL);
+
+ status = copy_file(conn,directory,newname,ofun,
+ count,target_is_directory);
+
+ if(!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ } else {
+ count++;
}
} else {
struct smb_Dir *dir_hnd = NULL;
const char *dname;
+ long offset = 0;
pstring destname;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, 0);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ dir_hnd = OpenDir(conn, directory, mask, 0);
+ if (dir_hnd == NULL) {
+ status = map_nt_error_from_unix(errno);
+ return ERROR_NT(status);
+ }
- if (dir_hnd) {
- long offset = 0;
- error = ERRbadfile;
+ error = ERRbadfile;
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- pstring fname;
- pstrcpy(fname,dname);
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ pstring fname;
+ pstrcpy(fname,dname);
- if (!is_visible_file(conn, directory, dname, &sbuf1, False))
- continue;
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
- continue;
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
+
+ error = ERRnoaccess;
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+ pstrcpy(destname,newname);
+ if (!resolve_wildcards(fname,destname)) {
+ continue;
+ }
- error = ERRnoaccess;
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- pstrcpy(destname,newname);
- if (resolve_wildcards(fname,destname)
- && NT_STATUS_IS_OK(status = copy_file(
- fname,destname,conn,ofun,
- count,target_is_directory)))
- count++;
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ status = check_name(conn, destname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+
+ status = copy_file(conn,fname,destname,ofun,
+ count,target_is_directory);
+ if (NT_STATUS_IS_OK(status)) {
+ count++;
}
- CloseDir(dir_hnd);
}
+ CloseDir(dir_hnd);
}
if (count == 0) {
return(UNIXERROR(ERRHRD,ERRgeneral));
}
- if (exists) {
- END_PROFILE(SMBcopy);
- return ERROR_DOS(ERRDOS,error);
- } else {
- if((errno == ENOENT) && (bad_path1 || bad_path2) &&
- !use_nt_status()) {
- /* Samba 3.0.22 has ERRDOS/ERRbadpath in the
- * DOS error code case
- */
- return ERROR_DOS(ERRDOS, ERRbadpath);
- }
- END_PROFILE(SMBcopy);
- return(UNIXERROR(ERRDOS,error));
- }
+ END_PROFILE(SMBcopy);
+ return ERROR_DOS(ERRDOS,error);
}
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,count);
END_PROFILE(SMBcopy);
{
int snum;
int outsize = 0;
- BOOL ok = False;
pstring newdir;
NTSTATUS status;
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
-
- if (strlen(newdir) == 0) {
- ok = True;
- } else {
- ok = vfs_directory_exist(conn,newdir,NULL);
- if (ok)
- set_conn_connectpath(conn,newdir);
- }
-
- if (!ok) {
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(pathworks_setdir);
- return ERROR_DOS(ERRDOS,ERRbadpath);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ if (strlen(newdir) != 0) {
+ if (!vfs_directory_exist(conn,newdir,NULL)) {
+ END_PROFILE(pathworks_setdir);
+ return ERROR_DOS(ERRDOS,ERRbadpath);
+ }
+ set_conn_connectpath(conn,newdir);
}
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
DEBUG(3,("setdir %s\n", newdir));
"pid %u, file %s\n", (double)offset, (double)count,
(unsigned int)lock_pid, fsp->fsp_name ));
- status = do_unlock(fsp,
+ status = do_unlock(smbd_messaging_context(),
+ fsp,
lock_pid,
count,
offset,
BOOL blocking_lock = lock_timeout ? True : False;
BOOL defer_lock = False;
struct byte_range_lock *br_lck;
+ uint32 block_smbpid;
- br_lck = do_lock(fsp,
+ br_lck = do_lock(smbd_messaging_context(),
+ fsp,
lock_pid,
count,
offset,
lock_type,
WINDOWS_LOCK,
blocking_lock,
- &status);
+ &status,
+ &block_smbpid);
if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
/* Windows internal resolution for blocking locks seems
lock_type,
WINDOWS_LOCK,
offset,
- count)) {
+ count,
+ block_smbpid)) {
TALLOC_FREE(br_lck);
END_PROFILE(SMBlockingX);
return -1;
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- do_unlock(fsp,
+ do_unlock(smbd_messaging_context(),
+ fsp,
lock_pid,
count,
offset,
return ERROR_NT(status);
}
- set_message(outbuf,2,0,True);
+ set_message(inbuf,outbuf,2,0,True);
DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
return ERROR_DOS(ERRSRV,ERRuseSTD);
}
- outsize = set_message(outbuf,8,0,True);
+ outsize = set_message(inbuf,outbuf,8,0,True);
CHECK_FSP(fsp,conn);
if (!CHECK_READ(fsp,inbuf)) {
if (nread < (ssize_t)N)
tcount = total_read + nread;
- set_message(outbuf,8,nread+pad,False);
+ set_message(inbuf,outbuf,8,nread+pad,False);
SIVAL(outbuf,smb_vwv0,startpos);
SSVAL(outbuf,smb_vwv2,tcount);
SSVAL(outbuf,smb_vwv6,nread);
int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- struct utimbuf unix_times;
+ struct timespec ts[2];
int outsize = 0;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBsetattrE);
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBsetattrE);
* time as UNIX can't set this.
*/
- unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
- unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
+ ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
/*
* Patch from Ray Frush <frush@engr.colostate.edu>
* Sometimes times are sent as zero - ignore them.
*/
- if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ if (null_timespec(ts[0]) && null_timespec(ts[1])) {
/* Ignore request */
if( DEBUGLVL( 3 ) ) {
dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
}
END_PROFILE(SMBsetattrE);
return(outsize);
- } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
/* set modify time = to access time if modify time was unset */
- unix_times.modtime = unix_times.actime;
+ ts[1] = ts[0];
}
/* Set the date on this file */
/* Should we set pending modtime here ? JRA */
- if(file_utime(conn, fsp->fsp_name, &unix_times)) {
+ if(file_ntimes(conn, fsp->fsp_name, ts)) {
END_PROFILE(SMBsetattrE);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
- fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
+ DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
+ fsp->fnum,
+ (unsigned int)ts[0].tv_sec,
+ (unsigned int)ts[1].tv_sec));
END_PROFILE(SMBsetattrE);
return(outsize);
SMBwritebmpx */
SCVAL(outbuf,smb_com,SMBwriteBmpx);
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
if (write_through && tcount==nwritten) {
/* We need to send both a primary and a secondary response */
- smb_setlen(outbuf,outsize - 4);
+ smb_setlen(inbuf,outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server_cleanly("reply_writebmpx: send_smb failed.");
/* Now the secondary */
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SCVAL(outbuf,smb_com,SMBwritec);
SSVAL(outbuf,smb_vwv0,nwritten);
}
wbms->wr_total_written += nwritten;
if(wbms->wr_total_written >= tcount) {
if (write_through) {
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(inbuf,outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
send_response = True;
}
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBgetattrE);
- outsize = set_message(outbuf,11,0,True);
+ outsize = set_message(inbuf,outbuf,11,0,True);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBgetattrE);