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;
}
}