2 * Copyright (c) 2005 Proofpoint, Inc. and its suppliers.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
12 SM_IDSTR(id, "@(#)$Id: t-lockfile.c,v 1.2 2013-11-22 20:51:50 ca Exp $")
19 #define FIRSTLINE "first line\n"
20 #define LASTLINE "last line\n"
25 ** OPENFILE -- open a file
28 ** owner -- create file?
29 ** filename -- name of file.
30 ** flags -- flags for open(2)
38 openfile(owner, filename, flags)
47 fd = open(filename, flags, 0640);
50 fprintf(stderr, "%d: %ld: owner=%d, open(%s) failed\n",
51 (int) pid, (long) time(NULL), owner, filename);
56 ** WRBUF -- write iobuf to fd
59 ** fd -- file descriptor.
74 r = write(fd, iobuf, sizeof(iobuf));
75 if (sizeof(iobuf) == r)
77 fprintf(stderr, "%d: %ld: owner=1, write(%s)=fail\n",
78 (int) pid, (long) time(NULL), iobuf);
83 ** RDBUF -- read from fd
86 ** fd -- file descriptor.
87 ** xbuf -- expected content.
90 ** ==0 read was ok and content matches
103 r = read(fd, iobuf, sizeof(iobuf));
104 if (sizeof(iobuf) != r)
106 fprintf(stderr, "%d: %ld: owner=0, read()=fail\n",
107 (int) pid, (long) time(NULL));
110 if (strncmp(iobuf, xbuf, strlen(xbuf)))
112 fprintf(stderr, "%d: %ld: owner=0, read=%s expected=%s\n",
113 (int) pid, (long) time(NULL), iobuf, xbuf);
120 ** LOCKTESTWR -- test WR/EX file locking
123 ** owner -- create file?
124 ** filename -- name of file.
125 ** flags -- flags for open(2)
126 ** delay -- how long to keep file locked?
133 #define DBGPRINTR(str) \
136 fprintf(stderr, "%d: %ld: owner=0, ", (int) pid, \
137 (long) time(NULL)); \
138 fprintf(stderr, str, filename, shared ? "RD" : "EX"); \
142 locktestwr(filename, flags, delay)
150 fd = openfile(1, filename, flags);
153 locked = lockfile(fd, filename, "[owner]", LOCK_EX);
156 fprintf(stderr, "%d: %ld: owner=1, lock(%s) failed\n",
157 (int) pid, (long) time(NULL), filename);
161 fprintf(stderr, "%d: %ld: owner=1, lock(%s) ok\n",
162 (int) pid, (long) time(NULL), filename);
164 sm_strlcpy(iobuf, FIRSTLINE, sizeof(iobuf));
169 sm_strlcpy(iobuf, LASTLINE, sizeof(iobuf));
172 locked = lockfile(fd, filename, "[owner]", LOCK_UN);
175 fprintf(stderr, "%d: %ld: owner=1, unlock(%s) failed\n",
176 (int) pid, (long) time(NULL), filename);
179 fprintf(stderr, "%d: %ld: owner=1, unlock(%s) done\n",
180 (int) pid, (long) time(NULL), filename);
190 ** CHKLCK -- check whether fd is locked (only for fcntl())
193 ** owner -- create file?
194 ** filename -- name of file.
195 ** flags -- flags for open(2)
196 ** delay -- how long to keep file locked?
200 ** >0 pid of process which holds a WR lock
212 (void) memset(&lfd, '\0', sizeof lfd);
213 lfd.l_type = F_RDLCK;
215 while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
219 if (F_WRLCK == lfd.l_type)
220 return (long)lfd.l_pid;
222 #else /* !HASFLOCK */
223 fprintf(stderr, "%d: %ld: flock(): no lock test\n",
224 (int) pid, (long) time(NULL));
226 #endif /* !HASFLOCK */
230 ** LOCKTESTRD -- test file locking for reading
233 ** filename -- name of file.
234 ** flags -- flags for open(2)
235 ** delay -- how long is file locked by owner?
236 ** shared -- LOCK_{EX/SH}
244 locktestrd(filename, flags, delay, shared)
254 fd = openfile(0, filename, flags);
263 fprintf(stderr, "%d: %ld: file=%s status=locked pid=%ld\n",
264 (int) pid, (long) time(NULL), filename, locked);
265 else if (0 == locked)
266 fprintf(stderr, "%d: %ld: file=%s status=not_locked\n",
267 (int) pid, (long) time(NULL), filename);
269 fprintf(stderr, "%d: %ld: file=%s status=unknown\n",
270 (int) pid, (long) time(NULL), filename);
279 for (cnt = 0; cnt < delay - 2; cnt++)
281 /* try to get lock: should fail (nonblocking) */
282 locked = lockfile(fd, filename, "[client]", lt|LOCK_NB);
285 DBGPRINTR("lock(%s)=%s succeeded\n");
292 locked = lockfile(fd, filename, "[client]", lt);
295 DBGPRINTR("lock(%s)=%s failed\n");
298 DBGPRINTR("lock(%s)=%s ok\n");
299 if (rdbuf(fd, FIRSTLINE))
301 if (rdbuf(fd, LASTLINE))
304 locked = lockfile(fd, filename, "[client]", LOCK_UN);
307 DBGPRINTR("unlock(%s)=%s failed\n");
310 DBGPRINTR("unlock(%s)=%s done\n");
322 ** USAGE -- show usage
325 ** prg -- name of program
335 fprintf(stderr, "usage: %s [options]\n"
336 "-f filename use filename\n"
337 "-i do not perform I/O\n"
338 "-n do not try non-blocking locking first\n"
339 "-R only start reader process\n"
340 "-r use shared locking for reader\n"
341 "-s delay sleep delay seconds before unlocking\n"
342 "-W only start writer process\n"
357 int ch, delay, r, status, flags, shared, nb, reader, writer;
363 filename = "testlock";
365 shared = nb = noio = reader = writer = chk = 0;
366 #define OPTIONS "cf:inRrs:W"
367 while ((ch = getopt(argc, argv, OPTIONS)) != -1)
396 delay = atoi(optarg);
411 if (0 == reader && 0 == writer && (fpid = fork()) < 0)
413 perror("fork failed\n");
418 if (reader || fpid == 0)
420 /* give the parent the chance to set up data */
423 r = locktestrd(filename, flags, nb ? delay : 0, shared);
425 if (writer || fpid > 0)
428 r = locktestwr(filename, flags, delay);
429 (void) wait(&status);
431 /* (void) unlink(filename); */