1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
|
/*
* Common/shared macros and routines.
*
* This file contains macros of the form
*
* mph_return_if_TYPE_overflow(val);
*
* Which tests `val' for a TYPE underflow/overflow (that is, is `val' within
* the range for TYPE?). If `val' can't fit in TYPE, errno is set to
* EOVERFLOW, and `return -1' is executed (which is why it's a macro).
*
* Assumptions:
*
* I'm working from GLibc, so that's the basis for my assumptions. They may
* not be completely portable, in which case I'll need to fix my assumptions.
* :-(
*
* See the typedefs for type size assumptions. These typedefs *must* be kept
* in sync with the types used in Mono.Posix.dll.
*
* See also:
* http://developer.apple.com/documentation/Darwin/Reference/ManPages/
*/
#ifndef INC_mph_H
#define INC_mph_H
#include <config.h>
#include <stddef.h> /* offsetof */
#include <limits.h> /* LONG_MAX, ULONG_MAX */
#include <errno.h> /* for ERANGE */
#include <glib.h> /* for g* types, etc. */
#ifdef HAVE_STDINT_H
#include <stdint.h> /* for SIZE_MAX */
#endif
#if __APPLE__ || __BSD__ || __FreeBSD__ || __OpenBSD__
#define MPH_ON_BSD
#endif
#ifdef HAVE_VISIBILITY_HIDDEN
#define MPH_INTERNAL __attribute__((visibility("hidden")))
#else
#define MPH_INTERNAL
#endif
#if !defined(EOVERFLOW)
# if defined(HOST_WIN32)
# define EOVERFLOW 75
# elif defined(__OpenBSD__)
# define EOVERFLOW 87
# endif
#endif /* !defined(EOVERFLOW) */
#if !defined (HOST_WIN32)
/*
* Solaris doesn't define these BSD values, and if they're not present then
* map.c:Mono_Posix_FromSeekFlags() breaks badly; see:
* http://bugzilla.gnome.org/show_bug.cgi?id=370081
*/
#ifndef L_SET
#define L_SET SEEK_SET
#endif /* ndef L_SET */
#ifndef L_INCR
#define L_INCR SEEK_CUR
#endif /* ndef L_INCR */
#ifndef L_XTND
#define L_XTND SEEK_END
#endif /* ndef L_XTND */
/*
* OS X doesn't define MAP_ANONYMOUS, but it does define MAP_ANON.
* Alias them to fix: https://bugzilla.xamarin.com/show_bug.cgi?id=3419
*/
#ifdef PLATFORM_MACOSX
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif /* ndef MAP_ANONYMOUS */
#endif /* ndef PLATFORM_MACOSX */
/*
* XATTR_AUTO is a synonym for 0 within XattrFlags, but most systems don't
* define it. map.c doesn't know that, though, so we ensure that it's defined
* so that the value 0 round-trips through MonoPosixHelper.
*/
#ifndef XATTR_AUTO
#define XATTR_AUTO 0
#endif /* ndef XATTR_AUTO */
#endif /* ndef HOST_WIN32 */
typedef gint64 mph_blkcnt_t;
typedef gint64 mph_blksize_t;
typedef guint64 mph_dev_t;
typedef guint64 mph_ino_t;
typedef guint64 mph_nlink_t;
typedef gint64 mph_off_t;
typedef guint64 mph_size_t;
typedef gint64 mph_ssize_t;
typedef gint32 mph_pid_t;
typedef guint32 mph_gid_t;
typedef guint32 mph_uid_t;
typedef gint64 mph_time_t;
typedef gint64 mph_clock_t;
typedef guint64 mph_fsblkcnt_t;
typedef guint64 mph_fsfilcnt_t;
/* Some versions of OS X don't define these typedefs, needed by map.c */
#ifndef HAVE_BLKCNT_T
typedef mph_blkcnt_t blkcnt_t;
#endif
#ifndef HAVE_BLKSIZE_T
typedef mph_blksize_t blksize_t;
#endif
#ifndef HAVE_SUSECONDS_T
typedef gint64 suseconds_t;
#endif
#ifdef HAVE_LARGE_FILE_SUPPORT
#define MPH_OFF_T_MAX G_MAXINT64
#define MPH_OFF_T_MIN G_MININT64
#else
#define MPH_OFF_T_MAX G_MAXINT32
#define MPH_OFF_T_MIN G_MININT32
#endif
#ifdef SIZE_MAX
#define MPH_SIZE_T_MAX SIZE_MAX
#elif SIZEOF_SIZE_T == 8
#define MPH_SIZE_T_MAX G_MAXUINT64
#elif SIZEOF_SIZE_T == 4
#define MPH_SIZE_T_MAX G_MAXUINT32
#else
#error "sizeof(size_t) is unknown!"
#endif
#define _mph_return_val_if_cb_(val, ret, cb) G_STMT_START{ \
if (cb (val)) { \
errno = EOVERFLOW; \
return ret; \
}}G_STMT_END
#define mph_have_uint_overflow(var) ((var) < 0 || (var) > UINT_MAX)
#define mph_return_val_if_uint_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_uint_overflow)
#define mph_return_if_uint_overflow(var) mph_return_val_if_uint_overflow(var, -1)
#define mph_have_long_overflow(var) ((var) > LONG_MAX || (var) < LONG_MIN)
#define mph_return_val_if_long_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_long_overflow)
#define mph_return_if_long_overflow(var) mph_return_val_if_long_overflow(var, -1)
#define mph_have_ulong_overflow(var) (var) < 0 || ((var) > ULONG_MAX)
#define mph_return_val_if_ulong_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_ulong_overflow)
#define mph_return_if_ulong_overflow(var) mph_return_val_if_ulong_overflow(var, -1)
#define mph_have_size_t_overflow(var) ((var) < 0 || (var) > MPH_SIZE_T_MAX)
#define mph_return_val_if_size_t_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_size_t_overflow)
#define mph_return_val_if_ssize_t_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_long_overflow)
#define mph_return_if_size_t_overflow(var) mph_return_val_if_size_t_overflow(var, -1)
#define mph_return_if_ssize_t_overflow(var) mph_return_val_if_ssize_t_overflow(var, -1)
#define mph_have_off_t_overflow(var) \
(((var) < MPH_OFF_T_MIN) || ((var) > MPH_OFF_T_MAX))
#define mph_return_val_if_off_t_overflow(var, ret) \
_mph_return_val_if_cb_(var, ret, mph_have_off_t_overflow)
#define mph_return_if_off_t_overflow(var) mph_return_val_if_size_t_overflow(var, -1)
#define mph_return_if_time_t_overflow(var) mph_return_if_long_overflow(var)
#define mph_return_if_socklen_t_overflow(var) mph_return_if_uint_overflow(var)
#define mph_return_if_val_in_list5(var,a,b,c,d,e) \
do { \
int v = (var); \
if (v == a || v == b || v == c || v == d || v == e) \
return -1; \
} while (0)
/*
* Helper function for functions which use ERANGE (such as getpwnam_r and
* getgrnam_r). These functions accept buffers which are dynamically
* allocated so that they're only as large as necessary. However, Linux and
* Mac OS X differ on how to signal an error value.
*
* Linux returns the error value directly, while Mac OS X is more traditional,
* returning -1 and setting errno accordingly.
*
* Unify the checking in one place.
*/
static inline int
recheck_range (int ret)
{
if (ret == ERANGE)
return 1;
if (ret == -1)
return errno == ERANGE;
return 0;
}
typedef unsigned int mph_string_offset_t;
enum {
MPH_STRING_OFFSET_PTR = 0x0,
MPH_STRING_OFFSET_ARRAY = 0x1,
MPH_STRING_OFFSET_MASK = 0x1
};
#define MPH_STRING_OFFSET(type,member,kind) ((offsetof(type,member) << 1) | kind)
MPH_INTERNAL char*
_mph_copy_structure_strings (
void *to, const mph_string_offset_t *to_offsets,
const void *from, const mph_string_offset_t *from_offsets,
size_t num_strings);
#endif /* ndef INC_mph_H */
/*
* vim: noexpandtab
*/
|