set.
****************************************************************************/
+/* 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 windows_path, BOOL
- *p_last_component_contains_wcard)
+ 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;
- if (p_last_component_contains_wcard) {
- *p_last_component_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. */
- if (p_last_component_contains_wcard) {
- *p_last_component_contains_wcard = False;
- }
+ *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" ! */
/*
/* We're still at the start of a name component, just the previous one. */
continue;
- } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- if (!windows_path) {
+ } 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 (windows_path) {
+ if (!posix_path) {
if (*s <= 0x1f) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
case '<':
case '>':
case '"':
- if (p_last_component_contains_wcard) {
- *p_last_component_contains_wcard = True;
- }
+ *p_last_component_contains_wcard = True;
break;
default:
break;
NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
- return check_path_syntax_internal(destname, srcname, True, NULL);
+ BOOL ignore;
+ return check_path_syntax_internal(destname, srcname, False, &ignore);
}
/****************************************************************************
NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
{
- return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
+ return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
}
/****************************************************************************
set (a safe assumption).
****************************************************************************/
-static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
{
- return check_path_syntax_internal(destname, srcname, False, NULL);
+ 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;
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)));
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBchkpth);
- /* 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;
- }
- }
- return ERROR_NT(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.
- */
- 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;
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 {
status = unix_convert(conn, fname, False, NULL,&sbuf);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
return ERROR_NT(status);
}
- 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)));
- }
+ 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);
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);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(status);
+ }
+
if (fname[0] == '.' && fname[1] == '\0') {
/*
* Not sure here is the right place to catch this
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
- if (!check_name(fname,conn)) {
- END_PROFILE(SMBsetatr);
- return UNIXERROR(ERRDOS, ERRnoaccess);
- }
-
mode = SVAL(inbuf,smb_vwv0);
mtime = srv_make_unix_date3(inbuf+smb_vwv1);
}
}
- 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;
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);
- nt_status = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf);
+ nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
}
- unix_format(dir2);
- 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);
- 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)) {
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);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
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)) ) {
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)) {
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
+ return ERROR_NT(status);
+ }
+
if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
&access_mask,
&share_mode,
}
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;
+ 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)) {
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ return ERROR_NT(status);
+ }
+
if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
}
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))) {
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);
}
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBctemp);
+ return ERROR_NT(status);
+ }
tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
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);
Check if a user is allowed to rename a file.
********************************************************************/
-static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
{
files_struct *fsp;
uint32 fmode;
status = open_file_ntcreate(conn, fname, pst,
DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
+ /* If we're checking our fsp don't deny for delete. */
+ self_open ?
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
}
/*******************************************************************
- Check if a user is allowed to delete a file.
-********************************************************************/
+ * unlink a file with all relevant access checks
+ *******************************************************************/
-static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype)
+static NTSTATUS do_unlink(connection_struct *conn, char *fname,
+ uint32 dirtype, BOOL can_defer)
{
SMB_STRUCT_STAT sbuf;
uint32 fattr;
uint32 dirtype_orig = dirtype;
NTSTATUS status;
- DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
+ DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
- 0,
+ can_defer ? 0 : INTERNAL_OPEN_ONLY,
NULL, &fsp);
- if (NT_STATUS_IS_OK(status)) {
- close_file(fsp,NORMAL_CLOSE);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("open_file_ntcreate failed: %s\n",
+ nt_errstr(status)));
+ return status;
}
- return status;
+
+ /* The set is across all open files on this dev/inode pair. */
+ if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
+ close_file(fsp, NORMAL_CLOSE);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return close_file(fsp,NORMAL_CLOSE);
}
/****************************************************************************
code.
****************************************************************************/
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
+ char *name, BOOL has_wild, BOOL can_defer)
{
pstring directory;
pstring mask;
if (dirtype == 0) {
dirtype = FILE_ATTRIBUTE_NORMAL;
}
- status = can_delete(conn,directory,dirtype);
- if (!NT_STATUS_IS_OK(status))
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
return status;
+ }
- if (SMB_VFS_UNLINK(conn,directory) == 0) {
- count++;
+ status = do_unlink(conn,directory,dirtype,can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+
+ count++;
} else {
struct smb_Dir *dir_hnd = NULL;
+ long offset = 0;
const char *dname;
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
- if (strequal(mask,"????????.???"))
+ 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;
- status = NT_STATUS_NO_SUCH_FILE;
+ status = NT_STATUS_NO_SUCH_FILE;
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- SMB_STRUCT_STAT st;
- pstring fname;
- 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])) {
- 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;
+ }
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- status = can_delete(conn, fname, dirtype);
- if (!NT_STATUS_IS_OK(status)) {
- continue;
- }
- if (SMB_VFS_UNLINK(conn,fname) == 0)
- count++;
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ CloseDir(dir_hnd);
+ return status;
+ }
+
+ status = do_unlink(conn, fname, dirtype, can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ continue;
}
- CloseDir(dir_hnd);
+
+ count++;
+ DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
+ fname));
}
+ CloseDir(dir_hnd);
}
if (count == 0 && NT_STATUS_IS_OK(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:
-
#endif
+normal_readbraw:
+
if (nread > 0) {
ret = read_file(fsp,outbuf+4,startpos,nread);
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
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 defined(WITH_SENDFILE)
- /*
- * We can only use sendfile on a non-chained packet
+ 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
* but we can use on a non-oplocked file. tridge proved this
* on a train in Germany :-). JRA.
*/
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;
}
- normal_read:
-
#endif
- nread = read_file(fsp,data,startpos,smb_maxcnt);
-
- if (nread < 0) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+normal_read:
- outsize = set_message(outbuf,12,nread,False);
- SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
- SSVAL(outbuf,smb_vwv5,nread);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
- SSVAL(smb_buf(outbuf),-2,nread);
-
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ if ((smb_maxcnt & 0xFF0000) > 0x10000) {
+ int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
+ /* Send out the header. */
+ if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
+ DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server_cleanly("send_file_readX sendfile failed");
+ }
+ if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
+ len_outbuf - (data-outbuf))) == -1) {
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server_cleanly("send_file_readX: fake_sendfile failed");
+ }
+ return -1;
+ } else {
+ nread = read_file(fsp,data,startpos,smb_maxcnt);
- /* Returning the number of bytes we want to send back - including header. */
- return outsize;
+ if (nread < 0) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ outsize = setup_readX_header(inbuf, outbuf,nread);
+
+ DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+
+ /* Returning the number of bytes we want to send back - including header. */
+ return outsize;
+ }
}
/****************************************************************************
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);
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)) {
return ERROR_NT(status);
}
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmkdir);
+ 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
}
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);
}
- return True;
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+
+ return NT_STATUS_OK;
}
/****************************************************************************
{
pstring directory;
int outsize = 0;
- BOOL ok = 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);
+ }
status = unix_convert(conn, directory, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
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,'/');
****************************************************************************/
static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
- SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
+ struct file_id id, const char *newname)
{
files_struct *fsp;
BOOL did_rename = False;
- for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+ for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) {
/* fsp_name is a relative path under the fsp. To change this for other
sharepaths we need to manipulate relative paths. */
/* TODO - create the absolute path and manipulate the newname
if (fsp->conn != conn) {
continue;
}
- DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
- fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
+ DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
+ fsp->fnum, file_id_static_string(&fsp->file_id),
fsp->fsp_name, newname ));
string_set(&fsp->fsp_name, newname);
did_rename = True;
}
if (!did_rename) {
- DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
- (unsigned int)dev, (double)inode, newname ));
+ DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
+ file_id_static_string(&id), newname ));
}
/* Send messages to all smbd's (not ourself) that the name has changed. */
- rename_share_filename(lck, conn->connectpath, newname);
+ rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
+ newname);
}
/****************************************************************************
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;
pstring newname_last_component;
ZERO_STRUCT(sbuf);
status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
+
+ /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
+
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
return status;
}
+ 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;
}
- status = can_rename(conn,newname,attrs,&sbuf);
+ /* Ensure we have a valid stat struct for the source. */
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+
+ status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
- if (dest_exists && !NT_STATUS_IS_OK(status)) {
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
nt_errstr(status), fsp->fsp_name,newname));
if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
status = NT_STATUS_ACCESS_DENIED;
return NT_STATUS_ACCESS_DENIED;
}
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
+ uint32 create_options = fsp->fh->private_options;
+
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
- rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
+
+ rename_open_files(conn, lck, fsp->file_id, newname);
+
+ /*
+ * A rename acts as a new file create w.r.t. allowing an initial delete
+ * on close, probably because in Windows there is a new handle to the
+ * new file. If initial delete on close was requested but not
+ * originally set, we need to set it here. This is probably not 100% correct,
+ * but will work for the CIFSFS client which in non-posix mode
+ * depends on these semantics. JRA.
+ */
+
+ set_allow_initial_delete_on_close(lck, fsp, True);
+
+ if (create_options & FILE_DELETE_ON_CLOSE) {
+ status = can_set_delete_on_close(fsp, True, 0);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Note that here we set the *inital* delete on close flag,
+ * not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
+ }
+ }
TALLOC_FREE(lck);
return NT_STATUS_OK;
}
return status;
}
+/*
+ * Do the notify calls from a rename
+ */
+
+static void notify_rename(connection_struct *conn, BOOL is_dir,
+ const char *oldpath, const char *newpath)
+{
+ char *olddir, *newdir;
+ const char *oldname, *newname;
+ uint32 mask;
+
+ mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
+ : FILE_NOTIFY_CHANGE_FILE_NAME;
+
+ if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
+ || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
+ TALLOC_FREE(olddir);
+ return;
+ }
+
+ if (strcmp(olddir, newdir) == 0) {
+ notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
+ }
+ else {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
+ }
+ TALLOC_FREE(olddir);
+ TALLOC_FREE(newdir);
+
+ /* this is a strange one. w2k3 gives an additional event for
+ CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
+ files, but not directories */
+ if (!is_dir) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES
+ |FILE_NOTIFY_CHANGE_CREATION,
+ newpath);
+ }
+}
+
/****************************************************************************
The guts of the rename command, split out so it may be called by the NT SMB
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, 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;
NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf1, sbuf2;
struct share_mode_lock *lck = NULL;
+ struct smb_Dir *dir_hnd = NULL;
+ const char *dname;
+ long offset = 0;
+ pstring destname;
+ struct file_id id;
*directory = *mask = 0;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1);
+ status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = unix_convert(conn, newname, True, last_component_dest, &sbuf2);
+ 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 (!VALID_STAT(sbuf1) && 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);
-
- /*
- * The source object must exist.
- */
-
- if (!vfs_object_exist(conn, directory, &sbuf1)) {
- DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
- directory,newname));
-
- if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
- /*
- * Must return different errors depending on whether the parent
- * directory existed or not.
- */
-
- p = strrchr_m(directory, '/');
- if (!p)
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- *p = '\0';
- if (vfs_object_exist(conn, directory, NULL))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- status = map_nt_error_from_unix(errno);
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), directory,newname));
-
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = can_rename(conn,directory,attrs,&sbuf1);
+ /*
+ * The source object must exist, and it may not have a
+ * conflicting share mode.
+ */
+ status = can_rename(conn,directory,attrs,&sbuf1,False);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), directory,newname));
+ DEBUG(3,("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
return status;
}
* don't do the rename, just return success.
*/
+ id = file_id_sbuf(&sbuf1);
+
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));
+ 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, id, NULL, NULL);
if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
- DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
- directory,newname));
- rename_open_files(conn, lck, 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, id, newname);
TALLOC_FREE(lck);
+ notify_rename(conn, S_ISDIR(sbuf1.st_mode),
+ directory, newname);
return NT_STATUS_OK;
}
TALLOC_FREE(lck);
- if (errno == ENOTDIR || errno == EISDIR)
+ if (errno == ENOTDIR || errno == EISDIR) {
status = NT_STATUS_OBJECT_NAME_COLLISION;
- else
+ } else {
status = map_nt_error_from_unix(errno);
+ }
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
nt_errstr(status), directory,newname));
return status;
- } else {
- /*
- * Wildcards - process each file that matches.
- */
- struct smb_Dir *dir_hnd = NULL;
- const char *dname;
- pstring destname;
-
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
+ }
+
+ /*
+ * 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;
- status = NT_STATUS_NO_SUCH_FILE;
-/* Was status = 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) {
- status = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- }
+ if (sysdir_entry) {
+ status = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
+ }
- status = NT_STATUS_ACCESS_DENIED;
- slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
- 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 (strcsequal(fname,destname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
- count++;
- status = NT_STATUS_OK;
- continue;
- }
+ status = 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));
- status = 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;
+ }
+
+ /*
+ * can_rename does an open_file_ntcreate which needs a valid
+ * stat in case the file exists
+ */
+
+ ZERO_STRUCT(sbuf1);
+ SMB_VFS_STAT(conn, fname, &sbuf1);
+
+ status = can_rename(conn,fname,attrs,&sbuf1,False);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused: %s\n", fname,
+ nt_errstr(status)));
+ continue;
+ }
+ pstrcpy(destname,newname);
+
+ if (!resolve_wildcards(fname,destname)) {
+ 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);
+ id = file_id_sbuf(&sbuf1);
- 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));
- }
- CloseDir(dir_hnd);
+ if (strcsequal(fname,destname)) {
+ DEBUG(3,("rename_internals: identical names "
+ "in wildcard rename %s - success\n",
+ fname));
+ count++;
+ status = NT_STATUS_OK;
+ continue;
}
-#if 0
- /* Don't think needed any more - JRA. */
- 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;
- }
+ if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+ DEBUG(6,("file_exist %s\n", destname));
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ continue;
}
-#endif
+
+ if (rename_path_prefix_equal(fname, destname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+
+ lck = get_share_mode_lock(NULL, id, NULL, NULL);
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, lck, id, newname);
+ count++;
+ status = NT_STATUS_OK;
+ }
+ TALLOC_FREE(lck);
+ DEBUG(3,("rename_internals: doing rename on %s -> "
+ "%s\n",fname,destname));
}
-
+ CloseDir(dir_hnd);
+
if (count == 0 && NT_STATUS_IS_OK(status)) {
status = map_nt_error_from_unix(errno);
}
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 path_contains_wcard1 = False;
- BOOL path_contains_wcard2 = False;
+ 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, path_contains_wcard1, NULL, &sbuf1);
+ status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
}
- status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
+ status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf1) && 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)
- && 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));
+ error = ERRnoaccess;
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+ pstrcpy(destname,newname);
+ if (!resolve_wildcards(fname,destname)) {
+ continue;
+ }
+
+ 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 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);