diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-09-12 14:16:22 +0000 |
---|---|---|
committer | <> | 2014-10-24 11:04:40 +0000 |
commit | a77e3a63f004e6ee789fa05e4a5bbc333b1529f1 (patch) | |
tree | efe8a68996c19b7b0765ebc689937721d1d99cf7 /common.h | |
download | sysv-ipc-tarball-master.tar.gz |
Imported from /home/lorry/working-area/delta_python-packages_sysv-ipc-tarball/sysv_ipc-0.6.8.tar.gz.HEADsysv_ipc-0.6.8master
Diffstat (limited to 'common.h')
-rw-r--r-- | common.h | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/common.h b/common.h new file mode 100644 index 0000000..89fa376 --- /dev/null +++ b/common.h @@ -0,0 +1,212 @@ +#include "Python.h" +#include "structmember.h" + +#if PY_MAJOR_VERSION >= 0x02050000 +#define PY_SSIZE_T_CLEAN +#define PY_STRING_LENGTH_MAX PY_SSIZE_T +#else +#define PY_STRING_LENGTH_MAX INT_MAX +#endif + +// define Py_TYPE for versions before Python 2.6 +#ifndef Py_TYPE +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + +// define PyVarObject_HEAD_INIT for versions before Python 2.6 +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif + +/* In sys/ipc.h under OS X, I get stuck with the old, "do not use" version +of the ipc_perm struct. This is unavoidable because Python.h #undefs +_POSIX_C_SOURCE and _XOPEN_SOURCE. This causes cdefs.h to #define +__DARWIN_UNIX03 to 0 (implying the "default" compilation environment, as +opposed to "strict") and therefore I get the crappy, old version of the +struct. I don't think there's any way around this unless Python changes +its headers. +*/ +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <sys/msg.h> + +#include "probe_results.h" + +/* Struct to contain a key which can be None */ +typedef struct { + int is_none; + key_t value; +} NoneableKey; + + +/* These identifiers are prefixed with SVIFP_ which stands for SysV Ipc +For Python. It's really just a random string of letters to prevent clashes +with other constants (as happens with SHM_SIZE on AIX). +*/ +enum GET_SET_IDENTIFIERS { + SVIFP_IPC_PERM_UID = 1, + SVIFP_IPC_PERM_GID, + SVIFP_IPC_PERM_CUID, + SVIFP_IPC_PERM_CGID, + SVIFP_IPC_PERM_MODE, + SVIFP_SEM_OTIME, + SVIFP_SHM_SIZE, + SVIFP_SHM_LAST_ATTACH_TIME, + SVIFP_SHM_LAST_DETACH_TIME, + SVIFP_SHM_LAST_CHANGE_TIME, + SVIFP_SHM_CREATOR_PID, + SVIFP_SHM_LAST_AT_DT_PID, + SVIFP_SHM_NUMBER_ATTACHED, + SVIFP_MQ_LAST_SEND_TIME, + SVIFP_MQ_LAST_RECEIVE_TIME, + SVIFP_MQ_LAST_CHANGE_TIME, + SVIFP_MQ_CURRENT_MESSAGES, + SVIFP_MQ_QUEUE_BYTES_MAX, + SVIFP_MQ_LAST_SEND_PID, + SVIFP_MQ_LAST_RECEIVE_PID +}; + +// Shorthand for lazy typists like me +#define IPC_CREX (IPC_CREAT | IPC_EXCL) + +#ifdef SYSV_IPC_DEBUG +#define DPRINTF(fmt, args...) fprintf(stderr, "+++ " fmt, ## args) +#else +#define DPRINTF(fmt, args...) +#endif + +/* ************************************************************************** +I have to do some guessing about types, mostly with regard to key_t. Since I +schlep these values back and forth between C and Python, I need to know +approximately what types these represent so that I can call the appropriate +Python function to convert them to Python values (e.g. PyInt_FromLong(), +PyFloat_FromDouble(), etc.) + +For most of these types the SUSv3 specification states that they're +integer-ish which means I can stuff them into a long and not worry. The macros +below safely convert each type and above each macro I document why my type +assumptions are safe. + +Unfortunately, key_t is an exception. The SUSv3 specification doesn't get more +detailed than saying it is "arithmetic", which includes signed and unsigned +short, int, long, long long, float and double (but thankfully excludes +pointers). I feel I can safely ignore long long since support for it is far +from ubiquitous. + +Ideally I would cast key_t to double and call PyWhatever_FromDouble() when +sending values to Python. Representing it as a double would ensure no data +loss regardless of whether it is typedef-ed as int, long, float, etc. + +In practice, this would be awkward. I have yet to see a platform where +key_t is not integer-ish, so most or all users of this library would be +surprised if it returned keys as floats. + +So I store keys as key_t types and cast them to long when Python forces +me to be specific. The two disadvantages to this are, (1) if any platforms +typedef key_t as a float or double, this code will break, and (2) KEY_MIN +and KEY_MAX don't represent the real min and max of keys. + +Point #1 is mitigated somewhat because if any OS typedefs key_t as float or +double, this code should complain loudly during compilation. + +Typedefs of key_t (for 32 bit systems): +OpenSolaris 2008.11 - int +OS X 10.5.8 - __int32_t (int) +Ubuntu 9.04 - int +Freebsd - l_int (int) +************************************************************************** */ + + +// key_t is guaranteed to be an arithmetic type. Some earlier versions +// of the standard didn't guarantee that it was arithmetic; the standard was +// changed to guarantee that it *is* arithmetic. +// ref: http://pubs.opengroup.org/onlinepubs/009696899/functions/xsh_chap02_12.html +// I assume it is a long; see comment above. +// Some functions return (key_t)-1, so I guess this has to be a signed type. +// ref: http://www.opengroup.org/austin/interps/doc.tpl?gdid=6226 +#if PY_MAJOR_VERSION > 2 + #define KEY_T_TO_PY(key) PyLong_FromLong(key) +#else + #define KEY_T_TO_PY(key) PyInt_FromLong(key) +#endif +// SUSv3 guarantees a uid_t to be an integer type. Some functions return +// (uid_t)-1, so I guess this has to be a signed type. +// ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html +// ref: http://www.opengroup.org/onlinepubs/9699919799/functions/chown.html +#if PY_MAJOR_VERSION > 2 + #define UID_T_TO_PY(uid) PyLong_FromLong(uid) +#else + #define UID_T_TO_PY(uid) PyInt_FromLong(uid) +#endif + +// SUSv3 guarantees a gid_t to be an integer type. Some functions return +// (gid_t)-1, so I guess this has to be a signed type. +// ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html +#if PY_MAJOR_VERSION > 2 + #define GID_T_TO_PY(gid) PyLong_FromLong(gid) +#else + #define GID_T_TO_PY(gid) PyInt_FromLong(gid) +#endif + +// I'm not sure what guarantees SUSv3 makes about a mode_t, but param 3 of +// shmget() is an int that contains flags in addition to the mode, so +// mode must be able to fit into an int. +// ref: http://www.opengroup.org/onlinepubs/009695399/functions/shmget.html +#if PY_MAJOR_VERSION > 2 + #define MODE_T_TO_PY(mode) PyLong_FromLong(mode) +#else + #define MODE_T_TO_PY(mode) PyInt_FromLong(mode) +#endif + +// I'm not sure what guarantees SUSv3 makes about a time_t, but the times +// I deal with here are all guaranteed to be after 1 Jan 1970 which means +// they'll always be positive numbers. A ulong sounds appropriate to me, +// and Python agrees in posixmodule.c. +#if PY_MAJOR_VERSION > 2 + #define TIME_T_TO_PY(time) PyLong_FromUnsignedLong(time) +#else + #define TIME_T_TO_PY(time) py_int_or_long_from_ulong(time) +#endif + +// C89 guarantees a size_t to be unsigned and fit into a ulong or smaller. +#if PY_MAJOR_VERSION > 2 + #define SIZE_T_TO_PY(size) PyLong_FromUnsignedLong(size) +#else + #define SIZE_T_TO_PY(size) py_int_or_long_from_ulong(size) +#endif + +// SUSv3 guarantees a pid_t to be a signed integer type. Some functions +// return (pid_t)-1 so I guess this has to be signed. +// ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/types.h.html#tag_13_67 +#if PY_MAJOR_VERSION > 2 + #define PID_T_TO_PY(pid) PyLong_FromLong(pid) +#else + #define PID_T_TO_PY(pid) PyInt_FromLong(pid) +#endif + +// The SUS guarantees a msglen_t to be an unsigned integer type. +// Ditto: msgqnum_t. +// ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/msg.h.html +#if PY_MAJOR_VERSION > 2 + #define MSGLEN_T_TO_PY(msglen) PyLong_FromUnsignedLong(msglen) + #define MSGQNUM_T_TO_PY(msgqnum) PyLong_FromUnsignedLong(msgqnum) +#else + #define MSGLEN_T_TO_PY(msglen) py_int_or_long_from_ulong(msglen) + #define MSGQNUM_T_TO_PY(msgqnum) py_int_or_long_from_ulong(msgqnum) +#endif + +/* Utility functions */ +key_t get_random_key(void); +int convert_key_param(PyObject *, void *); +#if PY_MAJOR_VERSION < 3 +PyObject *py_int_or_long_from_ulong(unsigned long); +#endif + +/* Custom Exceptions/Errors */ +extern PyObject *pBaseException; +extern PyObject *pInternalException; +extern PyObject *pPermissionsException; +extern PyObject *pExistentialException; +extern PyObject *pBusyException; +extern PyObject *pNotAttachedException; |