From c35f713ae46fef0bf5d5dbab434c2f581e1d1181 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Dec 2003 23:20:10 +0000 Subject: many more stuff git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@5 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- src/lock.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/lock.c (limited to 'src/lock.c') diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..48c409f --- /dev/null +++ b/src/lock.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lock.h" + +/* Where do lockfiles reside? */ +#define LOCK_PATH "/var/lock" + +static const char *lockfile(const char *dev) { + static char lockfile[PATH_MAX]; + snprintf(lockfile, sizeof(lockfile), "%s/LCK..%s", LOCK_PATH, basename(dev)); + return lockfile; +} + +static const char *tempfile(const char *path) { + static char t[PATH_MAX]; + snprintf(t, sizeof(t), "%s.tmp.%lu", path, (unsigned long) getpid()); + return t; +} + +int device_lock(const char *dev) { + struct stat st; + int fd; + char *path, *temp; + char buf[100]; + + if (stat(LOCK_PATH, &st) != 0 || !S_ISDIR(st.st_mode)) { + daemon_log(LOG_ERR, "Failed to lock device, directory "LOCK_PATH" not existent."); + return -1; + } + + path = lockfile(dev); + temp = tempfile(path); + + for (;;) { + + if ((fd = open(path, O_RDONLY)) < 0) { + if (errno != ENOENT) { + daemon_log(LOG_ERR, "Failed to open lock file: %s", strerror(errno)); + return -1; + } + } + + if (fd >= 0) { + ssize_t n; + + n = loop_read(fd, buf, sizeof(buf) - 1); + close(fd); + + if (n < 0) { + close(fd) + daemon_log(LOG_ERR, "Failed to read from lock file: %s", strerror(errno)); + return -1; + } + + if (n > 0) { + pid_t pid; + + if (n == 4) + pid = (pid_t) *((uint32_t*) buf); + else { + buf[n] = 0; + sscanf(buf, "%lu", &pid); + } + + if (pid > 0) { + if (kill(pid, 0) < 0 && errno == ESRCH) { + daemon_log(LOG_WARN, "Lockfile is stale. Overriding it."); + /* Yes, here is a race condition */ + unlink(path); + } else + return 1; + } + } + } + + if ((fd = open(temp, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) { + daemon_log(LOG_ERR, "Failed to create temporary lock file: %s", strerror(errno)); + return -1; + } + + snprintf(buf, sizeof(buf), "%10lu %s %.20s\n", (unsigned long) getpid(), appname, username); + if (loop_write(fd, buf, strlen(buf)) < 0) { + daemon_log(LOG_ERR, "Failed to write to temporary lock file: %s", sterror(errno)); + close(fd); + return -1; + } + + close(fd); + + if (link(temp, path) < 0) { + if (errno == EEXIST) + continue; + + daemon_log(LOG_ERR, "Failed to link temporary lock file: %s", strerror(errno)); + } + + + return 0; + } +} + +int device_unlock(const char *dev) { + + if (unlink(lockfile(dev)) < 0) { + daemon_log(LOG_ERR, "Failed to remove lock file: %s", strerror(errno)); + return -1; + } + + return 0; +} -- cgit