pidfile.c revision 169468
1149423Spjd/*- 2149423Spjd * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3149423Spjd * All rights reserved. 4149423Spjd * 5149423Spjd * Redistribution and use in source and binary forms, with or without 6149423Spjd * modification, are permitted provided that the following conditions 7149423Spjd * are met: 8149423Spjd * 1. Redistributions of source code must retain the above copyright 9149423Spjd * notice, this list of conditions and the following disclaimer. 10149423Spjd * 2. Redistributions in binary form must reproduce the above copyright 11149423Spjd * notice, this list of conditions and the following disclaimer in the 12149423Spjd * documentation and/or other materials provided with the distribution. 13149423Spjd * 14149423Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15149423Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16149423Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17149423Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18149423Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19149423Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20149423Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21149423Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22149423Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23149423Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24149423Spjd * SUCH DAMAGE. 25149423Spjd */ 26149423Spjd 27149423Spjd#include <sys/cdefs.h> 28149423Spjd__FBSDID("$FreeBSD: head/lib/libutil/pidfile.c 169468 2007-05-11 11:10:05Z des $"); 29149423Spjd 30149423Spjd#include <sys/param.h> 31149423Spjd#include <sys/file.h> 32149423Spjd#include <sys/stat.h> 33149423Spjd 34149423Spjd#include <stdio.h> 35149423Spjd#include <stdlib.h> 36149423Spjd#include <unistd.h> 37149423Spjd#include <fcntl.h> 38149423Spjd#include <string.h> 39149423Spjd#include <err.h> 40149423Spjd#include <errno.h> 41149423Spjd#include <libutil.h> 42149423Spjd 43149423Spjdstatic int _pidfile_remove(struct pidfh *pfh, int freeit); 44149423Spjd 45149423Spjdstatic int 46149423Spjdpidfile_verify(struct pidfh *pfh) 47149423Spjd{ 48149423Spjd struct stat sb; 49149423Spjd 50149423Spjd if (pfh == NULL || pfh->pf_fd == -1) 51149423Spjd return (EDOOFUS); 52149423Spjd /* 53149423Spjd * Check remembered descriptor. 54149423Spjd */ 55149423Spjd if (fstat(pfh->pf_fd, &sb) == -1) 56149423Spjd return (errno); 57149423Spjd if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) 58149423Spjd return (EDOOFUS); 59149423Spjd return (0); 60149423Spjd} 61149423Spjd 62149423Spjdstatic int 63149423Spjdpidfile_read(const char *path, pid_t *pidptr) 64149423Spjd{ 65149423Spjd char buf[16], *endptr; 66149423Spjd int error, fd, i; 67149423Spjd 68149423Spjd fd = open(path, O_RDONLY); 69149423Spjd if (fd == -1) 70149423Spjd return (errno); 71149423Spjd 72149423Spjd i = read(fd, buf, sizeof(buf) - 1); 73149423Spjd error = errno; /* Remember errno in case close() wants to change it. */ 74149423Spjd close(fd); 75149423Spjd if (i == -1) 76149423Spjd return (error); 77149423Spjd buf[i] = '\0'; 78149423Spjd 79149423Spjd *pidptr = strtol(buf, &endptr, 10); 80149423Spjd if (endptr != &buf[i]) 81149423Spjd return (EINVAL); 82149423Spjd 83149423Spjd return (0); 84149423Spjd} 85149423Spjd 86149423Spjdstruct pidfh * 87149423Spjdpidfile_open(const char *path, mode_t mode, pid_t *pidptr) 88149423Spjd{ 89149423Spjd struct pidfh *pfh; 90149423Spjd struct stat sb; 91169468Sdes int error, fd, len; 92149423Spjd 93149423Spjd pfh = malloc(sizeof(*pfh)); 94149423Spjd if (pfh == NULL) 95149423Spjd return (NULL); 96149423Spjd 97169468Sdes if (path == NULL) 98169468Sdes len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), 99169468Sdes "/var/run/%s.pid", getprogname()); 100169468Sdes else 101169468Sdes len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), 102169468Sdes "%s", path); 103169468Sdes if (len >= (int)sizeof(pfh->pf_path)) { 104149423Spjd free(pfh); 105149423Spjd errno = ENAMETOOLONG; 106149423Spjd return (NULL); 107149423Spjd } 108149423Spjd 109149423Spjd /* 110149423Spjd * Open the PID file and obtain exclusive lock. 111149423Spjd * We truncate PID file here only to remove old PID immediatelly, 112149423Spjd * PID file will be truncated again in pidfile_write(), so 113149423Spjd * pidfile_write() can be called multiple times. 114149423Spjd */ 115169448Sdes fd = flopen(pfh->pf_path, 116169448Sdes O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); 117149423Spjd if (fd == -1) { 118149423Spjd if (errno == EWOULDBLOCK && pidptr != NULL) { 119149423Spjd errno = pidfile_read(pfh->pf_path, pidptr); 120149423Spjd if (errno == 0) 121149423Spjd errno = EEXIST; 122149423Spjd } 123149423Spjd free(pfh); 124149423Spjd return (NULL); 125149423Spjd } 126149423Spjd /* 127149423Spjd * Remember file information, so in pidfile_write() we are sure we write 128149423Spjd * to the proper descriptor. 129149423Spjd */ 130149423Spjd if (fstat(fd, &sb) == -1) { 131149423Spjd error = errno; 132149423Spjd unlink(pfh->pf_path); 133149423Spjd close(fd); 134149423Spjd free(pfh); 135149423Spjd errno = error; 136149423Spjd return (NULL); 137149423Spjd } 138149423Spjd 139149423Spjd pfh->pf_fd = fd; 140149423Spjd pfh->pf_dev = sb.st_dev; 141149423Spjd pfh->pf_ino = sb.st_ino; 142149423Spjd 143149423Spjd return (pfh); 144149423Spjd} 145149423Spjd 146149423Spjdint 147149423Spjdpidfile_write(struct pidfh *pfh) 148149423Spjd{ 149149423Spjd char pidstr[16]; 150149423Spjd int error, fd; 151149423Spjd 152149423Spjd /* 153149423Spjd * Check remembered descriptor, so we don't overwrite some other 154149423Spjd * file if pidfile was closed and descriptor reused. 155149423Spjd */ 156149423Spjd errno = pidfile_verify(pfh); 157149423Spjd if (errno != 0) { 158149423Spjd /* 159149423Spjd * Don't close descriptor, because we are not sure if it's ours. 160149423Spjd */ 161149423Spjd return (-1); 162149423Spjd } 163149423Spjd fd = pfh->pf_fd; 164149423Spjd 165149423Spjd /* 166149423Spjd * Truncate PID file, so multiple calls of pidfile_write() are allowed. 167149423Spjd */ 168149423Spjd if (ftruncate(fd, 0) == -1) { 169149423Spjd error = errno; 170149423Spjd _pidfile_remove(pfh, 0); 171149423Spjd errno = error; 172149423Spjd return (-1); 173149423Spjd } 174149423Spjd 175149423Spjd snprintf(pidstr, sizeof(pidstr), "%u", getpid()); 176157671Sjmg if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { 177149423Spjd error = errno; 178149423Spjd _pidfile_remove(pfh, 0); 179149423Spjd errno = error; 180149423Spjd return (-1); 181149423Spjd } 182149423Spjd 183149423Spjd return (0); 184149423Spjd} 185149423Spjd 186149423Spjdint 187149423Spjdpidfile_close(struct pidfh *pfh) 188149423Spjd{ 189149423Spjd int error; 190149423Spjd 191149423Spjd error = pidfile_verify(pfh); 192149423Spjd if (error != 0) { 193149423Spjd errno = error; 194149423Spjd return (-1); 195149423Spjd } 196149423Spjd 197149423Spjd if (close(pfh->pf_fd) == -1) 198149423Spjd error = errno; 199149423Spjd free(pfh); 200149423Spjd if (error != 0) { 201149423Spjd errno = error; 202149423Spjd return (-1); 203149423Spjd } 204149423Spjd return (0); 205149423Spjd} 206149423Spjd 207149423Spjdstatic int 208149423Spjd_pidfile_remove(struct pidfh *pfh, int freeit) 209149423Spjd{ 210149423Spjd int error; 211149423Spjd 212149423Spjd error = pidfile_verify(pfh); 213149423Spjd if (error != 0) { 214149423Spjd errno = error; 215149423Spjd return (-1); 216149423Spjd } 217149423Spjd 218149423Spjd if (unlink(pfh->pf_path) == -1) 219149423Spjd error = errno; 220149423Spjd if (flock(pfh->pf_fd, LOCK_UN) == -1) { 221149423Spjd if (error == 0) 222149423Spjd error = errno; 223149423Spjd } 224149423Spjd if (close(pfh->pf_fd) == -1) { 225149423Spjd if (error == 0) 226149423Spjd error = errno; 227149423Spjd } 228149423Spjd if (freeit) 229149423Spjd free(pfh); 230149423Spjd else 231149423Spjd pfh->pf_fd = -1; 232149423Spjd if (error != 0) { 233149423Spjd errno = error; 234149423Spjd return (-1); 235149423Spjd } 236149423Spjd return (0); 237149423Spjd} 238149423Spjd 239149423Spjdint 240149423Spjdpidfile_remove(struct pidfh *pfh) 241149423Spjd{ 242149423Spjd 243149423Spjd return (_pidfile_remove(pfh, 1)); 244149423Spjd} 245