pidfile.c revision 157671
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 157671 2006-04-11 23:10:02Z jmg $"); 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 int fd; 50149423Spjd 51149423Spjd if (pfh == NULL || pfh->pf_fd == -1) 52149423Spjd return (EDOOFUS); 53149423Spjd /* 54149423Spjd * Check remembered descriptor. 55149423Spjd */ 56149423Spjd if (fstat(pfh->pf_fd, &sb) == -1) 57149423Spjd return (errno); 58149423Spjd if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) 59149423Spjd return (EDOOFUS); 60149423Spjd return (0); 61149423Spjd} 62149423Spjd 63149423Spjdstatic int 64149423Spjdpidfile_read(const char *path, pid_t *pidptr) 65149423Spjd{ 66149423Spjd char buf[16], *endptr; 67149423Spjd int error, fd, i; 68149423Spjd 69149423Spjd fd = open(path, O_RDONLY); 70149423Spjd if (fd == -1) 71149423Spjd return (errno); 72149423Spjd 73149423Spjd i = read(fd, buf, sizeof(buf) - 1); 74149423Spjd error = errno; /* Remember errno in case close() wants to change it. */ 75149423Spjd close(fd); 76149423Spjd if (i == -1) 77149423Spjd return (error); 78149423Spjd buf[i] = '\0'; 79149423Spjd 80149423Spjd *pidptr = strtol(buf, &endptr, 10); 81149423Spjd if (endptr != &buf[i]) 82149423Spjd return (EINVAL); 83149423Spjd 84149423Spjd return (0); 85149423Spjd} 86149423Spjd 87149423Spjdstruct pidfh * 88149423Spjdpidfile_open(const char *path, mode_t mode, pid_t *pidptr) 89149423Spjd{ 90149423Spjd struct pidfh *pfh; 91149423Spjd struct stat sb; 92149423Spjd int error, fd; 93149423Spjd 94149423Spjd pfh = malloc(sizeof(*pfh)); 95149423Spjd if (pfh == NULL) 96149423Spjd return (NULL); 97149423Spjd 98149423Spjd if (path == NULL) { 99149423Spjd snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid", 100149423Spjd getprogname()); 101149423Spjd } else { 102149423Spjd strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path)); 103149423Spjd } 104149423Spjd if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) { 105149423Spjd free(pfh); 106149423Spjd errno = ENAMETOOLONG; 107149423Spjd return (NULL); 108149423Spjd } 109149423Spjd 110149423Spjd /* 111149423Spjd * Open the PID file and obtain exclusive lock. 112149423Spjd * We truncate PID file here only to remove old PID immediatelly, 113149423Spjd * PID file will be truncated again in pidfile_write(), so 114149423Spjd * pidfile_write() can be called multiple times. 115149423Spjd */ 116149423Spjd fd = open(pfh->pf_path, 117149423Spjd O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode); 118149423Spjd if (fd == -1) { 119149423Spjd if (errno == EWOULDBLOCK && pidptr != NULL) { 120149423Spjd errno = pidfile_read(pfh->pf_path, pidptr); 121149423Spjd if (errno == 0) 122149423Spjd errno = EEXIST; 123149423Spjd } 124149423Spjd free(pfh); 125149423Spjd return (NULL); 126149423Spjd } 127149423Spjd /* 128149423Spjd * Remember file information, so in pidfile_write() we are sure we write 129149423Spjd * to the proper descriptor. 130149423Spjd */ 131149423Spjd if (fstat(fd, &sb) == -1) { 132149423Spjd error = errno; 133149423Spjd unlink(pfh->pf_path); 134149423Spjd close(fd); 135149423Spjd free(pfh); 136149423Spjd errno = error; 137149423Spjd return (NULL); 138149423Spjd } 139149423Spjd 140149423Spjd pfh->pf_fd = fd; 141149423Spjd pfh->pf_dev = sb.st_dev; 142149423Spjd pfh->pf_ino = sb.st_ino; 143149423Spjd 144149423Spjd return (pfh); 145149423Spjd} 146149423Spjd 147149423Spjdint 148149423Spjdpidfile_write(struct pidfh *pfh) 149149423Spjd{ 150149423Spjd struct stat sb; 151149423Spjd char pidstr[16]; 152149423Spjd int error, fd; 153149423Spjd 154149423Spjd /* 155149423Spjd * Check remembered descriptor, so we don't overwrite some other 156149423Spjd * file if pidfile was closed and descriptor reused. 157149423Spjd */ 158149423Spjd errno = pidfile_verify(pfh); 159149423Spjd if (errno != 0) { 160149423Spjd /* 161149423Spjd * Don't close descriptor, because we are not sure if it's ours. 162149423Spjd */ 163149423Spjd return (-1); 164149423Spjd } 165149423Spjd fd = pfh->pf_fd; 166149423Spjd 167149423Spjd /* 168149423Spjd * Truncate PID file, so multiple calls of pidfile_write() are allowed. 169149423Spjd */ 170149423Spjd if (ftruncate(fd, 0) == -1) { 171149423Spjd error = errno; 172149423Spjd _pidfile_remove(pfh, 0); 173149423Spjd errno = error; 174149423Spjd return (-1); 175149423Spjd } 176149423Spjd 177149423Spjd snprintf(pidstr, sizeof(pidstr), "%u", getpid()); 178157671Sjmg if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { 179149423Spjd error = errno; 180149423Spjd _pidfile_remove(pfh, 0); 181149423Spjd errno = error; 182149423Spjd return (-1); 183149423Spjd } 184149423Spjd 185149423Spjd return (0); 186149423Spjd} 187149423Spjd 188149423Spjdint 189149423Spjdpidfile_close(struct pidfh *pfh) 190149423Spjd{ 191149423Spjd int error; 192149423Spjd 193149423Spjd error = pidfile_verify(pfh); 194149423Spjd if (error != 0) { 195149423Spjd errno = error; 196149423Spjd return (-1); 197149423Spjd } 198149423Spjd 199149423Spjd if (close(pfh->pf_fd) == -1) 200149423Spjd error = errno; 201149423Spjd free(pfh); 202149423Spjd if (error != 0) { 203149423Spjd errno = error; 204149423Spjd return (-1); 205149423Spjd } 206149423Spjd return (0); 207149423Spjd} 208149423Spjd 209149423Spjdstatic int 210149423Spjd_pidfile_remove(struct pidfh *pfh, int freeit) 211149423Spjd{ 212149423Spjd int error; 213149423Spjd 214149423Spjd error = pidfile_verify(pfh); 215149423Spjd if (error != 0) { 216149423Spjd errno = error; 217149423Spjd return (-1); 218149423Spjd } 219149423Spjd 220149423Spjd if (unlink(pfh->pf_path) == -1) 221149423Spjd error = errno; 222149423Spjd if (flock(pfh->pf_fd, LOCK_UN) == -1) { 223149423Spjd if (error == 0) 224149423Spjd error = errno; 225149423Spjd } 226149423Spjd if (close(pfh->pf_fd) == -1) { 227149423Spjd if (error == 0) 228149423Spjd error = errno; 229149423Spjd } 230149423Spjd if (freeit) 231149423Spjd free(pfh); 232149423Spjd else 233149423Spjd pfh->pf_fd = -1; 234149423Spjd if (error != 0) { 235149423Spjd errno = error; 236149423Spjd return (-1); 237149423Spjd } 238149423Spjd return (0); 239149423Spjd} 240149423Spjd 241149423Spjdint 242149423Spjdpidfile_remove(struct pidfh *pfh) 243149423Spjd{ 244149423Spjd 245149423Spjd return (_pidfile_remove(pfh, 1)); 246149423Spjd} 247