1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019 Joyent, Inc.
14  */
15 
16 /*
17  * Utility functions for use in both acquire-lock and runtests.
18  */
19 
20 #include "util.h"
21 #include <err.h>
22 #include <errno.h>
23 #include <poll.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <strings.h>
28 #include <unistd.h>
29 
30 
31 boolean_t LOG = B_FALSE;
32 
33 
34 void
flock_log(const char * format,...)35 flock_log(const char *format, ...)
36 {
37 	va_list ap;
38 	if (!LOG) {
39 		return;
40 	}
41 
42 	va_start(ap, format);
43 	(void) vfprintf(stderr, format, ap);
44 	va_end(ap);
45 }
46 
47 
48 boolean_t
flock_nodata(int fd)49 flock_nodata(int fd)
50 {
51 	struct pollfd pfd = { fd, POLLIN, 0 };
52 	int ret = poll(&pfd, 1, 1000);
53 
54 	if (ret == -1) {
55 		err(EXIT_FAILURE, "poll failed");
56 	}
57 
58 	return (ret == 0);
59 }
60 
61 
62 void
flock_block(int fd)63 flock_block(int fd)
64 {
65 	char buf[1];
66 	int ret = 0;
67 	while (ret < 1) {
68 		ret = read(fd, buf, 1);
69 		if (ret == -1) {
70 			if (errno == EINTR)
71 				continue;
72 			err(EXIT_FAILURE, "read failed");
73 		}
74 	}
75 }
76 
77 
78 void
flock_alert(int fd)79 flock_alert(int fd)
80 {
81 	int ret = 0;
82 	while (ret < 1) {
83 		ret = write(fd, "1", 1);
84 		if (ret == -1) {
85 			if (errno == EINTR)
86 				continue;
87 			err(EXIT_FAILURE, "write failed");
88 		}
89 	}
90 }
91 
92 
93 lock_style_t
flock_styleenum(char * stylestr)94 flock_styleenum(char *stylestr)
95 {
96 	if (strcmp(stylestr, "posix") == 0) {
97 		return (LSTYLE_POSIX);
98 	} else if (strcmp(stylestr, "ofd") == 0) {
99 		return (LSTYLE_OFD);
100 	} else if (strcmp(stylestr, "flock") == 0) {
101 		return (LSTYLE_FLOCK);
102 	} else {
103 		errx(EXIT_FAILURE, BAD_LOCK_MESSAGE);
104 	}
105 }
106 
107 
108 char *
flock_stylestr(lock_style_t style)109 flock_stylestr(lock_style_t style)
110 {
111 	switch (style) {
112 	case LSTYLE_POSIX:
113 		return ("posix");
114 	case LSTYLE_OFD:
115 		return ("ofd");
116 	case LSTYLE_FLOCK:
117 		return ("flock");
118 	default:
119 		abort();
120 	}
121 }
122 
123 
124 char *
flock_stylename(lock_style_t style)125 flock_stylename(lock_style_t style)
126 {
127 	switch (style) {
128 	case LSTYLE_POSIX:
129 		return ("fcntl(2) POSIX");
130 	case LSTYLE_OFD:
131 		return ("fcntl(2) OFD");
132 	case LSTYLE_FLOCK:
133 		return ("flock(3C)");
134 	default:
135 		abort();
136 	}
137 }
138 
139 
140 void
flock_reinit(struct flock * flp,int ltype)141 flock_reinit(struct flock *flp, int ltype)
142 {
143 	bzero(flp, sizeof (*flp));
144 	flp->l_type = ltype;
145 }
146 
147 
148 char *
flock_cmdname(int cmd)149 flock_cmdname(int cmd)
150 {
151 	switch (cmd) {
152 	case F_SETLK:
153 		return ("F_SETLK");
154 	case F_OFD_SETLK:
155 		return ("F_OFD_SETLK");
156 	case F_SETLKW:
157 		return ("F_SETLKW");
158 	case F_OFD_SETLKW:
159 		return ("F_OFD_SETLKW");
160 	case F_GETLK:
161 		return ("F_GETLK");
162 	case F_OFD_GETLK:
163 		return ("F_OFD_GETLK");
164 	case F_FLOCK:
165 		return ("F_FLOCK");
166 	case F_FLOCKW:
167 		return ("F_FLOCKW");
168 #if !defined(_LP64)
169 	case F_OFD_SETLK64:
170 		return ("F_OFD_SETLK64");
171 	case F_OFD_SETLKW64:
172 		return ("F_OFD_SETLKW64");
173 	case F_OFD_GETLK64:
174 		return ("F_OFD_GETLK64");
175 #endif
176 	default:
177 		abort();
178 	}
179 }
180