155682Smarkm/*
2233294Sstas * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska H��gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
5233294Sstas *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
9233294Sstas *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
12233294Sstas *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
16233294Sstas *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
20233294Sstas *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include <config.h>
3555682Smarkm
3655682Smarkm#ifndef HAVE_FLOCK
3755682Smarkm
3855682Smarkm#include "roken.h"
3955682Smarkm
4055682Smarkm#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN)
4155682Smarkm
42233294Sstas
43233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
44233294Sstasrk_flock(int fd, int operation)
4555682Smarkm{
4655682Smarkm#if defined(HAVE_FCNTL) && defined(F_SETLK)
4755682Smarkm  struct flock arg;
4855682Smarkm  int code, cmd;
49233294Sstas
5055682Smarkm  arg.l_whence = SEEK_SET;
5155682Smarkm  arg.l_start = 0;
5255682Smarkm  arg.l_len = 0;		/* means to EOF */
5355682Smarkm
5455682Smarkm  if (operation & LOCK_NB)
5555682Smarkm    cmd = F_SETLK;
5655682Smarkm  else
5755682Smarkm    cmd = F_SETLKW;		/* Blocking */
5855682Smarkm
5955682Smarkm  switch (operation & OP_MASK) {
6055682Smarkm  case LOCK_UN:
6155682Smarkm    arg.l_type = F_UNLCK;
6255682Smarkm    code = fcntl(fd, F_SETLK, &arg);
6355682Smarkm    break;
6455682Smarkm  case LOCK_SH:
6555682Smarkm    arg.l_type = F_RDLCK;
6655682Smarkm    code = fcntl(fd, cmd, &arg);
6755682Smarkm    break;
6855682Smarkm  case LOCK_EX:
6955682Smarkm    arg.l_type = F_WRLCK;
7055682Smarkm    code = fcntl(fd, cmd, &arg);
7155682Smarkm    break;
7255682Smarkm  default:
7355682Smarkm    errno = EINVAL;
7455682Smarkm    code = -1;
7555682Smarkm    break;
7655682Smarkm  }
7755682Smarkm  return code;
78233294Sstas
79233294Sstas#elif defined(_WIN32)
80233294Sstas  /* Windows */
81233294Sstas
82233294Sstas#define FLOCK_OFFSET_LOW  0
83233294Sstas#define FLOCK_OFFSET_HIGH 0
84233294Sstas#define FLOCK_LENGTH_LOW  0x00000000
85233294Sstas#define FLOCK_LENGTH_HIGH 0x80000000
86233294Sstas
87233294Sstas  HANDLE hFile;
88233294Sstas  OVERLAPPED ov;
89233294Sstas  BOOL rv = FALSE;
90233294Sstas  DWORD f = 0;
91233294Sstas
92233294Sstas  hFile = (HANDLE) _get_osfhandle(fd);
93233294Sstas  if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
94233294Sstas      _set_errno(EBADF);
95233294Sstas      return -1;
96233294Sstas  }
97233294Sstas
98233294Sstas  ZeroMemory(&ov, sizeof(ov));
99233294Sstas  ov.hEvent = NULL;
100233294Sstas  ov.Offset = FLOCK_OFFSET_LOW;
101233294Sstas  ov.OffsetHigh = FLOCK_OFFSET_HIGH;
102233294Sstas
103233294Sstas  if (operation & LOCK_NB)
104233294Sstas      f = LOCKFILE_FAIL_IMMEDIATELY;
105233294Sstas
106233294Sstas  switch (operation & OP_MASK) {
107233294Sstas  case LOCK_UN:			/* Unlock */
108233294Sstas      rv = UnlockFileEx(hFile, 0,
109233294Sstas			FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov);
110233294Sstas      break;
111233294Sstas
112233294Sstas  case LOCK_SH:			/* Shared lock */
113233294Sstas      rv = LockFileEx(hFile, f, 0,
114233294Sstas		      FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov);
115233294Sstas      break;
116233294Sstas
117233294Sstas  case LOCK_EX:			/* Exclusive lock */
118233294Sstas      rv = LockFileEx(hFile, f|LOCKFILE_EXCLUSIVE_LOCK, 0,
119233294Sstas		      FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH,
120233294Sstas		      &ov);
121233294Sstas      break;
122233294Sstas
123233294Sstas  default:
124233294Sstas      _set_errno(EINVAL);
125233294Sstas      return -1;
126233294Sstas  }
127233294Sstas
128233294Sstas  if (!rv) {
129233294Sstas      switch (GetLastError()) {
130233294Sstas      case ERROR_SHARING_VIOLATION:
131233294Sstas      case ERROR_LOCK_VIOLATION:
132233294Sstas      case ERROR_IO_PENDING:
133233294Sstas	  _set_errno(EWOULDBLOCK);
134233294Sstas	  break;
135233294Sstas
136233294Sstas      case ERROR_ACCESS_DENIED:
137233294Sstas	  _set_errno(EACCES);
138233294Sstas	  break;
139233294Sstas
140233294Sstas      default:
141233294Sstas	  _set_errno(ENOLCK);
142233294Sstas      }
143233294Sstas      return -1;
144233294Sstas  }
145233294Sstas
146233294Sstas  return 0;
147233294Sstas
14855682Smarkm#else
14955682Smarkm  return -1;
15055682Smarkm#endif
15155682Smarkm}
15255682Smarkm
15355682Smarkm#endif
15455682Smarkm
155