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(owner, filename, flags)
34 fd = open(filename, flags, 0640);
37 fprintf(stderr, "%d: %ld: owner=%d, open(%s) failed\n",
38 (int) pid, (long) time(NULL), owner, filename);
50 r = write(fd, iobuf, sizeof(iobuf));
51 if (sizeof(iobuf) == r)
53 fprintf(stderr, "%d: %ld: owner=1, write(%s)=fail\n",
54 (int) pid, (long) time(NULL), iobuf);
67 r = read(fd, iobuf, sizeof(iobuf));
68 if (sizeof(iobuf) != r)
70 fprintf(stderr, "%d: %ld: owner=0, read()=fail\n",
71 (int) pid, (long) time(NULL));
74 if (strncmp(iobuf, xbuf, strlen(xbuf)))
76 fprintf(stderr, "%d: %ld: owner=0, read=%s expected=%s\n",
77 (int) pid, (long) time(NULL), iobuf, xbuf);
84 ** LOCKTEST -- test of file locking
87 ** owner -- create file?
88 ** filename -- name of file.
89 ** flags -- flags for open(2)
90 ** delay -- how long to keep file locked?
97 #define DBGPRINTR(str) \
100 fprintf(stderr, "%d: %ld: owner=0, ", (int) pid, \
101 (long) time(NULL)); \
102 fprintf(stderr, str, filename, shared ? "RD" : "EX"); \
106 locktestwr(filename, flags, delay)
114 fd = openfile(1, filename, flags);
117 locked = lockfile(fd, filename, "[owner]", LOCK_EX);
120 fprintf(stderr, "%d: %ld: owner=1, lock(%s) failed\n",
121 (int) pid, (long) time(NULL), filename);
125 fprintf(stderr, "%d: %ld: owner=1, lock(%s) ok\n",
126 (int) pid, (long) time(NULL), filename);
128 sm_strlcpy(iobuf, FIRSTLINE, sizeof(iobuf));
132 sm_strlcpy(iobuf, LASTLINE, sizeof(iobuf));
135 locked = lockfile(fd, filename, "[owner]", LOCK_UN);
138 fprintf(stderr, "%d: %ld: owner=1, unlock(%s) failed\n",
139 (int) pid, (long) time(NULL), filename);
142 fprintf(stderr, "%d: %ld: owner=1, unlock(%s) done\n",
143 (int) pid, (long) time(NULL), filename);
160 (void) memset(&lfd, '\0', sizeof lfd);
161 lfd.l_type = F_RDLCK;
163 while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
167 if (F_WRLCK == lfd.l_type)
168 return (long)lfd.l_pid;
170 #else /* !HASFLOCK */
171 fprintf(stderr, "%d: %ld: flock: no lock test\n",
172 (int) pid, (long) time(NULL));
174 #endif /* !HASFLOCK */
178 locktestrd(filename, flags, delay, shared)
188 fd = openfile(0, filename, flags);
197 fprintf(stderr, "%d: %ld: file=%s status=locked pid=%ld\n",
198 (int) pid, (long) time(NULL), filename, locked);
199 else if (0 == locked)
200 fprintf(stderr, "%d: %ld: file=%s status=not_locked\n",
201 (int) pid, (long) time(NULL), filename);
203 fprintf(stderr, "%d: %ld: file=%s status=unknown\n",
204 (int) pid, (long) time(NULL), filename);
213 for (cnt = 0; cnt < delay - 2; cnt++)
215 /* try to get lock: should fail (nonblocking) */
216 locked = lockfile(fd, filename, "[client]", lt|LOCK_NB);
219 DBGPRINTR("lock(%s)=%s succeeded\n");
226 locked = lockfile(fd, filename, "[client]", lt);
229 DBGPRINTR("lock(%s)=%s failed\n");
232 DBGPRINTR("lock(%s)=%s ok\n");
233 if (rdbuf(fd, FIRSTLINE))
235 if (rdbuf(fd, LASTLINE))
238 locked = lockfile(fd, filename, "[client]", LOCK_UN);
241 DBGPRINTR("unlock(%s)=%s failed\n");
244 DBGPRINTR("unlock(%s)=%s done\n");
259 fprintf(stderr, "usage: %s [options]\n"
260 "-f filename use filename\n"
261 "-i do not perform I/O\n"
262 "-n do not try non-blocking locking first\n"
263 "-R only start reader process\n"
264 "-r use shared locking for reader\n"
265 "-s delay sleep delay seconds before unlocking\n"
266 "-W only start writer process\n"
275 int ch, delay, r, status, flags, shared, nb, reader, writer;
281 filename = "testlock";
283 shared = nb = noio = reader = writer = chk = 0;
284 #define OPTIONS "cf:inRrs:W"
285 while ((ch = getopt(argc, argv, OPTIONS)) != -1)
314 delay = atoi(optarg);
329 if (0 == reader && 0 == writer && (fpid = fork()) < 0)
331 perror("fork failed\n");
336 if (reader || fpid == 0)
338 /* give the parent the chance to setup data */
341 r = locktestrd(filename, flags, nb ? delay : 0, shared);
343 if (writer || fpid > 0)
346 r = locktestwr(filename, flags, delay);
347 (void) wait(&status);
349 /* (void) unlink(filename); */