r6172: Tidy up error processing significantly. Remove unix_ERR_XXX global nastyness.
authorJeremy Allison <jra@samba.org>
Fri, 1 Apr 2005 23:11:28 +0000 (23:11 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:56:27 +0000 (10:56 -0500)
Jeremy.

12 files changed:
source/include/nt_status.h
source/include/nterr.h
source/include/smb.h
source/include/smb_macros.h
source/smbd/error.c
source/smbd/files.c
source/smbd/nttrans.c
source/smbd/open.c
source/smbd/oplock.c
source/smbd/process.c
source/smbd/reply.c
source/smbd/trans2.c

index 9747f73eb18a465133e6d9854e56bc274813fe24..ab768258df17fbccf04ad58c4567b9a1a00e2d91 100644 (file)
@@ -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))
index 6cf5a756d297ae4aa3a1e6062b1a2728fa4437ed..417719625e712d9f8af737a570197e7eb41ff815 100644 (file)
@@ -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. */
 
index efa74436ee707e2e5bdc33798e4c6be28fb1572e..d12459c2f986e5a3dd9a73b4420a5a6021ab0b6a 100644 (file)
@@ -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.
  */
index 2b3140783bf642b324bc1a042e9fff4394497e23..e19c51884ff8315b405dd87f24f4cb3dea175156 100644 (file)
@@ -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) )
 
 #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))
 
index d611e0ef873af4812b3b52439612d8d975720761..6988d74f91e276e4df5f65fd7bb952c0fceffa21 100644 (file)
 
 #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;
 }
index 143c1196937585687f8d2dbc0ccc4cb48edf7ee3..e893e9fefc1cc7df78a10357d5d85b8c9c063890 100644 (file)
@@ -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;
        }
 
index 5f5854cda370cabdf832a4fa40c373ebfa026dbc..6abea78239fe603bc2d0f9ae0f5a1738d745d5ed 100644 (file)
@@ -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);
index baea165d2a4acee747fecf25107aa2c9d59c4e7d..41ced420344c6928d9ccd4b295ae9c9189b3ae65 100644 (file)
@@ -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;
                        }
 
index a55d5443d56b3cbfcd556a1dbdc56628afb8f18a..ea3ac4374497e4647b1d9b47cd16723cbe5c8967 100644 (file)
@@ -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 );
index 54837c3b9ae8aa43af6250e294e745962d438d99..3043cadfd81a9b301bfe9a0bb9b2c47ea51a5b52 100644 (file)
@@ -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. */
index e2de97c47853f6c148121fa4753ccd9542941de2..aef9755122f14574ee9d7cca8d9ac933ee867ce5 100644 (file)
@@ -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
index e53b47c1f4c799ae125af13e0b4ae1f2c2e5309b..a497e8d81c1d6eacd6279115de7c2886618f89ba 100644 (file)
@@ -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);