7 /* dotlock file management
9 /* #include <dot_lockfile.h>
11 /* int dot_lockfile(path, why)
15 /* void dot_unlockfile(path)
18 /* dot_lockfile() constructs a lock file name by appending ".lock" to
19 /* \fIpath\fR and creates the named file exclusively. It tries several
20 /* times and attempts to break stale locks. A negative result value
21 /* means no lock file could be created.
23 /* dot_unlockfile() attempts to remove the lock file created by
24 /* dot_lockfile(). The operation always succeeds, and therefore
25 /* it preserves the errno value.
29 /* Name of the file to be locked or unlocked.
31 /* A null pointer, or storage for the reason why a lock file could
34 /* dot_lockfile() returns 0 upon success. In case of failure, the
35 /* result is -1, and the errno variable is set appropriately:
36 /* EEXIST when a "fresh" lock file already exists; other values as
38 /* CONFIGURATION PARAMETERS
39 /* deliver_lock_attempts, how many times to try to create a lock
40 /* deliver_lock_delay, how long to wait between attempts
41 /* stale_lock_time, when to break a stale lock
45 /* The Secure Mailer license must be distributed with this software.
48 /* IBM T.J. Watson Research
50 /* Yorktown Heights, NY 10598, USA
63 /* Utility library. */
66 #include <stringops.h>
72 #include "mail_params.h"
73 #include "dot_lockfile.h"
75 /* Application-specific. */
77 #define MILLION 1000000
79 /* dot_lockfile - create user.lock file */
81 int dot_lockfile(const char *path
, VSTRING
*why
)
89 lock_file
= concatenate(path
, ".lock", (char *) 0);
91 for (count
= 1; /* void */ ; count
++) {
94 * Attempt to create the lock. This code relies on O_EXCL | O_CREAT
95 * to not follow symlinks. With NFS file systems this operation can
96 * at the same time succeed and fail with errno of EEXIST.
98 if ((fd
= open(lock_file
, O_WRONLY
| O_EXCL
| O_CREAT
, 0)) >= 0) {
103 if (count
>= var_flock_tries
)
107 * We can deal only with "file exists" errors. Any other error means
108 * we better give up trying.
114 * Break the lock when it is too old. Give up when we are unable to
115 * remove a stale lock.
117 if (stat(lock_file
, &st
) == 0)
118 if (time((time_t *) 0) > st
.st_ctime
+ var_flock_stale
)
119 if (unlink(lock_file
) < 0)
123 rand_sleep(var_flock_delay
* MILLION
, var_flock_delay
* MILLION
/ 2);
126 vstring_sprintf(why
, "unable to create lock file %s: %m", lock_file
);
132 /* dot_unlockfile - remove .lock file */
134 void dot_unlockfile(const char *path
)
137 int saved_errno
= errno
;
139 lock_file
= concatenate(path
, ".lock", (char *) 0);
140 (void) unlink(lock_file
);
148 * Test program for setting a .lock file.
150 * Usage: dot_lockfile filename
152 * Creates filename.lock and removes it.
156 #include <msg_vstream.h>
157 #include <mail_conf.h>
159 int main(int argc
, char **argv
)
161 VSTRING
*why
= vstring_alloc(100);
163 msg_vstream_init(argv
[0], VSTREAM_ERR
);
165 msg_fatal("usage: %s file-to-be-locked", argv
[0]);
167 if (dot_lockfile(argv
[1], why
) < 0)
168 msg_fatal("%s", vstring_str(why
));
169 dot_unlockfile(argv
[1]);