From 411b7c87536a8639954bf1eb6876209abfb4e848 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 31 Jul 2017 15:11:33 +1000 Subject: [PATCH] util: New functions pidfile_path_create(), pidfile_fd_close() Uses the core of CTDB's create_pidfile_context() for pidfile_path_create(). pidfile_fd_close() is a subset of CTDB's pidfile_context_destructor(). Signed-off-by: Martin Schwenke Reviewed-by: Volker Lendecke --- lib/util/pidfile.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ lib/util/pidfile.h | 3 ++ 2 files changed, 102 insertions(+) diff --git a/lib/util/pidfile.c b/lib/util/pidfile.c index ede146f560e8..2be61966e26d 100644 --- a/lib/util/pidfile.c +++ b/lib/util/pidfile.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. pidfile handling Copyright (C) Andrew Tridgell 1998 + Copyright (C) Amitay Isaccs 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +32,104 @@ * @brief Pid file handling */ +int pidfile_path_create(const char *path, int *outfd) +{ + struct flock lck; + char tmp[64] = { 0 }; + pid_t pid; + int fd, ret = 0; + int len; + ssize_t nwritten; + + pid = getpid(); + + fd = open(path, O_CREAT|O_WRONLY|O_NONBLOCK, 0644); + if (fd == -1) { + return errno; + } + + if (! set_close_on_exec(fd)) { + close(fd); + return EIO; + } + + lck = (struct flock) { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + }; + + do { + ret = fcntl(fd, F_SETLK, &lck); + } while ((ret == -1) && (errno == EINTR)); + + if (ret != 0) { + ret = errno; + close(fd); + return ret; + } + + /* + * PID file is locked by us so from here on we should unlink + * on failure + */ + + do { + ret = ftruncate(fd, 0); + } while ((ret == -1) && (errno == EINTR)); + + if (ret == -1) { + ret = EIO; + goto fail_unlink; + } + + len = snprintf(tmp, sizeof(tmp), "%u\n", pid); + if (len < 0) { + ret = errno; + goto fail_unlink; + } + if (len >= sizeof(tmp)) { + ret = ENOSPC; + goto fail_unlink; + } + + do { + nwritten = write(fd, tmp, len); + } while ((nwritten == -1) && (errno == EINTR)); + + if ((nwritten == -1) || (nwritten != len)) { + ret = EIO; + goto fail_unlink; + } + + if (outfd != NULL) { + *outfd = fd; + } + return 0; + +fail_unlink: + unlink(path); + close(fd); + return ret; +} + +void pidfile_fd_close(int fd) +{ + struct flock lck = { + .l_type = F_UNLCK, + .l_whence = SEEK_SET, + }; + int ret; + + do { + ret = fcntl(fd, F_SETLK, &lck); + } while ((ret == -1) && (errno == EINTR)); + + do { + ret = close(fd); + } while ((ret == -1) && (errno == EINTR)); +} + + /** * return the pid in a pidfile. return 0 if the process (or pidfile) * does not exist diff --git a/lib/util/pidfile.h b/lib/util/pidfile.h index d504f526a5ce..d51161afc391 100644 --- a/lib/util/pidfile.h +++ b/lib/util/pidfile.h @@ -20,6 +20,9 @@ #ifndef _SAMBA_PIDFILE_H_ #define _SAMBA_PIDFILE_H_ +int pidfile_path_create(const char *path, int *outfd); +void pidfile_fd_close(int fd); + pid_t pidfile_pid(const char *piddir, const char *name); void pidfile_create(const char *piddir, const char *program_name); void pidfile_unlink(const char *piddir, const char *program_name);