1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: os_flock.c,v 1.21 2008/01/08 20:58:46 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13/* 14 * __os_fdlock -- 15 * Acquire/release a lock on a byte in a file. 16 */ 17int 18__os_fdlock(env, fhp, offset, acquire, nowait) 19 ENV *env; 20 DB_FH *fhp; 21 int acquire, nowait; 22 off_t offset; 23{ 24#ifdef DB_WINCE 25 /* 26 * This functionality is not supported by WinCE, so just fail. 27 * 28 * Should only happen if an app attempts to open an environment 29 * with the DB_REGISTER flag. 30 */ 31 __db_errx(env, "fdlock API not implemented for WinCE, DB_REGISTER " 32 "environment flag not supported."); 33 return (EFAULT); 34#else 35 DWORD low, high; 36 DB_ENV *dbenv; 37 OVERLAPPED over; 38 int ret; 39 40 dbenv = env == NULL ? NULL : env->dbenv; 41 42 DB_ASSERT(env, 43 F_ISSET(fhp, DB_FH_OPENED) && fhp->handle != INVALID_HANDLE_VALUE); 44 45 if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) 46 __db_msg(env, 47 "fileops: flock %s %s offset %lu", 48 fhp->name, acquire ? "acquire": "release", (u_long)offset); 49 50 /* 51 * Windows file locking interferes with read/write operations, so we 52 * map the ranges to an area past the end of the file. 53 */ 54 DB_ASSERT(env, offset < (u_int64_t)INT64_MAX); 55 offset = UINT64_MAX - offset; 56 low = (DWORD)offset; 57 high = (DWORD)(offset >> 32); 58 59 if (acquire) { 60 if (nowait) 61 RETRY_CHK_EINTR_ONLY( 62 !LockFile(fhp->handle, low, high, 1, 0), ret); 63 else if (__os_is_winnt()) { 64 memset(&over, 0, sizeof(over)); 65 over.Offset = low; 66 over.OffsetHigh = high; 67 RETRY_CHK_EINTR_ONLY( 68 !LockFileEx(fhp->handle, LOCKFILE_EXCLUSIVE_LOCK, 69 0, 1, 0, &over), 70 ret); 71 } else { 72 /* Windows 9x/ME doesn't support a blocking call. */ 73 for (;;) { 74 RETRY_CHK_EINTR_ONLY( 75 !LockFile(fhp->handle, low, high, 1, 0), 76 ret); 77 if (__os_posix_err(ret) != EAGAIN) 78 break; 79 __os_yield(env, 1, 0); 80 } 81 } 82 } else 83 RETRY_CHK_EINTR_ONLY( 84 !UnlockFile(fhp->handle, low, high, 1, 0), ret); 85 86 return (__os_posix_err(ret)); 87#endif 88} 89