From f3573a73831ee05d7d36dd4a5d89df5cbe2e4828 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 9 Jul 2014 09:31:49 -0700 Subject: [PATCH] Windows compat We mainly use Win32 functions, so cannot just use C-runtime strerror to return error messages. We have to use Win32-specific messages. Unfortunately, we document the API to return C-runtime error codes, so we can't just switch to all Win32 error codes. --- libraries/liblmdb/mdb.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index c2f2c74..4712ac2 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1259,6 +1259,14 @@ static char *const mdb_errstr[] = { char * mdb_strerror(int err) { +#ifdef _WIN32 + /** HACK: pad 4KB on stack over the buf. Return system msgs in buf. + * This works as long as no function between the call to mdb_strerror + * and the actual use of the message uses more than 4K of stack. + */ + char pad[4096]; + char buf[1024], *ptr = buf; +#endif int i; if (!err) return ("Successful return: 0"); @@ -1268,7 +1276,32 @@ mdb_strerror(int err) return mdb_errstr[i]; } +#ifdef _WIN32 + /* These are the C-runtime error codes we use. The comment indicates + * their numeric value, and the Win32 error they would correspond to + * if the error actually came from a Win32 API. A major mess, we should + * have used LMDB-specific error codes for everything. + */ + switch(err) { + case ENOENT: /* 2, FILE_NOT_FOUND */ + case EIO: /* 5, ACCESS_DENIED */ + case ENOMEM: /* 12, INVALID_ACCESS */ + case EACCES: /* 13, INVALID_DATA */ + case EBUSY: /* 16, CURRENT_DIRECTORY */ + case EINVAL: /* 22, BAD_COMMAND */ + case ENOSPC: /* 28, OUT_OF_PAPER */ + return strerror(err); + default: + ; + } + buf[0] = 0; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, 0, ptr, sizeof(buf), pad); + return ptr; +#else return strerror(err); +#endif } /** assert(3) variant in cursor context */ @@ -2572,7 +2605,7 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret) } if ((txn = calloc(1, size)) == NULL) { - DPRINTF(("calloc: %s", strerror(ErrCode()))); + DPRINTF(("calloc: %s", strerror(errno))); return ENOMEM; } txn->mt_dbs = (MDB_db *) ((char *)txn + tsize);