90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello/*
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * This file and its contents are supplied under the terms of the
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Common Development and Distribution License ("CDDL"), version 1.0.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * You may only use this file in accordance with the terms of version
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * 1.0 of the CDDL.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello *
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * A full copy of the text of the CDDL should have accompanied this
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * source. A copy of the CDDL is also available via the Internet at
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * http://www.illumos.org/license/CDDL.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello/*
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Copyright 2016 Joyent, Inc.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello/*
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Acquire the specified kind of lock with the specified parameters. After
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * acquiring the lock, a byte will be written to stdout. The program will
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * then wait for a byte to be written to stdin before exiting.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello *
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Usage: <posix|ofd|flock> <shared|exclusive> <path>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include "util.h"
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <err.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <errno.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <fcntl.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <stdio.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <stdlib.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <strings.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <sys/file.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello#include <unistd.h>
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void acq_fcntl(int, int, int);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void acq_flock(int fd, int mode);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void acq_run(int, lock_style_t, boolean_t);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Melloacq_fcntl(int fd, int cmd, int mode)
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello{
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello struct flock fl;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello int ret, i;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /*
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Acquire the lock, and then try reacquiring it several times. Once we
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * have acquired the lock, trying to acquire it again should succeed,
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * and shouldn't upgrade, downgrade or free the lock.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello for (i = 0; i < 3; i++) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_reinit(&fl, mode);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Acquiring lock (fcntl)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello ret = fcntl(fd, cmd, &fl);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (ret == -1) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello err(EXIT_FAILURE, "fcntl failed");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /* Let the parent know we have the lock and wait */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Waiting (fcntl)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_alert(1);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_block(0);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /* Now unlock */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_reinit(&fl, F_UNLCK);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Releasing lock (fcntl)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello ret = fcntl(fd, cmd, &fl);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (ret == -1) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello err(EXIT_FAILURE, "fcntl failed");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello}
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Melloacq_flock(int fd, int mode)
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello{
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello int ret, i;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /*
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * Acquire the lock, and then try reacquiring it several times. Once we
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * have acquired the lock, trying to acquire it again should succeed,
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello * and shouldn't upgrade, downgrade or free the lock.
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello for (i = 0; i < 3; i++) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Acquiring lock (flock)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello ret = flock(fd, mode);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (ret == -1) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello err(EXIT_FAILURE, "flock failed");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /* Wait to be okayed to unlock */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Waiting (flock)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_alert(1);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_block(0);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello /* Release lock */
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello flock_log("Releasing lock (flock)...\n");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello ret = flock(fd, LOCK_UN);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (ret == -1) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello err(EXIT_FAILURE, "flock failed");
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello}
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellostatic void
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Melloacq_run(int fd, lock_style_t style, boolean_t is_exclusive)
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello{
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello switch (style) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello case LSTYLE_POSIX:
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello acq_fcntl(fd, F_SETLKW, is_exclusive ? F_WRLCK : F_RDLCK);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello break;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello case LSTYLE_OFD:
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello acq_fcntl(fd, F_OFD_SETLKW, is_exclusive ? F_WRLCK : F_RDLCK);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello break;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello case LSTYLE_FLOCK:
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello acq_flock(fd, is_exclusive ? LOCK_EX : LOCK_SH);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello break;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello default:
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello abort();
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello}
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Melloint
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mellomain(int argc, char *argv[])
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello{
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello char *modestr, *path;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello lock_style_t style;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello boolean_t is_exclusive;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello int fd;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (argc < 4) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello errx(EXIT_FAILURE, BAD_ARGS_MESSAGE, argc - 1);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello modestr = argv[2];
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello path = argv[3];
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello style = flock_styleenum(argv[1]);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (strcmp(modestr, "shared") == 0) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello is_exclusive = B_FALSE;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello } else if (strcmp(modestr, "exclusive") == 0) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello is_exclusive = B_TRUE;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello } else {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello errx(EXIT_FAILURE, BAD_MODE_MESSAGE);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello boolean_t rdonly = style == LSTYLE_FLOCK || !is_exclusive;
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello fd = open(path, rdonly ? O_RDONLY : O_WRONLY);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello if (fd == -1) {
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello err(EXIT_FAILURE, "Failed to open %s", path);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello }
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello acq_run(fd, style, is_exclusive);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello return (0);
90221f9148b67fdc90178b67f9600b7bd4e3bc7cCody Peter Mello}