summaryrefslogtreecommitdiff
path: root/db-4.8.30/os
diff options
context:
space:
mode:
Diffstat (limited to 'db-4.8.30/os')
-rw-r--r--db-4.8.30/os/os_abort.c33
-rw-r--r--db-4.8.30/os/os_abs.c24
-rw-r--r--db-4.8.30/os/os_addrinfo.c176
-rw-r--r--db-4.8.30/os/os_alloc.c459
-rw-r--r--db-4.8.30/os/os_clock.c73
-rw-r--r--db-4.8.30/os/os_config.c70
-rw-r--r--db-4.8.30/os/os_cpu.c47
-rw-r--r--db-4.8.30/os/os_ctime.c47
-rw-r--r--db-4.8.30/os/os_dir.c119
-rw-r--r--db-4.8.30/os/os_errno.c129
-rw-r--r--db-4.8.30/os/os_fid.c134
-rw-r--r--db-4.8.30/os/os_flock.c62
-rw-r--r--db-4.8.30/os/os_fsync.c103
-rw-r--r--db-4.8.30/os/os_getenv.c58
-rw-r--r--db-4.8.30/os/os_handle.c241
-rw-r--r--db-4.8.30/os/os_map.c594
-rw-r--r--db-4.8.30/os/os_mkdir.c51
-rw-r--r--db-4.8.30/os/os_open.c160
-rw-r--r--db-4.8.30/os/os_pid.c57
-rw-r--r--db-4.8.30/os/os_rename.c52
-rw-r--r--db-4.8.30/os/os_root.c27
-rw-r--r--db-4.8.30/os/os_rpath.c36
-rw-r--r--db-4.8.30/os/os_rw.c285
-rw-r--r--db-4.8.30/os/os_seek.c64
-rw-r--r--db-4.8.30/os/os_stack.c45
-rw-r--r--db-4.8.30/os/os_stat.c107
-rw-r--r--db-4.8.30/os/os_tmpdir.c138
-rw-r--r--db-4.8.30/os/os_truncate.c61
-rw-r--r--db-4.8.30/os/os_uid.c55
-rw-r--r--db-4.8.30/os/os_unlink.c78
-rw-r--r--db-4.8.30/os/os_yield.c96
31 files changed, 3681 insertions, 0 deletions
diff --git a/db-4.8.30/os/os_abort.c b/db-4.8.30/os/os_abort.c
new file mode 100644
index 0000000..a119000
--- /dev/null
+++ b/db-4.8.30/os/os_abort.c
@@ -0,0 +1,33 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2005-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_abort --
+ *
+ * PUBLIC: void __os_abort __P((ENV *));
+ */
+void
+__os_abort(env)
+ ENV *env;
+{
+ __os_stack(env); /* Try and get a stack trace. */
+
+#ifdef HAVE_ABORT
+ abort(); /* Try and drop core. */
+ /* NOTREACHED */
+#endif
+#ifdef SIGABRT
+ (void)raise(SIGABRT); /* Try and drop core. */
+#endif
+ exit(1); /* Quit anyway. */
+ /* NOTREACHED */
+}
diff --git a/db-4.8.30/os/os_abs.c b/db-4.8.30/os/os_abs.c
new file mode 100644
index 0000000..59b167c
--- /dev/null
+++ b/db-4.8.30/os/os_abs.c
@@ -0,0 +1,24 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_abspath --
+ * Return if a path is an absolute path.
+ *
+ * PUBLIC: int __os_abspath __P((const char *));
+ */
+int
+__os_abspath(path)
+ const char *path;
+{
+ return (path[0] == '/');
+}
diff --git a/db-4.8.30/os/os_addrinfo.c b/db-4.8.30/os/os_addrinfo.c
new file mode 100644
index 0000000..57554f8
--- /dev/null
+++ b/db-4.8.30/os/os_addrinfo.c
@@ -0,0 +1,176 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2006-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#define __INCLUDE_NETWORKING 1
+#include "db_int.h"
+
+/*
+ * __os_getaddrinfo and __os_freeaddrinfo wrap the getaddrinfo and freeaddrinfo
+ * calls, as well as the associated platform dependent error handling, mapping
+ * the error return to a ANSI C/POSIX error return.
+ */
+
+/*
+ * __os_getaddrinfo --
+ *
+ * PUBLIC: #if defined(HAVE_REPLICATION_THREADS)
+ * PUBLIC: int __os_getaddrinfo __P((ENV *, const char *, u_int,
+ * PUBLIC: const char *, const ADDRINFO *, ADDRINFO **));
+ * PUBLIC: #endif
+ */
+int
+__os_getaddrinfo(env, nodename, port, servname, hints, res)
+ ENV *env;
+ const char *nodename, *servname;
+ u_int port;
+ const ADDRINFO *hints;
+ ADDRINFO **res;
+{
+#ifdef HAVE_GETADDRINFO
+ int ret;
+
+ if ((ret = getaddrinfo(nodename, servname, hints, res)) == 0)
+ return (0);
+
+ __db_errx(env, "%s(%u): host lookup failed: %s",
+ nodename == NULL ? "" : nodename, port,
+#ifdef DB_WIN32
+ gai_strerrorA(ret));
+#else
+ gai_strerror(ret));
+#endif
+ return (__os_posix_err(ret));
+#else
+ ADDRINFO *answer;
+ struct hostent *hostaddr;
+ struct sockaddr_in sin;
+ u_int32_t tmpaddr;
+ int ret;
+
+ COMPQUIET(hints, NULL);
+ COMPQUIET(servname, NULL);
+
+ /* INADDR_NONE is not defined on Solaris 2.6, 2.7 or 2.8. */
+#ifndef INADDR_NONE
+#define INADDR_NONE ((u_long)0xffffffff)
+#endif
+
+ /*
+ * Basic implementation of IPv4 component of getaddrinfo.
+ * Limited to the functionality used by repmgr.
+ */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (nodename) {
+ if (nodename[0] == '\0')
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ else if ((tmpaddr = inet_addr(nodename)) != INADDR_NONE) {
+ sin.sin_addr.s_addr = tmpaddr;
+ } else {
+ hostaddr = gethostbyname(nodename);
+ if (hostaddr == NULL) {
+#ifdef DB_WIN32
+ ret = __os_get_neterr();
+ __db_syserr(env, ret,
+ "%s(%u): host lookup failed",
+ nodename == NULL ? "" : nodename, port);
+ return (__os_posix_err(ret));
+#else
+ /*
+ * Historic UNIX systems used the h_errno
+ * global variable to return gethostbyname
+ * errors. The only function we currently
+ * use that needs h_errno is gethostbyname,
+ * so we deal with it here.
+ *
+ * hstrerror is not available on Solaris 2.6
+ * (it is in libresolv but is a private,
+ * unexported symbol).
+ */
+#ifdef HAVE_HSTRERROR
+ __db_errx(env,
+ "%s(%u): host lookup failed: %s",
+ nodename == NULL ? "" : nodename, port,
+ hstrerror(h_errno));
+#else
+ __db_errx(env,
+ "%s(%u): host lookup failed: %d",
+ nodename == NULL ? "" : nodename, port,
+ h_errno);
+#endif
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ return (EHOSTUNREACH);
+ case TRY_AGAIN:
+ return (EAGAIN);
+ case NO_RECOVERY:
+ default:
+ return (EFAULT);
+ }
+ /* NOTREACHED */
+#endif
+ }
+ memcpy(&(sin.sin_addr),
+ hostaddr->h_addr, (size_t)hostaddr->h_length);
+ }
+ } else /* No host specified. */
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons((u_int16_t)port);
+
+ if ((ret = __os_calloc(env, 1, sizeof(ADDRINFO), &answer)) != 0)
+ return (ret);
+ if ((ret = __os_malloc(env, sizeof(sin), &answer->ai_addr)) != 0) {
+ __os_free(env, answer);
+ return (ret);
+ }
+
+ answer->ai_family = AF_INET;
+ answer->ai_protocol = IPPROTO_TCP;
+ answer->ai_socktype = SOCK_STREAM;
+ answer->ai_addrlen = sizeof(sin);
+ memcpy(answer->ai_addr, &sin, sizeof(sin));
+ *res = answer;
+
+ return (0);
+#endif /* HAVE_GETADDRINFO */
+}
+
+/*
+ * __os_freeaddrinfo --
+ *
+ * PUBLIC: #if defined(HAVE_REPLICATION_THREADS)
+ * PUBLIC: void __os_freeaddrinfo __P((ENV *, ADDRINFO *));
+ * PUBLIC: #endif
+ */
+void
+__os_freeaddrinfo(env, ai)
+ ENV *env;
+ ADDRINFO *ai;
+{
+#ifdef HAVE_GETADDRINFO
+ COMPQUIET(env, NULL);
+
+ freeaddrinfo(ai);
+#else
+ ADDRINFO *next, *tmpaddr;
+
+ for (next = ai; next != NULL; next = tmpaddr) {
+ if (next->ai_canonname != NULL)
+ __os_free(env, next->ai_canonname);
+
+ if (next->ai_addr != NULL)
+ __os_free(env, next->ai_addr);
+
+ tmpaddr = next->ai_next;
+ __os_free(env, next);
+ }
+#endif
+}
diff --git a/db-4.8.30/os/os_alloc.c b/db-4.8.30/os/os_alloc.c
new file mode 100644
index 0000000..70af8a5
--- /dev/null
+++ b/db-4.8.30/os/os_alloc.c
@@ -0,0 +1,459 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifdef DIAGNOSTIC
+static void __os_guard __P((ENV *));
+
+typedef union {
+ size_t size;
+ uintmax_t align;
+} db_allocinfo_t;
+#endif
+
+/*
+ * !!!
+ * Correct for systems that return NULL when you allocate 0 bytes of memory.
+ * There are several places in DB where we allocate the number of bytes held
+ * by the key/data item, and it can be 0. Correct here so that malloc never
+ * returns a NULL for that reason (which behavior is permitted by ANSI). We
+ * could make these calls macros on non-Alpha architectures (that's where we
+ * saw the problem), but it's probably not worth the autoconf complexity.
+ *
+ * !!!
+ * Correct for systems that don't set errno when malloc and friends fail.
+ *
+ * Out of memory.
+ * We wish to hold the whole sky,
+ * But we never will.
+ */
+
+/*
+ * __os_umalloc --
+ * Allocate memory to be used by the application.
+ *
+ * Use, in order of preference, the allocation function specified to the
+ * ENV handle, the allocation function specified as a replacement for
+ * the library malloc, or the library malloc().
+ *
+ * PUBLIC: int __os_umalloc __P((ENV *, size_t, void *));
+ */
+int
+__os_umalloc(env, size, storep)
+ ENV *env;
+ size_t size;
+ void *storep;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+ if (dbenv == NULL || dbenv->db_malloc == NULL) {
+ if (DB_GLOBAL(j_malloc) != NULL)
+ *(void **)storep = DB_GLOBAL(j_malloc)(size);
+ else
+ *(void **)storep = malloc(size);
+ if (*(void **)storep == NULL) {
+ /*
+ * Correct error return, see __os_malloc.
+ */
+ if ((ret = __os_get_errno_ret_zero()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(env, ret, "malloc: %lu", (u_long)size);
+ return (ret);
+ }
+ return (0);
+ }
+
+ if ((*(void **)storep = dbenv->db_malloc(size)) == NULL) {
+ __db_errx(env,
+ "user-specified malloc function returned NULL");
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+/*
+ * __os_urealloc --
+ * Allocate memory to be used by the application.
+ *
+ * A realloc(3) counterpart to __os_umalloc's malloc(3).
+ *
+ * PUBLIC: int __os_urealloc __P((ENV *, size_t, void *));
+ */
+int
+__os_urealloc(env, size, storep)
+ ENV *env;
+ size_t size;
+ void *storep;
+{
+ DB_ENV *dbenv;
+ int ret;
+ void *ptr;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ ptr = *(void **)storep;
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+ if (dbenv == NULL || dbenv->db_realloc == NULL) {
+ if (ptr == NULL)
+ return (__os_umalloc(env, size, storep));
+
+ if (DB_GLOBAL(j_realloc) != NULL)
+ *(void **)storep = DB_GLOBAL(j_realloc)(ptr, size);
+ else
+ *(void **)storep = realloc(ptr, size);
+ if (*(void **)storep == NULL) {
+ /*
+ * Correct errno, see __os_realloc.
+ */
+ if ((ret = __os_get_errno_ret_zero()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(env, ret, "realloc: %lu", (u_long)size);
+ return (ret);
+ }
+ return (0);
+ }
+
+ if ((*(void **)storep = dbenv->db_realloc(ptr, size)) == NULL) {
+ __db_errx(env,
+ "User-specified realloc function returned NULL");
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+/*
+ * __os_ufree --
+ * Free memory used by the application.
+ *
+ * A free(3) counterpart to __os_umalloc's malloc(3).
+ *
+ * PUBLIC: void __os_ufree __P((ENV *, void *));
+ */
+void
+__os_ufree(env, ptr)
+ ENV *env;
+ void *ptr;
+{
+ DB_ENV *dbenv;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL && dbenv->db_free != NULL)
+ dbenv->db_free(ptr);
+ else if (DB_GLOBAL(j_free) != NULL)
+ DB_GLOBAL(j_free)(ptr);
+ else
+ free(ptr);
+}
+
+/*
+ * __os_strdup --
+ * The strdup(3) function for DB.
+ *
+ * PUBLIC: int __os_strdup __P((ENV *, const char *, void *));
+ */
+int
+__os_strdup(env, str, storep)
+ ENV *env;
+ const char *str;
+ void *storep;
+{
+ size_t size;
+ int ret;
+ void *p;
+
+ *(void **)storep = NULL;
+
+ size = strlen(str) + 1;
+ if ((ret = __os_malloc(env, size, &p)) != 0)
+ return (ret);
+
+ memcpy(p, str, size);
+
+ *(void **)storep = p;
+ return (0);
+}
+
+/*
+ * __os_calloc --
+ * The calloc(3) function for DB.
+ *
+ * PUBLIC: int __os_calloc __P((ENV *, size_t, size_t, void *));
+ */
+int
+__os_calloc(env, num, size, storep)
+ ENV *env;
+ size_t num, size;
+ void *storep;
+{
+ int ret;
+
+ size *= num;
+ if ((ret = __os_malloc(env, size, storep)) != 0)
+ return (ret);
+
+ memset(*(void **)storep, 0, size);
+
+ return (0);
+}
+
+/*
+ * __os_malloc --
+ * The malloc(3) function for DB.
+ *
+ * PUBLIC: int __os_malloc __P((ENV *, size_t, void *));
+ */
+int
+__os_malloc(env, size, storep)
+ ENV *env;
+ size_t size;
+ void *storep;
+{
+ int ret;
+ void *p;
+
+ *(void **)storep = NULL;
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+#ifdef DIAGNOSTIC
+ /* Add room for size and a guard byte. */
+ size += sizeof(db_allocinfo_t) + 1;
+#endif
+
+ if (DB_GLOBAL(j_malloc) != NULL)
+ p = DB_GLOBAL(j_malloc)(size);
+ else
+ p = malloc(size);
+ if (p == NULL) {
+ /*
+ * Some C libraries don't correctly set errno when malloc(3)
+ * fails. We'd like to 0 out errno before calling malloc,
+ * but it turns out that setting errno is quite expensive on
+ * Windows/NT in an MT environment.
+ */
+ if ((ret = __os_get_errno_ret_zero()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(env, ret, "malloc: %lu", (u_long)size);
+ return (ret);
+ }
+
+#ifdef DIAGNOSTIC
+ /* Overwrite memory. */
+ memset(p, CLEAR_BYTE, size);
+
+ /*
+ * Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional
+ * byte after the memory and set it to a special value that we check
+ * for when the memory is free'd.
+ */
+ ((u_int8_t *)p)[size - 1] = CLEAR_BYTE;
+
+ ((db_allocinfo_t *)p)->size = size;
+ p = &((db_allocinfo_t *)p)[1];
+#endif
+ *(void **)storep = p;
+
+ return (0);
+}
+
+/*
+ * __os_realloc --
+ * The realloc(3) function for DB.
+ *
+ * PUBLIC: int __os_realloc __P((ENV *, size_t, void *));
+ */
+int
+__os_realloc(env, size, storep)
+ ENV *env;
+ size_t size;
+ void *storep;
+{
+ int ret;
+ void *p, *ptr;
+
+ ptr = *(void **)storep;
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+ /* If we haven't yet allocated anything yet, simply call malloc. */
+ if (ptr == NULL)
+ return (__os_malloc(env, size, storep));
+
+#ifdef DIAGNOSTIC
+ /* Add room for size and a guard byte. */
+ size += sizeof(db_allocinfo_t) + 1;
+
+ /* Back up to the real beginning */
+ ptr = &((db_allocinfo_t *)ptr)[-1];
+
+ {
+ size_t s;
+
+ s = ((db_allocinfo_t *)ptr)->size;
+ if (((u_int8_t *)ptr)[s - 1] != CLEAR_BYTE)
+ __os_guard(env);
+ }
+#endif
+
+ /*
+ * Don't overwrite the original pointer, there are places in DB we
+ * try to continue after realloc fails.
+ */
+ if (DB_GLOBAL(j_realloc) != NULL)
+ p = DB_GLOBAL(j_realloc)(ptr, size);
+ else
+ p = realloc(ptr, size);
+ if (p == NULL) {
+ /*
+ * Some C libraries don't correctly set errno when malloc(3)
+ * fails. We'd like to 0 out errno before calling malloc,
+ * but it turns out that setting errno is quite expensive on
+ * Windows/NT in an MT environment.
+ */
+ if ((ret = __os_get_errno_ret_zero()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(env, ret, "realloc: %lu", (u_long)size);
+ return (ret);
+ }
+#ifdef DIAGNOSTIC
+ ((u_int8_t *)p)[size - 1] = CLEAR_BYTE; /* Initialize guard byte. */
+
+ ((db_allocinfo_t *)p)->size = size;
+ p = &((db_allocinfo_t *)p)[1];
+#endif
+
+ *(void **)storep = p;
+
+ return (0);
+}
+
+/*
+ * __os_free --
+ * The free(3) function for DB.
+ *
+ * PUBLIC: void __os_free __P((ENV *, void *));
+ */
+void
+__os_free(env, ptr)
+ ENV *env;
+ void *ptr;
+{
+#ifdef DIAGNOSTIC
+ size_t size;
+#endif
+
+ /*
+ * ANSI C requires free(NULL) work. Don't depend on the underlying
+ * library.
+ */
+ if (ptr == NULL)
+ return;
+
+#ifdef DIAGNOSTIC
+ /*
+ * Check that the guard byte (one past the end of the memory) is
+ * still CLEAR_BYTE.
+ */
+ ptr = &((db_allocinfo_t *)ptr)[-1];
+ size = ((db_allocinfo_t *)ptr)->size;
+ if (((u_int8_t *)ptr)[size - 1] != CLEAR_BYTE)
+ __os_guard(env);
+
+ /* Overwrite memory. */
+ if (size != 0)
+ memset(ptr, CLEAR_BYTE, size);
+#else
+ COMPQUIET(env, NULL);
+#endif
+
+ if (DB_GLOBAL(j_free) != NULL)
+ DB_GLOBAL(j_free)(ptr);
+ else
+ free(ptr);
+}
+
+#ifdef DIAGNOSTIC
+/*
+ * __os_guard --
+ * Complain and abort.
+ */
+static void
+__os_guard(env)
+ ENV *env;
+{
+ __db_errx(env, "Guard byte incorrect during free");
+ __os_abort(env);
+ /* NOTREACHED */
+}
+#endif
+
+/*
+ * __ua_memcpy --
+ * Copy memory to memory without relying on any kind of alignment.
+ *
+ * There are places in DB that we have unaligned data, for example,
+ * when we've stored a structure in a log record as a DBT, and now
+ * we want to look at it. Unfortunately, if you have code like:
+ *
+ * struct a {
+ * int x;
+ * } *p;
+ *
+ * void *func_argument;
+ * int local;
+ *
+ * p = (struct a *)func_argument;
+ * memcpy(&local, p->x, sizeof(local));
+ *
+ * compilers optimize to use inline instructions requiring alignment,
+ * and records in the log don't have any particular alignment. (This
+ * isn't a compiler bug, because it's a structure they're allowed to
+ * assume alignment.)
+ *
+ * Casting the memcpy arguments to (u_int8_t *) appears to work most
+ * of the time, but we've seen examples where it wasn't sufficient
+ * and there's nothing in ANSI C that requires that work.
+ *
+ * PUBLIC: void *__ua_memcpy __P((void *, const void *, size_t));
+ */
+void *
+__ua_memcpy(dst, src, len)
+ void *dst;
+ const void *src;
+ size_t len;
+{
+ return ((void *)memcpy(dst, src, len));
+}
diff --git a/db-4.8.30/os/os_clock.c b/db-4.8.30/os/os_clock.c
new file mode 100644
index 0000000..d4c822e
--- /dev/null
+++ b/db-4.8.30/os/os_clock.c
@@ -0,0 +1,73 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_gettime --
+ * Return the current time-of-day clock in seconds and nanoseconds.
+ *
+ * PUBLIC: void __os_gettime __P((ENV *, db_timespec *, int));
+ */
+void
+__os_gettime(env, tp, monotonic)
+ ENV *env;
+ db_timespec *tp;
+ int monotonic;
+{
+ const char *sc;
+ int ret;
+
+#if defined(HAVE_CLOCK_GETTIME)
+#if defined(HAVE_CLOCK_MONOTONIC)
+ if (monotonic)
+ RETRY_CHK((clock_gettime(
+ CLOCK_MONOTONIC, (struct timespec *)tp)), ret);
+ else
+#endif
+ RETRY_CHK((clock_gettime(
+ CLOCK_REALTIME, (struct timespec *)tp)), ret);
+
+ RETRY_CHK((clock_gettime(CLOCK_REALTIME, (struct timespec *)tp)), ret);
+ if (ret != 0) {
+ sc = "clock_gettime";
+ goto err;
+ }
+#elif defined(HAVE_GETTIMEOFDAY)
+ struct timeval v;
+
+ RETRY_CHK((gettimeofday(&v, NULL)), ret);
+ if (ret != 0) {
+ sc = "gettimeofday";
+ goto err;
+ }
+
+ tp->tv_sec = v.tv_sec;
+ tp->tv_nsec = v.tv_usec * NS_PER_US;
+#elif defined(HAVE_TIME)
+ time_t now;
+
+ RETRY_CHK((time(&now) == (time_t)-1 ? 1 : 0), ret);
+ if (ret != 0) {
+ sc = "time";
+ goto err;
+ }
+
+ tp->tv_sec = now;
+ tp->tv_nsec = 0;
+#else
+ NO AVAILABLE CLOCK IMPLEMENTATION
+#endif
+ COMPQUIET(monotonic, 0);
+ return;
+
+err: __db_syserr(env, ret, "%s", sc);
+ (void)__env_panic(env, __os_posix_err(ret));
+}
diff --git a/db-4.8.30/os/os_config.c b/db-4.8.30/os/os_config.c
new file mode 100644
index 0000000..4e94291
--- /dev/null
+++ b/db-4.8.30/os/os_config.c
@@ -0,0 +1,70 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_fs_notzero --
+ * Return 1 if allocated filesystem blocks are not zeroed.
+ *
+ * PUBLIC: int __os_fs_notzero __P((void));
+ */
+int
+__os_fs_notzero()
+{
+ /* Most filesystems zero out implicitly created pages. */
+ return (0);
+}
+
+/*
+ * __os_support_direct_io --
+ * Return 1 if we support direct I/O.
+ *
+ * PUBLIC: int __os_support_direct_io __P((void));
+ */
+int
+__os_support_direct_io()
+{
+ int ret;
+
+ ret = 0;
+
+#ifdef HAVE_O_DIRECT
+ ret = 1;
+#endif
+#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
+ ret = 1;
+#endif
+ return (ret);
+}
+
+/*
+ * __os_support_db_register --
+ * Return 1 if the system supports DB_REGISTER.
+ *
+ * PUBLIC: int __os_support_db_register __P((void));
+ */
+int
+__os_support_db_register()
+{
+ return (1);
+}
+
+/*
+ * __os_support_replication --
+ * Return 1 if the system supports replication.
+ *
+ * PUBLIC: int __os_support_replication __P((void));
+ */
+int
+__os_support_replication()
+{
+ return (1);
+}
diff --git a/db-4.8.30/os/os_cpu.c b/db-4.8.30/os/os_cpu.c
new file mode 100644
index 0000000..71387b0
--- /dev/null
+++ b/db-4.8.30/os/os_cpu.c
@@ -0,0 +1,47 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifdef HAVE_SYSTEM_INCLUDE_FILES
+#if defined(HAVE_PSTAT_GETDYNAMIC)
+#include <sys/pstat.h>
+#endif
+#endif
+
+/*
+ * __os_cpu_count --
+ * Return the number of CPUs.
+ *
+ * PUBLIC: u_int32_t __os_cpu_count __P((void));
+ */
+u_int32_t
+__os_cpu_count()
+{
+#if defined(HAVE_PSTAT_GETDYNAMIC)
+ /*
+ * HP/UX.
+ */
+ struct pst_dynamic psd;
+
+ return ((u_int32_t)pstat_getdynamic(&psd,
+ sizeof(psd), (size_t)1, 0) == -1 ? 1 : psd.psd_proc_cnt);
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+ /*
+ * Solaris, Linux.
+ */
+ long nproc;
+
+ nproc = sysconf(_SC_NPROCESSORS_ONLN);
+ return ((u_int32_t)(nproc > 1 ? nproc : 1));
+#else
+ return (1);
+#endif
+}
diff --git a/db-4.8.30/os/os_ctime.c b/db-4.8.30/os/os_ctime.c
new file mode 100644
index 0000000..843ae60
--- /dev/null
+++ b/db-4.8.30/os/os_ctime.c
@@ -0,0 +1,47 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_ctime --
+ * Format a time-stamp.
+ *
+ * PUBLIC: char *__os_ctime __P((const time_t *, char *));
+ */
+char *
+__os_ctime(tod, time_buf)
+ const time_t *tod;
+ char *time_buf;
+{
+ time_buf[CTIME_BUFLEN - 1] = '\0';
+
+ /*
+ * The ctime_r interface is the POSIX standard, thread-safe version of
+ * ctime. However, it was implemented in three different ways (with
+ * and without a buffer length argument, and where the buffer length
+ * argument was an int vs. a size_t *). Also, you can't depend on a
+ * return of (char *) from ctime_r, HP-UX 10.XX's version returned an
+ * int.
+ */
+#if defined(HAVE_VXWORKS)
+ {
+ size_t buflen = CTIME_BUFLEN;
+ (void)ctime_r(tod, time_buf, &buflen);
+ }
+#elif defined(HAVE_CTIME_R_3ARG)
+ (void)ctime_r(tod, time_buf, CTIME_BUFLEN);
+#elif defined(HAVE_CTIME_R)
+ (void)ctime_r(tod, time_buf);
+#else
+ (void)strncpy(time_buf, ctime(tod), CTIME_BUFLEN - 1);
+#endif
+ return (time_buf);
+}
diff --git a/db-4.8.30/os/os_dir.c b/db-4.8.30/os/os_dir.c
new file mode 100644
index 0000000..6e7cb5a
--- /dev/null
+++ b/db-4.8.30/os/os_dir.c
@@ -0,0 +1,119 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#define __INCLUDE_DIRECTORY 1
+#include "db_int.h"
+
+/*
+ * __os_dirlist --
+ * Return a list of the files in a directory.
+ *
+ * PUBLIC: int __os_dirlist __P((ENV *, const char *, int, char ***, int *));
+ */
+int
+__os_dirlist(env, dir, returndir, namesp, cntp)
+ ENV *env;
+ const char *dir;
+ int returndir, *cntp;
+ char ***namesp;
+{
+ DB_ENV *dbenv;
+ struct dirent *dp;
+ DIR *dirp;
+ struct stat sb;
+ int arraysz, cnt, ret;
+ char **names, buf[DB_MAXPATHLEN];
+
+ *namesp = NULL;
+ *cntp = 0;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: directory list %s", dir);
+
+ if (DB_GLOBAL(j_dirlist) != NULL)
+ return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp));
+
+ if ((dirp = opendir(CHAR_STAR_CAST dir)) == NULL)
+ return (__os_get_errno());
+ names = NULL;
+ for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL;) {
+ snprintf(buf, sizeof(buf), "%s/%s", dir, dp->d_name);
+
+ RETRY_CHK(stat(buf, &sb), ret);
+ if (ret != 0) {
+ ret = __os_posix_err(ret);
+ goto err;
+ }
+
+ /*
+ * We return regular files, and optionally return directories
+ * (except for dot and dot-dot).
+ *
+ * Shared memory files are of a different type on QNX, and we
+ * return those as well.
+ */
+#ifdef HAVE_QNX
+ if (!S_ISREG(sb.st_mode) && !S_TYPEISSHM(&sb)) {
+#else
+ if (!S_ISREG(sb.st_mode)) {
+#endif
+ if (!returndir || !S_ISDIR(sb.st_mode))
+ continue;
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+ }
+
+ if (cnt >= arraysz) {
+ arraysz += 100;
+ if ((ret = __os_realloc(env,
+ (u_int)arraysz * sizeof(names[0]), &names)) != 0)
+ goto err;
+ }
+ if ((ret = __os_strdup(env, dp->d_name, &names[cnt])) != 0)
+ goto err;
+ cnt++;
+ }
+ (void)closedir(dirp);
+
+ *namesp = names;
+ *cntp = cnt;
+ return (0);
+
+err: if (names != NULL)
+ __os_dirfree(env, names, cnt);
+ if (dirp != NULL)
+ (void)closedir(dirp);
+ return (ret);
+}
+
+/*
+ * __os_dirfree --
+ * Free the list of files.
+ *
+ * PUBLIC: void __os_dirfree __P((ENV *, char **, int));
+ */
+void
+__os_dirfree(env, names, cnt)
+ ENV *env;
+ char **names;
+ int cnt;
+{
+ if (DB_GLOBAL(j_dirfree) != NULL)
+ DB_GLOBAL(j_dirfree)(names, cnt);
+ else {
+ while (cnt > 0)
+ __os_free(env, names[--cnt]);
+ __os_free(env, names);
+ }
+}
diff --git a/db-4.8.30/os/os_errno.c b/db-4.8.30/os/os_errno.c
new file mode 100644
index 0000000..d74d1d9
--- /dev/null
+++ b/db-4.8.30/os/os_errno.c
@@ -0,0 +1,129 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_get_errno_ret_zero --
+ * Return the last system error, including an error of zero.
+ *
+ * PUBLIC: int __os_get_errno_ret_zero __P((void));
+ */
+int
+__os_get_errno_ret_zero()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ return (errno);
+}
+
+/*
+ * We've seen cases where system calls failed but errno was never set. For
+ * that reason, __os_get_errno() and __os_get_syserr set errno to EAGAIN if
+ * it's not already set, to work around the problem. For obvious reasons,
+ * we can only call this function if we know an error has occurred, that
+ * is, we can't test the return for a non-zero value after the get call.
+ *
+ * __os_get_errno --
+ * Return the last ANSI C "errno" value or EAGAIN if the last error
+ * is zero.
+ *
+ * PUBLIC: int __os_get_errno __P((void));
+ */
+int
+__os_get_errno()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ return (__os_get_syserr());
+}
+
+#if 0
+/*
+ * __os_get_neterr --
+ * Return the last network-related error or EAGAIN if the last
+ * error is zero.
+ *
+ * PUBLIC: int __os_get_neterr __P((void));
+ */
+int
+__os_get_neterr()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ return (__os_get_syserr());
+}
+#endif
+
+/*
+ * __os_get_syserr --
+ * Return the last system error or EAGAIN if the last error is zero.
+ *
+ * PUBLIC: int __os_get_syserr __P((void));
+ */
+int
+__os_get_syserr()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ if (errno == 0)
+ __os_set_errno(EAGAIN);
+ return (errno);
+}
+
+/*
+ * __os_set_errno --
+ * Set the value of errno.
+ *
+ * PUBLIC: void __os_set_errno __P((int));
+ */
+void
+__os_set_errno(evalue)
+ int evalue;
+{
+ /*
+ * This routine is called by the compatibility interfaces (DB 1.85,
+ * dbm and hsearch). Force values > 0, that is, not one of DB 2.X
+ * and later's public error returns. If something bad has happened,
+ * default to EFAULT -- a nasty return. Otherwise, default to EINVAL.
+ * As the compatibility APIs aren't included on Windows, the Windows
+ * version of this routine doesn't need this behavior.
+ */
+ errno =
+ evalue >= 0 ? evalue : (evalue == DB_RUNRECOVERY ? EFAULT : EINVAL);
+}
+
+/*
+ * __os_strerror --
+ * Return a string associated with the system error.
+ *
+ * PUBLIC: char *__os_strerror __P((int, char *, size_t));
+ */
+char *
+__os_strerror(error, buf, len)
+ int error;
+ char *buf;
+ size_t len;
+{
+ /* No translation is needed in the POSIX layer. */
+ (void)strncpy(buf, strerror(error), len - 1);
+ buf[len - 1] = '\0';
+
+ return (buf);
+}
+
+/*
+ * __os_posix_err
+ * Convert a system error to a POSIX error.
+ *
+ * PUBLIC: int __os_posix_err __P((int));
+ */
+int
+__os_posix_err(error)
+ int error;
+{
+ return (error);
+}
diff --git a/db-4.8.30/os/os_fid.c b/db-4.8.30/os/os_fid.c
new file mode 100644
index 0000000..59cb8dd
--- /dev/null
+++ b/db-4.8.30/os/os_fid.c
@@ -0,0 +1,134 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_fileid --
+ * Return a unique identifier for a file.
+ *
+ * PUBLIC: int __os_fileid __P((ENV *, const char *, int, u_int8_t *));
+ */
+int
+__os_fileid(env, fname, unique_okay, fidp)
+ ENV *env;
+ const char *fname;
+ int unique_okay;
+ u_int8_t *fidp;
+{
+ pid_t pid;
+ size_t i;
+ u_int32_t tmp;
+ u_int8_t *p;
+
+#ifdef HAVE_STAT
+ struct stat sb;
+ int ret;
+
+ /*
+ * The structure of a fileid on a POSIX/UNIX system is:
+ *
+ * ino[4] dev[4] unique-ID[4] serial-counter[4] empty[4].
+ *
+ * For real files, which have a backing inode and device, the first
+ * 8 bytes are filled in and the following bytes are left 0. For
+ * temporary files, the following 12 bytes are filled in.
+ *
+ * Clear the buffer.
+ */
+ memset(fidp, 0, DB_FILE_ID_LEN);
+ RETRY_CHK((stat(CHAR_STAR_CAST fname, &sb)), ret);
+ if (ret != 0) {
+ __db_syserr(env, ret, "stat: %s", fname);
+ return (__os_posix_err(ret));
+ }
+
+ /*
+ * !!!
+ * Nothing is ever big enough -- on Sparc V9, st_ino, st_dev and the
+ * time_t types are all 8 bytes. As DB_FILE_ID_LEN is only 20 bytes,
+ * we convert to a (potentially) smaller fixed-size type and use it.
+ *
+ * We don't worry about byte sexing or the actual variable sizes.
+ *
+ * When this routine is called from the DB access methods, it's only
+ * called once -- whatever ID is generated when a database is created
+ * is stored in the database file's metadata, and that is what is
+ * saved in the mpool region's information to uniquely identify the
+ * file.
+ *
+ * When called from the mpool layer this routine will be called each
+ * time a new thread of control wants to share the file, which makes
+ * things tougher. As far as byte sexing goes, since the mpool region
+ * lives on a single host, there's no issue of that -- the entire
+ * region is byte sex dependent. As far as variable sizes go, we make
+ * the simplifying assumption that 32-bit and 64-bit processes will
+ * get the same 32-bit values if we truncate any returned 64-bit value
+ * to a 32-bit value. When we're called from the mpool layer, though,
+ * we need to be careful not to include anything that isn't
+ * reproducible for a given file, such as the timestamp or serial
+ * number.
+ */
+ tmp = (u_int32_t)sb.st_ino;
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+
+ tmp = (u_int32_t)sb.st_dev;
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+#else
+ /*
+ * Use the file name.
+ *
+ * XXX
+ * Cast the first argument, the BREW ARM compiler is unhappy if
+ * we don't.
+ */
+ (void)strncpy((char *)fidp, fname, DB_FILE_ID_LEN);
+#endif /* HAVE_STAT */
+
+ if (unique_okay) {
+ /* Add in 32-bits of (hopefully) unique number. */
+ __os_unique_id(env, &tmp);
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+
+ /*
+ * Initialize/increment the serial number we use to help
+ * avoid fileid collisions. Note we don't bother with
+ * locking; it's unpleasant to do from down in here, and
+ * if we race on this no real harm will be done, since the
+ * finished fileid has so many other components.
+ *
+ * We use the bottom 32-bits of the process ID, hoping they
+ * are more random than the top 32-bits (should we be on a
+ * machine with 64-bit process IDs).
+ *
+ * We increment by 100000 on each call as a simple way of
+ * randomizing; simply incrementing seems potentially less
+ * useful if pids are also simply incremented, since this
+ * is process-local and we may be one of a set of processes
+ * starting up. 100000 pushes us out of pid space on most
+ * 32-bit platforms, and has few interesting properties in
+ * base 2.
+ */
+ if (DB_GLOBAL(fid_serial) == 0) {
+ __os_id(env->dbenv, &pid, NULL);
+ DB_GLOBAL(fid_serial) = (u_int32_t)pid;
+ } else
+ DB_GLOBAL(fid_serial) += 100000;
+
+ for (p = (u_int8_t *)
+ &DB_GLOBAL(fid_serial), i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+ }
+
+ return (0);
+}
diff --git a/db-4.8.30/os/os_flock.c b/db-4.8.30/os/os_flock.c
new file mode 100644
index 0000000..6997719
--- /dev/null
+++ b/db-4.8.30/os/os_flock.c
@@ -0,0 +1,62 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_fdlock --
+ * Acquire/release a lock on a byte in a file.
+ *
+ * PUBLIC: int __os_fdlock __P((ENV *, DB_FH *, off_t, int, int));
+ */
+int
+__os_fdlock(env, fhp, offset, acquire, nowait)
+ ENV *env;
+ DB_FH *fhp;
+ int acquire, nowait;
+ off_t offset;
+{
+#ifdef HAVE_FCNTL
+ DB_ENV *dbenv;
+ struct flock fl;
+ int ret, t_ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: flock %s %s offset %lu",
+ fhp->name, acquire ? "acquire": "release", (u_long)offset);
+
+ fl.l_start = offset;
+ fl.l_len = 1;
+ fl.l_type = acquire ? F_WRLCK : F_UNLCK;
+ fl.l_whence = SEEK_SET;
+
+ RETRY_CHK_EINTR_ONLY(
+ (fcntl(fhp->fd, nowait ? F_SETLK : F_SETLKW, &fl)), ret);
+
+ if (ret == 0)
+ return (0);
+
+ if ((t_ret = __os_posix_err(ret)) != EACCES && t_ret != EAGAIN)
+ __db_syserr(env, ret, "fcntl");
+ return (t_ret);
+#else
+ COMPQUIET(fhp, NULL);
+ COMPQUIET(acquire, 0);
+ COMPQUIET(nowait, 0);
+ COMPQUIET(offset, 0);
+ __db_syserr(env, DB_OPNOTSUP, "advisory file locking unavailable");
+ return (DB_OPNOTSUP);
+#endif
+}
diff --git a/db-4.8.30/os/os_fsync.c b/db-4.8.30/os/os_fsync.c
new file mode 100644
index 0000000..35e244c
--- /dev/null
+++ b/db-4.8.30/os/os_fsync.c
@@ -0,0 +1,103 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifdef HAVE_VXWORKS
+#include "ioLib.h"
+
+#define fsync(fd) __vx_fsync(fd)
+
+int
+__vx_fsync(fd)
+ int fd;
+{
+ int ret;
+
+ /*
+ * The results of ioctl are driver dependent. Some will return the
+ * number of bytes sync'ed. Only if it returns 'ERROR' should we
+ * flag it.
+ */
+ if ((ret = ioctl(fd, FIOSYNC, 0)) != ERROR)
+ return (0);
+ return (ret);
+}
+#endif
+
+#ifdef __hp3000s900
+#define fsync(fd) __mpe_fsync(fd)
+
+int
+__mpe_fsync(fd)
+ int fd;
+{
+ extern FCONTROL(short, short, void *);
+
+ FCONTROL(_MPE_FILENO(fd), 2, NULL); /* Flush the buffers */
+ FCONTROL(_MPE_FILENO(fd), 6, NULL); /* Write the EOF */
+ return (0);
+}
+#endif
+
+/*
+ * __os_fsync --
+ * Flush a file descriptor.
+ *
+ * PUBLIC: int __os_fsync __P((ENV *, DB_FH *));
+ */
+int
+__os_fsync(env, fhp)
+ ENV *env;
+ DB_FH *fhp;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+ /*
+ * Do nothing if the file descriptor has been marked as not requiring
+ * any sync to disk.
+ */
+ if (F_ISSET(fhp, DB_FH_NOSYNC))
+ return (0);
+
+ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: flush %s", fhp->name);
+
+ if (DB_GLOBAL(j_fsync) != NULL)
+ ret = DB_GLOBAL(j_fsync)(fhp->fd);
+ else {
+#if defined(F_FULLFSYNC)
+ RETRY_CHK((fcntl(fhp->fd, F_FULLFSYNC, 0)), ret);
+ /*
+ * On OS X, F_FULLSYNC only works on HFS+, so we need to fall
+ * back to regular fsync on other filesystems.
+ */
+ if (ret == ENOTSUP)
+ RETRY_CHK((fsync(fhp->fd)), ret);
+#elif defined(HAVE_QNX)
+ ret = __qnx_fsync(fhp);
+#elif defined(HAVE_FDATASYNC)
+ RETRY_CHK((fdatasync(fhp->fd)), ret);
+#else
+ RETRY_CHK((fsync(fhp->fd)), ret);
+#endif
+ }
+
+ if (ret != 0) {
+ __db_syserr(env, ret, "fsync");
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_getenv.c b/db-4.8.30/os/os_getenv.c
new file mode 100644
index 0000000..581f412
--- /dev/null
+++ b/db-4.8.30/os/os_getenv.c
@@ -0,0 +1,58 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_getenv --
+ * Retrieve an environment variable.
+ *
+ * PUBLIC: int __os_getenv __P((ENV *, const char *, char **, size_t));
+ */
+int
+__os_getenv(env, name, bpp, buflen)
+ ENV *env;
+ const char *name;
+ char **bpp;
+ size_t buflen;
+{
+ /*
+ * If we have getenv, there's a value and the buffer is large enough:
+ * copy value into the pointer, return 0
+ * If we have getenv, there's a value and the buffer is too short:
+ * set pointer to NULL, return EINVAL
+ * If we have getenv and there's no value:
+ * set pointer to NULL, return 0
+ * If we don't have getenv:
+ * set pointer to NULL, return 0
+ */
+#ifdef HAVE_GETENV
+ char *p;
+
+ if ((p = getenv(name)) != NULL) {
+ if (strlen(p) < buflen) {
+ (void)strcpy(*bpp, p);
+ return (0);
+ }
+
+ *bpp = NULL;
+ __db_errx(env,
+ "%s: buffer too small to hold environment variable %s",
+ name, p);
+ return (EINVAL);
+ }
+#else
+ COMPQUIET(env, NULL);
+ COMPQUIET(name, NULL);
+ COMPQUIET(buflen, 0);
+#endif
+ *bpp = NULL;
+ return (0);
+}
diff --git a/db-4.8.30/os/os_handle.c b/db-4.8.30/os/os_handle.c
new file mode 100644
index 0000000..e833aa1
--- /dev/null
+++ b/db-4.8.30/os/os_handle.c
@@ -0,0 +1,241 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_openhandle --
+ * Open a file, using POSIX 1003.1 open flags.
+ *
+ * PUBLIC: int __os_openhandle
+ * PUBLIC: __P((ENV *, const char *, int, int, DB_FH **));
+ */
+int
+__os_openhandle(env, name, flags, mode, fhpp)
+ ENV *env;
+ const char *name;
+ int flags, mode;
+ DB_FH **fhpp;
+{
+ DB_FH *fhp;
+ u_int nrepeat, retries;
+ int fcntl_flags, ret;
+#ifdef HAVE_VXWORKS
+ int newflags;
+#endif
+ /*
+ * Allocate the file handle and copy the file name. We generally only
+ * use the name for verbose or error messages, but on systems where we
+ * can't unlink temporary files immediately, we use the name to unlink
+ * the temporary file when the file handle is closed.
+ *
+ * Lock the ENV handle and insert the new file handle on the list.
+ */
+ if ((ret = __os_calloc(env, 1, sizeof(DB_FH), &fhp)) != 0)
+ return (ret);
+ if ((ret = __os_strdup(env, name, &fhp->name)) != 0)
+ goto err;
+ if (env != NULL) {
+ MUTEX_LOCK(env, env->mtx_env);
+ TAILQ_INSERT_TAIL(&env->fdlist, fhp, q);
+ MUTEX_UNLOCK(env, env->mtx_env);
+ F_SET(fhp, DB_FH_ENVLINK);
+ }
+
+ /* If the application specified an interface, use it. */
+ if (DB_GLOBAL(j_open) != NULL) {
+ if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1) {
+ ret = __os_posix_err(__os_get_syserr());
+ goto err;
+ }
+ goto done;
+ }
+
+ retries = 0;
+ for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
+ ret = 0;
+#ifdef HAVE_VXWORKS
+ /*
+ * VxWorks does not support O_CREAT on open, you have to use
+ * creat() instead. (It does not support O_EXCL or O_TRUNC
+ * either, even though they are defined "for future support".)
+ * We really want the POSIX behavior that if O_CREAT is set,
+ * we open if it exists, or create it if it doesn't exist.
+ * If O_CREAT is specified, single thread and try to open the
+ * file. If successful, and O_EXCL return EEXIST. If
+ * unsuccessful call creat and then end single threading.
+ */
+ if (LF_ISSET(O_CREAT)) {
+ DB_BEGIN_SINGLE_THREAD;
+ newflags = flags & ~(O_CREAT | O_EXCL);
+ if ((fhp->fd = open(name, newflags, mode)) != -1) {
+ /*
+ * We need to mark the file opened at this
+ * point so that if we get any error below
+ * we will properly close the fd we just
+ * opened on the error path.
+ */
+ F_SET(fhp, DB_FH_OPENED);
+ if (LF_ISSET(O_EXCL)) {
+ /*
+ * If we get here, want O_EXCL create,
+ * and the file exists. Close and
+ * return EEXISTS.
+ */
+ DB_END_SINGLE_THREAD;
+ ret = EEXIST;
+ goto err;
+ }
+ /*
+ * XXX
+ * Assume any error means non-existence.
+ * Unfortunately return values (even for
+ * non-existence) are driver specific so
+ * there is no single error we can use to
+ * verify we truly got the equivalent of
+ * ENOENT.
+ */
+ } else
+ fhp->fd = creat(name, newflags);
+ DB_END_SINGLE_THREAD;
+ } else
+ /* FALLTHROUGH */
+#endif
+#ifdef __VMS
+ /*
+ * !!!
+ * Open with full sharing on VMS.
+ *
+ * We use these flags because they are the ones set by the VMS
+ * CRTL mmap() call when it opens a file, and we have to be
+ * able to open files that mmap() has previously opened, e.g.,
+ * when we're joining already existing DB regions.
+ */
+ fhp->fd = open(name, flags, mode, "shr=get,put,upd,del,upi");
+#else
+ fhp->fd = open(name, flags, mode);
+#endif
+ if (fhp->fd != -1) {
+ ret = 0;
+ break;
+ }
+
+ switch (ret = __os_posix_err(__os_get_syserr())) {
+ case EMFILE:
+ case ENFILE:
+ case ENOSPC:
+ /*
+ * If it's a "temporary" error, we retry up to 3 times,
+ * waiting up to 12 seconds. While it's not a problem
+ * if we can't open a database, an inability to open a
+ * log file is cause for serious dismay.
+ */
+ __os_yield(env, nrepeat * 2, 0);
+ break;
+ case EAGAIN:
+ case EBUSY:
+ case EINTR:
+ /*
+ * If an EAGAIN, EBUSY or EINTR, retry immediately for
+ * DB_RETRY times.
+ */
+ if (++retries < DB_RETRY)
+ --nrepeat;
+ break;
+ default:
+ /* Open is silent on error. */
+ goto err;
+ }
+ }
+
+ if (ret == 0) {
+#if defined(HAVE_FCNTL_F_SETFD)
+ /* Deny file descriptor access to any child process. */
+ if ((fcntl_flags = fcntl(fhp->fd, F_GETFD)) == -1 ||
+ fcntl(fhp->fd, F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "fcntl(F_SETFD)");
+ ret = __os_posix_err(ret);
+ goto err;
+ }
+#else
+ COMPQUIET(fcntl_flags, 0);
+#endif
+
+done: F_SET(fhp, DB_FH_OPENED);
+ *fhpp = fhp;
+ return (0);
+ }
+
+err: (void)__os_closehandle(env, fhp);
+ return (ret);
+}
+
+/*
+ * __os_closehandle --
+ * Close a file.
+ *
+ * PUBLIC: int __os_closehandle __P((ENV *, DB_FH *));
+ */
+int
+__os_closehandle(env, fhp)
+ ENV *env;
+ DB_FH *fhp;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ ret = 0;
+
+ /*
+ * If we linked the DB_FH handle into the ENV, it needs to be
+ * unlinked.
+ */
+ DB_ASSERT(env, env != NULL || !F_ISSET(fhp, DB_FH_ENVLINK));
+
+ if (env != NULL) {
+ dbenv = env->dbenv;
+ if (fhp->name != NULL && FLD_ISSET(
+ dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: close %s", fhp->name);
+
+ if (F_ISSET(fhp, DB_FH_ENVLINK)) {
+ /*
+ * Lock the ENV handle and remove this file
+ * handle from the list.
+ */
+ MUTEX_LOCK(env, env->mtx_env);
+ TAILQ_REMOVE(&env->fdlist, fhp, q);
+ MUTEX_UNLOCK(env, env->mtx_env);
+ }
+ }
+
+ /* Discard any underlying system file reference. */
+ if (F_ISSET(fhp, DB_FH_OPENED)) {
+ if (DB_GLOBAL(j_close) != NULL)
+ ret = DB_GLOBAL(j_close)(fhp->fd);
+ else
+ RETRY_CHK((close(fhp->fd)), ret);
+ if (ret != 0) {
+ __db_syserr(env, ret, "close");
+ ret = __os_posix_err(ret);
+ }
+ }
+
+ /* Unlink the file if we haven't already done so. */
+ if (F_ISSET(fhp, DB_FH_UNLINK))
+ (void)__os_unlink(env, fhp->name, 0);
+
+ if (fhp->name != NULL)
+ __os_free(env, fhp->name);
+ __os_free(env, fhp);
+
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_map.c b/db-4.8.30/os/os_map.c
new file mode 100644
index 0000000..b5de0ed
--- /dev/null
+++ b/db-4.8.30/os/os_map.c
@@ -0,0 +1,594 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifdef HAVE_SYSTEM_INCLUDE_FILES
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+#ifdef HAVE_SHMGET
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+#endif
+
+#ifdef HAVE_MMAP
+static int __os_map __P((ENV *, char *, DB_FH *, size_t, int, int, void **));
+#endif
+#ifdef HAVE_SHMGET
+static int __shm_mode __P((ENV *));
+#else
+static int __no_system_mem __P((ENV *));
+#endif
+
+/*
+ * __os_attach --
+ * Create/join a shared memory region.
+ *
+ * PUBLIC: int __os_attach __P((ENV *, REGINFO *, REGION *));
+ */
+int
+__os_attach(env, infop, rp)
+ ENV *env;
+ REGINFO *infop;
+ REGION *rp;
+{
+ DB_ENV *dbenv;
+ int create_ok, ret;
+
+ /*
+ * We pass a DB_ENV handle to the user's replacement map function,
+ * so there must be a valid handle.
+ */
+ DB_ASSERT(env, env != NULL && env->dbenv != NULL);
+ dbenv = env->dbenv;
+
+ if (DB_GLOBAL(j_region_map) != NULL) {
+ /*
+ * We have to find out if the region is being created. Ask
+ * the underlying map function, and use the REGINFO structure
+ * to pass that information back to our caller.
+ */
+ create_ok = F_ISSET(infop, REGION_CREATE) ? 1 : 0;
+ ret = DB_GLOBAL(j_region_map)
+ (dbenv, infop->name, rp->size, &create_ok, &infop->addr);
+ if (create_ok)
+ F_SET(infop, REGION_CREATE);
+ else
+ F_CLR(infop, REGION_CREATE);
+ return (ret);
+ }
+
+ if (F_ISSET(env, ENV_SYSTEM_MEM)) {
+ /*
+ * If the region is in system memory on UNIX, we use shmget(2).
+ *
+ * !!!
+ * There exist spinlocks that don't work in shmget memory, e.g.,
+ * the HP/UX msemaphore interface. If we don't have locks that
+ * will work in shmget memory, we better be private and not be
+ * threaded. If we reach this point, we know we're public, so
+ * it's an error.
+ */
+#if defined(HAVE_MUTEX_HPPA_MSEM_INIT)
+ __db_errx(env,
+ "architecture does not support locks inside system shared memory");
+ return (EINVAL);
+#endif
+#if defined(HAVE_SHMGET)
+ {
+ key_t segid;
+ int id, mode;
+
+ /*
+ * We could potentially create based on REGION_CREATE_OK, but
+ * that's dangerous -- we might get crammed in sideways if
+ * some of the expected regions exist but others do not. Also,
+ * if the requested size differs from an existing region's
+ * actual size, then all sorts of nasty things can happen.
+ * Basing create solely on REGION_CREATE is much safer -- a
+ * recovery will get us straightened out.
+ */
+ if (F_ISSET(infop, REGION_CREATE)) {
+ /*
+ * The application must give us a base System V IPC key
+ * value. Adjust that value based on the region's ID,
+ * and correct so the user's original value appears in
+ * the ipcs output.
+ */
+ if (dbenv->shm_key == INVALID_REGION_SEGID) {
+ __db_errx(env,
+ "no base system shared memory ID specified");
+ return (EINVAL);
+ }
+
+ /*
+ * !!!
+ * The BDB API takes a "long" as the base segment ID,
+ * then adds an unsigned 32-bit value and stores it
+ * in a key_t. Wrong, admittedly, but not worth an
+ * API change to fix.
+ */
+ segid = (key_t)
+ ((u_long)dbenv->shm_key + (infop->id - 1));
+
+ /*
+ * If map to an existing region, assume the application
+ * crashed and we're restarting. Delete the old region
+ * and re-try. If that fails, return an error, the
+ * application will have to select a different segment
+ * ID or clean up some other way.
+ */
+ if ((id = shmget(segid, 0, 0)) != -1) {
+ (void)shmctl(id, IPC_RMID, NULL);
+ if ((id = shmget(segid, 0, 0)) != -1) {
+ __db_errx(env,
+ "shmget: key: %ld: shared system memory region already exists",
+ (long)segid);
+ return (EAGAIN);
+ }
+ }
+
+ /*
+ * Map the DbEnv::open method file mode permissions to
+ * shmget call permissions.
+ */
+ mode = IPC_CREAT | __shm_mode(env);
+ if ((id = shmget(segid, rp->size, mode)) == -1) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret,
+ "shmget: key: %ld: unable to create shared system memory region",
+ (long)segid);
+ return (__os_posix_err(ret));
+ }
+ rp->segid = id;
+ } else
+ id = rp->segid;
+
+ if ((infop->addr = shmat(id, NULL, 0)) == (void *)-1) {
+ infop->addr = NULL;
+ ret = __os_get_syserr();
+ __db_syserr(env, ret,
+ "shmat: id %d: unable to attach to shared system memory region", id);
+ return (__os_posix_err(ret));
+ }
+
+ /* Optionally lock the memory down. */
+ if (F_ISSET(env, ENV_LOCKDOWN)) {
+#ifdef HAVE_SHMCTL_SHM_LOCK
+ ret = shmctl(
+ id, SHM_LOCK, NULL) == 0 ? 0 : __os_get_syserr();
+#else
+ ret = DB_OPNOTSUP;
+#endif
+ if (ret != 0) {
+ __db_syserr(env, ret,
+ "shmctl/SHM_LOCK: id %d: unable to lock down shared memory region", id);
+ return (__os_posix_err(ret));
+ }
+ }
+
+ return (0);
+ }
+#else
+ return (__no_system_mem(env));
+#endif
+ }
+
+#ifdef HAVE_MMAP
+ {
+ DB_FH *fhp;
+
+ fhp = NULL;
+
+ /*
+ * Try to open/create the shared region file. We DO NOT need to ensure
+ * that multiple threads/processes attempting to simultaneously create
+ * the region are properly ordered, our caller has already taken care
+ * of that.
+ */
+ if ((ret = __os_open(env, infop->name, 0,
+ DB_OSO_REGION |
+ (F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE : 0),
+ env->db_mode, &fhp)) != 0)
+ __db_err(env, ret, "%s", infop->name);
+
+ /*
+ * If we created the file, grow it to its full size before mapping
+ * it in. We really want to avoid touching the buffer cache after
+ * mmap(2) is called, doing anything else confuses the hell out of
+ * systems without merged VM/buffer cache systems, or, more to the
+ * point, *badly* merged VM/buffer cache systems.
+ */
+ if (ret == 0 && F_ISSET(infop, REGION_CREATE)) {
+ if (F_ISSET(dbenv, DB_ENV_REGION_INIT))
+ ret = __db_file_write(env, fhp,
+ rp->size / MEGABYTE, rp->size % MEGABYTE, 0x00);
+ else
+ ret = __db_file_extend(env, fhp, rp->size);
+ }
+
+ /* Map the file in. */
+ if (ret == 0)
+ ret = __os_map(env,
+ infop->name, fhp, rp->size, 1, 0, &infop->addr);
+
+ if (fhp != NULL)
+ (void)__os_closehandle(env, fhp);
+
+ return (ret);
+ }
+#else
+ COMPQUIET(infop, NULL);
+ COMPQUIET(rp, NULL);
+ __db_errx(env,
+ "architecture lacks mmap(2), shared environments not possible");
+ return (DB_OPNOTSUP);
+#endif
+}
+
+/*
+ * __os_detach --
+ * Detach from a shared memory region.
+ *
+ * PUBLIC: int __os_detach __P((ENV *, REGINFO *, int));
+ */
+int
+__os_detach(env, infop, destroy)
+ ENV *env;
+ REGINFO *infop;
+ int destroy;
+{
+ DB_ENV *dbenv;
+ REGION *rp;
+ int ret;
+
+ /*
+ * We pass a DB_ENV handle to the user's replacement unmap function,
+ * so there must be a valid handle.
+ */
+ DB_ASSERT(env, env != NULL && env->dbenv != NULL);
+ dbenv = env->dbenv;
+
+ rp = infop->rp;
+
+ /* If the user replaced the unmap call, call through their interface. */
+ if (DB_GLOBAL(j_region_unmap) != NULL)
+ return (DB_GLOBAL(j_region_unmap)(dbenv, infop->addr));
+
+ if (F_ISSET(env, ENV_SYSTEM_MEM)) {
+#ifdef HAVE_SHMGET
+ int segid;
+
+ /*
+ * We may be about to remove the memory referenced by rp,
+ * save the segment ID, and (optionally) wipe the original.
+ */
+ segid = rp->segid;
+ if (destroy)
+ rp->segid = INVALID_REGION_SEGID;
+
+ if (shmdt(infop->addr) != 0) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "shmdt");
+ return (__os_posix_err(ret));
+ }
+
+ if (destroy && shmctl(segid, IPC_RMID,
+ NULL) != 0 && (ret = __os_get_syserr()) != EINVAL) {
+ __db_syserr(env, ret,
+ "shmctl: id %d: unable to delete system shared memory region",
+ segid);
+ return (__os_posix_err(ret));
+ }
+
+ return (0);
+#else
+ return (__no_system_mem(env));
+#endif
+ }
+
+#ifdef HAVE_MMAP
+#ifdef HAVE_MUNLOCK
+ if (F_ISSET(env, ENV_LOCKDOWN))
+ (void)munlock(infop->addr, rp->size);
+#endif
+ if (munmap(infop->addr, rp->size) != 0) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "munmap");
+ return (__os_posix_err(ret));
+ }
+
+ if (destroy && (ret = __os_unlink(env, infop->name, 1)) != 0)
+ return (ret);
+
+ return (0);
+#else
+ COMPQUIET(destroy, 0);
+ COMPQUIET(ret, 0);
+ return (EINVAL);
+#endif
+}
+
+/*
+ * __os_mapfile --
+ * Map in a shared memory file.
+ *
+ * PUBLIC: int __os_mapfile __P((ENV *, char *, DB_FH *, size_t, int, void **));
+ */
+int
+__os_mapfile(env, path, fhp, len, is_rdonly, addrp)
+ ENV *env;
+ char *path;
+ DB_FH *fhp;
+ int is_rdonly;
+ size_t len;
+ void **addrp;
+{
+#if defined(HAVE_MMAP) && !defined(HAVE_QNX)
+ DB_ENV *dbenv;
+
+ /* If the user replaced the map call, call through their interface. */
+ if (DB_GLOBAL(j_file_map) != NULL) {
+ /*
+ * We pass a DB_ENV handle to the user's replacement map
+ * function, so there must be a valid handle.
+ */
+ DB_ASSERT(env, env != NULL && env->dbenv != NULL);
+ dbenv = env->dbenv;
+
+ return (
+ DB_GLOBAL(j_file_map)(dbenv, path, len, is_rdonly, addrp));
+ }
+
+ return (__os_map(env, path, fhp, len, 0, is_rdonly, addrp));
+#else
+ COMPQUIET(env, NULL);
+ COMPQUIET(path, NULL);
+ COMPQUIET(fhp, NULL);
+ COMPQUIET(is_rdonly, 0);
+ COMPQUIET(len, 0);
+ COMPQUIET(addrp, NULL);
+ return (DB_OPNOTSUP);
+#endif
+}
+
+/*
+ * __os_unmapfile --
+ * Unmap the shared memory file.
+ *
+ * PUBLIC: int __os_unmapfile __P((ENV *, void *, size_t));
+ */
+int
+__os_unmapfile(env, addr, len)
+ ENV *env;
+ void *addr;
+ size_t len;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ /*
+ * We pass a DB_ENV handle to the user's replacement unmap function,
+ * so there must be a valid handle.
+ */
+ DB_ASSERT(env, env != NULL && env->dbenv != NULL);
+ dbenv = env->dbenv;
+
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: munmap");
+
+ /* If the user replaced the map call, call through their interface. */
+ if (DB_GLOBAL(j_file_unmap) != NULL)
+ return (DB_GLOBAL(j_file_unmap)(dbenv, addr));
+
+#ifdef HAVE_MMAP
+#ifdef HAVE_MUNLOCK
+ if (F_ISSET(env, ENV_LOCKDOWN))
+ RETRY_CHK((munlock(addr, len)), ret);
+ /*
+ * !!!
+ * The return value is ignored.
+ */
+#else
+ COMPQUIET(env, NULL);
+#endif
+ RETRY_CHK((munmap(addr, len)), ret);
+ ret = __os_posix_err(ret);
+#else
+ COMPQUIET(env, NULL);
+ ret = EINVAL;
+#endif
+ return (ret);
+}
+
+#ifdef HAVE_MMAP
+/*
+ * __os_map --
+ * Call the mmap(2) function.
+ */
+static int
+__os_map(env, path, fhp, len, is_region, is_rdonly, addrp)
+ ENV *env;
+ char *path;
+ DB_FH *fhp;
+ int is_region, is_rdonly;
+ size_t len;
+ void **addrp;
+{
+ DB_ENV *dbenv;
+ int flags, prot, ret;
+ void *p;
+
+ /*
+ * We pass a DB_ENV handle to the user's replacement map function,
+ * so there must be a valid handle.
+ */
+ DB_ASSERT(env, env != NULL && env->dbenv != NULL);
+ dbenv = env->dbenv;
+
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: mmap %s", path);
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+ /*
+ * If it's read-only, it's private, and if it's not, it's shared.
+ * Don't bother with an additional parameter.
+ */
+ flags = is_rdonly ? MAP_PRIVATE : MAP_SHARED;
+
+#ifdef MAP_FILE
+ /*
+ * Historically, MAP_FILE was required for mapping regular files,
+ * even though it was the default. Some systems have it, some
+ * don't, some that have it set it to 0.
+ */
+ flags |= MAP_FILE;
+#endif
+
+ /*
+ * I know of no systems that implement the flag to tell the system
+ * that the region contains semaphores, but it's not an unreasonable
+ * thing to do, and has been part of the design since forever. I
+ * don't think anyone will object, but don't set it for read-only
+ * files, it doesn't make sense.
+ */
+#ifdef MAP_HASSEMAPHORE
+ if (is_region && !is_rdonly)
+ flags |= MAP_HASSEMAPHORE;
+#else
+ COMPQUIET(is_region, 0);
+#endif
+
+ /*
+ * FreeBSD:
+ * Causes data dirtied via this VM map to be flushed to physical media
+ * only when necessary (usually by the pager) rather then gratuitously.
+ * Typically this prevents the update daemons from flushing pages
+ * dirtied through such maps and thus allows efficient sharing of
+ * memory across unassociated processes using a file-backed shared
+ * memory map.
+ */
+#ifdef MAP_NOSYNC
+ flags |= MAP_NOSYNC;
+#endif
+
+ prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE);
+
+ /*
+ * XXX
+ * Work around a bug in the VMS V7.1 mmap() implementation. To map
+ * a file into memory on VMS it needs to be opened in a certain way,
+ * originally. To get the file opened in that certain way, the VMS
+ * mmap() closes the file and re-opens it. When it does this, it
+ * doesn't flush any caches out to disk before closing. The problem
+ * this causes us is that when the memory cache doesn't get written
+ * out, the file isn't big enough to match the memory chunk and the
+ * mmap() call fails. This call to fsync() fixes the problem. DEC
+ * thinks this isn't a bug because of language in XPG5 discussing user
+ * responsibility for on-disk and in-memory synchronization.
+ */
+#ifdef VMS
+ if (__os_fsync(env, fhp) == -1)
+ return (__os_posix_err(__os_get_syserr()));
+#endif
+
+ /* MAP_FAILED was not defined in early mmap implementations. */
+#ifndef MAP_FAILED
+#define MAP_FAILED -1
+#endif
+ if ((p = mmap(NULL,
+ len, prot, flags, fhp->fd, (off_t)0)) == (void *)MAP_FAILED) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "mmap");
+ return (__os_posix_err(ret));
+ }
+
+ /*
+ * If it's a region, we want to make sure that the memory isn't paged.
+ * For example, Solaris will page large mpools because it thinks that
+ * I/O buffer memory is more important than we are. The mlock system
+ * call may or may not succeed (mlock is restricted to the super-user
+ * on some systems). Currently, the only other use of mmap in DB is
+ * to map read-only databases -- we don't want them paged, either, so
+ * the call isn't conditional.
+ */
+ if (F_ISSET(env, ENV_LOCKDOWN)) {
+#ifdef HAVE_MLOCK
+ ret = mlock(p, len) == 0 ? 0 : __os_get_syserr();
+#else
+ ret = DB_OPNOTSUP;
+#endif
+ if (ret != 0) {
+ __db_syserr(env, ret, "mlock");
+ return (__os_posix_err(ret));
+ }
+ }
+
+ *addrp = p;
+ return (0);
+}
+#endif
+
+#ifdef HAVE_SHMGET
+#ifndef SHM_R
+#define SHM_R 0400
+#endif
+#ifndef SHM_W
+#define SHM_W 0200
+#endif
+
+/*
+ * __shm_mode --
+ * Map the DbEnv::open method file mode permissions to shmget call
+ * permissions.
+ */
+static int
+__shm_mode(env)
+ ENV *env;
+{
+ int mode;
+
+ /* Default to r/w owner, r/w group. */
+ if (env->db_mode == 0)
+ return (SHM_R | SHM_W | SHM_R >> 3 | SHM_W >> 3);
+
+ mode = 0;
+ if (env->db_mode & S_IRUSR)
+ mode |= SHM_R;
+ if (env->db_mode & S_IWUSR)
+ mode |= SHM_W;
+ if (env->db_mode & S_IRGRP)
+ mode |= SHM_R >> 3;
+ if (env->db_mode & S_IWGRP)
+ mode |= SHM_W >> 3;
+ if (env->db_mode & S_IROTH)
+ mode |= SHM_R >> 6;
+ if (env->db_mode & S_IWOTH)
+ mode |= SHM_W >> 6;
+ return (mode);
+}
+#else
+/*
+ * __no_system_mem --
+ * No system memory environments error message.
+ */
+static int
+__no_system_mem(env)
+ ENV *env;
+{
+ __db_errx(env,
+ "architecture doesn't support environments in system memory");
+ return (DB_OPNOTSUP);
+}
+#endif /* HAVE_SHMGET */
diff --git a/db-4.8.30/os/os_mkdir.c b/db-4.8.30/os/os_mkdir.c
new file mode 100644
index 0000000..238be1a
--- /dev/null
+++ b/db-4.8.30/os/os_mkdir.c
@@ -0,0 +1,51 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_mkdir --
+ * Create a directory.
+ *
+ * PUBLIC: int __os_mkdir __P((ENV *, const char *, int));
+ */
+int
+__os_mkdir(env, name, mode)
+ ENV *env;
+ const char *name;
+ int mode;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: mkdir %s", name);
+
+ /* Make the directory, with paranoid permissions. */
+#if defined(HAVE_VXWORKS)
+ RETRY_CHK((mkdir(CHAR_STAR_CAST name)), ret);
+#else
+ RETRY_CHK((mkdir(name, DB_MODE_700)), ret);
+#endif
+ if (ret != 0)
+ return (__os_posix_err(ret));
+
+ /* Set the absolute permissions, if specified. */
+#if !defined(HAVE_VXWORKS)
+ if (mode != 0) {
+ RETRY_CHK((chmod(name, mode)), ret);
+ if (ret != 0)
+ ret = __os_posix_err(ret);
+ }
+#endif
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_open.c b/db-4.8.30/os/os_open.c
new file mode 100644
index 0000000..a9eeef3
--- /dev/null
+++ b/db-4.8.30/os/os_open.c
@@ -0,0 +1,160 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_open --
+ * Open a file descriptor (including page size and log size information).
+ *
+ * PUBLIC: int __os_open __P((ENV *,
+ * PUBLIC: const char *, u_int32_t, u_int32_t, int, DB_FH **));
+ */
+int
+__os_open(env, name, page_size, flags, mode, fhpp)
+ ENV *env;
+ const char *name;
+ u_int32_t page_size, flags;
+ int mode;
+ DB_FH **fhpp;
+{
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+ int oflags, ret;
+
+ COMPQUIET(page_size, 0);
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ *fhpp = NULL;
+ oflags = 0;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: open %s", name);
+
+#define OKFLAGS \
+ (DB_OSO_ABSMODE | DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC |\
+ DB_OSO_EXCL | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | \
+ DB_OSO_TEMP | DB_OSO_TRUNC)
+ if ((ret = __db_fchk(env, "__os_open", flags, OKFLAGS)) != 0)
+ return (ret);
+
+#if defined(O_BINARY)
+ /*
+ * If there's a binary-mode open flag, set it, we never want any
+ * kind of translation. Some systems do translations by default,
+ * e.g., with Cygwin, the default mode for an open() is set by the
+ * mode of the mount that underlies the file.
+ */
+ oflags |= O_BINARY;
+#endif
+
+ /*
+ * DB requires the POSIX 1003.1 semantic that two files opened at the
+ * same time with DB_OSO_CREATE/O_CREAT and DB_OSO_EXCL/O_EXCL flags
+ * set return an EEXIST failure in at least one.
+ */
+ if (LF_ISSET(DB_OSO_CREATE))
+ oflags |= O_CREAT;
+
+ if (LF_ISSET(DB_OSO_EXCL))
+ oflags |= O_EXCL;
+
+#ifdef HAVE_O_DIRECT
+ if (LF_ISSET(DB_OSO_DIRECT))
+ oflags |= O_DIRECT;
+#endif
+#ifdef O_DSYNC
+ if (LF_ISSET(DB_OSO_DSYNC))
+ oflags |= O_DSYNC;
+#endif
+
+ if (LF_ISSET(DB_OSO_RDONLY))
+ oflags |= O_RDONLY;
+ else
+ oflags |= O_RDWR;
+
+ if (LF_ISSET(DB_OSO_TRUNC))
+ oflags |= O_TRUNC;
+
+ /*
+ * Undocumented feature: allow applications to create intermediate
+ * directories whenever a file is opened.
+ */
+ if (dbenv != NULL &&
+ env->dir_mode != 0 && LF_ISSET(DB_OSO_CREATE) &&
+ (ret = __db_mkpath(env, name)) != 0)
+ return (ret);
+
+ /* Open the file. */
+#ifdef HAVE_QNX
+ if (LF_ISSET(DB_OSO_REGION))
+ ret = __os_qnx_region_open(env, name, oflags, mode, &fhp);
+ else
+#endif
+ ret = __os_openhandle(env, name, oflags, mode, &fhp);
+ if (ret != 0)
+ return (ret);
+
+ if (LF_ISSET(DB_OSO_REGION))
+ F_SET(fhp, DB_FH_REGION);
+#ifdef HAVE_FCHMOD
+ /*
+ * If the code using Berkeley DB is a library, that code may not be able
+ * to control the application's umask value. Allow applications to set
+ * absolute file modes. We can't fix the race between file creation and
+ * the fchmod call -- we can't modify the process' umask here since the
+ * process may be multi-threaded and the umask value is per-process, not
+ * per-thread.
+ */
+ if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_ABSMODE))
+ (void)fchmod(fhp->fd, mode);
+#endif
+
+#ifdef O_DSYNC
+ /*
+ * If we can configure the file descriptor to flush on write, the
+ * file descriptor does not need to be explicitly sync'd.
+ */
+ if (LF_ISSET(DB_OSO_DSYNC))
+ F_SET(fhp, DB_FH_NOSYNC);
+#endif
+
+#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
+ /*
+ * The Solaris C library includes directio, but you have to set special
+ * compile flags to #define DIRECTIO_ON. Require both in order to call
+ * directio.
+ */
+ if (LF_ISSET(DB_OSO_DIRECT))
+ (void)directio(fhp->fd, DIRECTIO_ON);
+#endif
+
+ /*
+ * Delete any temporary file.
+ *
+ * !!!
+ * There's a race here, where we've created a file and we crash before
+ * we can unlink it. Temporary files aren't common in DB, regardless,
+ * it's not a security problem because the file is empty. There's no
+ * reasonable way to avoid the race (playing signal games isn't worth
+ * the portability nightmare), so we just live with it.
+ */
+ if (LF_ISSET(DB_OSO_TEMP)) {
+#if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST)
+ F_SET(fhp, DB_FH_UNLINK);
+#else
+ (void)__os_unlink(env, name, 0);
+#endif
+ }
+
+ *fhpp = fhp;
+ return (0);
+}
diff --git a/db-4.8.30/os/os_pid.c b/db-4.8.30/os/os_pid.c
new file mode 100644
index 0000000..4eb74f2
--- /dev/null
+++ b/db-4.8.30/os/os_pid.c
@@ -0,0 +1,57 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_id --
+ * Return the current process ID.
+ *
+ * PUBLIC: void __os_id __P((DB_ENV *, pid_t *, db_threadid_t*));
+ */
+void
+__os_id(dbenv, pidp, tidp)
+ DB_ENV *dbenv;
+ pid_t *pidp;
+ db_threadid_t *tidp;
+{
+ /*
+ * We can't depend on dbenv not being NULL, this routine is called
+ * from places where there's no DB_ENV handle.
+ *
+ * We cache the pid in the ENV handle, getting the process ID is a
+ * fairly slow call on lots of systems.
+ */
+ if (pidp != NULL) {
+ if (dbenv == NULL) {
+#if defined(HAVE_VXWORKS)
+ *pidp = taskIdSelf();
+#else
+ *pidp = getpid();
+#endif
+ } else
+ *pidp = dbenv->env->pid_cache;
+ }
+
+ if (tidp != NULL) {
+#if defined(DB_WIN32)
+ *tidp = GetCurrentThreadId();
+#elif defined(HAVE_MUTEX_UI_THREADS)
+ *tidp = thr_self();
+#elif defined(HAVE_PTHREAD_SELF)
+ *tidp = pthread_self();
+#else
+ /*
+ * Default to just getpid.
+ */
+ *tidp = 0;
+#endif
+ }
+}
diff --git a/db-4.8.30/os/os_rename.c b/db-4.8.30/os/os_rename.c
new file mode 100644
index 0000000..4245b98
--- /dev/null
+++ b/db-4.8.30/os/os_rename.c
@@ -0,0 +1,52 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_rename --
+ * Rename a file.
+ *
+ * PUBLIC: int __os_rename __P((ENV *,
+ * PUBLIC: const char *, const char *, u_int32_t));
+ */
+int
+__os_rename(env, oldname, newname, silent)
+ ENV *env;
+ const char *oldname, *newname;
+ u_int32_t silent;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: rename %s to %s", oldname, newname);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ if (DB_GLOBAL(j_rename) != NULL)
+ ret = DB_GLOBAL(j_rename)(oldname, newname);
+ else
+ RETRY_CHK((rename(oldname, newname)), ret);
+
+ /*
+ * If "silent" is not set, then errors are OK and we should not output
+ * an error message.
+ */
+ if (ret != 0) {
+ if (!silent)
+ __db_syserr(
+ env, ret, "rename %s %s", oldname, newname);
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_root.c b/db-4.8.30/os/os_root.c
new file mode 100644
index 0000000..79fe398
--- /dev/null
+++ b/db-4.8.30/os/os_root.c
@@ -0,0 +1,27 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_isroot --
+ * Return if user has special permissions.
+ *
+ * PUBLIC: int __os_isroot __P((void));
+ */
+int
+__os_isroot()
+{
+#ifdef HAVE_GETUID
+ return (getuid() == 0);
+#else
+ return (0);
+#endif
+}
diff --git a/db-4.8.30/os/os_rpath.c b/db-4.8.30/os/os_rpath.c
new file mode 100644
index 0000000..c59855b
--- /dev/null
+++ b/db-4.8.30/os/os_rpath.c
@@ -0,0 +1,36 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __db_rpath --
+ * Return the last path separator in the path or NULL if none found.
+ *
+ * PUBLIC: char *__db_rpath __P((const char *));
+ */
+char *
+__db_rpath(path)
+ const char *path;
+{
+ const char *s, *last;
+
+ s = path;
+ last = NULL;
+ if (PATH_SEPARATOR[1] != '\0') {
+ for (; s[0] != '\0'; ++s)
+ if (strchr(PATH_SEPARATOR, s[0]) != NULL)
+ last = s;
+ } else
+ for (; s[0] != '\0'; ++s)
+ if (s[0] == PATH_SEPARATOR[0])
+ last = s;
+ return ((char *)last);
+}
diff --git a/db-4.8.30/os/os_rw.c b/db-4.8.30/os/os_rw.c
new file mode 100644
index 0000000..235f993
--- /dev/null
+++ b/db-4.8.30/os/os_rw.c
@@ -0,0 +1,285 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_io --
+ * Do an I/O.
+ *
+ * PUBLIC: int __os_io __P((ENV *, int, DB_FH *, db_pgno_t,
+ * PUBLIC: u_int32_t, u_int32_t, u_int32_t, u_int8_t *, size_t *));
+ */
+int
+__os_io(env, op, fhp, pgno, pgsize, relative, io_len, buf, niop)
+ ENV *env;
+ int op;
+ DB_FH *fhp;
+ db_pgno_t pgno;
+ u_int32_t pgsize, relative, io_len;
+ u_int8_t *buf;
+ size_t *niop;
+{
+#if defined(HAVE_PREAD) && defined(HAVE_PWRITE)
+ DB_ENV *dbenv;
+ off_t offset;
+ ssize_t nio;
+#endif
+ int ret;
+
+ /*
+ * Check for illegal usage.
+ *
+ * This routine is used in one of two ways: reading bytes from an
+ * absolute offset and reading a specific database page. All of
+ * our absolute offsets are known to fit into a u_int32_t, while
+ * our database pages might be at offsets larger than a u_int32_t.
+ * We don't want to specify an absolute offset in our caller as we
+ * aren't exactly sure what size an off_t might be.
+ */
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+ DB_ASSERT(env, (pgno == 0 && pgsize == 0) || relative == 0);
+
+#if defined(HAVE_PREAD) && defined(HAVE_PWRITE)
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if ((offset = relative) == 0)
+ offset = (off_t)pgno * pgsize;
+ switch (op) {
+ case DB_IO_READ:
+ if (DB_GLOBAL(j_read) != NULL)
+ goto slow;
+#if defined(HAVE_STATISTICS)
+ ++fhp->read_count;
+#endif
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: read %s: %lu bytes at offset %lu",
+ fhp->name, (u_long)io_len, (u_long)offset);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ nio = DB_GLOBAL(j_pread) != NULL ?
+ DB_GLOBAL(j_pread)(fhp->fd, buf, io_len, offset) :
+ pread(fhp->fd, buf, io_len, offset);
+ break;
+ case DB_IO_WRITE:
+ if (DB_GLOBAL(j_write) != NULL)
+ goto slow;
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ if (__os_fs_notzero())
+ goto slow;
+#endif
+#if defined(HAVE_STATISTICS)
+ ++fhp->write_count;
+#endif
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: write %s: %lu bytes at offset %lu",
+ fhp->name, (u_long)io_len, (u_long)offset);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ nio = DB_GLOBAL(j_pwrite) != NULL ?
+ DB_GLOBAL(j_pwrite)(fhp->fd, buf, io_len, offset) :
+ pwrite(fhp->fd, buf, io_len, offset);
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (nio == (ssize_t)io_len) {
+ *niop = io_len;
+ return (0);
+ }
+slow:
+#endif
+ MUTEX_LOCK(env, fhp->mtx_fh);
+
+ if ((ret = __os_seek(env, fhp, pgno, pgsize, relative)) != 0)
+ goto err;
+ switch (op) {
+ case DB_IO_READ:
+ ret = __os_read(env, fhp, buf, io_len, niop);
+ break;
+ case DB_IO_WRITE:
+ ret = __os_write(env, fhp, buf, io_len, niop);
+ break;
+ default:
+ ret = EINVAL;
+ break;
+ }
+
+err: MUTEX_UNLOCK(env, fhp->mtx_fh);
+
+ return (ret);
+
+}
+
+/*
+ * __os_read --
+ * Read from a file handle.
+ *
+ * PUBLIC: int __os_read __P((ENV *, DB_FH *, void *, size_t, size_t *));
+ */
+int
+__os_read(env, fhp, addr, len, nrp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nrp;
+{
+ DB_ENV *dbenv;
+ size_t offset;
+ ssize_t nr;
+ int ret;
+ u_int8_t *taddr;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ ret = 0;
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+#if defined(HAVE_STATISTICS)
+ ++fhp->read_count;
+#endif
+ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: read %s: %lu bytes", fhp->name, (u_long)len);
+
+ if (DB_GLOBAL(j_read) != NULL) {
+ *nrp = len;
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ if (DB_GLOBAL(j_read)(fhp->fd, addr, len) != (ssize_t)len) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "read: %#lx, %lu",
+ P_TO_ULONG(addr), (u_long)len);
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+ }
+
+ for (taddr = addr, offset = 0;
+ offset < len; taddr += nr, offset += (u_int32_t)nr) {
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ RETRY_CHK(((nr = read(fhp->fd,
+ CHAR_STAR_CAST taddr, len - offset)) < 0 ? 1 : 0), ret);
+ if (nr == 0 || ret != 0)
+ break;
+ }
+ *nrp = (size_t)(taddr - (u_int8_t *)addr);
+ if (ret != 0) {
+ __db_syserr(env, ret, "read: %#lx, %lu",
+ P_TO_ULONG(taddr), (u_long)len - offset);
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+}
+
+/*
+ * __os_write --
+ * Write to a file handle.
+ *
+ * PUBLIC: int __os_write __P((ENV *, DB_FH *, void *, size_t, size_t *));
+ */
+int
+__os_write(env, fhp, addr, len, nwp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nwp;
+{
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ /* Zero-fill as necessary. */
+ if (__os_fs_notzero()) {
+ int ret;
+ if ((ret = __db_zero_fill(env, fhp)) != 0)
+ return (ret);
+ }
+#endif
+ return (__os_physwrite(env, fhp, addr, len, nwp));
+}
+
+/*
+ * __os_physwrite --
+ * Physical write to a file handle.
+ *
+ * PUBLIC: int __os_physwrite
+ * PUBLIC: __P((ENV *, DB_FH *, void *, size_t, size_t *));
+ */
+int
+__os_physwrite(env, fhp, addr, len, nwp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nwp;
+{
+ DB_ENV *dbenv;
+ size_t offset;
+ ssize_t nw;
+ int ret;
+ u_int8_t *taddr;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ ret = 0;
+
+#if defined(HAVE_STATISTICS)
+ ++fhp->write_count;
+#endif
+ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: write %s: %lu bytes", fhp->name, (u_long)len);
+
+#if defined(HAVE_FILESYSTEM_NOTZERO) && defined(DIAGNOSTIC)
+ if (__os_fs_notzero()) {
+ struct stat sb;
+ off_t cur_off;
+
+ DB_ASSERT(env, fstat(fhp->fd, &sb) != -1 &&
+ (cur_off = lseek(fhp->fd, (off_t)0, SEEK_CUR)) != -1 &&
+ cur_off <= sb.st_size);
+ }
+#endif
+ if (DB_GLOBAL(j_write) != NULL) {
+ *nwp = len;
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ if (DB_GLOBAL(j_write)(fhp->fd, addr, len) != (ssize_t)len) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "write: %#lx, %lu",
+ P_TO_ULONG(addr), (u_long)len);
+ ret = __os_posix_err(ret);
+
+ DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL);
+ }
+ return (ret);
+ }
+
+ for (taddr = addr, offset = 0;
+ offset < len; taddr += nw, offset += (u_int32_t)nw) {
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ RETRY_CHK(((nw = write(fhp->fd,
+ CHAR_STAR_CAST taddr, len - offset)) < 0 ? 1 : 0), ret);
+ if (ret != 0)
+ break;
+ }
+ *nwp = len;
+ if (ret != 0) {
+ __db_syserr(env, ret, "write: %#lx, %lu",
+ P_TO_ULONG(taddr), (u_long)len - offset);
+ ret = __os_posix_err(ret);
+
+ DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL);
+ }
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_seek.c b/db-4.8.30/os/os_seek.c
new file mode 100644
index 0000000..7c9c9e9
--- /dev/null
+++ b/db-4.8.30/os/os_seek.c
@@ -0,0 +1,64 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_seek --
+ * Seek to a page/byte offset in the file.
+ *
+ * PUBLIC: int __os_seek __P((ENV *,
+ * PUBLIC: DB_FH *, db_pgno_t, u_int32_t, u_int32_t));
+ */
+int
+__os_seek(env, fhp, pgno, pgsize, relative)
+ ENV *env;
+ DB_FH *fhp;
+ db_pgno_t pgno;
+ u_int32_t pgsize;
+ u_int32_t relative;
+{
+ DB_ENV *dbenv;
+ off_t offset;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+#if defined(HAVE_STATISTICS)
+ ++fhp->seek_count;
+#endif
+
+ offset = (off_t)pgsize * pgno + relative;
+
+ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: seek %s to %lu", fhp->name, (u_long)offset);
+
+ if (DB_GLOBAL(j_seek) != NULL)
+ ret = DB_GLOBAL(j_seek)(fhp->fd, offset, SEEK_SET);
+ else
+ RETRY_CHK((lseek(
+ fhp->fd, offset, SEEK_SET) == -1 ? 1 : 0), ret);
+
+ if (ret == 0) {
+ fhp->pgsize = pgsize;
+ fhp->pgno = pgno;
+ fhp->offset = relative;
+ } else {
+ __db_syserr(env, ret,
+ "seek: %lu: (%lu * %lu) + %lu", (u_long)offset,
+ (u_long)pgno, (u_long)pgsize, (u_long)relative);
+ ret = __os_posix_err(ret);
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_stack.c b/db-4.8.30/os/os_stack.c
new file mode 100644
index 0000000..ee859b7
--- /dev/null
+++ b/db-4.8.30/os/os_stack.c
@@ -0,0 +1,45 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_BACKTRACE) && \
+ defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+/*
+ * __os_stack --
+ * Output a stack trace to the message file handle.
+ *
+ * PUBLIC: void __os_stack __P((ENV *));
+ */
+void
+__os_stack(env)
+ ENV *env;
+{
+#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
+ void *array[200];
+ size_t i, size;
+ char **strings;
+
+ /*
+ * Solaris and the GNU C library support this interface. Solaris
+ * has additional interfaces (printstack and walkcontext), I don't
+ * know if they offer any additional value or not.
+ */
+ size = backtrace(array, sizeof(array) / sizeof(array[0]));
+ strings = backtrace_symbols(array, size);
+
+ for (i = 0; i < size; ++i)
+ __db_errx(env, "%s", strings[i]);
+ free(strings);
+#endif
+ COMPQUIET(env, NULL);
+}
diff --git a/db-4.8.30/os/os_stat.c b/db-4.8.30/os/os_stat.c
new file mode 100644
index 0000000..1c3b44a
--- /dev/null
+++ b/db-4.8.30/os/os_stat.c
@@ -0,0 +1,107 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_exists --
+ * Return if the file exists.
+ *
+ * PUBLIC: int __os_exists __P((ENV *, const char *, int *));
+ */
+int
+__os_exists(env, path, isdirp)
+ ENV *env;
+ const char *path;
+ int *isdirp;
+{
+ DB_ENV *dbenv;
+ struct stat sb;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: stat %s", path);
+
+ if (DB_GLOBAL(j_exists) != NULL)
+ return (DB_GLOBAL(j_exists)(path, isdirp));
+
+ RETRY_CHK((stat(CHAR_STAR_CAST path, &sb)), ret);
+ if (ret != 0)
+ return (__os_posix_err(ret));
+
+#if !defined(S_ISDIR) || defined(STAT_MACROS_BROKEN)
+#undef S_ISDIR
+#ifdef _S_IFDIR
+#define S_ISDIR(m) (_S_IFDIR & (m))
+#else
+#define S_ISDIR(m) (((m) & 0170000) == 0040000)
+#endif
+#endif
+ if (isdirp != NULL)
+ *isdirp = S_ISDIR(sb.st_mode);
+
+ return (0);
+}
+
+/*
+ * __os_ioinfo --
+ * Return file size and I/O size; abstracted to make it easier
+ * to replace.
+ *
+ * PUBLIC: int __os_ioinfo __P((ENV *, const char *,
+ * PUBLIC: DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *));
+ */
+int
+__os_ioinfo(env, path, fhp, mbytesp, bytesp, iosizep)
+ ENV *env;
+ const char *path;
+ DB_FH *fhp;
+ u_int32_t *mbytesp, *bytesp, *iosizep;
+{
+ struct stat sb;
+ int ret;
+
+ if (DB_GLOBAL(j_ioinfo) != NULL)
+ return (DB_GLOBAL(j_ioinfo)(path,
+ fhp->fd, mbytesp, bytesp, iosizep));
+
+ DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+ RETRY_CHK((fstat(fhp->fd, &sb)), ret);
+ if (ret != 0) {
+ __db_syserr(env, ret, "fstat");
+ return (__os_posix_err(ret));
+ }
+
+ /* Return the size of the file. */
+ if (mbytesp != NULL)
+ *mbytesp = (u_int32_t)(sb.st_size / MEGABYTE);
+ if (bytesp != NULL)
+ *bytesp = (u_int32_t)(sb.st_size % MEGABYTE);
+
+ /*
+ * Return the underlying filesystem I/O size, if available.
+ *
+ * XXX
+ * Check for a 0 size -- the HP MPE/iX architecture has st_blksize,
+ * but it's always 0.
+ */
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ if (iosizep != NULL && (*iosizep = sb.st_blksize) == 0)
+ *iosizep = DB_DEF_IOSIZE;
+#else
+ if (iosizep != NULL)
+ *iosizep = DB_DEF_IOSIZE;
+#endif
+ return (0);
+}
diff --git a/db-4.8.30/os/os_tmpdir.c b/db-4.8.30/os/os_tmpdir.c
new file mode 100644
index 0000000..c5369eb
--- /dev/null
+++ b/db-4.8.30/os/os_tmpdir.c
@@ -0,0 +1,138 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifdef HAVE_SYSTEM_INCLUDE_FILES
+#ifdef macintosh
+#include <TFileSpec.h>
+#endif
+#endif
+
+/*
+ * __os_tmpdir --
+ * Set the temporary directory path.
+ *
+ * The order of items in the list structure and the order of checks in
+ * the environment are documented.
+ *
+ * PUBLIC: int __os_tmpdir __P((ENV *, u_int32_t));
+ */
+int
+__os_tmpdir(env, flags)
+ ENV *env;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int isdir, ret;
+ char *tdir, tdir_buf[DB_MAXPATHLEN];
+
+ dbenv = env->dbenv;
+
+ /* Use the environment if it's permitted and initialized. */
+ if (LF_ISSET(DB_USE_ENVIRON) ||
+ (LF_ISSET(DB_USE_ENVIRON_ROOT) && __os_isroot())) {
+ /* POSIX: TMPDIR */
+ tdir = tdir_buf;
+ if ((ret = __os_getenv(
+ env, "TMPDIR", &tdir, sizeof(tdir_buf))) != 0)
+ return (ret);
+ if (tdir != NULL && tdir[0] != '\0')
+ goto found;
+
+ /*
+ * Windows: TEMP, TMP
+ */
+ tdir = tdir_buf;
+ if ((ret = __os_getenv(
+ env, "TEMP", &tdir, sizeof(tdir_buf))) != 0)
+ return (ret);
+ if (tdir != NULL && tdir[0] != '\0')
+ goto found;
+
+ tdir = tdir_buf;
+ if ((ret = __os_getenv(
+ env, "TMP", &tdir, sizeof(tdir_buf))) != 0)
+ return (ret);
+ if (tdir != NULL && tdir[0] != '\0')
+ goto found;
+
+ /* Macintosh */
+ tdir = tdir_buf;
+ if ((ret = __os_getenv(
+ env, "TempFolder", &tdir, sizeof(tdir_buf))) != 0)
+ return (ret);
+
+ if (tdir != NULL && tdir[0] != '\0')
+found: return (__os_strdup(env, tdir, &dbenv->db_tmp_dir));
+ }
+
+#ifdef macintosh
+ /* Get the path to the temporary folder. */
+ {FSSpec spec;
+
+ if (!Special2FSSpec(kTemporaryFolderType,
+ kOnSystemDisk, 0, &spec))
+ return (__os_strdup(env,
+ FSp2FullPath(&spec), &dbenv->db_tmp_dir));
+ }
+#endif
+#ifdef DB_WIN32
+ /* Get the path to the temporary directory. */
+ {
+ _TCHAR tpath[DB_MAXPATHLEN + 1];
+ char *path, *eos;
+
+ if (GetTempPath(DB_MAXPATHLEN, tpath) > 2) {
+ FROM_TSTRING(env, tpath, path, ret);
+ if (ret != 0)
+ return (ret);
+
+ eos = path + strlen(path) - 1;
+ if (*eos == '\\' || *eos == '/')
+ *eos = '\0';
+ if (__os_exists(env, path, &isdir) == 0 && isdir) {
+ ret = __os_strdup(env,
+ path, &dbenv->db_tmp_dir);
+ FREE_STRING(env, path);
+ return (ret);
+ }
+ FREE_STRING(env, path);
+ }
+ }
+#endif
+
+ /*
+ * Step through the static list looking for a possibility.
+ *
+ * We don't use the obvious data structure because some C compilers
+ * (and I use the phrase loosely) don't like static data arrays.
+ */
+#define DB_TEMP_DIRECTORY(n) { \
+ char *__p = n; \
+ if (__os_exists(env, __p, &isdir) == 0 && isdir != 0) \
+ return (__os_strdup(env, __p, &dbenv->db_tmp_dir)); \
+ }
+#ifdef DB_WIN32
+ DB_TEMP_DIRECTORY("/temp");
+ DB_TEMP_DIRECTORY("C:/temp");
+ DB_TEMP_DIRECTORY("C:/tmp");
+#else
+ DB_TEMP_DIRECTORY("/var/tmp");
+ DB_TEMP_DIRECTORY("/usr/tmp");
+ DB_TEMP_DIRECTORY("/tmp");
+#endif
+
+ /*
+ * If we don't have any other place to store temporary files, store
+ * them in the current directory.
+ */
+ return (__os_strdup(env, "", &dbenv->db_tmp_dir));
+}
diff --git a/db-4.8.30/os/os_truncate.c b/db-4.8.30/os/os_truncate.c
new file mode 100644
index 0000000..1e01bfc
--- /dev/null
+++ b/db-4.8.30/os/os_truncate.c
@@ -0,0 +1,61 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_truncate --
+ * Truncate the file.
+ *
+ * PUBLIC: int __os_truncate __P((ENV *, DB_FH *, db_pgno_t, u_int32_t));
+ */
+int
+__os_truncate(env, fhp, pgno, pgsize)
+ ENV *env;
+ DB_FH *fhp;
+ db_pgno_t pgno;
+ u_int32_t pgsize;
+{
+ DB_ENV *dbenv;
+ off_t offset;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ /*
+ * Truncate a file so that "pgno" is discarded from the end of the
+ * file.
+ */
+ offset = (off_t)pgsize * pgno;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: truncate %s to %lu", fhp->name, (u_long)offset);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ if (DB_GLOBAL(j_ftruncate) != NULL)
+ ret = DB_GLOBAL(j_ftruncate)(fhp->fd, offset);
+ else {
+#ifdef HAVE_FTRUNCATE
+ RETRY_CHK((ftruncate(fhp->fd, offset)), ret);
+#else
+ ret = DB_OPNOTSUP;
+#endif
+ }
+
+ if (ret != 0) {
+ __db_syserr(env, ret, "ftruncate: %lu", (u_long)offset);
+ ret = __os_posix_err(ret);
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_uid.c b/db-4.8.30/os/os_uid.c
new file mode 100644
index 0000000..0575077
--- /dev/null
+++ b/db-4.8.30/os/os_uid.c
@@ -0,0 +1,55 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_unique_id --
+ * Return a unique 32-bit value.
+ *
+ * PUBLIC: void __os_unique_id __P((ENV *, u_int32_t *));
+ */
+void
+__os_unique_id(env, idp)
+ ENV *env;
+ u_int32_t *idp;
+{
+ DB_ENV *dbenv;
+ db_timespec v;
+ pid_t pid;
+ u_int32_t id;
+
+ *idp = 0;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ /*
+ * Our randomized value is comprised of our process ID, the current
+ * time of day and a stack address, all XOR'd together.
+ */
+ __os_id(dbenv, &pid, NULL);
+ __os_gettime(env, &v, 1);
+
+ id = (u_int32_t)pid ^
+ (u_int32_t)v.tv_sec ^ (u_int32_t)v.tv_nsec ^ P_TO_UINT32(&pid);
+
+ /*
+ * We could try and find a reasonable random-number generator, but
+ * that's not all that easy to do. Seed and use srand()/rand(), if
+ * we can find them.
+ */
+ if (DB_GLOBAL(uid_init) == 0) {
+ DB_GLOBAL(uid_init) = 1;
+ srand((u_int)id);
+ }
+ id ^= (u_int)rand();
+
+ *idp = id;
+}
diff --git a/db-4.8.30/os/os_unlink.c b/db-4.8.30/os/os_unlink.c
new file mode 100644
index 0000000..bdbcb98
--- /dev/null
+++ b/db-4.8.30/os/os_unlink.c
@@ -0,0 +1,78 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_unlink --
+ * Remove a file.
+ *
+ * PUBLIC: int __os_unlink __P((ENV *, const char *, int));
+ */
+int
+__os_unlink(env, path, overwrite_test)
+ ENV *env;
+ const char *path;
+ int overwrite_test;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: unlink %s", path);
+
+ /* Optionally overwrite the contents of the file to enhance security. */
+ if (dbenv != NULL && overwrite_test && F_ISSET(dbenv, DB_ENV_OVERWRITE))
+ (void)__db_file_multi_write(env, path);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ if (DB_GLOBAL(j_unlink) != NULL)
+ ret = DB_GLOBAL(j_unlink)(path);
+ else {
+ RETRY_CHK((unlink(CHAR_STAR_CAST path)), ret);
+#ifdef HAVE_QNX
+ /*
+ * The file may be a region file created by shm_open, not a
+ * regular file. Try and delete using unlink, and if that
+ * fails for an unexpected reason, try a shared memory unlink.
+ */
+ if (ret != 0 && __os_posix_err(ret) != ENOENT)
+ RETRY_CHK((shm_unlink(path)), ret);
+#endif
+ }
+
+ /*
+ * !!!
+ * The results of unlink are file system driver specific on VxWorks.
+ * In the case of removing a file that did not exist, some, at least,
+ * return an error, but with an errno of 0, not ENOENT. We do not
+ * have to test for that explicitly, the RETRY_CHK macro resets "ret"
+ * to be the errno, and so we'll just slide right on through.
+ *
+ * XXX
+ * We shouldn't be testing for an errno of ENOENT here, but ENOENT
+ * signals that a file is missing, and we attempt to unlink things
+ * (such as v. 2.x environment regions, in ENV->remove) that we
+ * are expecting not to be there. Reporting errors in these cases
+ * is annoying.
+ */
+ if (ret != 0) {
+ t_ret = __os_posix_err(ret);
+ if (t_ret != ENOENT)
+ __db_syserr(env, ret, "unlink: %s", path);
+ ret = t_ret;
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os/os_yield.c b/db-4.8.30/os/os_yield.c
new file mode 100644
index 0000000..4a6107e
--- /dev/null
+++ b/db-4.8.30/os/os_yield.c
@@ -0,0 +1,96 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#define __INCLUDE_SELECT_H 1
+#include "db_int.h"
+
+#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_SCHED_YIELD)
+#include <sched.h>
+#endif
+
+static void __os_sleep __P((ENV *, u_long, u_long));
+
+/*
+ * __os_yield --
+ * Yield the processor, optionally pausing until running again.
+ *
+ * PUBLIC: void __os_yield __P((ENV *, u_long, u_long));
+ */
+void
+__os_yield(env, secs, usecs)
+ ENV *env;
+ u_long secs, usecs; /* Seconds and microseconds. */
+{
+ /*
+ * Don't require the values be normalized (some operating systems
+ * return an error if the usecs argument to select is too large).
+ */
+ for (; usecs >= US_PER_SEC; usecs -= US_PER_SEC)
+ ++secs;
+
+ if (DB_GLOBAL(j_yield) != NULL) {
+ (void)DB_GLOBAL(j_yield)(secs, usecs);
+ return;
+ }
+
+ /*
+ * Yield the processor so other processes or threads can run. Use
+ * the local yield call if not pausing, otherwise call the select
+ * function.
+ */
+ if (secs != 0 || usecs != 0)
+ __os_sleep(env, secs, usecs);
+ else {
+#if defined(HAVE_MUTEX_UI_THREADS)
+ thr_yield();
+#elif defined(HAVE_PTHREAD_YIELD)
+ pthread_yield();
+#elif defined(HAVE_SCHED_YIELD)
+ (void)sched_yield();
+#elif defined(HAVE_YIELD)
+ yield();
+#else
+ __os_sleep(env, 0, 0);
+#endif
+ }
+}
+
+/*
+ * __os_sleep --
+ * Pause the thread of control.
+ */
+static void
+__os_sleep(env, secs, usecs)
+ ENV *env;
+ u_long secs, usecs; /* Seconds and microseconds. */
+{
+ struct timeval t;
+ int ret;
+
+ /*
+ * Sheer raving paranoia -- don't select for 0 time, in case some
+ * implementation doesn't yield the processor in that case.
+ */
+ t.tv_sec = (long)secs;
+ t.tv_usec = (long)usecs + 1;
+
+ /*
+ * We don't catch interrupts and restart the system call here, unlike
+ * other Berkeley DB system calls. This may be a user attempting to
+ * interrupt a sleeping DB utility (for example, db_checkpoint), and
+ * we want the utility to see the signal and quit. This assumes it's
+ * always OK for DB to sleep for less time than originally scheduled.
+ */
+ if (select(0, NULL, NULL, NULL, &t) == -1) {
+ ret = __os_get_syserr();
+ if (__os_posix_err(ret) != EINTR)
+ __db_syserr(env, ret, "select");
+ }
+}