diff --git a/include/nwnss/include/msg.h b/include/nwnss/include/msg.h new file mode 100644 index 0000000..87ca3ce --- /dev/null +++ b/include/nwnss/include/msg.h @@ -0,0 +1,315 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Storage Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2007-04-12 01:48:56 +0530 (Thu, 12 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1932 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define the message structures used by NSS and the bit masks and + | other values used by NSS APIs. + +-------------------------------------------------------------------------*/ +#ifndef _NSS_MSG_H_ +#define _NSS_MSG_H_ + +#ifndef _ZOMNI_H_ +# include +#endif + +#ifndef _ZMSG_H_ +# include +#endif + +#ifndef _QUE_H_ +# include +#endif + +#ifndef _SLAB_H +# include +#endif + +typedef void *(*objfunc_t)(); /* Function returns a pointer to an object */ + +typedef struct XIPC_Msg_s +{ + zWorkProc_s work; + CIRlink_t link; + void *page; + struct net_s + { + LONG dataLength; + LONG type; + QUAD key; + LONG method; + Msg_s msg; + } net; +} XIPC_Msg_s; + + /* + * An Object is an instance of a Type. The Object holds the data + * while the Type has the methods. + */ +typedef struct mObject_s +{ + struct mType_s *o_type; /* Type of the object -- methods */ + NINT o_count; /* Number of references to object */ + DQlink_t o_instance; /* Other instances of this object type */ + NINT o_properties; + +#if 0 +// struct { +// NINT w_next; +//#define NUM_WHERE 32 +// char *w_where[NUM_WHERE]; +// } o_w; +#endif +} mObject_s; + +#if 0 +#define OBJ_TRACE(_obj) \ + ((_obj)->o_w.w_where[(_obj)->o_w.w_next++ & (NUM_WHERE-1)] = WHERE) +#endif + + /* + * A door maps a key to an object and keeps track of + * who owns the object. + */ +typedef struct mDoor_s +{ + mObject_s dr_obj; + struct mDoor_s *dr_next; + Key_t dr_key; + struct mManager_s *dr_owner; + DQlink_t dr_ownerList; +} mDoor_s; + + /* + * Managers create and own doors. It has a table of doors + * that it manages. In a more traditional system, this would + * be a process. + */ +typedef struct mManager_s +{ + mObject_s obj; + DQhead_t doors; /* All the doors this manager owns */ + DQhead_t types; /* All the types this manager created */ +} mManager_s; + + /* + * Each Door Manager can manage a number of different + * door types. This could also be thought of as a class. + * All the methods are held by the type. + * + * In addition to the method table, a number of standard + * functions can be set. If not supplied, a default function + * will be provided. + * preconstructor - used by objCache to initialize obj when + * slab is first allocated. Not called + * on subsequent allocations. + * constructor - called each time the object is allocated to + * initialize the object. Because no + * arguments can be passed, this is of + * limited use. + * destructor - called to clean up the object. + * notify - called to notify someone that the object + * is about to be destroyed. + * unregister - called when unregistering a type. Example: + * types that have doors, will use MSG_BreakDoor. + */ +#define MSG_INIT_TYPE(name, parent, objSize, numMethods, \ + preconstructor, constructor, destructor, notify, unregister)\ +{ \ + name, parent, objSize, numMethods, NULL, \ + (voidfunc_t)preconstructor, (objfunc_t)constructor, \ + (statusfunc_t)destructor, (voidfunc_t)notify, \ + (voidfunc_t)unregister, \ + { 0 } \ +} + +typedef struct mTypeHeader_s +{ + char *name; + struct mTypeHeader_s *parent; /* Weak inheritance */ + NINT objSize; + NINT numMethods; + mManager_s *manager; + voidfunc_t preconstructor; + objfunc_t constructor; + statusfunc_t destructor; // Used in multiple places + voidfunc_t notify; + voidfunc_t unregister; + DQlink_t typeList; + DQhead_t instances; + ObjCache_s objCache; +} mTypeHeader_s; + +typedef struct mType_s +{ + mTypeHeader_s hdr; + statusfunc_t method[1]; +} mType_s; + + /* + * The Manager Manager. + */ +#define NUM_MGR_METHODS 0 + +typedef struct mVirtualType_s /* Has no methods nor objects */ +{ + mTypeHeader_s hdr; +} mVirtualType_s; + +typedef STATUS (*MSG_RemoteMethod_t)( + mDoor_s *door, + NINT method, + Msg_s *msg); + +typedef STATUS (*MSG_RemoteMethodKey_t)( + mDoor_s *door, + NINT method, + Msg_s *msg, + mDoor_s *passedDoor); + + +extern mVirtualType_s DoorType; +extern mVirtualType_s ManagerType; +extern mManager_s *Manager; + +/********************** + * Function prototypes + */ +STATUS MSG_DestroyKey(Key_t key); + +STATUS NullMethod(Msg_s *msg); + +STATUS MSG_Call( + Key_t key, + NINT method, + Msg_s *msg); + +STATUS MSG_SendKey( + Key_t key, + NINT method, + Msg_s *msg); + +STATUS zMSG_Call( + Key_t key, + NINT method, + Msg_s *msg); + +STATUS mpkMSG_Call( + Key_t key, + NINT method, + Msg_s *msg); + +STATUS MSG_Send( + Key_t key, + NINT method, + Msg_s *msg); + +void MSG_ChangeOwner( + mDoor_s *door, + mManager_s *owner); + +void *MSG_CreateDoor( + mTypeHeader_s *type, + mManager_s *manager, + NINT properties, + Key_t *retKey); + +void *MSG_CreateObject( + mTypeHeader_s *type); + +void MSG_ReleaseObject(mObject_s *obj); + +STATUS MSG_DestroyKey(Key_t key); + +STATUS MSG_RegisterType( + mTypeHeader_s *type, + mManager_s *manager); + +void MSG_UnregisterType(mTypeHeader_s *type); + +void MSG_KillManager(mManager_s *mgr); + +STATUS MSG_BreakDoor(mDoor_s *door); + +void MSG_BreakSetOfDoors( + mTypeHeader_s *type, + boolfunc_t match, + void *args); + +void MSG_DestroySetOfKeys( + mManager_s *owner, + mTypeHeader_s *type, + boolfunc_t match, + void *args); + +Key_t MSG_LookupShortKey(LONG key); + +void msgFreeDoor(mDoor_s *door); +extern NINT NSS_StoreCallers(void **, NINT,SNINT); + +#define MSG_USE_OBJECT(_obj) (++(_obj).o_count) +#define MSG_RELEASE_OBJECT(_obj) { \ + (--(_obj).o_count); \ + MSG_ReleaseObject( &(_obj)); \ +} + +#define MSG_USE_DOOR(_door) (++(_door)->dr_obj.o_count) + /* + * The door should be freed. + * By giving a door an initial count of zero, we + * can handle one time doors here without any + * additional tests. + * Re-get the type because the door may have + * been broken while the last message was being + * processed. + */ +#define MSG_RELEASE_DOOR(_door) \ +{ \ + --(_door)->dr_obj.o_count; \ + if ((_door)->dr_obj.o_count == 0) \ + { \ + msgFreeDoor(_door); \ + } \ +} + +void MSG_RegisterXIPC( + MSG_RemoteMethod_t call, + MSG_RemoteMethod_t send, + MSG_RemoteMethodKey_t sendKey); + +void MSG_UnregisterXIPC(void); + +extern mDoor_s *findDoor(Key_t key); +extern XIPC_Msg_s *allocMsgBuf(); +extern void freeMsgBuf(XIPC_Msg_s *xmsg); + +#endif diff --git a/include/nwnss/include/msgGen.h b/include/nwnss/include/msgGen.h new file mode 100644 index 0000000..05f1e3c --- /dev/null +++ b/include/nwnss/include/msgGen.h @@ -0,0 +1,288 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) General Message Structure defines + | + |--------------------------------------------------------------------------- + | + | $Author: randys $ + | $Date: 2005-06-06 19:11:43 +0530 (Mon, 06 Jun 2005) $ + | + | $RCSfile$ + | $Revision: 1029 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define the MESSAGE structure that is passed between layers of the + | system. + | + | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! + | + | This header file should ONLY be used for NSS internal development. + | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). + | Any other use may cause conflicts which NSS will NOT fix. + +-------------------------------------------------------------------------*/ +#ifndef _MSGGEN_H_ +#define _MSGGEN_H_ + +#ifndef _ZOMNI_H_ +# include +#endif + +#ifndef _XSTRING_H_ +# include +#endif + +#ifndef _LATCH_H_ +# include +#endif + +#ifndef _XERROR_H_ +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------------------- + * Pattern used to FILL the MSG structures with while DEBUG is enabled + *---------------------------------------------------------------------------*/ +#define COMN_MSG_FILL_PATTERN 0xA5A5A5A5 + +#if NSS_DEBUG IS_ENABLED +# define COMN_MSG_FILL(_buf,_size) \ + (zASSERT(((_size) & (sizeof(LONG)-1)) == 0), \ + LB_memlset((_buf),COMN_MSG_FILL_PATTERN,((_size)/sizeof(LONG)))) +#else +# define COMN_MSG_FILL(_buf,_size) ((void) 0) +#endif + + +/*--------------------------------------------------------------------------- + * This MACRO is used to INITIALIZE any structure with a pattern. This + * MUST be used before a MSG or PARAM struct is initialized with data. + *---------------------------------------------------------------------------*/ +#define COMN_STRUCT_INIT(_msg) \ + COMN_MSG_FILL(&(_msg),sizeof(_msg)) + +//#if NSS_DEBUG IS_ENABLED +//# define COMN_CHECK_STRUCT_INIT(_genMsg) zASSERT((_genMsg)->fillCheck == COMN_MSG_FILL_PATTERN) +//#else +//# define COMN_CHECK_STRUCT_INIT(_genMsg) ((void) 0) +//#endif + + +/*=========================================================================== + *=========================================================================== + *=========================================================================== + * + * This defines basic structures used to keep track of HANDLE ID's and + * their associated pointers. With these ID/POINTER pairs we can cache + * the pointers in memory so we don't have to keep resolveing the ID's + * + *=========================================================================== + *=========================================================================== + *===========================================================================*/ + +/*--------------------------------------------------------------------------- + * IDP for conections + *---------------------------------------------------------------------------*/ +typedef struct ConnectionIDP_s +{ + NINT id; /* connectionID */ + struct NSSConnection_s *ptr; +} ConnectionIDP_s; + +#define COMN_SET_CONNECTION_ID(_conIDP,_conid) \ + (((_conIDP)->id = (_conid)),((_conIDP)->ptr = NULL)) + + + +/*--------------------------------------------------------------------------- + * IDP for context handles + *---------------------------------------------------------------------------*/ +typedef struct ContextHandleIDP_s +{ + NINT id; /* contextHandleID */ + struct ContextHandleInfo_s *ptr; +} ContextHandleIDP_s; + +#define COMN_SET_CONTEXTHANDLE(_cxIDP,_cxid,_cxptr) \ + (((_cxIDP)->id = (_cxid)),((_cxIDP)->ptr = (_cxptr))) + +#define COMN_SET_CONTEXTHANDLE_ID(_cxIDP,_cxid) \ + COMN_SET_CONTEXTHANDLE(_cxIDP,_cxid,NULL) + + + +/*--------------------------------------------------------------------------- + * IDP for file handles + *---------------------------------------------------------------------------*/ +typedef struct FileHandleIDP_s +{ + Key_t key; + struct FileHandle_s *ptr; +} FileHandleIDP_s; + +#define COMN_SET_FILEHANDLE(_fhIDP,_fhkey,_fhptr) \ + (((_fhIDP)->key = (_fhkey)),((_fhIDP)->ptr = (_fhptr))) + +#define COMN_SET_FILEHANDLE_ID(_fhIDP,_fhkey) \ + COMN_SET_FILEHANDLE(_fhIDP,_fhkey,NULL) + + + +/*--------------------------------------------------------------------------- + * IDP for generic semantic agent handles + *---------------------------------------------------------------------------*/ +typedef struct SAHandleIDP_s +{ + NINT id; /* semantic Agent HandleID*/ + struct SAHandle_s *ptr; +} SAHandleIDP_s; + +#define COMN_SET_SAHANDLE(_sahIDP,_sahid,_sahptr) \ + (((_sahIDP)->id = (_sahid)),((_sahIDP)->ptr = (_sahptr))) + +#define COMN_SET_SAHANDLE_ID(_sahIDP,_sahid) \ + COMN_SET_SAHANDLE(_sahIDP,_sahid,NULL) + + + +/*--------------------------------------------------------------------------- + * IDP for search maps + *---------------------------------------------------------------------------*/ +typedef struct SearchMapIDP_s +{ + NINT id; /* searchMapID */ + struct SearchMap_s *ptr; +} SearchMapIDP_s; + +#define COMN_SET_SEARCHMAP(_smIDP,_smid,_smptr) \ + (((_smIDP)->id = (_smid)),((_smIDP)->ptr = (_smptr))) + +#define COMN_SET_SEARCHMAP_ID(_smIDP,_smid) \ + COMN_SET_SEARCHMAP(_smIDP,_smid,NULL) + + + +/*--------------------------------------------------------------------------- + * This contains GENERAL parameters across ALL APIs + *---------------------------------------------------------------------------*/ +typedef struct GeneralMsg_s +{ + STATUS errStatus; /* holds current status*/ + char *errStatusSetter; /* WHERE information. Used + * to determine who set errStatus last. + * This should be only used for + * debug purposes. + */ + ConnectionIDP_s pssConn; /* connection ID*/ + NINT taskID; /* taskID for this operation*/ + WORD saID; /* semantic agent making the call */ + WORD flags; /* to see if the openFiles have a + * latch already on the conn */ +} GeneralMsg_s; + + +/* Values for flags */ +#define FILEHANDLE_IS_XLATCHED 0x0001 +#define DO_NOT_SEND_EVENTS 0x0002 +#define DO_NOT_SEND_FSHOOKS 0x0004 +#define ALLOW_SECURE_ACCESS 0x0008 +#define DO_NOT_UNPACK_FMAP 0x0010 +#define COPY_FMAP_TO_SNAP 0x0020 +#define GM_FLAGS_INTERNAL_VOLUME 0x0040 /* Set if user is using an internal + * volume. The caller must set + * this bit for lookup of the volume + * to succeed. ZLSS uses internal + * volumes to store information + * about Logical Volumes in a Pool. + */ +#define ALLOW_INACTIVE_VOLUME 0x0080 /* Set by purgeLog processing to + * cause volume lookups to not + * require the volume to be active + */ +#define UPDATE_EXISTING_BEAST 0x0200 /* When unpacking the beast, it is + * not a new beast, but an existing + * beast that needs to be updated + * used by XLSS. + */ +#define DO_NOT_CHECK_SPACE_QUOTA 0x0400 /* If set, do not check for user space + * restriction and directory space + * restriction + */ +#define ALLOW_BST_STATE_PURGING 0x0800 /* WARNING --- DO NOT USE THIS + * UNLESS YOU KNOW EXACTLY WHAT + * YOU ARE DOING!!!! + * If set, this allows a beast + * to be looked up even if it's + * state is BST_STATE_PURGING, but + * only if it has a non-zero use + * count. + */ + +#define COMN_GENMSG_RESOLVE_CONNECTION(genMsg) \ + (((genMsg)->pssConn.ptr != NULL) ? (genMsg)->pssConn.ptr : COMN_DoResolveConnection((genMsg))) + +/* Note - must set saID and flags before calling COMN_GENMSG_RESOLVE_CONNECTION + * in this macro. COMN_DoResolveConnection sets some flags based on + * the saID field. + */ +#define COMN_SETUP_GENERAL_MSG(_genMsg,_conid,_ptaskid,_sagentID) \ + (ClearErrno((_genMsg)), \ + (_genMsg)->saID = (_sagentID), \ + (_genMsg)->flags = 0), \ + (_genMsg)->taskID = (_ptaskid), \ + COMN_SET_CONNECTION_ID(&(_genMsg)->pssConn,_conid), \ + COMN_GENMSG_RESOLVE_CONNECTION(_genMsg) + +#define COMN_SETUP_GENERAL_MSG_NOSA(_genMsg) \ + COMN_SETUP_GENERAL_MSG(_genMsg,zSYS_CONNECTION, \ + zNO_TASK,zSAGENT_NONE) + +#define COMN_SETUP_GENERAL_MSG_NO_CONNECTION_RESOLVE(_genMsg) \ + (ClearErrno((_genMsg)), \ + COMN_SET_CONNECTION_ID(&(_genMsg)->pssConn,zSYS_CONNECTION), \ + (_genMsg)->taskID = (zNO_TASK), \ + (_genMsg)->saID = (zSAGENT_NONE), \ + (_genMsg)->flags = 0) + +#define X_LATCH_SET_FLAG(genMsg, latch) \ +{ \ + X_LATCH(latch); \ + (genMsg)->flags |= FILEHANDLE_IS_XLATCHED; \ +} + +#define UNX_LATCH_SET_FLAG(genMsg, latch) \ +{ \ + UNX_LATCH(latch); \ + (genMsg)->flags &= ~FILEHANDLE_IS_XLATCHED; \ +} + + +#ifdef __cplusplus +} +#endif + +#endif /* _MSGGEN_H_ */ diff --git a/include/nwnss/public/zMsg.h b/include/nwnss/public/zMsg.h new file mode 100644 index 0000000..084256a --- /dev/null +++ b/include/nwnss/public/zMsg.h @@ -0,0 +1,182 @@ +/**************************************************************************** + | + | (C) Copyright 2001 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Storage Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2006-12-13 05:04:43 +0530 (Wed, 13 Dec 2006) $ + | + | $RCSfile$ + | $Revision: 1760 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define the message structures used by NSS and the bit masks and + | other values used by NSS APIs. + +-------------------------------------------------------------------------*/ +#ifndef _ZMSG_H_ +#define _ZMSG_H_ + +#ifndef _ZOMNI_H_ +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* + * Key properties. 'm' added because of conflicts with NWREG.H. + */ +#define mKEY_NOTIFY 0x1 +#define mKEY_DUPLICATE 0x2 +#define mKEY_1_USE 0x4 +#define mKEY_PASS_1_USE 0x8 +#define mKEY_PASS_N_USE 0x10 +#define mKEY_PASS_ANY (mKEY_PASS_1_USE | mKEY_PASS_N_USE) +#define mKEY_REMOTE 0x20 +#define mKEY_DYING 0x40 +#define mKEY_DESTRUCT 0x80 + +/* Valid properties when creating a door */ +#define mKEY_VALID_PROPERTIES (mKEY_NOTIFY | mKEY_DUPLICATE | mKEY_1_USE \ + | mKEY_PASS_ANY) + +#define INVALID_KEY 0 + + +/******************** + * Message Structure + * The following definitions of SystemMsg structure have been designed to + * allow application compiled on a 32 bit little-endian machine work on + * a 64 bit little-endian machine. + */ + +#define MAX_DATA_AREAS 2 + +#ifdef __LP64__ + #define zPADDING(_x) +#else + #define zPADDING(_x) LONG padding ## _x ; +#endif + +struct kernelDataArea_s +{ + void *start; + zPADDING(start); + NINT length; + zPADDING(length); +}; + +struct kernelSystemMsg_s +{ + STATUS status; /* Status of the operation */ + /* Placed first to match genMsg */ + BYTE numDataAreas;/* Number of data areas */ + BYTE readMask; /* Data areas that are readable */ + BYTE writeMask; /* Data areas that are writeable */ + BYTE padding[1]; + + char *where; /* Where in the code the status was set */ + zPADDING(where) + + Key_t passedKey; /* Key that was passed with the request */ + + struct mDoor_s *door; /* Door/obj msg was send through */ + zPADDING(door) + + struct mManager_s *owner; /* Owner of the object */ + zPADDING(owner) + + struct kernelDataArea_s data[MAX_DATA_AREAS]; + + voidfunc_t callback; /* Call back function */ + zPADDING(callback) +}; + +struct userDataArea_s +{ + QUAD start; + QUAD length; +}; + +struct userSystemMsg_s +{ + STATUS status; /* Status of the operation */ + /* Placed first to match genMsg */ + BYTE numDataAreas;/* Number of data areas */ + BYTE readMask; /* Data areas that are readable */ + BYTE writeMask; /* Data areas that are writeable */ + BYTE padding[1]; + + QUAD where; /* Where in the code the status was set */ + Key_t passedKey; /* Key that was passed with the request */ + QUAD door; /* Door/obj msg was send through */ + QUAD owner; /* Owner of the object */ + struct userDataArea_s data[MAX_DATA_AREAS]; + QUAD callback; /* Call back function */ +}; + +#ifdef __KERNEL__ +typedef struct kernelDataArea_s mDataArea_s; +typedef struct kernelSystemMsg_s mSystemMsg_s; +#else +typedef struct userDataArea_s mDataArea_s; +typedef struct userSystemMsg_s mSystemMsg_s; +#endif + +enum { DATA_AREA_CORRECT = + 1 / (sizeof(struct kernelDataArea_s) == sizeof(struct userDataArea_s)), + SYSTEM_MSG_CORRECT = + 1 / (sizeof(struct kernelSystemMsg_s) == sizeof(struct userSystemMsg_s)) +}; + + + /* This number should be small but engineered to the + * system, so the message can be passed in registers + * on a machine with a reasonable number of registers. + * (Remember, the header will have to passed in the + * registers too). + */ +#define MSG_BODY_SIZE 128 + +typedef union mBody_u +{ + QUAD quad[MSG_BODY_SIZE/sizeof(QUAD)]; + LONG ulng[MSG_BODY_SIZE/sizeof(LONG)]; + WORD word[MSG_BODY_SIZE/sizeof(WORD)]; + BYTE byte[MSG_BODY_SIZE/sizeof(BYTE)]; +} mBody_u; + +typedef struct Msg_s +{ + mSystemMsg_s sys; + mBody_u body; +} Msg_s; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/nwnss/CMakeLists.txt b/src/nwnss/CMakeLists.txt index 9e00c1f..2bebb44 100644 --- a/src/nwnss/CMakeLists.txt +++ b/src/nwnss/CMakeLists.txt @@ -102,6 +102,7 @@ add_library(nwnss SHARED nss/lib/bitmap.c nss/lib/crc.c nss/lib/hash.c + nss/lib/setErrno.c nss/msg/slab.c unicodeTableBuild.c utcUserland.c) diff --git a/src/nwnss/nss/lib/setErrno.c b/src/nwnss/nss/lib/setErrno.c new file mode 100644 index 0000000..55f12d3 --- /dev/null +++ b/src/nwnss/nss/lib/setErrno.c @@ -0,0 +1,167 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2006-09-14 03:22:08 +0530 (Thu, 14 Sep 2006) $ + | + | $RCSfile$ + | $Revision: 1529 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | General PSS Error handling routines + +-------------------------------------------------------------------------*/ +#include + +#include + +#include +#include +#include + +/* Linux userspace port: NSS kernel RunningProcess is represented by 0 here. */ +#ifndef RunningProcess +#define RunningProcess ((ADDR)0) +#endif + +#if NSS_DEBUG IS_ENABLED +#define ERROR_LOG_SIZE 4000 +#else +#define ERROR_LOG_SIZE 2000 +#endif + + +typedef struct ErrorLog_s +{ + STATUS errCode; + char *where; + LONG utcTime; + ADDR thread; +} ErrorLog_s; + +typedef struct NSSErrorLog_s +{ + QUAD NEL_ErrorCount; + NINT NEL_ErrorLogSize; + ErrorLog_s *NEL_NextError; + ErrorLog_s NEL_ErrorLog[ERROR_LOG_SIZE]; +} NSSErrorLog_s; + + +NSSErrorLog_s NSS_ErrorItems = +{ + 0, ERROR_LOG_SIZE, &NSS_ErrorItems.NEL_ErrorLog[0] +}; + + +#define LOG_ERROR(_status, _where) \ +{ \ + NSS_ErrorItems.NEL_NextError->errCode = _status; \ + NSS_ErrorItems.NEL_NextError->where = _where; \ + NSS_ErrorItems.NEL_NextError->utcTime = GetUTCTime(); \ + NSS_ErrorItems.NEL_NextError->thread = RunningProcess; \ + NSS_ErrorItems.NEL_ErrorCount += 1; \ + if (++NSS_ErrorItems.NEL_NextError == &NSS_ErrorItems.NEL_ErrorLog[ERROR_LOG_SIZE]) \ + { \ + NSS_ErrorItems.NEL_NextError = &NSS_ErrorItems.NEL_ErrorLog[0]; \ + } \ +} + + + +void LB_ForceSetErrnoWithWhere( GeneralMsg_s *genMsg, STATUS status, char *where ) +{ + genMsg->errStatus = status; + genMsg->errStatusSetter = where; + LOG_ERROR(status, where); + return; +} + + +/************************************************************************** + * This will set an ERROR into the ERRNO field of the msg structure. + * Following are the rules for setting errors: + * - OUT OF SPACE errors are always set. + * - OUT OF MEMORY errors are set if current error is not OUT_OF_SPACE. + * - We will only set an error if there is not currently an error. + ***************************************************************************/ +void LB_SetErrno( + GeneralMsg_s *genMsg, + STATUS status, + char *where + ) +{ + zASSERT(genMsg != NULL); + if (genMsg != NULL) + { + /*COMN_CHECK_STRUCT_INIT(genMsg);*/ + if (genMsg->errStatus == zOK) + { + genMsg->errStatus = status; + genMsg->errStatusSetter = where; + } + else + { + if ((genMsg->errStatus != zERR_OUT_OF_SPACE) && + ((status == zERR_NO_MEMORY) || + (status == zERR_OUT_OF_SPACE))) + { + genMsg->errStatus = status; + genMsg->errStatusSetter = where; + } + } + } + LOG_ERROR(status, where); +} + + /* + * SetStatus replaces SetErrno as we convert over to message layer + */ +void MSG_SetStatus ( + void *voidMsg, + STATUS status, + char *where) +{ + Msg_s *msg = voidMsg; + + zASSERT(msg != NULL); + if (msg->sys.status == zOK) + { + msg->sys.status = status; + msg->sys.where = (QUAD)(uintptr_t)where; + } + else + { + if ((msg->sys.status != zERR_OUT_OF_SPACE) && + ((status == zERR_NO_MEMORY) || + (status == zERR_OUT_OF_SPACE))) + { + msg->sys.status = status; + msg->sys.where = (QUAD)(uintptr_t)where; + } + } + LOG_ERROR(status, where); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index af997d3..c8d5004 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,7 @@ if(MARS_NWE_BUILD_NWFS_TESTS) add_subdirectory(nwnss/parse) add_subdirectory(nwnss/fsm) add_subdirectory(nwnss/latch) + add_subdirectory(nwnss/xerror) add_subdirectory(nwnss/zalloc) add_subdirectory(nwnss/stdio) add_subdirectory(nwnss/wio) diff --git a/tests/nwnss/CMakeLists.txt b/tests/nwnss/CMakeLists.txt index 8cce955..0686023 100644 --- a/tests/nwnss/CMakeLists.txt +++ b/tests/nwnss/CMakeLists.txt @@ -35,3 +35,5 @@ add_subdirectory(worktodo) add_subdirectory(xctype) add_subdirectory(xstring) add_subdirectory(zalloc) + +add_subdirectory(xerror) diff --git a/tests/nwnss/xerror/CMakeLists.txt b/tests/nwnss/xerror/CMakeLists.txt new file mode 100644 index 0000000..3db14cd --- /dev/null +++ b/tests/nwnss/xerror/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(test_nwnss_xerror test_nwnss_xerror.c) +target_link_libraries(test_nwnss_xerror PRIVATE mars_nwe::nwnss) +add_test(NAME nwnss.xerror COMMAND test_nwnss_xerror) diff --git a/tests/nwnss/xerror/test_nwnss_xerror.c b/tests/nwnss/xerror/test_nwnss_xerror.c new file mode 100644 index 0000000..8fc910b --- /dev/null +++ b/tests/nwnss/xerror/test_nwnss_xerror.c @@ -0,0 +1,68 @@ +#include +#include +#include + +#include +#include + +#define CHECK(expr) do { \ + if (!(expr)) { \ + fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #expr); \ + return 1; \ + } \ +} while (0) + +static int check_general_errno(void) +{ + GeneralMsg_s genMsg; + + genMsg.errStatus = zOK; + genMsg.errStatusSetter = NULL; + + LB_SetErrno(&genMsg, zERR_FAILURE, "first"); + CHECK(genMsg.errStatus == zERR_FAILURE); + CHECK(genMsg.errStatusSetter != NULL); + + LB_SetErrno(&genMsg, zERR_NO_MEMORY, "oom"); + CHECK(genMsg.errStatus == zERR_NO_MEMORY); + + LB_SetErrno(&genMsg, zERR_FAILURE, "ignored"); + CHECK(genMsg.errStatus == zERR_NO_MEMORY); + + LB_ForceSetErrnoWithWhere(&genMsg, zERR_FAILURE, "forced"); + CHECK(genMsg.errStatus == zERR_FAILURE); + CHECK(genMsg.errStatusSetter != NULL); + + return 0; +} + +static int check_msg_status(void) +{ + Msg_s msg; + + msg.sys.status = zOK; + msg.sys.where = 0; + + MSG_SetStatus(&msg, zERR_FAILURE, "first"); + CHECK(msg.sys.status == zERR_FAILURE); + CHECK(msg.sys.where != 0); + + MSG_SetStatus(&msg, zERR_OUT_OF_SPACE, "space"); + CHECK(msg.sys.status == zERR_OUT_OF_SPACE); + + MSG_SetStatus(&msg, zERR_FAILURE, "ignored"); + CHECK(msg.sys.status == zERR_OUT_OF_SPACE); + + return 0; +} + +int main(void) +{ + if (check_general_errno() != 0) { + return 1; + } + if (check_msg_status() != 0) { + return 1; + } + return 0; +}