util: New functions pidfile_path_create(), pidfile_fd_close()
authorMartin Schwenke <martin@meltin.net>
Mon, 31 Jul 2017 05:11:33 +0000 (15:11 +1000)
committerMartin Schwenke <martins@samba.org>
Wed, 2 Aug 2017 01:39:11 +0000 (03:39 +0200)
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 <martin@meltin.net>
Reviewed-by: Volker Lendecke <vl@samba.org>
lib/util/pidfile.c
lib/util/pidfile.h

index ede146f560e8142b05c83e34fb3170ccbb6db742..2be61966e26d5e0d10c2cedc7af5648a8a130073 100644 (file)
@@ -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
  * @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
index d504f526a5cee2aa11a0f33e2443ee2630e9e102..d51161afc391136b5de3a3a3db36ed86d5ff5461 100644 (file)
@@ -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);