9 /* #include <myflock.h>
11 /* int myflock(fd, lock_style, operation)
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.
23 /* The open file to be locked/unlocked.
25 /* One of the following values:
27 /* .IP MYFLOCK_STYLE_FLOCK
28 /* Use BSD-style flock() locking.
29 /* .IP MYFLOCK_STYLE_FCNTL
30 /* Use POSIX-style fcntl() locking.
33 /* One of the following values:
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.
44 /* In addition, setting the MYFLOCK_OP_NOWAIT bit causes the
45 /* call to return immediately when the requested lock cannot
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.
59 /* The Secure Mailer license must be distributed with this software.
62 /* IBM T.J. Watson Research
64 /* Yorktown Heights, NY 10598, USA
82 /* Utility library. */
87 /* myflock - lock/unlock entire open file */
89 int myflock(int fd
, int lock_style
, int operation
)
96 if ((operation
& (MYFLOCK_OP_BITS
)) != operation
)
97 msg_panic("myflock: improper operation type: 0x%x", operation
);
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
120 * fcntl() is standard and does more than we need, but we can handle
123 #ifdef HAS_FCNTL_LOCK
124 case MYFLOCK_STYLE_FCNTL
:
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
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
)