summaryrefslogtreecommitdiff
path: root/db-4.8.30/os_windows
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
committerJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
commit54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch)
tree18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/os_windows
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/os_windows')
-rw-r--r--db-4.8.30/os_windows/ce_ctime.c87
-rw-r--r--db-4.8.30/os_windows/os_abs.c30
-rw-r--r--db-4.8.30/os_windows/os_clock.c79
-rw-r--r--db-4.8.30/os_windows/os_config.c133
-rw-r--r--db-4.8.30/os_windows/os_cpu.c27
-rw-r--r--db-4.8.30/os_windows/os_dir.c122
-rw-r--r--db-4.8.30/os_windows/os_errno.c427
-rw-r--r--db-4.8.30/os_windows/os_fid.c129
-rw-r--r--db-4.8.30/os_windows/os_flock.c88
-rw-r--r--db-4.8.30/os_windows/os_fsync.c43
-rw-r--r--db-4.8.30/os_windows/os_getenv.c102
-rw-r--r--db-4.8.30/os_windows/os_handle.c165
-rw-r--r--db-4.8.30/os_windows/os_map.c362
-rw-r--r--db-4.8.30/os_windows/os_mkdir.c43
-rw-r--r--db-4.8.30/os_windows/os_open.c255
-rw-r--r--db-4.8.30/os_windows/os_rename.c81
-rw-r--r--db-4.8.30/os_windows/os_rw.c215
-rw-r--r--db-4.8.30/os_windows/os_seek.c65
-rw-r--r--db-4.8.30/os_windows/os_stat.c90
-rw-r--r--db-4.8.30/os_windows/os_truncate.c98
-rw-r--r--db-4.8.30/os_windows/os_unlink.c108
-rw-r--r--db-4.8.30/os_windows/os_yield.c35
22 files changed, 2784 insertions, 0 deletions
diff --git a/db-4.8.30/os_windows/ce_ctime.c b/db-4.8.30/os_windows/ce_ctime.c
new file mode 100644
index 0000000..1937c0a
--- /dev/null
+++ b/db-4.8.30/os_windows/ce_ctime.c
@@ -0,0 +1,87 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+static void __os_windows_ct_numb __P((char *, int));
+
+/*
+ * __os_ctime --
+ * Format a time-stamp.
+ */
+char *
+__os_ctime(tod, time_buf)
+ const time_t *tod;
+ char *time_buf;
+{
+ char *ncp;
+ __int64 i64_tod;
+ struct _FILETIME file_tod, file_loc;
+ struct _SYSTEMTIME sys_loc;
+static const __int64 SECS_BETWEEN_EPOCHS = 11644473600;
+static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */
+
+ strcpy(time_buf, "Thu Jan 01 00:00:00 1970");
+ time_buf[CTIME_BUFLEN - 1] = '\0';
+
+ /* Convert the tod to a SYSTEM_TIME struct */
+ i64_tod = *tod;
+ i64_tod = (i64_tod + SECS_BETWEEN_EPOCHS)*SECS_TO_100NS;
+ memcpy(&file_tod, &i64_tod, sizeof(file_tod));
+ FileTimeToLocalFileTime(&file_tod, &file_loc);
+ FileTimeToSystemTime(&file_loc, &sys_loc);
+
+ /*
+ * Convert the _SYSTEMTIME to the correct format in time_buf.
+ * Based closely on the os_brew/ctime.c implementation.
+ *
+ * wWeekDay : Day of the week 0-6 (0=Monday, 6=Sunday)
+ */
+ ncp = &"MonTueWedThuFriSatSun"[sys_loc.wDayOfWeek*3];
+ time_buf[0] = *ncp++;
+ time_buf[1] = *ncp++;
+ time_buf[2] = *ncp;
+ ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(sys_loc.wMonth - 1) * 3];
+ time_buf[4] = *ncp++;
+ time_buf[5] = *ncp++;
+ time_buf[6] = *ncp;
+
+ __os_windows_ct_numb(time_buf + 8, sys_loc.wDay);
+ /* Add 100 to keep the leading zero. */
+ __os_windows_ct_numb(time_buf + 11, sys_loc.wHour + 100);
+ __os_windows_ct_numb(time_buf + 14, sys_loc.wMinute + 100);
+ __os_windows_ct_numb(time_buf + 17, sys_loc.wSecond + 100);
+
+ if (sys_loc.wYear < 100) { /* 9 99 */
+ time_buf[20] = ' ';
+ time_buf[21] = ' ';
+ __os_windows_ct_numb(time_buf + 22, sys_loc.wYear);
+ } else { /* 99 1999 */
+ __os_windows_ct_numb(time_buf + 20, sys_loc.wYear / 100);
+ __os_windows_ct_numb(time_buf + 22, sys_loc.wYear % 100 + 100);
+ }
+
+ return (time_buf);
+}
+
+/*
+ * __os_windows_ct_numb --
+ * Append ASCII representations for two digits to a string.
+ */
+static void
+__os_windows_ct_numb(cp, n)
+ char *cp;
+ int n;
+{
+ cp[0] = ' ';
+ if (n >= 10)
+ cp[0] = (n / 10) % 10 + '0';
+ cp[1] = n % 10 + '0';
+}
diff --git a/db-4.8.30/os_windows/os_abs.c b/db-4.8.30/os_windows/os_abs.c
new file mode 100644
index 0000000..4ab39f5
--- /dev/null
+++ b/db-4.8.30/os_windows/os_abs.c
@@ -0,0 +1,30 @@
+/*-
+ * 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.
+ */
+int
+__os_abspath(path)
+ const char *path;
+{
+ /*
+ * !!!
+ * Check for drive specifications, e.g., "C:". In addition, the path
+ * separator used by the win32 DB (PATH_SEPARATOR) is \; look for both
+ * / and \ since these are user-input paths.
+ */
+ if (isalpha(path[0]) && path[1] == ':')
+ path += 2;
+ return (path[0] == '/' || path[0] == '\\');
+}
diff --git a/db-4.8.30/os_windows/os_clock.c b/db-4.8.30/os_windows/os_clock.c
new file mode 100644
index 0000000..66c1ece
--- /dev/null
+++ b/db-4.8.30/os_windows/os_clock.c
@@ -0,0 +1,79 @@
+/*-
+ * 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.
+ */
+void
+__os_gettime(env, tp, monotonic)
+ ENV *env;
+ db_timespec *tp;
+ int monotonic;
+{
+ if (monotonic) {
+ /*
+ * The elapsed time is stored as a DWORD value, so time wraps
+ * around to zero if the system runs for 49.7 days. Initialize
+ * a base value with 50 days worth of seconds, and add 50 more
+ * days every time the counter wraps. That ensures we always
+ * move forward.
+ *
+ * It's possible this code could race, but the danger is we
+ * would increment base_seconds more than once per wrap and
+ * eventually overflow, which is a pretty remote possibility.
+ */
+#define TIMER_WRAP_SECONDS (50 * 24 * 60 * 60)
+ static DWORD last_ticks;
+ static time_t base_seconds;
+ DWORD ticks;
+
+ ticks = GetTickCount();
+ if (ticks < last_ticks)
+ base_seconds += TIMER_WRAP_SECONDS;
+ last_ticks = ticks;
+ tp->tv_sec = base_seconds + (u_int32_t)(ticks / 1000);
+ tp->tv_nsec = (u_int32_t)((ticks % 1000) * NS_PER_MS);
+ } else {
+#ifdef DB_WINCE
+ FILETIME ft;
+ LARGE_INTEGER large_int;
+ LONGLONG ns_since_epoch, utc1970;
+ SYSTEMTIME st;
+
+ (void)GetSystemTime(&st);
+ (void)SystemTimeToFileTime(&st, &ft);
+
+ /*
+ * A FILETIME expresses time as 100 nanosecond chunks from
+ * Jan 1, 1601; convert to a timespec where the time is
+ * is expressed in seconds and nanoseconds from Jan 1, 1970.
+ *
+ * UTC_1970 is the number of 100-nano-second chunks from
+ * 1601 to 1970.
+ */
+#define NS100_PER_SEC (NS_PER_SEC / 100)
+#define UTC_1970 (((LONGLONG)27111902 << 32) + (LONGLONG)3577643008)
+ memcpy(&large_int, &ft, sizeof(large_int));
+ utc1970 = UTC_1970;
+ ns_since_epoch = (large_int.QuadPart - utc1970);
+ tp->tv_sec = (time_t)(ns_since_epoch / NS100_PER_SEC);
+ tp->tv_nsec = (long)(ns_since_epoch % NS100_PER_SEC);
+#else
+ struct _timeb now;
+
+ _ftime(&now);
+ tp->tv_sec = now.time;
+ tp->tv_nsec = now.millitm * NS_PER_MS;
+#endif
+ }
+}
diff --git a/db-4.8.30/os_windows/os_config.c b/db-4.8.30/os_windows/os_config.c
new file mode 100644
index 0000000..5833d58
--- /dev/null
+++ b/db-4.8.30/os_windows/os_config.c
@@ -0,0 +1,133 @@
+/*-
+ * 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_is_winnt --
+ * Return 1 if Windows/NT, otherwise 0.
+ *
+ * PUBLIC: int __os_is_winnt __P((void));
+ */
+int
+__os_is_winnt()
+{
+#ifdef DB_WINCE
+ return (1);
+#else
+ static int __os_type = -1;
+
+ /*
+ * The value of __os_type is computed only once, and cached to
+ * avoid the overhead of repeated calls to GetVersion().
+ */
+ if (__os_type == -1) {
+ if ((GetVersion() & 0x80000000) == 0)
+ __os_type = 1;
+ else
+ __os_type = 0;
+ }
+ return (__os_type);
+#endif
+}
+
+/*
+ * __os_fs_notzero --
+ * Return 1 if allocated filesystem blocks are not zeroed.
+ */
+int
+__os_fs_notzero()
+{
+#ifdef DB_WINCE
+ return (1);
+#else
+ static int __os_notzero = -1;
+ OSVERSIONINFO osvi;
+
+ /*
+ * Windows/NT zero-fills pages that were never explicitly written to
+ * the file. Note however that this is *NOT* documented. In fact, the
+ * Win32 documentation makes it clear that there are no guarantees that
+ * uninitialized bytes will be zeroed:
+ *
+ * If the file is extended, the contents of the file between the old
+ * EOF position and the new position are not defined.
+ *
+ * Experiments confirm that NT/2K/XP all zero fill for both NTFS and
+ * FAT32. Cygwin also relies on this behavior. This is the relevant
+ * comment from Cygwin:
+ *
+ * Oops, this is the bug case - Win95 uses whatever is on the disk
+ * instead of some known (safe) value, so we must seek back and fill
+ * in the gap with zeros. - DJ
+ * Note: this bug doesn't happen on NT4, even though the
+ * documentation for WriteFile() says that it *may* happen on any OS.
+ *
+ * We're making a bet, here, but we made it a long time ago and haven't
+ * yet seen any evidence that it was wrong.
+ *
+ * Windows 95/98 and On-Time give random garbage, and that breaks
+ * Berkeley DB.
+ *
+ * The value of __os_notzero is computed only once, and cached to
+ * avoid the overhead of repeated calls to GetVersion().
+ */
+ if (__os_notzero == -1) {
+ if (__os_is_winnt()) {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+ if (_tcscmp(osvi.szCSDVersion, _T("RTTarget-32")) == 0)
+ __os_notzero = 1; /* On-Time */
+ else
+ __os_notzero = 0; /* Windows/NT */
+ } else
+ __os_notzero = 1; /* Not Windows/NT */
+ }
+ return (__os_notzero);
+#endif
+}
+
+/*
+ * __os_support_direct_io --
+ * Check to see if we support direct I/O.
+ */
+int
+__os_support_direct_io()
+{
+ return (1);
+}
+
+/*
+ * __os_support_db_register --
+ * Return 1 if the system supports DB_REGISTER.
+ */
+int
+__os_support_db_register()
+{
+#ifdef DB_WINCE
+ return (0);
+#else
+ return (__os_is_winnt());
+#endif
+}
+
+/*
+ * __os_support_replication --
+ * Return 1 if the system supports replication.
+ */
+int
+__os_support_replication()
+{
+#ifdef DB_WINCE
+ return (0);
+#else
+ return (__os_is_winnt());
+#endif
+}
diff --git a/db-4.8.30/os_windows/os_cpu.c b/db-4.8.30/os_windows/os_cpu.c
new file mode 100644
index 0000000..5238904
--- /dev/null
+++ b/db-4.8.30/os_windows/os_cpu.c
@@ -0,0 +1,27 @@
+/*-
+ * 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_cpu_count --
+ * Return the number of CPUs.
+ *
+ * PUBLIC: u_int32_t __os_cpu_count __P((void));
+ */
+u_int32_t
+__os_cpu_count()
+{
+ SYSTEM_INFO SystemInfo;
+
+ GetSystemInfo(&SystemInfo);
+
+ return ((u_int32_t)SystemInfo.dwNumberOfProcessors);
+}
diff --git a/db-4.8.30/os_windows/os_dir.c b/db-4.8.30/os_windows/os_dir.c
new file mode 100644
index 0000000..acb646d
--- /dev/null
+++ b/db-4.8.30/os_windows/os_dir.c
@@ -0,0 +1,122 @@
+/*-
+ * 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_dirlist --
+ * Return a list of the files in a directory.
+ */
+int
+__os_dirlist(env, dir, returndir, namesp, cntp)
+ ENV *env;
+ const char *dir;
+ int returndir, *cntp;
+ char ***namesp;
+{
+ HANDLE dirhandle;
+ WIN32_FIND_DATA fdata;
+ int arraysz, cnt, ret;
+ char **names, *onename;
+ _TCHAR tfilespec[DB_MAXPATHLEN + 1];
+ _TCHAR *tdir;
+
+ *namesp = NULL;
+ *cntp = 0;
+
+ TO_TSTRING(env, dir, tdir, ret);
+ if (ret != 0)
+ return (ret);
+
+ (void)_sntprintf(tfilespec, DB_MAXPATHLEN,
+ _T("%s%hc*"), tdir, PATH_SEPARATOR[0]);
+
+ /*
+ * On WinCE, FindFirstFile will return INVALID_HANDLE_VALUE when
+ * the searched directory is empty, and set last error to
+ * ERROR_NO_MORE_FILES, on Windows it will return "." instead.
+ */
+ if ((dirhandle =
+ FindFirstFile(tfilespec, &fdata)) == INVALID_HANDLE_VALUE) {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ return (0);
+ return (__os_posix_err(__os_get_syserr()));
+ }
+
+ names = NULL;
+ arraysz = cnt = ret = 0;
+ for (;;) {
+ if (returndir ||
+ (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ if (fdata.cFileName[0] == _T('.') &&
+ (fdata.cFileName[1] == _T('\0') ||
+ (fdata.cFileName[1] == _T('.') &&
+ fdata.cFileName[2] == _T('\0'))))
+ goto next;
+ if (cnt >= arraysz) {
+ arraysz += 100;
+ if ((ret = __os_realloc(env,
+ arraysz * sizeof(names[0]), &names)) != 0)
+ goto err;
+ }
+ /*
+ * FROM_TSTRING doesn't necessarily allocate new
+ * memory, so we must do that explicitly.
+ * Unfortunately, when compiled with UNICODE, we'll
+ * copy twice.
+ */
+ FROM_TSTRING(env, fdata.cFileName, onename, ret);
+ if (ret != 0)
+ goto err;
+ ret = __os_strdup(env, onename, &names[cnt]);
+ FREE_STRING(env, onename);
+ if (ret != 0)
+ goto err;
+ cnt++;
+ }
+next:
+ if (!FindNextFile(dirhandle, &fdata)) {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ break;
+ else {
+ ret = __os_posix_err(__os_get_syserr());
+ goto err;
+ }
+ }
+ }
+
+err: if (!FindClose(dirhandle) && ret == 0)
+ ret = __os_posix_err(__os_get_syserr());
+
+ if (ret == 0) {
+ *namesp = names;
+ *cntp = cnt;
+ } else if (names != NULL)
+ __os_dirfree(env, names, cnt);
+
+ FREE_STRING(env, tdir);
+
+ return (ret);
+}
+
+/*
+ * __os_dirfree --
+ * Free the list of files.
+ */
+void
+__os_dirfree(env, names, cnt)
+ ENV *env;
+ char **names;
+ int cnt;
+{
+ while (cnt > 0)
+ __os_free(env, names[--cnt]);
+ __os_free(env, names);
+}
diff --git a/db-4.8.30/os_windows/os_errno.c b/db-4.8.30/os_windows/os_errno.c
new file mode 100644
index 0000000..35b540b
--- /dev/null
+++ b/db-4.8.30/os_windows/os_errno.c
@@ -0,0 +1,427 @@
+/*-
+ * 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.
+ */
+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.
+ */
+int
+__os_get_errno()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ if (errno == 0)
+ __os_set_errno(EAGAIN);
+ return (errno);
+}
+
+#ifdef HAVE_REPLICATION_THREADS
+/*
+ * __os_get_neterr --
+ * Return the last networking error or EAGAIN if the last error is zero.
+ *
+ * PUBLIC: #ifdef HAVE_REPLICATION_THREADS
+ * PUBLIC: int __os_get_neterr __P((void));
+ * PUBLIC: #endif
+ */
+int
+__os_get_neterr()
+{
+ int err;
+
+ /* This routine must be able to return the same value repeatedly. */
+ err = WSAGetLastError();
+ if (err == 0)
+ WSASetLastError(err = ERROR_RETRY);
+ return (err);
+}
+#endif
+
+/*
+ * __os_get_syserr --
+ * Return the last system error or EAGAIN if the last error is zero.
+ */
+int
+__os_get_syserr()
+{
+ int err;
+
+ /* This routine must be able to return the same value repeatedly. */
+ err = GetLastError();
+ if (err == 0)
+ SetLastError(err = ERROR_RETRY);
+ return (err);
+}
+
+/*
+ * __os_set_errno --
+ * Set the value of errno.
+ */
+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.
+ */
+char *
+__os_strerror(error, buf, len)
+ int error;
+ char *buf;
+ size_t len;
+{
+#ifdef DB_WINCE
+#define MAX_TMPBUF_LEN 512
+ _TCHAR tbuf[MAX_TMPBUF_LEN];
+ size_t maxlen;
+
+ DB_ASSERT(NULL, error != 0);
+
+ memset(tbuf, 0, sizeof(_TCHAR)*MAX_TMPBUF_LEN);
+ maxlen = (len > MAX_TMPBUF_LEN ? MAX_TMPBUF_LEN : len);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, (DWORD)error,
+ 0, tbuf, maxlen-1, NULL);
+
+ if (WideCharToMultiByte(CP_UTF8, 0, tbuf, -1,
+ buf, len, 0, NULL) == 0)
+ strncpy(buf, "Error message translation failed.", len);
+#else
+ DB_ASSERT(NULL, error != 0);
+ /*
+ * Explicitly call FormatMessageA, since we want to receive a char
+ * string back, not a tchar string.
+ */
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, (DWORD)error, 0, buf, (DWORD)(len - 1), NULL);
+ buf[len - 1] = '\0';
+#endif
+
+ return (buf);
+}
+
+/*
+ * __os_posix_err --
+ * Convert a system error to a POSIX error.
+ */
+int
+__os_posix_err(error)
+ int error;
+{
+ /* Handle calls on successful returns. */
+ if (error == 0)
+ return (0);
+
+ /*
+ * Translate the Windows error codes we care about.
+ */
+ switch (error) {
+ case ERROR_INVALID_PARAMETER:
+ return (EINVAL);
+
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_PATH_NOT_FOUND:
+ return (ENOENT);
+
+ case ERROR_NO_MORE_FILES:
+ case ERROR_TOO_MANY_OPEN_FILES:
+ return (EMFILE);
+
+ case ERROR_ACCESS_DENIED:
+ return (EPERM);
+
+ case ERROR_INVALID_HANDLE:
+ return (EBADF);
+
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return (ENOMEM);
+
+ case ERROR_DISK_FULL:
+ return (ENOSPC);
+
+ case ERROR_ARENA_TRASHED:
+ case ERROR_BAD_COMMAND:
+ case ERROR_BAD_ENVIRONMENT:
+ case ERROR_BAD_FORMAT:
+ case ERROR_GEN_FAILURE:
+ case ERROR_INVALID_ACCESS:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_INVALID_DATA:
+ case ERROR_READ_FAULT:
+ case ERROR_WRITE_FAULT:
+ return (EFAULT);
+
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
+ return (EEXIST);
+
+ case ERROR_NOT_SAME_DEVICE:
+ return (EXDEV);
+
+ case ERROR_WRITE_PROTECT:
+ return (EACCES);
+
+ case ERROR_LOCK_FAILED:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_NOT_READY:
+ case ERROR_SHARING_VIOLATION:
+ return (EBUSY);
+
+ case ERROR_RETRY:
+ return (EINTR);
+ }
+
+ /*
+ * Translate the Windows socket error codes.
+ */
+ switch (error) {
+ case WSAEADDRINUSE:
+#ifdef EADDRINUSE
+ return (EADDRINUSE);
+#else
+ break;
+#endif
+ case WSAEADDRNOTAVAIL:
+#ifdef EADDRNOTAVAIL
+ return (EADDRNOTAVAIL);
+#else
+ break;
+#endif
+ case WSAEAFNOSUPPORT:
+#ifdef EAFNOSUPPORT
+ return (EAFNOSUPPORT);
+#else
+ break;
+#endif
+ case WSAEALREADY:
+#ifdef EALREADY
+ return (EALREADY);
+#else
+ break;
+#endif
+ case WSAEBADF:
+ return (EBADF);
+ case WSAECONNABORTED:
+#ifdef ECONNABORTED
+ return (ECONNABORTED);
+#else
+ break;
+#endif
+ case WSAECONNREFUSED:
+#ifdef ECONNREFUSED
+ return (ECONNREFUSED);
+#else
+ break;
+#endif
+ case WSAECONNRESET:
+#ifdef ECONNRESET
+ return (ECONNRESET);
+#else
+ break;
+#endif
+ case WSAEDESTADDRREQ:
+#ifdef EDESTADDRREQ
+ return (EDESTADDRREQ);
+#else
+ break;
+#endif
+ case WSAEFAULT:
+ return (EFAULT);
+ case WSAEHOSTDOWN:
+#ifdef EHOSTDOWN
+ return (EHOSTDOWN);
+#else
+ break;
+#endif
+ case WSAEHOSTUNREACH:
+#ifdef EHOSTUNREACH
+ return (EHOSTUNREACH);
+#else
+ break;
+#endif
+ case WSAEINPROGRESS:
+#ifdef EINPROGRESS
+ return (EINPROGRESS);
+#else
+ break;
+#endif
+ case WSAEINTR:
+ return (EINTR);
+ case WSAEINVAL:
+ return (EINVAL);
+ case WSAEISCONN:
+#ifdef EISCONN
+ return (EISCONN);
+#else
+ break;
+#endif
+ case WSAELOOP:
+#ifdef ELOOP
+ return (ELOOP);
+#else
+ break;
+#endif
+ case WSAEMFILE:
+ return (EMFILE);
+ case WSAEMSGSIZE:
+#ifdef EMSGSIZE
+ return (EMSGSIZE);
+#else
+ break;
+#endif
+ case WSAENAMETOOLONG:
+ return (ENAMETOOLONG);
+ case WSAENETDOWN:
+#ifdef ENETDOWN
+ return (ENETDOWN);
+#else
+ break;
+#endif
+ case WSAENETRESET:
+#ifdef ENETRESET
+ return (ENETRESET);
+#else
+ break;
+#endif
+ case WSAENETUNREACH:
+#ifdef ENETUNREACH
+ return (ENETUNREACH);
+#else
+ break;
+#endif
+ case WSAENOBUFS:
+#ifdef ENOBUFS
+ return (ENOBUFS);
+#else
+ break;
+#endif
+ case WSAENOPROTOOPT:
+#ifdef ENOPROTOOPT
+ return (ENOPROTOOPT);
+#else
+ break;
+#endif
+ case WSAENOTCONN:
+#ifdef ENOTCONN
+ return (ENOTCONN);
+#else
+ break;
+#endif
+ case WSANOTINITIALISED:
+ return (EAGAIN);
+ case WSAENOTSOCK:
+#ifdef ENOTSOCK
+ return (ENOTSOCK);
+#else
+ break;
+#endif
+ case WSAEOPNOTSUPP:
+ return (DB_OPNOTSUP);
+ case WSAEPFNOSUPPORT:
+#ifdef EPFNOSUPPORT
+ return (EPFNOSUPPORT);
+#else
+ break;
+#endif
+ case WSAEPROTONOSUPPORT:
+#ifdef EPROTONOSUPPORT
+ return (EPROTONOSUPPORT);
+#else
+ break;
+#endif
+ case WSAEPROTOTYPE:
+#ifdef EPROTOTYPE
+ return (EPROTOTYPE);
+#else
+ break;
+#endif
+ case WSAESHUTDOWN:
+#ifdef ESHUTDOWN
+ return (ESHUTDOWN);
+#else
+ break;
+#endif
+ case WSAESOCKTNOSUPPORT:
+#ifdef ESOCKTNOSUPPORT
+ return (ESOCKTNOSUPPORT);
+#else
+ break;
+#endif
+ case WSAETIMEDOUT:
+#ifdef ETIMEDOUT
+ return (ETIMEDOUT);
+#else
+ break;
+#endif
+ case WSAETOOMANYREFS:
+#ifdef ETOOMANYREFS
+ return (ETOOMANYREFS);
+#else
+ break;
+#endif
+ case WSAEWOULDBLOCK:
+#ifdef EWOULDBLOCK
+ return (EWOULDBLOCK);
+#else
+ return (EAGAIN);
+#endif
+ case WSAHOST_NOT_FOUND:
+#ifdef EHOSTUNREACH
+ return (EHOSTUNREACH);
+#else
+ break;
+#endif
+ case WSASYSNOTREADY:
+ return (EAGAIN);
+ case WSATRY_AGAIN:
+ return (EAGAIN);
+ case WSAVERNOTSUPPORTED:
+ return (DB_OPNOTSUP);
+ case WSAEACCES:
+ return (EACCES);
+ }
+
+ /*
+ * EFAULT is the default if we don't have a translation.
+ */
+ return (EFAULT);
+}
diff --git a/db-4.8.30/os_windows/os_fid.c b/db-4.8.30/os_windows/os_fid.c
new file mode 100644
index 0000000..3283ea5
--- /dev/null
+++ b/db-4.8.30/os_windows/os_fid.c
@@ -0,0 +1,129 @@
+/*-
+ * 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.
+ */
+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;
+ int ret;
+
+ /*
+ * The documentation for GetFileInformationByHandle() states that the
+ * inode-type numbers are not constant between processes. Actually,
+ * they are, they're the NTFS MFT indexes. So, this works on NTFS,
+ * but perhaps not on other platforms, and perhaps not over a network.
+ * Can't think of a better solution right now.
+ */
+ DB_FH *fhp;
+ BY_HANDLE_FILE_INFORMATION fi;
+ BOOL retval = FALSE;
+
+ DB_ASSERT(env, fname != NULL);
+
+ /* Clear the buffer. */
+ memset(fidp, 0, DB_FILE_ID_LEN);
+
+ /*
+ * First we open the file, because we're not given a handle to it.
+ * If we can't open it, we're in trouble.
+ */
+ if ((ret = __os_open(env, fname, 0,
+ DB_OSO_RDONLY, DB_MODE_400, &fhp)) != 0)
+ return (ret);
+
+ /* File open, get its info */
+ if ((retval = GetFileInformationByHandle(fhp->handle, &fi)) == FALSE)
+ ret = __os_get_syserr();
+ (void)__os_closehandle(env, fhp);
+
+ if (retval == FALSE)
+ return (__os_posix_err(ret));
+
+ /*
+ * We want the three 32-bit words which tell us the volume ID and
+ * the file ID. We make a crude attempt to copy the bytes over to
+ * the callers buffer.
+ *
+ * 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.
+ */
+ tmp = (u_int32_t)fi.nFileIndexLow;
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+ tmp = (u_int32_t)fi.nFileIndexHigh;
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+
+ 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;
+
+ } else {
+ tmp = (u_int32_t)fi.dwVolumeSerialNumber;
+ for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+ }
+
+ return (0);
+}
diff --git a/db-4.8.30/os_windows/os_flock.c b/db-4.8.30/os_windows/os_flock.c
new file mode 100644
index 0000000..df2492f
--- /dev/null
+++ b/db-4.8.30/os_windows/os_flock.c
@@ -0,0 +1,88 @@
+/*-
+ * 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.
+ */
+int
+__os_fdlock(env, fhp, offset, acquire, nowait)
+ ENV *env;
+ DB_FH *fhp;
+ int acquire, nowait;
+ off_t offset;
+{
+#ifdef DB_WINCE
+ /*
+ * This functionality is not supported by WinCE, so just fail.
+ *
+ * Should only happen if an app attempts to open an environment
+ * with the DB_REGISTER flag.
+ */
+ __db_errx(env, "fdlock API not implemented for WinCE, DB_REGISTER "
+ "environment flag not supported.");
+ return (EFAULT);
+#else
+ DWORD low, high;
+ DB_ENV *dbenv;
+ OVERLAPPED over;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ DB_ASSERT(env,
+ F_ISSET(fhp, DB_FH_OPENED) && fhp->handle != INVALID_HANDLE_VALUE);
+
+ 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);
+
+ /*
+ * Windows file locking interferes with read/write operations, so we
+ * map the ranges to an area past the end of the file.
+ */
+ DB_ASSERT(env, offset < (u_int64_t)INT64_MAX);
+ offset = UINT64_MAX - offset;
+ low = (DWORD)offset;
+ high = (DWORD)(offset >> 32);
+
+ if (acquire) {
+ if (nowait)
+ RETRY_CHK_EINTR_ONLY(
+ !LockFile(fhp->handle, low, high, 1, 0), ret);
+ else if (__os_is_winnt()) {
+ memset(&over, 0, sizeof(over));
+ over.Offset = low;
+ over.OffsetHigh = high;
+ RETRY_CHK_EINTR_ONLY(
+ !LockFileEx(fhp->handle, LOCKFILE_EXCLUSIVE_LOCK,
+ 0, 1, 0, &over),
+ ret);
+ } else {
+ /* Windows 9x/ME doesn't support a blocking call. */
+ for (;;) {
+ RETRY_CHK_EINTR_ONLY(
+ !LockFile(fhp->handle, low, high, 1, 0),
+ ret);
+ if (__os_posix_err(ret) != EAGAIN)
+ break;
+ __os_yield(env, 1, 0);
+ }
+ }
+ } else
+ RETRY_CHK_EINTR_ONLY(
+ !UnlockFile(fhp->handle, low, high, 1, 0), ret);
+
+ return (__os_posix_err(ret));
+#endif
+}
diff --git a/db-4.8.30/os_windows/os_fsync.c b/db-4.8.30/os_windows/os_fsync.c
new file mode 100644
index 0000000..0e57cb4
--- /dev/null
+++ b/db-4.8.30/os_windows/os_fsync.c
@@ -0,0 +1,43 @@
+/*-
+ * 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_fsync --
+ * Flush a file descriptor.
+ */
+int
+__os_fsync(env, fhp)
+ ENV *env;
+ DB_FH *fhp;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ /*
+ * 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);
+
+ RETRY_CHK((!FlushFileBuffers(fhp->handle)), ret);
+ if (ret != 0) {
+ __db_syserr(env, ret, "FlushFileBuffers");
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_getenv.c b/db-4.8.30/os_windows/os_getenv.c
new file mode 100644
index 0000000..0f4cb12
--- /dev/null
+++ b/db-4.8.30/os_windows/os_getenv.c
@@ -0,0 +1,102 @@
+/*-
+ * 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.
+ */
+int
+__os_getenv(env, name, bpp, buflen)
+ ENV *env;
+ const char *name;
+ char **bpp;
+ size_t buflen;
+{
+#ifdef DB_WINCE
+ COMPQUIET(name, NULL);
+ /* WinCE does not have a getenv implementation. */
+ return (0);
+#else
+ _TCHAR *tname, tbuf[1024];
+ int ret;
+ char *p;
+
+ /*
+ * If there's a value and the buffer is large enough:
+ * copy value into the pointer, return 0
+ * If there's a value and the buffer is too short:
+ * set pointer to NULL, return EINVAL
+ * If there's no value:
+ * set pointer to NULL, return 0
+ */
+ if ((p = getenv(name)) != NULL) {
+ if (strlen(p) < buflen) {
+ (void)strcpy(*bpp, p);
+ return (0);
+ }
+ goto small_buf;
+ }
+
+ TO_TSTRING(env, name, tname, ret);
+ if (ret != 0)
+ return (ret);
+ /*
+ * The declared size of the tbuf buffer limits the maximum environment
+ * variable size in Berkeley DB on Windows. If that's too small, or if
+ * we need to get rid of large allocations on the BDB stack, we should
+ * malloc the tbuf memory.
+ */
+ ret = GetEnvironmentVariable(tname, tbuf, sizeof(tbuf));
+ FREE_STRING(env, tname);
+
+ /*
+ * If GetEnvironmentVariable succeeds, the return value is the number
+ * of characters stored in the buffer pointed to by lpBuffer, not
+ * including the terminating null character. If the buffer is not
+ * large enough to hold the data, the return value is the buffer size,
+ * in characters, required to hold the string and its terminating null
+ * character. If GetEnvironmentVariable fails, the return value is
+ * zero. If the specified environment variable was not found in the
+ * environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
+ */
+ if (ret == 0) {
+ if ((ret = __os_get_syserr()) == ERROR_ENVVAR_NOT_FOUND) {
+ *bpp = NULL;
+ return (0);
+ }
+ __db_syserr(env, ret, "GetEnvironmentVariable");
+ return (__os_posix_err(ret));
+ }
+ if (ret > (int)sizeof(tbuf))
+ goto small_buf;
+
+ FROM_TSTRING(env, tbuf, p, ret);
+ if (ret != 0)
+ return (ret);
+ if (strlen(p) < buflen)
+ (void)strcpy(*bpp, p);
+ else
+ *bpp = NULL;
+ FREE_STRING(env, p);
+ if (*bpp == NULL)
+ goto small_buf;
+
+ return (0);
+
+small_buf:
+ *bpp = NULL;
+ __db_errx(env,
+ "%s: buffer too small to hold environment variable %s",
+ name, p);
+ return (EINVAL);
+#endif
+}
diff --git a/db-4.8.30/os_windows/os_handle.c b/db-4.8.30/os_windows/os_handle.c
new file mode 100644
index 0000000..74681e3
--- /dev/null
+++ b/db-4.8.30/os_windows/os_handle.c
@@ -0,0 +1,165 @@
+/*-
+ * 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.
+ */
+int
+__os_openhandle(env, name, flags, mode, fhpp)
+ ENV *env;
+ const char *name;
+ int flags, mode;
+ DB_FH **fhpp;
+{
+#ifdef DB_WINCE
+ /*
+ * __os_openhandle API is not implemented on WinCE.
+ * It is not currently called from within the Berkeley DB library,
+ * so don't log the failure via the __db_err mechanism.
+ */
+ return (EFAULT);
+#else
+ DB_FH *fhp;
+ int ret, nrepeat, retries;
+
+ /*
+ * 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);
+ }
+
+ retries = 0;
+ for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
+ fhp->fd = _open(name, flags, mode);
+
+ 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) {
+ F_SET(fhp, DB_FH_OPENED);
+ *fhpp = fhp;
+ return (0);
+ }
+
+err: (void)__os_closehandle(env, fhp);
+ return (ret);
+#endif
+}
+
+/*
+ * __os_closehandle --
+ * Close a file.
+ */
+int
+__os_closehandle(env, fhp)
+ ENV *env;
+ DB_FH *fhp;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ ret = 0;
+
+ 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: %s: close", 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 (fhp->handle != INVALID_HANDLE_VALUE)
+ RETRY_CHK((!CloseHandle(fhp->handle)), ret);
+ else
+#ifdef DB_WINCE
+ ret = EFAULT;
+#else
+ RETRY_CHK((_close(fhp->fd)), ret);
+#endif
+
+ if (fhp->trunc_handle != INVALID_HANDLE_VALUE) {
+ RETRY_CHK((!CloseHandle(fhp->trunc_handle)), t_ret);
+ if (t_ret != 0 && ret == 0)
+ ret = t_ret;
+ }
+
+ if (ret != 0) {
+ __db_syserr(env, ret, "CloseHandle");
+ 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_windows/os_map.c b/db-4.8.30/os_windows/os_map.c
new file mode 100644
index 0000000..0889969
--- /dev/null
+++ b/db-4.8.30/os_windows/os_map.c
@@ -0,0 +1,362 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+static int __os_map
+ __P((ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **));
+static int __os_unique_name __P((_TCHAR *, HANDLE, _TCHAR *, size_t));
+
+/*
+ * __os_attach --
+ * Create/join a shared memory region.
+ */
+int
+__os_attach(env, infop, rp)
+ ENV *env;
+ REGINFO *infop;
+ REGION *rp;
+{
+ DB_FH *fhp;
+ int ret;
+
+ /*
+ * On Windows/9X, files that are opened by multiple processes do not
+ * share data correctly. For this reason, we require that DB_PRIVATE
+ * be specified on that platform.
+ */
+ if (!F_ISSET(env, ENV_PRIVATE) && __os_is_winnt() == 0) {
+ __db_err(env,
+ EINVAL, "Windows 9X systems must specify DB_PRIVATE");
+ return (EINVAL);
+ }
+
+ /*
+ * Try to open/create the 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);
+ return (ret);
+ }
+
+ /*
+ * Map the file in. If we're creating an in-system-memory region,
+ * specify a segment ID (which is never used again) so that the
+ * calling code writes out the REGENV_REF structure to the primary
+ * environment file.
+ */
+ ret = __os_map(env, infop->name, infop, fhp, rp->size,
+ 1, F_ISSET(env, ENV_SYSTEM_MEM), 0, &infop->addr);
+ if (ret == 0 && F_ISSET(env, ENV_SYSTEM_MEM))
+ rp->segid = 1;
+
+ (void)__os_closehandle(env, fhp);
+
+ return (ret);
+}
+
+/*
+ * __os_detach --
+ * Detach from a shared memory region.
+ */
+int
+__os_detach(env, infop, destroy)
+ ENV *env;
+ REGINFO *infop;
+ int destroy;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ dbenv = env->dbenv;
+
+ if (infop->wnt_handle != NULL) {
+ (void)CloseHandle(infop->wnt_handle);
+ infop->wnt_handle = NULL;
+ }
+
+ ret = !UnmapViewOfFile(infop->addr) ? __os_get_syserr() : 0;
+ if (ret != 0) {
+ __db_syserr(env, ret, "UnmapViewOfFile");
+ ret = __os_posix_err(ret);
+ }
+
+ if (!F_ISSET(env, ENV_SYSTEM_MEM) && destroy &&
+ (t_ret = __os_unlink(env, infop->name, 1)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __os_mapfile --
+ * Map in a shared memory file.
+ */
+int
+__os_mapfile(env, path, fhp, len, is_rdonly, addr)
+ ENV *env;
+ char *path;
+ DB_FH *fhp;
+ int is_rdonly;
+ size_t len;
+ void **addr;
+{
+#ifdef DB_WINCE
+ /*
+ * Windows CE has special requirements for file mapping to work.
+ * * The input handle needs to be opened using CreateFileForMapping
+ * * Concurrent access via a non mapped file is not supported.
+ * So we disable support for memory mapping files on Windows CE. It is
+ * currently only used as an optimization in mpool for small read only
+ * databases.
+ */
+ return (EFAULT);
+#else
+ DB_ENV *dbenv;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: mmap %s", path);
+ return (__os_map(env, path, NULL, fhp, len, 0, 0, is_rdonly, addr));
+#endif
+}
+
+/*
+ * __os_unmapfile --
+ * Unmap the shared memory file.
+ */
+int
+__os_unmapfile(env, addr, len)
+ ENV *env;
+ void *addr;
+ size_t len;
+{
+ DB_ENV *dbenv;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: munmap");
+
+ return (!UnmapViewOfFile(addr) ? __os_posix_err(__os_get_syserr()) : 0);
+}
+
+/*
+ * __os_unique_name --
+ * Create a unique identifying name from a pathname (may be absolute or
+ * relative) and/or a file descriptor.
+ *
+ * The name returned must be unique (different files map to different
+ * names), and repeatable (same files, map to same names). It's not
+ * so easy to do by name. Should handle not only:
+ *
+ * foo.bar == ./foo.bar == c:/whatever_path/foo.bar
+ *
+ * but also understand that:
+ *
+ * foo.bar == Foo.Bar (FAT file system)
+ * foo.bar != Foo.Bar (NTFS)
+ *
+ * The best solution is to use the file index, found in the file
+ * information structure (similar to UNIX inode #).
+ *
+ * When a file is deleted, its file index may be reused,
+ * but if the unique name has not gone from its namespace,
+ * we may get a conflict. So to ensure some tie in to the
+ * original pathname, we also use the creation time and the
+ * file basename. This is not a perfect system, but it
+ * should work for all but anamolous test cases.
+ *
+ */
+static int
+__os_unique_name(orig_path, hfile, result_path, result_path_len)
+ _TCHAR *orig_path, *result_path;
+ HANDLE hfile;
+ size_t result_path_len;
+{
+ BY_HANDLE_FILE_INFORMATION fileinfo;
+ _TCHAR *basename, *p;
+
+ /*
+ * In Windows, pathname components are delimited by '/' or '\', and
+ * if neither is present, we need to strip off leading drive letter
+ * (e.g. c:foo.txt).
+ */
+ basename = _tcsrchr(orig_path, '/');
+ p = _tcsrchr(orig_path, '\\');
+ if (basename == NULL || (p != NULL && p > basename))
+ basename = p;
+ if (basename == NULL)
+ basename = _tcsrchr(orig_path, ':');
+
+ if (basename == NULL)
+ basename = orig_path;
+ else
+ basename++;
+
+ if (!GetFileInformationByHandle(hfile, &fileinfo))
+ return (__os_posix_err(__os_get_syserr()));
+
+ (void)_sntprintf(result_path, result_path_len,
+ _T("__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s"),
+ fileinfo.dwVolumeSerialNumber,
+ fileinfo.nFileIndexHigh,
+ fileinfo.nFileIndexLow,
+ fileinfo.ftCreationTime.dwHighDateTime,
+ fileinfo.ftCreationTime.dwHighDateTime,
+ basename);
+
+ return (0);
+}
+
+/*
+ * __os_map --
+ * The mmap(2) function for Windows.
+ */
+static int
+__os_map(env, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
+ ENV *env;
+ REGINFO *infop;
+ char *path;
+ DB_FH *fhp;
+ int is_region, is_system, is_rdonly;
+ size_t len;
+ void **addr;
+{
+ HANDLE hMemory;
+ int ret, use_pagefile;
+ _TCHAR *tpath, shmem_name[DB_MAXPATHLEN];
+ void *pMemory;
+ unsigned __int64 len64;
+
+ ret = 0;
+ if (infop != NULL)
+ infop->wnt_handle = NULL;
+
+ /*
+ * On 64 bit systems, len is already a 64 bit value.
+ * On 32 bit systems len is a 32 bit value.
+ * Always convert to a 64 bit value, so that the high order
+ * DWORD can be simply extracted on 64 bit platforms.
+ */
+ len64 = len;
+
+ use_pagefile = is_region && is_system;
+
+ /*
+ * If creating a region in system space, get a matching name in the
+ * paging file namespace.
+ */
+ if (use_pagefile) {
+#ifdef DB_WINCE
+ __db_errx(env, "Unable to memory map regions using system "
+ "memory on WinCE.");
+ return (EFAULT);
+#endif
+ TO_TSTRING(env, path, tpath, ret);
+ if (ret != 0)
+ return (ret);
+ ret = __os_unique_name(tpath, fhp->handle,
+ shmem_name, sizeof(shmem_name));
+ FREE_STRING(env, tpath);
+ if (ret != 0)
+ return (ret);
+ }
+
+ /*
+ * XXX
+ * DB: We have not implemented copy-on-write here.
+ *
+ * If this is an region in system memory, we try to open it using the
+ * OpenFileMapping() first, and only call CreateFileMapping() if we're
+ * really creating the section. There are two reasons:
+ *
+ * 1) We only create the mapping if we have newly created the region.
+ * This avoids a long-running problem caused by Windows reference
+ * counting, where regions that are closed by all processes are
+ * deleted. It turns out that just checking for a zeroed region
+ * is not good enough. See [#4882] and [#7127] for the details.
+ *
+ * 2) CreateFileMapping seems to mess up making the commit charge to
+ * the process. It thinks, incorrectly, that when we want to join a
+ * previously existing section, that it should make a commit charge
+ * for the whole section. In fact, there is no new committed memory
+ * whatever. The call can fail if there is insufficient memory free
+ * to handle the erroneous commit charge. So, we find that the
+ * bogus commit is not made if we call OpenFileMapping.
+ */
+ hMemory = NULL;
+ if (use_pagefile) {
+#ifndef DB_WINCE
+ hMemory = OpenFileMapping(
+ is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
+ 0, shmem_name);
+
+ if (hMemory == NULL && F_ISSET(infop, REGION_CREATE_OK))
+ hMemory = CreateFileMapping((HANDLE)-1, 0,
+ is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
+ (DWORD)(len64 >> 32), (DWORD)len64, shmem_name);
+#endif
+ } else {
+ hMemory = CreateFileMapping(fhp->handle, 0,
+ is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
+ (DWORD)(len64 >> 32), (DWORD)len64, NULL);
+#ifdef DB_WINCE
+ /*
+ * WinCE automatically closes the handle passed in.
+ * Ensure DB does not attempt to close the handle again.
+ */
+ fhp->handle = INVALID_HANDLE_VALUE;
+ F_CLR(fhp, DB_FH_OPENED);
+#endif
+ }
+
+ if (hMemory == NULL) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "OpenFileMapping");
+ return (__env_panic(env, __os_posix_err(ret)));
+ }
+
+ pMemory = MapViewOfFile(hMemory,
+ (is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len);
+ if (pMemory == NULL) {
+ ret = __os_get_syserr();
+ __db_syserr(env, ret, "MapViewOfFile");
+ return (__env_panic(env, __os_posix_err(ret)));
+ }
+
+ /*
+ * XXX
+ * It turns out that the kernel object underlying the named section
+ * is reference counted, but that the call to MapViewOfFile() above
+ * does NOT increment the reference count! So, if we close the handle
+ * here, the kernel deletes the object from the kernel namespace.
+ * When a second process comes along to join the region, the kernel
+ * happily creates a new object with the same name, but completely
+ * different identity. The two processes then have distinct isolated
+ * mapped sections, not at all what was wanted. Not closing the handle
+ * here fixes this problem. We carry the handle around in the region
+ * structure so we can close it when unmap is called.
+ */
+ if (use_pagefile && infop != NULL)
+ infop->wnt_handle = hMemory;
+ else
+ CloseHandle(hMemory);
+
+ *addr = pMemory;
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_mkdir.c b/db-4.8.30/os_windows/os_mkdir.c
new file mode 100644
index 0000000..b739986
--- /dev/null
+++ b/db-4.8.30/os_windows/os_mkdir.c
@@ -0,0 +1,43 @@
+/*-
+ * 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.
+ */
+int
+__os_mkdir(env, name, mode)
+ ENV *env;
+ const char *name;
+ int mode;
+{
+ DB_ENV *dbenv;
+ _TCHAR *tname;
+ 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. */
+ TO_TSTRING(env, name, tname, ret);
+ if (ret != 0)
+ return (ret);
+ RETRY_CHK(!CreateDirectory(tname, NULL), ret);
+ FREE_STRING(env, tname);
+ if (ret != 0)
+ return (__os_posix_err(ret));
+
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_open.c b/db-4.8.30/os_windows/os_open.c
new file mode 100644
index 0000000..e15222f
--- /dev/null
+++ b/db-4.8.30/os_windows/os_open.c
@@ -0,0 +1,255 @@
+/*-
+ * 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).
+ */
+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;
+#ifndef DB_WINCE
+ DWORD cluster_size, sector_size, free_clusters, total_clusters;
+ _TCHAR *drive, dbuf[4]; /* <letter><colon><slash><nul> */
+#endif
+ int access, attr, createflag, nrepeat, ret, share;
+ _TCHAR *tname;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ *fhpp = NULL;
+ tname = NULL;
+
+ 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);
+
+ TO_TSTRING(env, name, tname, ret);
+ if (ret != 0)
+ goto err;
+
+ /*
+ * 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);
+ }
+
+ /*
+ * Otherwise, use the Windows/32 CreateFile interface so that we can
+ * play magic games with files to get data flush effects similar to
+ * the POSIX O_DSYNC flag.
+ *
+ * !!!
+ * We currently ignore the 'mode' argument. It would be possible
+ * to construct a set of security attributes that we could pass to
+ * CreateFile that would accurately represents the mode. In worst
+ * case, this would require looking up user and all group names and
+ * creating an entry for each. Alternatively, we could call the
+ * _chmod (partial emulation) function after file creation, although
+ * this leaves us with an obvious race. However, these efforts are
+ * largely meaningless on FAT, the most common file system, which
+ * only has a "readable" and "writeable" flag, applying to all users.
+ */
+ access = GENERIC_READ;
+ if (!LF_ISSET(DB_OSO_RDONLY))
+ access |= GENERIC_WRITE;
+
+#ifdef DB_WINCE
+ /*
+ * WinCE translates these flags into share flags for
+ * CreateFileForMapping.
+ * Also WinCE does not support the FILE_SHARE_DELETE flag.
+ */
+ if (LF_ISSET(DB_OSO_REGION))
+ share = GENERIC_READ | GENERIC_WRITE;
+ else
+ share = FILE_SHARE_READ | FILE_SHARE_WRITE;
+#else
+ share = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ if (__os_is_winnt())
+ share |= FILE_SHARE_DELETE;
+#endif
+ attr = FILE_ATTRIBUTE_NORMAL;
+
+ /*
+ * Reproduce POSIX 1003.1 semantics: if O_CREATE and O_EXCL are both
+ * specified, fail, returning EEXIST, unless we create the file.
+ */
+ if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_EXCL))
+ createflag = CREATE_NEW; /* create only if !exist*/
+ else if (!LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_TRUNC))
+ createflag = TRUNCATE_EXISTING; /* truncate, fail if !exist */
+ else if (LF_ISSET(DB_OSO_TRUNC))
+ createflag = CREATE_ALWAYS; /* create and truncate */
+ else if (LF_ISSET(DB_OSO_CREATE))
+ createflag = OPEN_ALWAYS; /* open or create */
+ else
+ createflag = OPEN_EXISTING; /* open only if existing */
+
+ if (LF_ISSET(DB_OSO_DSYNC)) {
+ F_SET(fhp, DB_FH_NOSYNC);
+ attr |= FILE_FLAG_WRITE_THROUGH;
+ }
+
+#ifndef DB_WINCE
+ if (LF_ISSET(DB_OSO_SEQ))
+ attr |= FILE_FLAG_SEQUENTIAL_SCAN;
+ else
+ attr |= FILE_FLAG_RANDOM_ACCESS;
+#endif
+
+ if (LF_ISSET(DB_OSO_TEMP))
+ attr |= FILE_FLAG_DELETE_ON_CLOSE;
+
+ /*
+ * We can turn filesystem buffering off if the page size is a
+ * multiple of the disk's sector size. To find the sector size,
+ * we call GetDiskFreeSpace, which expects a drive name like "d:\\"
+ * or NULL for the current disk (i.e., a relative path).
+ *
+ * WinCE only has GetDiskFreeSpaceEx which does not
+ * return the sector size.
+ */
+#ifndef DB_WINCE
+ if (LF_ISSET(DB_OSO_DIRECT) && page_size != 0 && name[0] != '\0') {
+ if (name[1] == ':') {
+ drive = dbuf;
+ _sntprintf(dbuf, sizeof(dbuf), _T("%c:\\"), tname[0]);
+ } else
+ drive = NULL;
+
+ /*
+ * We ignore all results except sectorsize, but some versions
+ * of Windows require that the parameters are non-NULL.
+ */
+ if (GetDiskFreeSpace(drive, &cluster_size,
+ &sector_size, &free_clusters, &total_clusters) &&
+ page_size % sector_size == 0)
+ attr |= FILE_FLAG_NO_BUFFERING;
+ }
+#endif
+
+ fhp->handle = fhp->trunc_handle = INVALID_HANDLE_VALUE;
+ for (nrepeat = 1;; ++nrepeat) {
+ if (fhp->handle == INVALID_HANDLE_VALUE) {
+#ifdef DB_WINCE
+ if (LF_ISSET(DB_OSO_REGION))
+ fhp->handle = CreateFileForMapping(tname,
+ access, share, NULL, createflag, attr, 0);
+ else
+#endif
+ fhp->handle = CreateFile(tname,
+ access, share, NULL, createflag, attr, 0);
+ }
+
+#ifdef HAVE_FTRUNCATE
+ /*
+ * Older versions of WinCE may not support truncate, if so, the
+ * HAVE_FTRUNCATE macro should be #undef'ed, and we
+ * don't need to open this second handle.
+ *
+ * WinCE dose not support opening a second handle on the same
+ * file via CreateFileForMapping, but this dose not matter
+ * since we are not truncating region files but database files.
+ *
+ * But some older versions of WinCE even
+ * dose not allow a second handle opened via CreateFile. If
+ * this is the case, users will need to #undef the
+ * HAVE_FTRUNCATE macro in build_wince/db_config.h.
+ */
+
+ /*
+ * Windows does not provide truncate directly. There is no
+ * safe way to use a handle for truncate concurrently with
+ * reads or writes. To deal with this, we open a second handle
+ * used just for truncating.
+ */
+ if (fhp->handle != INVALID_HANDLE_VALUE &&
+ !LF_ISSET(DB_OSO_RDONLY | DB_OSO_TEMP) &&
+ fhp->trunc_handle == INVALID_HANDLE_VALUE
+#ifdef DB_WINCE
+ /* Do not open trunc handle for region files. */
+ && (!LF_ISSET(DB_OSO_REGION))
+#endif
+ )
+ fhp->trunc_handle = CreateFile(
+ tname, access, share, NULL, OPEN_EXISTING, attr, 0);
+#endif
+
+#ifndef HAVE_FTRUNCATE
+ if (fhp->handle == INVALID_HANDLE_VALUE)
+#else
+ if (fhp->handle == INVALID_HANDLE_VALUE ||
+ (!LF_ISSET(DB_OSO_RDONLY | DB_OSO_TEMP) &&
+ fhp->trunc_handle == INVALID_HANDLE_VALUE
+#ifdef DB_WINCE
+ /* Do not open trunc handle for region files. */
+ && (!LF_ISSET(DB_OSO_REGION))
+#endif
+ ))
+#endif
+ {
+ /*
+ * 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.
+ */
+ ret = __os_posix_err(__os_get_syserr());
+ if ((ret != ENFILE && ret != EMFILE && ret != ENOSPC) ||
+ nrepeat > 3)
+ goto err;
+
+ __os_yield(env, nrepeat * 2, 0);
+ } else
+ break;
+ }
+
+ FREE_STRING(env, tname);
+
+ if (LF_ISSET(DB_OSO_REGION))
+ F_SET(fhp, DB_FH_REGION);
+ F_SET(fhp, DB_FH_OPENED);
+ *fhpp = fhp;
+ return (0);
+
+err: FREE_STRING(env, tname);
+ if (fhp != NULL)
+ (void)__os_closehandle(env, fhp);
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_rename.c b/db-4.8.30/os_windows/os_rename.c
new file mode 100644
index 0000000..9312d8a
--- /dev/null
+++ b/db-4.8.30/os_windows/os_rename.c
@@ -0,0 +1,81 @@
+/*-
+ * 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.
+ */
+int
+__os_rename(env, oldname, newname, silent)
+ ENV *env;
+ const char *oldname, *newname;
+ u_int32_t silent;
+{
+ DB_ENV *dbenv;
+ _TCHAR *toldname, *tnewname;
+ 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);
+
+ TO_TSTRING(env, oldname, toldname, ret);
+ if (ret != 0)
+ return (ret);
+ TO_TSTRING(env, newname, tnewname, ret);
+ if (ret != 0) {
+ FREE_STRING(env, toldname);
+ return (ret);
+ }
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ if (!MoveFile(toldname, tnewname))
+ ret = __os_get_syserr();
+
+ if (__os_posix_err(ret) == EEXIST) {
+ ret = 0;
+#ifndef DB_WINCE
+ if (__os_is_winnt()) {
+ if (!MoveFileEx(
+ toldname, tnewname, MOVEFILE_REPLACE_EXISTING))
+ ret = __os_get_syserr();
+ } else
+#endif
+ {
+ /*
+ * There is no MoveFileEx for Win9x/Me/CE, so we have to
+ * do the best we can. Note that the MoveFile call
+ * above would have succeeded if oldname and newname
+ * refer to the same file, so we don't need to check
+ * that here.
+ */
+ (void)DeleteFile(tnewname);
+ if (!MoveFile(toldname, tnewname))
+ ret = __os_get_syserr();
+ }
+ }
+
+ FREE_STRING(env, tnewname);
+ FREE_STRING(env, toldname);
+
+ if (ret != 0) {
+ if (silent == 0)
+ __db_syserr(
+ env, ret, "MoveFileEx %s %s", oldname, newname);
+ ret = __os_posix_err(ret);
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_rw.c b/db-4.8.30/os_windows/os_rw.c
new file mode 100644
index 0000000..5e46e03
--- /dev/null
+++ b/db-4.8.30/os_windows/os_rw.c
@@ -0,0 +1,215 @@
+/*-
+ * 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.
+ */
+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;
+{
+ int ret;
+
+#ifndef DB_WINCE
+ if (__os_is_winnt()) {
+ DB_ENV *dbenv;
+ DWORD nbytes;
+ OVERLAPPED over;
+ ULONG64 off;
+ dbenv = env == NULL ? NULL : env->dbenv;
+ if ((off = relative) == 0)
+ off = (ULONG64)pgsize * pgno;
+ over.Offset = (DWORD)(off & 0xffffffff);
+ over.OffsetHigh = (DWORD)(off >> 32);
+ over.hEvent = 0; /* we don't want asynchronous notifications */
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL))
+ __db_msg(env,
+ "fileops: %s %s: %lu bytes at offset %lu",
+ op == DB_IO_READ ? "read" : "write",
+ fhp->name, (u_long)io_len, (u_long)off);
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ switch (op) {
+ case DB_IO_READ:
+#if defined(HAVE_STATISTICS)
+ ++fhp->read_count;
+#endif
+ if (!ReadFile(fhp->handle,
+ buf, (DWORD)io_len, &nbytes, &over))
+ goto slow;
+ break;
+ case DB_IO_WRITE:
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ if (__os_fs_notzero())
+ goto slow;
+#endif
+#if defined(HAVE_STATISTICS)
+ ++fhp->write_count;
+#endif
+ if (!WriteFile(fhp->handle,
+ buf, (DWORD)io_len, &nbytes, &over))
+ goto slow;
+ break;
+ }
+ if (nbytes == io_len) {
+ *niop = (size_t)nbytes;
+ 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;
+ }
+
+err: MUTEX_UNLOCK(env, fhp->mtx_fh);
+
+ return (ret);
+}
+
+/*
+ * __os_read --
+ * Read from a file handle.
+ */
+int
+__os_read(env, fhp, addr, len, nrp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nrp;
+{
+ DB_ENV *dbenv;
+ DWORD count;
+ size_t offset, nr;
+ u_int8_t *taddr;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ ret = 0;
+
+#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);
+
+ for (taddr = addr,
+ offset = 0; offset < len; taddr += nr, offset += nr) {
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ RETRY_CHK((!ReadFile(fhp->handle,
+ taddr, (DWORD)(len - offset), &count, NULL)), ret);
+ if (count == 0 || ret != 0)
+ break;
+ nr = (size_t)count;
+ }
+ *nrp = taddr - (u_int8_t *)addr;
+ if (ret != 0) {
+ __db_syserr(env, ret, "read: 0x%lx, %lu",
+ P_TO_ULONG(taddr), (u_long)len - offset);
+ ret = __os_posix_err(ret);
+ }
+ return (ret);
+}
+
+/*
+ * __os_write --
+ * Write to a file handle.
+ */
+int
+__os_write(env, fhp, addr, len, nwp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nwp;
+{
+ int ret;
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ /* Zero-fill as necessary. */
+ if (__os_fs_notzero() &&
+ (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.
+ */
+int
+__os_physwrite(env, fhp, addr, len, nwp)
+ ENV *env;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nwp;
+{
+ DB_ENV *dbenv;
+ DWORD count;
+ size_t offset, nw;
+ u_int8_t *taddr;
+ int ret;
+
+ 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);
+
+ for (taddr = addr,
+ offset = 0; offset < len; taddr += nw, offset += nw) {
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+ RETRY_CHK((!WriteFile(fhp->handle,
+ taddr, (DWORD)(len - offset), &count, NULL)), ret);
+ if (ret != 0)
+ break;
+ nw = (size_t)count;
+ }
+ *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_windows/os_seek.c b/db-4.8.30/os_windows/os_seek.c
new file mode 100644
index 0000000..be689b9
--- /dev/null
+++ b/db-4.8.30/os_windows/os_seek.c
@@ -0,0 +1,65 @@
+/*-
+ * 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.
+ */
+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;
+{
+ /* Yes, this really is how Microsoft designed their API. */
+ union {
+ __int64 bigint;
+ struct {
+ unsigned long low;
+ long high;
+ };
+ } offbytes;
+ DB_ENV *dbenv;
+ off_t offset;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+#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);
+
+ offbytes.bigint = offset;
+ ret = (SetFilePointer(fhp->handle, offbytes.low,
+ &offbytes.high, FILE_BEGIN) == (DWORD)-1) ? __os_get_syserr() : 0;
+
+ 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_windows/os_stat.c b/db-4.8.30/os_windows/os_stat.c
new file mode 100644
index 0000000..0f40a05
--- /dev/null
+++ b/db-4.8.30/os_windows/os_stat.c
@@ -0,0 +1,90 @@
+/*-
+ * 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.
+ */
+int
+__os_exists(env, path, isdirp)
+ ENV *env;
+ const char *path;
+ int *isdirp;
+{
+ DB_ENV *dbenv;
+ DWORD attrs;
+ _TCHAR *tpath;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+
+ TO_TSTRING(env, path, tpath, ret);
+ if (ret != 0)
+ return (ret);
+
+ if (dbenv != NULL &&
+ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL))
+ __db_msg(env, "fileops: stat %s", path);
+
+ RETRY_CHK(
+ ((attrs = GetFileAttributes(tpath)) == (DWORD)-1 ? 1 : 0), ret);
+ if (ret == 0) {
+ if (isdirp != NULL)
+ *isdirp = (attrs & FILE_ATTRIBUTE_DIRECTORY);
+ } else
+ ret = __os_posix_err(ret);
+
+ FREE_STRING(env, tpath);
+ return (ret);
+}
+
+/*
+ * __os_ioinfo --
+ * Return file size and I/O size; abstracted to make it easier
+ * to replace.
+ */
+int
+__os_ioinfo(env, path, fhp, mbytesp, bytesp, iosizep)
+ ENV *env;
+ const char *path;
+ DB_FH *fhp;
+ u_int32_t *mbytesp, *bytesp, *iosizep;
+{
+ int ret;
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ unsigned __int64 filesize;
+
+ RETRY_CHK((!GetFileInformationByHandle(fhp->handle, &bhfi)), ret);
+ if (ret != 0) {
+ __db_syserr(env, ret, "GetFileInformationByHandle");
+ return (__os_posix_err(ret));
+ }
+
+ filesize = ((unsigned __int64)bhfi.nFileSizeHigh << 32) +
+ bhfi.nFileSizeLow;
+
+ /* Return the size of the file. */
+ if (mbytesp != NULL)
+ *mbytesp = (u_int32_t)(filesize / MEGABYTE);
+ if (bytesp != NULL)
+ *bytesp = (u_int32_t)(filesize % MEGABYTE);
+
+ /*
+ * The filesystem I/O size is not easily available. In particular,
+ * the values returned by GetDiskFreeSpace() are not very helpful
+ * (NTFS volumes often report 512B clusters, which are too small to
+ * be a useful default).
+ */
+ if (iosizep != NULL)
+ *iosizep = DB_DEF_IOSIZE;
+ return (0);
+}
diff --git a/db-4.8.30/os_windows/os_truncate.c b/db-4.8.30/os_windows/os_truncate.c
new file mode 100644
index 0000000..b35233b
--- /dev/null
+++ b/db-4.8.30/os_windows/os_truncate.c
@@ -0,0 +1,98 @@
+/*-
+ * 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.
+ */
+int
+__os_truncate(env, fhp, pgno, pgsize)
+ ENV *env;
+ DB_FH *fhp;
+ db_pgno_t pgno;
+ u_int32_t pgsize;
+{
+ /* Yes, this really is how Microsoft have designed their API */
+ union {
+ __int64 bigint;
+ struct {
+ unsigned long low;
+ long high;
+ };
+ } off;
+ DB_ENV *dbenv;
+ off_t offset;
+ int ret;
+
+ dbenv = env == NULL ? NULL : env->dbenv;
+ offset = (off_t)pgsize * pgno;
+ ret = 0;
+
+ 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);
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ /*
+ * If the filesystem doesn't zero fill, it isn't safe to extend the
+ * file, or we end up with junk blocks. Just return in that case.
+ */
+ if (__os_fs_notzero()) {
+ off_t stat_offset;
+ u_int32_t mbytes, bytes;
+
+ /* Stat the file. */
+ if ((ret =
+ __os_ioinfo(env, NULL, fhp, &mbytes, &bytes, NULL)) != 0)
+ return (ret);
+ stat_offset = (off_t)mbytes * MEGABYTE + bytes;
+
+ if (offset > stat_offset)
+ return (0);
+ }
+#endif
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ /*
+ * Windows doesn't provide truncate directly. Instead, it has
+ * SetEndOfFile, which truncates to the current position. To
+ * deal with that, we open a duplicate file handle for truncating.
+ *
+ * We want to retry the truncate call, which involves a SetFilePointer
+ * and a SetEndOfFile, but there are several complications:
+ *
+ * 1) since the Windows API deals in 32-bit values, it's possible that
+ * the return from SetFilePointer (the low 32-bits) is
+ * INVALID_SET_FILE_POINTER even when the call has succeeded. So we
+ * have to also check whether GetLastError() returns NO_ERROR.
+ *
+ * 2) when it returns, SetFilePointer overwrites the high bits of the
+ * offset, so if we need to retry, we have to reset the offset each
+ * time.
+ *
+ * We can't switch to SetFilePointerEx, which knows about 64-bit
+ * offsets, because it isn't supported on Win9x/ME.
+ */
+ RETRY_CHK((off.bigint = (__int64)pgsize * pgno,
+ (SetFilePointer(fhp->trunc_handle, off.low, &off.high, FILE_BEGIN)
+ == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) ||
+ !SetEndOfFile(fhp->trunc_handle)), ret);
+
+ if (ret != 0) {
+ __db_syserr(env, ret, "SetFilePointer: %lu", pgno * pgsize);
+ ret = __os_posix_err(ret);
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_unlink.c b/db-4.8.30/os_windows/os_unlink.c
new file mode 100644
index 0000000..7b5544c
--- /dev/null
+++ b/db-4.8.30/os_windows/os_unlink.c
@@ -0,0 +1,108 @@
+/*-
+ * 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.
+ */
+int
+__os_unlink(env, path, overwrite_test)
+ ENV *env;
+ const char *path;
+ int overwrite_test;
+{
+ DB_ENV *dbenv;
+ HANDLE h;
+ _TCHAR *tpath, *orig_tpath, buf[DB_MAXPATHLEN];
+ u_int32_t id;
+ 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);
+
+ TO_TSTRING(env, path, tpath, ret);
+ if (ret != 0)
+ return (ret);
+ orig_tpath = tpath;
+
+ LAST_PANIC_CHECK_BEFORE_IO(env);
+
+ /*
+ * Windows NT and its descendants allow removal of open files, but the
+ * DeleteFile Win32 system call isn't equivalent to a POSIX unlink.
+ * Firstly, it only succeeds if FILE_SHARE_DELETE is set when the file
+ * is opened. Secondly, it leaves the file in a "zombie" state, where
+ * it can't be opened again, but a new file with the same name can't be
+ * created either.
+ *
+ * Since we depend on being able to recreate files (during recovery,
+ * say), we have to first rename the file, and then delete it. It
+ * still hangs around, but with a name we don't care about. The rename
+ * will fail if the file doesn't exist, which isn't a problem, but if
+ * it fails for some other reason, we need to know about it or a
+ * subsequent open may fail for no apparent reason.
+ */
+ if (__os_is_winnt()) {
+ __os_unique_id(env, &id);
+ _sntprintf(buf, DB_MAXPATHLEN, _T("%s.del.%010u"), tpath, id);
+ if (MoveFile(tpath, buf))
+ tpath = buf;
+ else {
+ ret = __os_get_syserr();
+ if (__os_posix_err(ret) != ENOENT)
+ __db_err(env, ret,
+ "MoveFile: rename %s to temporary file",
+ path);
+ }
+
+ /*
+ * Try removing the file using the delete-on-close flag. This
+ * plays nicer with files that are still open than DeleteFile.
+ */
+ h = CreateFile(tpath, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ if (h != INVALID_HANDLE_VALUE) {
+ (void)CloseHandle (h);
+ if (GetFileAttributes(tpath) == INVALID_FILE_ATTRIBUTES)
+ goto skipdel;
+ }
+ }
+
+ RETRY_CHK((!DeleteFile(tpath)), ret);
+
+skipdel:
+ FREE_STRING(env, orig_tpath);
+
+ /*
+ * 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) {
+ if ((t_ret = __os_posix_err(ret)) != ENOENT)
+ __db_syserr(env, ret, "DeleteFile: %s", path);
+ ret = t_ret;
+ }
+
+ return (ret);
+}
diff --git a/db-4.8.30/os_windows/os_yield.c b/db-4.8.30/os_windows/os_yield.c
new file mode 100644
index 0000000..3d07386
--- /dev/null
+++ b/db-4.8.30/os_windows/os_yield.c
@@ -0,0 +1,35 @@
+/*-
+ * 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_yield --
+ * Yield the processor, optionally pausing until running again.
+ */
+void
+__os_yield(env, secs, usecs)
+ ENV *env;
+ u_long secs, usecs; /* Seconds and microseconds. */
+{
+ COMPQUIET(env, NULL);
+
+ /* Don't require the values be normalized. */
+ for (; usecs >= US_PER_SEC; usecs -= US_PER_SEC)
+ ++secs;
+
+ /*
+ * Yield the processor so other processes or threads can run.
+ *
+ * Sheer raving paranoia -- don't sleep for 0 time, in case some
+ * implementation doesn't yield the processor in that case.
+ */
+ Sleep(secs * MS_PER_SEC + (usecs / US_PER_MS) + 1);
+}