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 posix_path,
BOOL *p_last_component_contains_wcard)
{
char *d = destname;
*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.
*/
/* Eat multiple '/' or '\\' */
- while (IS_DIRECTORY_SEP(*s)) {
+ while (IS_PATH_SEP(*s,posix_path)) {
s++;
}
if ((d != destname) && (*s != '\0')) {
}
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;
}
NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
BOOL ignore;
- return check_path_syntax_internal(destname, srcname, True, &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)
{
BOOL ignore;
- return check_path_syntax_internal(destname, srcname, False, &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 */
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ 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);
+ }
+ goto path_err;
+ }
DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
}
- outsize = set_message(outbuf,0,0,False);
+ outsize = set_message(inbuf,outbuf,0,0,False);
END_PROFILE(SMBcheckpath);
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(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! */
}
}
- 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)) ) {
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);
}
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBsetatr);
- return ERROR_NT(status);
- }
-
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;
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, True, NULL, &sbuf);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
}
- unix_format(dir2);
nt_status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(nt_status)) {
return ERROR_NT(nt_status);
}
- p = strrchr_m(dir2,'/');
- if (p == NULL) {
- pstrcpy(mask,dir2);
- *dir2 = 0;
- } else {
- *p = 0;
- pstrcpy(mask,p+1);
- }
-
p = strrchr_m(directory,'/');
if (!p) {
- *directory = 0;
+ pstrcpy(mask,directory);
+ pstrcpy(directory,".");
} else {
*p = 0;
+ pstrcpy(mask,p+1);
}
- if (strlen(directory) == 0) {
+ if (*directory == '\0') {
pstrcpy(directory,".");
}
memset((char *)status,'\0',21);
}
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);
}
p = smb_buf(outbuf) + 3;
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, BOOL can_defer)
+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;
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);
}
/****************************************************************************
if (dirtype == 0) {
dirtype = FILE_ATTRIBUTE_NORMAL;
}
- status = can_delete(conn,directory,dirtype,can_defer);
+
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- if (SMB_VFS_UNLINK(conn,directory) == 0) {
- count++;
- notify_fname(conn, directory,
- FILE_NOTIFY_CHANGE_FILE,
- NOTIFY_ACTION_REMOVED);
+ 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;
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- status = can_delete(conn, fname, dirtype, can_defer);
+
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
- continue;
+ CloseDir(dir_hnd);
+ return status;
}
- if (SMB_VFS_UNLINK(conn,fname) == 0) {
- count++;
- DEBUG(3,("unlink_internals: succesful unlink "
- "[%s]\n",fname));
- notify_action(conn, directory, dname,
- FILE_NOTIFY_CHANGE_FILE,
- NOTIFY_ACTION_REMOVED);
+
+ status = do_unlink(conn, fname, dirtype, can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ continue;
}
-
+
+ count++;
+ DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
+ fname));
}
CloseDir(dir_hnd);
}
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));
return ERROR_NT(status);
}
- 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(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;
}
- 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)
{
int ret;
SMB_STRUCT_STAT st;
- ret = SMB_VFS_RMDIR(conn,directory);
+ /* 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, directory, FILE_NOTIFY_CHANGE_DIR_NAME,
- NOTIFY_ACTION_REMOVED);
- return True;
+ 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))) {
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);
}
- notify_fname(conn, directory, FILE_NOTIFY_CHANGE_DIR_NAME,
- NOTIFY_ACTION_REMOVED);
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
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)) {
}
dptr_closepath(directory,SVAL(inbuf,smb_pid));
- if (!rmdir_internals(conn, directory)) {
+ 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);
+ }
+ }
- if (dest_exists && !NT_STATUS_IS_OK(status)) {
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
+
+ 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;
}
nt_errstr(status), directory,newname));
return status;
- } else {
- /*
- * Wildcards - process each file that matches.
- */
- struct smb_Dir *dir_hnd = NULL;
- const char *dname;
- long offset = 0;
- pstring destname;
-
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
+ }
+
+ /*
+ * Wildcards - process each file that matches.
+ */
+ if (strequal(mask,"????????.???")) {
+ pstrcpy(mask,"*");
+ }
- status = check_name(conn, directory);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ 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);
- }
+ dir_hnd = OpenDir(conn, directory, mask, attrs);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
- 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);
+ status = NT_STATUS_ACCESS_DENIED;
+ slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /*
+ * can_rename does an open_file_ntcreate which needs a valid
+ * stat in case the file exists
+ */
+
+ ZERO_STRUCT(sbuf1);
+ SMB_VFS_STAT(conn, fname, &sbuf1);
+
+ status = can_rename(conn,fname,attrs,&sbuf1,False);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused: %s\n", fname,
+ nt_errstr(status)));
+ continue;
+ }
+ pstrcpy(destname,newname);
- if (!resolve_wildcards(fname,destname)) {
- DEBUG(6,("resolve_wildcards %s %s failed\n",
- fname, destname));
- continue;
- }
+ 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;
- }
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, destname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- 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;
- }
+ id = file_id_sbuf(&sbuf1);
- lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+ if (strcsequal(fname,destname)) {
+ 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++;
- status = NT_STATUS_OK;
- }
- TALLOC_FREE(lck);
- DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
+ 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;
}
- CloseDir(dir_hnd);
- }
-#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;
- }
+ 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;
}
-#endif
+ 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);
}
- 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 = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
+ 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, newname, path_contains_wcard2, NULL, &sbuf2);
+ 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, 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);
}
- if (!count) {
- exists = vfs_file_exist(conn,directory,NULL);
+
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ 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;
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))) {
+ 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++;
}
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
}
CloseDir(dir_hnd);
}
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);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(pathworks_setdir);
+ 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)) {
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);