#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) {
	struct flock lock;
	lock.l_type = type;
	lock.l_start = offset;
	lock.l_whence = whence;
	lock.l_len = len;

	return ( fcntl(fd, cmd, &lock) );
}

int read_lock(int fd, off_t offset, int whence, off_t len) {
	return lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len);
}

int readw_lock(int fd, off_t offset, int whence, off_t len) {
	return lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len);
}

int write_lock(int fd, off_t offset, int whence, off_t len) {
	return lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len);
}

int writew_lock(int fd, off_t offset, int whence, off_t len) {
	return lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len);
}

int un_lock(int fd, off_t offset, int whence, off_t len) {
	return lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len);
}

pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len) {
	struct flock lock;
	lock.l_type = type;
	lock.l_start = offset;
	lock.l_whence = whence;
	lock.l_len = len;

	if ( fcntl(fd, F_GETLK, &lock) < 0 ) {
		fprintf(stderr, "fcntl error");
		exit(1);
	}

	if ( lock.l_type == F_UNLCK )
		return 0;

	return lock.l_pid;
}

pid_t is_read_lockable(int fd, off_t offset, int whence, off_t len) {
	return lock_test(fd, F_RDLCK, offset, whence, len);
}

pid_t is_write_lockable(int fd, off_t offset, int whence, off_t len) {
	return lock_test(fd, F_WRLCK, offset, whence, len);
}

int main (int argc, char* argv[]) {
	int fd;
	off_t pos;
	int i;
	FILE *tfile;

	fd = open("locktest.txt", O_CREAT|O_RDWR, 0664);
	for ( i = 0; i < 100; i++) {
		int success = 0;
		while ( success == 0 ) {
			pos = lseek(fd, 0, SEEK_END);
			if ( write_lock(fd, pos, SEEK_SET, 52) >= 0 ) {
				char s[1024];
				sprintf(s,"item: %44d \n",i);
				write(fd,s,52);
				success = 1;
				un_lock(fd, pos, SEEK_SET, 52);
			} 
		}
	}
	return 0;
}

