/*
 * lockf(3) and flock(2) emulation for MiNT by Dave Gymer
 * Placed in the public domain; do with me as you will!
 * BUGS: doesn't block, unlike BSD or SysV
 */

#include <compiler.h>
#include "lib.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <mintbind.h>
#ifdef __TURBOC__
#include <sys\file.h>
#else
#include <sys/file.h>
#endif

static int do_lock __PROTO((int fd, int cmd, long size, int whence));

static int
do_lock(fd, cmd, size, whence)
	int fd;
	int cmd;
	long size;
	int whence;
{
	struct flock lock;
	int fcmd;
	long r;
	extern int __mint;

	if (!__mint) {
		errno = -EINVAL;
		return -1;
	}
	lock.l_whence = whence;
	lock.l_start = 0;
	lock.l_len = size;
	switch (cmd) {
		case F_ULOCK:
			lock.l_type = F_UNLCK;
			fcmd = F_SETLK;
			break;
		case F_TEST:
			lock.l_type = F_WRLCK;
			fcmd = F_GETLK;
			break;
		case F_TLOCK:
			lock.l_type = F_WRLCK;
			fcmd = F_SETLK;
			break;
		case F_LOCK:
			lock.l_type = F_WRLCK;
			fcmd = F_SETLK;
			break;
		default:
			errno = -EINVAL;
			return -1;
	}
	if ((r = Fcntl(fd, &lock, fcmd)) < 0) {
		errno = (int) -r;
		return -1;
	}
	return 0;
}

int
lockf(fd, cmd, size)
	int fd;
	int cmd;
	long size;
{
	return do_lock(fd, cmd, size, 1);
}

int
flock(fd, op)
	int fd, op;
{
	int cmd;

	if (op & (LOCK_SH | LOCK_EX))
		cmd = (op & LOCK_NB) ? F_TLOCK : F_LOCK;
	else if (op & LOCK_UN)
		cmd = F_ULOCK;
	else {
		errno = -EINVAL;
		return -1;
	}
	return do_lock(fd, cmd, 0L, 0);
}
