summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/nt_status.h1
-rw-r--r--source3/include/nterr.h3
-rw-r--r--source3/include/smb.h23
-rw-r--r--source3/include/smb_macros.h23
-rw-r--r--source3/smbd/error.c143
-rw-r--r--source3/smbd/files.c6
-rw-r--r--source3/smbd/nttrans.c32
-rw-r--r--source3/smbd/open.c101
-rw-r--r--source3/smbd/oplock.c3
-rw-r--r--source3/smbd/process.c3
-rw-r--r--source3/smbd/reply.c78
-rw-r--r--source3/smbd/trans2.c1
12 files changed, 186 insertions, 231 deletions
diff --git a/source3/include/nt_status.h b/source3/include/nt_status.h
index 9747f73eb1..ab768258df 100644
--- a/source3/include/nt_status.h
+++ b/source3/include/nt_status.h
@@ -56,6 +56,7 @@ typedef uint32 WERROR;
#define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0)
#define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000)
+#define NT_STATUS_IS_INVALID(x) (NT_STATUS_V(x) == 0xFFFFFFFF)
#define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y))
#define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0)
#define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y))
diff --git a/source3/include/nterr.h b/source3/include/nterr.h
index 6cf5a756d2..417719625e 100644
--- a/source3/include/nterr.h
+++ b/source3/include/nterr.h
@@ -37,6 +37,9 @@
#define STATUS_NOTIFY_ENUM_DIR NT_STATUS(0x010c)
#define ERROR_INVALID_DATATYPE NT_STATUS(0x070c)
+/* Special "invalid" NT status code. */
+#define NT_STATUS_INVALID NT_STATUS(0xFFFFFFFF)
+
/* Win32 Error codes extracted using a loop in smbclient then printing a
netmon sniff to a file. */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index efa74436ee..d12459c2f9 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -357,14 +357,14 @@ typedef struct time_info
} UTIME;
/* Structure used when SMBwritebmpx is active */
-typedef struct
-{
- size_t wr_total_written; /* So we know when to discard this */
- int32 wr_timeout;
- int32 wr_errclass;
- int32 wr_error; /* Cached errors */
- BOOL wr_mode; /* write through mode) */
- BOOL wr_discard; /* discard all further data */
+typedef struct {
+ size_t wr_total_written; /* So we know when to discard this */
+ int32 wr_timeout;
+ int32 wr_errclass; /* Cached errors */
+ int32 wr_error; /* Cached errors */
+ NTSTATUS wr_status; /* Cached errors */
+ BOOL wr_mode; /* write through mode) */
+ BOOL wr_discard; /* discard all further data */
} write_bmpx_struct;
typedef struct write_cache
@@ -1384,13 +1384,6 @@ enum case_handling {CASE_LOWER,CASE_UPPER};
*/
#define COPYBUF_SIZE (8*1024)
-/*
- * Values used to override error codes.
- */
-extern int unix_ERR_class;
-extern int unix_ERR_code;
-extern NTSTATUS unix_ERR_ntstatus;
-
/*
* Used in chaining code.
*/
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 2b3140783b..e19c51884f 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -97,9 +97,6 @@
#define CHECK_WRITE(fsp) if (!(fsp)->can_write) \
return(ERROR_DOS(ERRDOS,ERRbadaccess))
-#define CHECK_ERROR(fsp) if (HAS_CACHED_ERROR(fsp)) \
- return(CACHED_ERROR(fsp))
-
#define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \
NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) )
@@ -158,25 +155,23 @@
#define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx)))
#define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx)))
-/* Macro to cache an error in a write_bmpx_struct */
-#define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \
- w->wr_discard = True, -1)
/* Macro to test if an error has been cached for this fnum */
#define HAS_CACHED_ERROR(fsp) ((fsp)->wbmpx_ptr && \
(fsp)->wbmpx_ptr->wr_discard)
/* Macro to turn the cached error into an error packet */
#define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__)
-/* these are the datagram types */
-#define DGRAM_DIRECT_UNIQUE 0x10
-
-#define ERROR_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,False,__LINE__,__FILE__)
-#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,True,__LINE__,__FILE__)
-#define ERROR_NT(status) error_packet(outbuf,status,0,0,False,__LINE__,__FILE__)
-#define ERROR_BOTH(status,class,code) error_packet(outbuf,status,class,code,False,__LINE__,__FILE__)
+#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
+#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_INVALID,__LINE__,__FILE__)
+#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__)
+#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__)
+#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__)
/* this is how errors are generated */
-#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
+#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__)
+
+/* these are the datagram types */
+#define DGRAM_DIRECT_UNIQUE 0x10
#define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x))
diff --git a/source3/smbd/error.c b/source3/smbd/error.c
index d611e0ef87..6988d74f91 100644
--- a/source3/smbd/error.c
+++ b/source3/smbd/error.c
@@ -20,23 +20,43 @@
#include "includes.h"
-/* these can be set by some functions to override the error codes */
-int unix_ERR_class=SMB_SUCCESS;
-int unix_ERR_code=0;
-NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK;
-
/* From lib/error.c */
extern struct unix_error_map unix_dos_nt_errmap[];
+/* these can be set by some functions to override the error codes */
+static int override_ERR_class;
+static int override_ERR_code;
+static NTSTATUS override_ERR_ntstatus;
+
/****************************************************************************
- Ensure we don't have any errors cached.
+ Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors.
+ Setting status only and eclass and ecode to -1 forces NT errors.
****************************************************************************/
-void clear_cached_errors(void)
+void set_saved_error_triple(int eclass, int ecode, NTSTATUS status)
+{
+ override_ERR_class = eclass;
+ override_ERR_code = ecode;
+ override_ERR_ntstatus = status;
+}
+
+/****************************************************************************
+ Return the current settings of the error triple. Return True if any are set.
+****************************************************************************/
+
+BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus)
{
- unix_ERR_class = SMB_SUCCESS;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
+ if (peclass) {
+ *peclass = override_ERR_class;
+ }
+ if (pecode) {
+ *pecode = override_ERR_code;
+ }
+ if (pstatus) {
+ *pstatus = override_ERR_ntstatus;
+ }
+
+ return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus));
}
/****************************************************************************
@@ -46,36 +66,29 @@ void clear_cached_errors(void)
int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file)
{
write_bmpx_struct *wbmpx = fsp->wbmpx_ptr;
-
int32 eclass = wbmpx->wr_errclass;
int32 err = wbmpx->wr_error;
+ NTSTATUS ntstatus = wbmpx->wr_status;
/* We can now delete the auxiliary struct */
- free((char *)wbmpx);
- fsp->wbmpx_ptr = NULL;
- return error_packet(outbuf,NT_STATUS_OK,eclass,err,False,line,file);
+ SAFE_FREE(fsp->wbmpx_ptr);
+ return error_packet(outbuf,eclass,err,ntstatus,line,file);
}
/****************************************************************************
Create an error packet from errno.
****************************************************************************/
-int unix_error_packet(char *outbuf,int def_class,uint32 def_code,
- int line, const char *file)
+int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file)
{
int eclass=def_class;
int ecode=def_code;
- NTSTATUS ntstatus = NT_STATUS_OK;
+ NTSTATUS ntstatus = def_status;
int i=0;
- if (unix_ERR_class != SMB_SUCCESS) {
- eclass = unix_ERR_class;
- ecode = unix_ERR_code;
- ntstatus = unix_ERR_ntstatus;
- unix_ERR_class = SMB_SUCCESS;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- } else {
+ if (errno != 0) {
+ DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno)));
+
while (unix_dos_nt_errmap[i].dos_class != 0) {
if (unix_dos_nt_errmap[i].unix_error == errno) {
eclass = unix_dos_nt_errmap[i].dos_class;
@@ -87,39 +100,44 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,
}
}
- return error_packet(outbuf,ntstatus,eclass,ecode,False,line,file);
+ return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
}
/****************************************************************************
Create an error packet. Normally called using the ERROR() macro.
+ Setting eclass and ecode only and status to NT_STATUS_OK forces DOS errors.
+ Setting status only and eclass and ecode to zero forces NT errors.
+ If the override errors are set they take precedence over any passed in values.
****************************************************************************/
-int error_packet(char *outbuf,NTSTATUS ntstatus,
- uint8 eclass,uint32 ecode,BOOL force_dos, int line, const char *file)
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
{
int outsize = set_message(outbuf,0,0,True);
extern uint32 global_client_caps;
+ BOOL force_nt_status = False;
+ BOOL force_dos_status = False;
+
+ if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) {
+ eclass = override_ERR_class;
+ ecode = override_ERR_code;
+ ntstatus = override_ERR_ntstatus;
+ override_ERR_class = SMB_SUCCESS;
+ override_ERR_code = 0;
+ override_ERR_ntstatus = NT_STATUS_OK;
+ }
- if (errno != 0)
- DEBUG(3,("error string = %s\n",strerror(errno)));
-
-#if defined(DEVELOPER)
- if (unix_ERR_class != SMB_SUCCESS || unix_ERR_code != 0 || !NT_STATUS_IS_OK(unix_ERR_ntstatus))
- smb_panic("logic error in error processing");
-#endif
-
- /*
- * We can explicitly force 32 bit error codes even when the
- * parameter "nt status" is set to no by pre-setting the
- * FLAGS2_32_BIT_ERROR_CODES bit in the smb_flg2 outbuf.
- * This is to allow work arounds for client bugs that are needed
- * when talking with clients that normally expect nt status codes. JRA.
- */
-
- if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32) && (!force_dos)) {
- if (NT_STATUS_V(ntstatus) == 0 && eclass)
+ if (eclass == (uint8)-1) {
+ force_nt_status = True;
+ } else if (NT_STATUS_IS_INVALID(ntstatus)) {
+ force_dos_status = True;
+ }
+
+ if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) {
+ /* We're returning an NT error. */
+ if (NT_STATUS_V(ntstatus) == 0 && eclass) {
ntstatus = dos_to_ntstatus(eclass, ecode);
+ }
SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus));
SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n",
@@ -127,22 +145,23 @@ int error_packet(char *outbuf,NTSTATUS ntstatus,
(int)CVAL(outbuf,smb_com),
smb_fn_name(CVAL(outbuf,smb_com)),
nt_errstr(ntstatus)));
- return outsize;
- }
-
- if (eclass == 0 && NT_STATUS_V(ntstatus))
- ntstatus_to_dos(ntstatus, &eclass, &ecode);
-
- SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES);
- SSVAL(outbuf,smb_rcls,eclass);
- SSVAL(outbuf,smb_err,ecode);
-
- DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n",
- file, line,
- (int)CVAL(outbuf,smb_com),
- smb_fn_name(CVAL(outbuf,smb_com)),
- eclass,
- ecode));
+ } else {
+ /* We're returning a DOS error only. */
+ if (eclass == 0 && NT_STATUS_V(ntstatus)) {
+ ntstatus_to_dos(ntstatus, &eclass, &ecode);
+ }
+
+ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES);
+ SSVAL(outbuf,smb_rcls,eclass);
+ SSVAL(outbuf,smb_err,ecode);
+
+ DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n",
+ file, line,
+ (int)CVAL(outbuf,smb_com),
+ smb_fn_name(CVAL(outbuf,smb_com)),
+ eclass,
+ ecode));
+ }
return outsize;
}
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 143c119693..e893e9fefc 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -95,15 +95,13 @@ files_struct *file_new(connection_struct *conn)
}
DEBUG(0,("ERROR! Out of file structures\n"));
- unix_ERR_class = ERRSRV;
- unix_ERR_code = ERRnofids;
+ set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES);
return NULL;
}
fsp = SMB_MALLOC_P(files_struct);
if (!fsp) {
- unix_ERR_class = ERRSRV;
- unix_ERR_code = ERRnofids;
+ set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY);
return NULL;
}
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 5f5854cda3..6abea78239 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -889,10 +889,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if (create_options & FILE_NON_DIRECTORY_FILE) {
restore_case_semantics(conn, file_attributes);
- SSVAL(outbuf, smb_flg2,
- SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
+ return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
@@ -909,7 +907,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
END_PROFILE(SMBntcreateX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
@@ -1493,8 +1490,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (create_options & FILE_NON_DIRECTORY_FILE) {
restore_case_semantics(conn, file_attributes);
- SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
+ return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
@@ -1510,7 +1506,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
restore_case_semantics(conn, file_attributes);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
@@ -1782,12 +1777,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
&access_mode,&smb_action);
if (!fsp1) {
- status = NT_STATUS_ACCESS_DENIED;
- if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- status = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
+ get_saved_error_triple(NULL, NULL, &status);
+ if (NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
return status;
}
@@ -1796,12 +1790,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
&access_mode,&smb_action);
if (!fsp2) {
- status = NT_STATUS_ACCESS_DENIED;
- if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- status = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
+ get_saved_error_triple(NULL, NULL, &status);
+ if (NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
close_file(fsp1,False);
return status;
}
@@ -1907,7 +1900,6 @@ int reply_ntrename(connection_struct *conn,
END_PROFILE(SMBntrename);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return ERROR_NT(status);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index baea165d2a..41ced42034 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -76,9 +76,7 @@ static void check_for_pipe(const char *fname)
strlower_m(s);
if (strstr(s,"pipe/")) {
DEBUG(3,("Rejecting named pipe open for %s\n",fname));
- unix_ERR_class = ERRSRV;
- unix_ERR_code = ERRaccess;
- unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED;
+ set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED);
}
}
@@ -250,9 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
/* Don't create files with Microsoft wildcard characters. */
if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRinvalidname;
- unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID;
+ set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID);
return False;
}
@@ -487,9 +483,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
fname ));
/* Use errno to map to correct error. */
- unix_ERR_class = SMB_SUCCESS;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
+ set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK);
return False;
}
@@ -529,10 +523,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
(!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) {
DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n",
fname ));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
-
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return False;
}
@@ -557,10 +548,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) {
DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n",
fname ));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
-
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return False;
}
@@ -573,18 +561,14 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) {
DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n",
fname ));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return False;
}
#if 0
/* Bluarc test may need this ... needs further investigation. */
if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return False;
}
#endif
@@ -614,10 +598,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
deny_mode,old_deny_mode,old_open_mode,
(int)share->pid,fname, fcbopen, *flags, access_allowed));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
-
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return False;
}
@@ -768,10 +749,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi
DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
SAFE_FREE(old_shares);
- errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return -1;
}
@@ -835,9 +813,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n"
if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) {
free_broken_entry_list(broken_entry_list);
errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return -1;
}
@@ -1104,9 +1080,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
delete_defered_open_entry_record(conn, dib.dev, dib.inode);
unlock_share_entry(conn, dib.dev, dib.inode);
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return NULL;
}
/* Ensure we don't reprocess this message. */
@@ -1136,11 +1110,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
break;
}
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRinvalidparam;
- unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE;
- /* need to reset errno or DEVELOPER will cause us to coredump */
- errno = 0;
+ /* Cause caller to force dos errors. */
+ set_saved_error_triple(ERRDOS, ERRbadaccess, NT_STATUS_INVALID);
return NULL;
}
@@ -1163,13 +1134,9 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
/* this is for OS/2 long file names - say we don't support them */
if (strstr(fname,".+,;=[].")) {
- unix_ERR_class = ERRDOS;
/* OS/2 Workplace shell fix may be main code stream in a later release. */
- unix_ERR_code = ERRcannotopen;
- unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND);
DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n"));
- /* need to reset errno or DEVELOPER will cause us to coredump */
- errno = 0;
return NULL;
}
@@ -1232,11 +1199,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
desired_access = FILE_READ_DATA|FILE_WRITE_DATA;
break;
default:
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRinvalidparam;
- unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE;
- /* need to reset errno or DEVELOPER will cause us to coredump */
- errno = 0;
+ /* Force DOS error. */
+ set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID);
return NULL;
}
@@ -1311,9 +1275,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open ));
if (!fsp_open && errno) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRnoaccess;
- unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED;
+ /* Default error. */
+ set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED);
}
/*
@@ -1321,9 +1284,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
* the braindead 1 second delay.
*/
- if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) {
- /* The fsp->open_time here represents the current time of day. */
- defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+ if (!internal_only_open) {
+ NTSTATUS status;
+ get_saved_error_triple(NULL, NULL, &status);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
+ /* The fsp->open_time here represents the current time of day. */
+ defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+ }
}
unlock_share_entry(conn, dev, inode);
@@ -1333,9 +1300,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
* We have detected a sharing violation here
* so return the correct error code
*/
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
}
file_free(fsp);
return NULL;
@@ -1407,7 +1372,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
* the braindead 1 second delay.
*/
- if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) {
+ NTSTATUS status;
+ get_saved_error_triple(NULL, NULL, &status);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
/* The fsp->open_time here represents the current time of day. */
defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
}
@@ -1419,9 +1386,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
* We have detected a sharing violation here, so
* return the correct code.
*/
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
return NULL;
}
@@ -1549,9 +1514,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
fd_close(conn,fsp);
file_free(fsp);
ntstatus_to_dos(result, &u_e_c, &u_e_code);
- unix_ERR_ntstatus = result;
- unix_ERR_class = u_e_c;
- unix_ERR_code = u_e_code;
+ set_saved_error_triple(u_e_c, u_e_code, result);
return NULL;
}
}
@@ -1704,7 +1667,7 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR
fname, strerror(errno) ));
file_free(fsp);
/* Ensure we return the correct NT status to the client. */
- unix_ERR_ntstatus = status;
+ set_saved_error_triple(0, 0, status);
return NULL;
}
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index a55d5443d5..ea3ac43744 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -934,6 +934,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id,
abort();
}
+ /* We know we have no saved errors here. */
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+
if( DEBUGLVL( 3 ) ) {
dbgtext( "oplock_break: returning success for " );
dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id );
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 54837c3b9a..3043cadfd8 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -211,6 +211,7 @@ BOOL open_was_deferred(uint16 mid)
for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
if (SVAL(pml->buf.data,smb_mid) == mid) {
+ set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK);
return True;
}
}
@@ -859,6 +860,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
pid = sys_getpid();
errno = 0;
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+
last_message = type;
/* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index e2de97c478..aef9755122 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1206,7 +1206,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
END_PROFILE(SMBopen);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
@@ -1304,7 +1303,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
END_PROFILE(SMBopenX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
@@ -1453,7 +1451,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
END_PROFILE(SMBcreate);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
@@ -1537,7 +1534,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
END_PROFILE(SMBctemp);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
@@ -1599,20 +1595,19 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
return NT_STATUS_OK;
/* We need a better way to return NT status codes from open... */
- unix_ERR_class = 0;
- unix_ERR_code = 0;
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
- NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
- if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- ret = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- return ret;
+ NTSTATUS ret;
+ if (get_saved_error_triple(NULL, NULL, &ret)) {
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+ return ret;
+ }
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+ return NT_STATUS_ACCESS_DENIED;
}
close_file(fsp,False);
return NT_STATUS_OK;
@@ -1672,22 +1667,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_
don't do it here as we'll get it wrong. */
/* We need a better way to return NT status codes from open... */
- unix_ERR_class = 0;
- unix_ERR_code = 0;
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
- NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
- if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
- ret = unix_ERR_ntstatus;
- else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- ret = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- return ret;
+ NTSTATUS ret;
+ if (get_saved_error_triple(NULL, NULL, &ret)) {
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+ return ret;
+ }
+ set_saved_error_triple(0, 0, NT_STATUS_OK);
+ return NT_STATUS_ACCESS_DENIED;
}
close_file(fsp,False);
}
@@ -1856,7 +1848,6 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return ERROR_NT(status);
@@ -3456,21 +3447,6 @@ NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL b
return map_nt_error_from_unix(errno);
}
- /* The following 2 clauses set explicit DOS error codes. JRA. */
- if (ms_has_wild(directory)) {
- DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRinvalidname;
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
-
- if( strchr_m(directory, ':')) {
- DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory));
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRinvalidname;
- return NT_STATUS_NOT_A_DIRECTORY;
- }
-
if (bad_path) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
@@ -3521,6 +3497,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if( strchr_m(directory, ':')) {
+ DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
+ END_PROFILE(SMBmkdir);
+ return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
+ }
+
status = mkdir_internal(conn, directory,bad_path);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
@@ -3530,7 +3512,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
if (lp_inherit_owner(SNUM(conn))) {
/* Ensure we're checking for a symlink here.... */
/* We don't want to get caught by a symlink racer. */
-
+
if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
END_PROFILE(SMBmkdir);
return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -4328,7 +4310,6 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
END_PROFILE(SMBmv);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return ERROR_NT(status);
@@ -4592,8 +4573,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_DOS(ERRDOS,error);
} else {
if((errno == ENOENT) && (bad_path1 || bad_path2)) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
+ set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
}
END_PROFILE(SMBcopy);
return(UNIXERROR(ERRDOS,error));
@@ -5149,7 +5129,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
CHECK_FSP(fsp,conn);
CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
+ if (HAS_CACHED_ERROR(fsp)) {
+ return(CACHED_ERROR(fsp));
+ }
tcount = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
@@ -5292,8 +5274,12 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
END_PROFILE(SMBwriteBs);
return(ERROR_DOS(ERRHRD,ERRdiskfull));
}
+ wbms->wr_errclass = ERRHRD;
+ wbms->wr_error = ERRdiskfull;
+ wbms->wr_status = NT_STATUS_DISK_FULL;
+ wbms->wr_discard = True;
END_PROFILE(SMBwriteBs);
- return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+ return -1;
}
/* Increment the total written, if this matches tcount
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index e53b47c1f4..a497e8d81c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -814,7 +814,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
talloc_destroy(ctx);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
- clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);