1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/*++
/* NAME
/* dot_lockfile 3
/* SUMMARY
/* dotlock file management
/* SYNOPSIS
/* #include <dot_lockfile.h>
/*
/* int dot_lockfile(path, why)
/* const char *path;
/* VSTRING *why;
/*
/* void dot_unlockfile(path)
/* const char *path;
/* DESCRIPTION
/* dot_lockfile() constructs a lock file name by appending ".lock" to
/* \fIpath\fR and creates the named file exclusively. It tries several
/* times and attempts to break stale locks. A negative result value
/* means no lock file could be created.
/*
/* dot_unlockfile() attempts to remove the lock file created by
/* dot_lockfile().
/*
/* Arguments:
/* .IP path
/* Name of the file to be locked or unlocked.
/* .IP why
/* A null pointer, or storage for the reason why a lock file could
/* not be created.
/* CONFIGURATION PARAMETERS
/* deliver_lock_attempts, how many times to try to create a lock
/* deliver_lock_delay, how long to wait between attempts
/* stale_lock_time, when to break a stale lock
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include "sys_defs.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
/* Utility library. */
#include <vstring.h>
#include <stringops.h>
#include <mymalloc.h>
/* Global library. */
#include "mail_params.h"
#include "dot_lockfile.h"
/* dot_lockfile - create user.lock file */
int dot_lockfile(const char *path, VSTRING *why)
{
char *lock_file;
int count;
struct stat st;
int fd;
int status = -1;
lock_file = concatenate(path, ".lock", (char *) 0);
for (count = 0; /* void */ ; count++) {
if (count >= var_flock_tries)
break;
if (count > 0)
sleep(var_flock_delay);
/*
* Attempt to create the lock. This code relies on O_EXCL | O_CREAT
* to not follow symlinks.
*/
if ((fd = open(lock_file, O_WRONLY | O_EXCL | O_CREAT, 0)) >= 0) {
close(fd);
status = 0;
break;
}
/*
* We can deal only with "file exists" errors. Any other error means
* we better give up trying.
*/
if (errno != EEXIST)
break;
/*
* Break the lock when it is too old. Give up when we are unable to
* remove a stale lock.
*/
if (stat(lock_file, &st) == 0)
if (time((time_t *) 0) > st.st_ctime + var_flock_stale)
if (unlink(lock_file) < 0)
if (errno != ENOENT)
break;
errno = EEXIST;
}
if (status && why)
vstring_sprintf(why, "unable to create lock file %s: %m", lock_file);
myfree(lock_file);
return (status);
}
/* dot_unlockfile - remove .lock file */
void dot_unlockfile(const char *path)
{
char *lock_file;
lock_file = concatenate(path, ".lock", (char *) 0);
(void) unlink(lock_file);
myfree(lock_file);
}
#ifdef TEST
/*
* Test program for setting a .lock file.
*
* Usage: dot_lockfile filename
*
* Creates filename.lock and removes it.
*/
#include <msg.h>
#include <vstream.h>
#include <msg_vstream.h>
#include <mail_conf.h>
main(int argc, char **argv)
{
VSTRING *why = vstring_alloc(100);
msg_vstream_init(argv[0], VSTREAM_ERR);
if (argc != 2)
msg_fatal("usage: %s file-to-be-locked", argv[0]);
mail_conf_read();
if (dot_lockfile(argv[1], why) < 0)
msg_fatal("%s", vstring_str(why));
dot_unlockfile(argv[1]);
vstring_free(why);
return (0);
}
#endif
|