Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / myflock.c
blob5d7607554622d58d882aab38a01a3cb1ecd200ba
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* myflock 3
6 /* SUMMARY
7 /* lock open file
8 /* SYNOPSIS
9 /* #include <myflock.h>
11 /* int myflock(fd, lock_style, operation)
12 /* int fd;
13 /* int lock_style;
14 /* int operation;
15 /* DESCRIPTION
16 /* myflock() locks or unlocks an entire open file.
18 /* In the case of a blocking request, a call that fails due to
19 /* forseeable transient problems is retried once per second.
21 /* Arguments:
22 /* .IP fd
23 /* The open file to be locked/unlocked.
24 /* .IP lock_style
25 /* One of the following values:
26 /* .RS
27 /* .IP MYFLOCK_STYLE_FLOCK
28 /* Use BSD-style flock() locking.
29 /* .IP MYFLOCK_STYLE_FCNTL
30 /* Use POSIX-style fcntl() locking.
31 /* .RE
32 /* .IP operation
33 /* One of the following values:
34 /* .RS
35 /* .IP MYFLOCK_OP_NONE
36 /* Release any locks the process has on the specified open file.
37 /* .IP MYFLOCK_OP_SHARED
38 /* Attempt to acquire a shared lock on the specified open file.
39 /* This is appropriate for read-only access.
40 /* .IP MYFLOCK_OP_EXCLUSIVE
41 /* Attempt to acquire an exclusive lock on the specified open
42 /* file. This is appropriate for write access.
43 /* .PP
44 /* In addition, setting the MYFLOCK_OP_NOWAIT bit causes the
45 /* call to return immediately when the requested lock cannot
46 /* be acquired.
47 /* .RE
48 /* DIAGNOSTICS
49 /* myflock() returns 0 in case of success, -1 in case of failure.
50 /* A problem description is returned via the global \fIerrno\fR
51 /* variable. In the case of a non-blocking lock request the value
52 /* EAGAIN means that a lock is claimed by someone else.
54 /* Panic: attempts to use an unsupported file locking method or
55 /* to implement an unsupported operation.
56 /* LICENSE
57 /* .ad
58 /* .fi
59 /* The Secure Mailer license must be distributed with this software.
60 /* AUTHOR(S)
61 /* Wietse Venema
62 /* IBM T.J. Watson Research
63 /* P.O. Box 704
64 /* Yorktown Heights, NY 10598, USA
65 /*--*/
67 /* System library. */
69 #include "sys_defs.h"
70 #include <errno.h>
71 #include <unistd.h>
73 #ifdef HAS_FCNTL_LOCK
74 #include <fcntl.h>
75 #include <string.h>
76 #endif
78 #ifdef HAS_FLOCK_LOCK
79 #include <sys/file.h>
80 #endif
82 /* Utility library. */
84 #include "msg.h"
85 #include "myflock.h"
87 /* myflock - lock/unlock entire open file */
89 int myflock(int fd, int lock_style, int operation)
91 int status;
94 * Sanity check.
96 if ((operation & (MYFLOCK_OP_BITS)) != operation)
97 msg_panic("myflock: improper operation type: 0x%x", operation);
99 switch (lock_style) {
102 * flock() does exactly what we need. Too bad it is not standard.
104 #ifdef HAS_FLOCK_LOCK
105 case MYFLOCK_STYLE_FLOCK:
107 static int lock_ops[] = {
108 LOCK_UN, LOCK_SH, LOCK_EX, -1,
109 -1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
112 while ((status = flock(fd, lock_ops[operation])) < 0
113 && errno == EINTR)
114 sleep(1);
115 break;
117 #endif
120 * fcntl() is standard and does more than we need, but we can handle
121 * it.
123 #ifdef HAS_FCNTL_LOCK
124 case MYFLOCK_STYLE_FCNTL:
126 struct flock lock;
127 int request;
128 static int lock_ops[] = {
129 F_UNLCK, F_RDLCK, F_WRLCK
132 memset((char *) &lock, 0, sizeof(lock));
133 lock.l_type = lock_ops[operation & ~MYFLOCK_OP_NOWAIT];
134 request = (operation & MYFLOCK_OP_NOWAIT) ? F_SETLK : F_SETLKW;
135 while ((status = fcntl(fd, request, &lock)) < 0
136 && errno == EINTR)
137 sleep(1);
138 break;
140 #endif
141 default:
142 msg_panic("myflock: unsupported lock style: 0x%x", lock_style);
146 * Return a consistent result. Some systems return EACCES when a lock is
147 * taken by someone else, and that would complicate error processing.
149 if (status < 0 && (operation & MYFLOCK_OP_NOWAIT) != 0)
150 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EACCES)
151 errno = EAGAIN;
153 return (status);