1/*	$NetBSD: flock.c,v 1.2 2017/01/28 21:31:50 christos Exp $	*/
2
3/*
4 * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska H��gskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <config.h>
37
38#ifndef HAVE_FLOCK
39
40#include <krb5/roken.h>
41
42#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN)
43
44
45ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
46rk_flock(int fd, int operation)
47{
48#if defined(HAVE_FCNTL) && defined(F_SETLK)
49  struct flock arg;
50  int code, cmd;
51
52  arg.l_whence = SEEK_SET;
53  arg.l_start = 0;
54  arg.l_len = 0;		/* means to EOF */
55
56  if (operation & LOCK_NB)
57    cmd = F_SETLK;
58  else
59    cmd = F_SETLKW;		/* Blocking */
60
61  switch (operation & OP_MASK) {
62  case LOCK_UN:
63    arg.l_type = F_UNLCK;
64    code = fcntl(fd, F_SETLK, &arg);
65    break;
66  case LOCK_SH:
67    arg.l_type = F_RDLCK;
68    code = fcntl(fd, cmd, &arg);
69    break;
70  case LOCK_EX:
71    arg.l_type = F_WRLCK;
72    code = fcntl(fd, cmd, &arg);
73    break;
74  default:
75    errno = EINVAL;
76    code = -1;
77    break;
78  }
79  return code;
80
81#elif defined(_WIN32)
82  /* Windows */
83
84#define FLOCK_OFFSET_LOW  0
85#define FLOCK_OFFSET_HIGH 0
86#define FLOCK_LENGTH_LOW  0x00000000
87#define FLOCK_LENGTH_HIGH 0x80000000
88
89  HANDLE hFile;
90  OVERLAPPED ov;
91  BOOL rv = FALSE;
92  DWORD f = 0;
93
94  hFile = (HANDLE) _get_osfhandle(fd);
95  if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
96      _set_errno(EBADF);
97      return -1;
98  }
99
100  ZeroMemory(&ov, sizeof(ov));
101  ov.hEvent = NULL;
102  ov.Offset = FLOCK_OFFSET_LOW;
103  ov.OffsetHigh = FLOCK_OFFSET_HIGH;
104
105  if (operation & LOCK_NB)
106      f = LOCKFILE_FAIL_IMMEDIATELY;
107
108  switch (operation & OP_MASK) {
109  case LOCK_UN:			/* Unlock */
110      rv = UnlockFileEx(hFile, 0,
111			FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov);
112      break;
113
114  case LOCK_SH:			/* Shared lock */
115      rv = LockFileEx(hFile, f, 0,
116		      FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov);
117      break;
118
119  case LOCK_EX:			/* Exclusive lock */
120      rv = LockFileEx(hFile, f|LOCKFILE_EXCLUSIVE_LOCK, 0,
121		      FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH,
122		      &ov);
123      break;
124
125  default:
126      _set_errno(EINVAL);
127      return -1;
128  }
129
130  if (!rv) {
131      switch (GetLastError()) {
132      case ERROR_SHARING_VIOLATION:
133      case ERROR_LOCK_VIOLATION:
134      case ERROR_IO_PENDING:
135	  _set_errno(EWOULDBLOCK);
136	  break;
137
138      case ERROR_ACCESS_DENIED:
139	  _set_errno(EACCES);
140	  break;
141
142      default:
143	  _set_errno(ENOLCK);
144      }
145      return -1;
146  }
147
148  return 0;
149
150#else
151  return -1;
152#endif
153}
154
155#endif
156
157