Jeremy.
#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))
#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. */
} 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
*/
#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.
*/
#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))
#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));
}
/****************************************************************************
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;
}
}
- 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",
(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;
}
}
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;
}
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;
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);
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;
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);
&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;
}
&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;
}
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);
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);
}
}
/* 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;
}
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;
}
(!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;
}
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;
}
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
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;
}
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;
}
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;
}
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. */
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;
}
/* 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;
}
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;
}
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);
}
/*
* 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);
* 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;
* 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);
}
* 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;
}
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;
}
}
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;
}
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 );
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;
}
}
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. */
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);
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);
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);
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);
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;
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);
}
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);
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;
}
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);
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));
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);
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));
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);
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
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);