packages feed

colock-0.2.2: System_IO_Lock.c

#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>

#define RETRY(V, X) do { \
	int return_value_; \
	do { \
		return_value_ = (X); \
	} while (return_value_ == -1 && errno == EINTR); \
	(V) = return_value_; \
} while (0)

int System_IO_Lock_get_lock_async(int *got, int *release, int fd, int exclusive, short whence, off_t start, off_t len) {
	int in[2], out[2];
	pid_t pid;
	int r, e;

	RETRY(r, pipe(in));
	if (r) {
		return -1;
	}

	RETRY(r, pipe(out));
	if (r) {
		close(in[0]);
		close(in[1]);
		return -1;
	}

	switch ((pid = fork())) {
		case -1:
			return -1;

		case 0:
			RETRY(r, close(in[0]));
			RETRY(r, close(out[1]));
			switch (fork()) {
				case -1:
					e = errno;
					RETRY(r, write(in[1], &e, sizeof e));
					_exit(1);

				case 0: {
					struct flock fl;
					fl.l_type = exclusive ? F_WRLCK : F_RDLCK;
					fl.l_whence = whence;
					fl.l_start = start;
					fl.l_len = len;
					RETRY(r, fcntl(fd, F_SETLKW, &fl));
					e = r ? errno : 0;
					RETRY(r, write(in[1], &e, sizeof e));
					if (!e) {
						RETRY(r, close(in[1]));
						RETRY(r, read(out[0], &e, 1));
					}
					_exit(0);
				}

				default:
					_exit(0);
			}

		default:
			RETRY(r, close(in[1]));
			RETRY(r, close(out[0]));
			RETRY(r, waitpid(pid, NULL, 0));
			*got = in[0];
			*release = out[1];
			return 0;
	}
}