aboutsummaryrefslogtreecommitdiff
path: root/src/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lock.c')
-rw-r--r--src/lock.c275
1 files changed, 0 insertions, 275 deletions
diff --git a/src/lock.c b/src/lock.c
deleted file mode 100644
index f2ed532..0000000
--- a/src/lock.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* wydawca - automatic release submission daemon
- Copyright (C) 2007, 2009-2013, 2017, 2019-2020 Sergey Poznyakoff
-
- Wydawca is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
-
- Wydawca is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with wydawca. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "wydawca.h"
-
-int enable_locking = 1;
-char *lockdir;
-time_t lock_expire_time = 5 * 60;
-time_t lock_timeout = 60;
-
-#define LOCKFILE_MODE 0644
-
-static int
-stat_check(const char *file, int fd, int links)
-{
- struct stat fn_stat;
- struct stat fd_stat;
- int err = 0;
- int localfd = -1;
-
- if (fd == -1) {
- localfd = open(file, O_RDONLY);
-
- if (localfd == -1)
- return errno;
- fd = localfd;
- }
-
- /* We should always be able to stat a valid fd, so this
- is an error condition. */
- if (lstat(file, &fn_stat) || fstat(fd, &fd_stat))
- err = errno;
- else {
- /* If the link and stat don't report the same info, or the
- file is a symlink, fail the locking. */
-#define CHK(X) if(X) err = EINVAL
-
- CHK(!S_ISREG(fn_stat.st_mode));
- CHK(!S_ISREG(fd_stat.st_mode));
- CHK(fn_stat.st_nlink != links);
- CHK(fn_stat.st_dev != fd_stat.st_dev);
- CHK(fn_stat.st_ino != fd_stat.st_ino);
- CHK(fn_stat.st_mode != fd_stat.st_mode);
- CHK(fn_stat.st_nlink != fd_stat.st_nlink);
- CHK(fn_stat.st_uid != fd_stat.st_uid);
- CHK(fn_stat.st_gid != fd_stat.st_gid);
- CHK(fn_stat.st_rdev != fd_stat.st_rdev);
-
-#undef CHK
- }
- if (localfd != -1)
- close(localfd);
-
- return err;
-}
-
-int
-_lock_internal(const char *file, const char *fname)
-{
- int err = 0;
- int fd;
- FILE *fp;
-
- fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_MODE);
- if (fd == -1) {
- if (errno == EEXIST)
- return LOCK_RETRY;
- else {
- wy_log(LOG_ERR, _("cannot create lock file %s: %s"),
- fname, strerror(errno));
- return LOCK_FAILURE;
- }
- }
- close(fd);
-
- /* Try to link to the lockfile. */
- if (link(fname, file) == -1) {
- unlink(fname);
- if (errno == EEXIST)
- return LOCK_RETRY;
- else {
- wy_log(LOG_ERR, _("cannot create lock file %s: %s"),
- file, strerror(errno));
- return LOCK_FAILURE;
- }
- }
-
- if ((fd = open(file, O_RDWR)) == -1) {
- unlink(fname);
- wy_log(LOG_ERR, _("cannot open lock file %s: %s"),
- fname, strerror(errno));
- return LOCK_FAILURE;
- }
-
- err = stat_check(fname, fd, 2);
- if (err) {
- unlink(fname);
- wy_log(LOG_ERR, _("lock file check failed: %s"), strerror(errno));
- return (err == EINVAL) ? LOCK_INVALID : LOCK_FAILURE;
- }
-
- unlink(fname);
-
- fp = fdopen(fd, "w");
- fprintf(fp, "%lu", (unsigned long) getpid());
- fclose(fp);
-
- return 0;
-}
-
-static void
-expire_stale_lock(const char *file)
-{
- int stale = 0;
- char buf[80];
- int fd;
- int len;
-
- fd = open(file, O_RDONLY);
- if (fd == -1)
- return;
-
- len = read(fd, buf, sizeof(buf) - 1);
- if (len > 0) {
- pid_t pid;
-
- buf[len] = 0;
- pid = strtoul(buf, NULL, 10);
- if (pid > 0) {
- /* Process is gone so we try to remove the lock. */
- if (kill(pid, 0) == -1)
- stale = 1;
- } else
- stale = 1; /* Corrupted file, remove the lock. */
- }
-
- if (!stale && lock_expire_time > 0) {
- struct stat stbuf;
- fstat(fd, &stbuf);
- /* The lock has expired. */
- if ((time(NULL) - stbuf.st_mtime) > lock_expire_time)
- stale = 1;
- }
-
- close(fd);
- if (stale)
- unlink(file);
-}
-
-static char *
-host_name()
-{
- static char *hostbuf = NULL;
- size_t size = 0;
- int rc;
-
- if (hostbuf)
- return hostbuf;
-
- do {
- if (!hostbuf) {
- size = 256;
- hostbuf = grecs_malloc(size);
- } else {
- size_t ns = size * 2;
- if (size < ns)
- grecs_alloc_die();
- size = ns;
- hostbuf = grecs_realloc(hostbuf, size);
- }
- }
- while ((rc = gethostname(hostbuf, size)) == -1
- && (errno == EINVAL
-#ifdef ENAMETOOLONG
- || errno == ENAMETOOLONG
-#endif
- ));
- if (rc) {
- wy_log(LOG_ERR, _("cannot get hostname: %s"), strerror(rc));
- exit(EX_SOFTWARE);
- }
- return hostbuf;
-}
-
-int
-wydawca_lock(const char *lockname)
-{
- char *tempname = NULL;
- size_t size = 0;
- int rc;
-
- if (!enable_locking)
- return 0;
- expire_stale_lock(lockname);
-
- /* build the NFS hitching-post to the lock file */
- grecs_asprintf(&tempname, &size, "%s.%lu.%lu.%s",
- lockname,
- (unsigned long) getpid(),
- (unsigned long) time(NULL), host_name());
- if (!tempname)
- return LOCK_FAILURE;
- if (lock_timeout) {
- time_t start = time(NULL);
-
- do {
- rc = _lock_internal(lockname, tempname);
- if (rc == LOCK_RETRY)
- sleep(1);
- else
- break;
- }
- while (time(NULL) - start < lock_timeout);
- } else
- rc = _lock_internal(lockname, tempname);
-
- free(tempname);
- return rc;
-}
-
-void
-wydawca_unlock(const char *lockfile)
-{
- if (enable_locking)
- unlink(lockfile);
-}
-
-static char *
-fix_tagname(const char *tag)
-{
- char *tagname = grecs_strdup(tag);
- char *p;
-
- for (p = tagname; *p; p++)
- if (!isalnum(*p) && *p != '_' && *p != '-')
- *p = '_';
- return tagname;
-}
-
-char *
-wydawca_lockname(const char *tag)
-{
- char *lockname = NULL;
- size_t size = 0;
- char *tagname = fix_tagname(tag);
- grecs_asprintf(&lockname, &size, "%s/LCK.%s", lockdir, tagname);
- if (!lockname)
- grecs_alloc_die();
- free(tagname);
- return lockname;
-}
-
-void
-wydawca_lock_init()
-{
- if (enable_locking) {
- if (!lockdir)
- lockdir = grecs_strdup(LOCALSTATEDIR "/lock/" PACKAGE);
- if (create_hierarchy(AT_FDCWD, lockdir))
- exit(EX_OSFILE);
- }
-}

Return to:

Send suggestions and report system problems to the System administrator.