pidfile.c (51e75198fa09e683bd79de67cb82402373a79b3d) pidfile.c (412fa8f1145545ad30922007c6cb607d7ddb1003)
1/*-
2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 22 unchanged lines hidden (view full) ---

31#include <sys/file.h>
32#include <sys/stat.h>
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <string.h>
1/*-
2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 22 unchanged lines hidden (view full) ---

31#include <sys/file.h>
32#include <sys/stat.h>
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <string.h>
39#include <time.h>
40#include <err.h>
41#include <errno.h>
42#include <libutil.h>
43
44static int _pidfile_remove(struct pidfh *pfh, int freeit);
45
46static int
47pidfile_verify(struct pidfh *pfh)
48{
49 struct stat sb;
39#include <err.h>
40#include <errno.h>
41#include <libutil.h>
42
43static int _pidfile_remove(struct pidfh *pfh, int freeit);
44
45static int
46pidfile_verify(struct pidfh *pfh)
47{
48 struct stat sb;
49 int fd;
50
51 if (pfh == NULL || pfh->pf_fd == -1)
52 return (EDOOFUS);
53 /*
54 * Check remembered descriptor.
55 */
56 if (fstat(pfh->pf_fd, &sb) == -1)
57 return (errno);

--- 12 unchanged lines hidden (view full) ---

70 if (fd == -1)
71 return (errno);
72
73 i = read(fd, buf, sizeof(buf) - 1);
74 error = errno; /* Remember errno in case close() wants to change it. */
75 close(fd);
76 if (i == -1)
77 return (error);
50
51 if (pfh == NULL || pfh->pf_fd == -1)
52 return (EDOOFUS);
53 /*
54 * Check remembered descriptor.
55 */
56 if (fstat(pfh->pf_fd, &sb) == -1)
57 return (errno);

--- 12 unchanged lines hidden (view full) ---

70 if (fd == -1)
71 return (errno);
72
73 i = read(fd, buf, sizeof(buf) - 1);
74 error = errno; /* Remember errno in case close() wants to change it. */
75 close(fd);
76 if (i == -1)
77 return (error);
78 else if (i == 0)
79 return (EAGAIN);
80 buf[i] = '\0';
81
82 *pidptr = strtol(buf, &endptr, 10);
83 if (endptr != &buf[i])
84 return (EINVAL);
85
86 return (0);
87}
88
89struct pidfh *
90pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
91{
92 struct pidfh *pfh;
93 struct stat sb;
78 buf[i] = '\0';
79
80 *pidptr = strtol(buf, &endptr, 10);
81 if (endptr != &buf[i])
82 return (EINVAL);
83
84 return (0);
85}
86
87struct pidfh *
88pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
89{
90 struct pidfh *pfh;
91 struct stat sb;
94 int error, fd, len, count;
95 struct timespec rqtp;
92 int error, fd;
96
97 pfh = malloc(sizeof(*pfh));
98 if (pfh == NULL)
99 return (NULL);
100
93
94 pfh = malloc(sizeof(*pfh));
95 if (pfh == NULL)
96 return (NULL);
97
101 if (path == NULL)
102 len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
103 "/var/run/%s.pid", getprogname());
104 else
105 len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
106 "%s", path);
107 if (len >= (int)sizeof(pfh->pf_path)) {
98 if (path == NULL) {
99 snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid",
100 getprogname());
101 } else {
102 strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path));
103 }
104 if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) {
108 free(pfh);
109 errno = ENAMETOOLONG;
110 return (NULL);
111 }
112
113 /*
114 * Open the PID file and obtain exclusive lock.
115 * We truncate PID file here only to remove old PID immediatelly,
116 * PID file will be truncated again in pidfile_write(), so
117 * pidfile_write() can be called multiple times.
118 */
105 free(pfh);
106 errno = ENAMETOOLONG;
107 return (NULL);
108 }
109
110 /*
111 * Open the PID file and obtain exclusive lock.
112 * We truncate PID file here only to remove old PID immediatelly,
113 * PID file will be truncated again in pidfile_write(), so
114 * pidfile_write() can be called multiple times.
115 */
119 fd = flopen(pfh->pf_path,
120 O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
116 fd = open(pfh->pf_path,
117 O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode);
121 if (fd == -1) {
118 if (fd == -1) {
122 count = 0;
123 rqtp.tv_sec = 0;
124 rqtp.tv_nsec = 5000000;
125 if (errno == EWOULDBLOCK && pidptr != NULL) {
119 if (errno == EWOULDBLOCK && pidptr != NULL) {
126 again:
127 errno = pidfile_read(pfh->pf_path, pidptr);
128 if (errno == 0)
129 errno = EEXIST;
120 errno = pidfile_read(pfh->pf_path, pidptr);
121 if (errno == 0)
122 errno = EEXIST;
130 else if (errno == EAGAIN) {
131 if (++count <= 3) {
132 nanosleep(&rqtp, 0);
133 goto again;
134 }
135 }
136 }
137 free(pfh);
138 return (NULL);
139 }
140 /*
141 * Remember file information, so in pidfile_write() we are sure we write
142 * to the proper descriptor.
143 */

--- 11 unchanged lines hidden (view full) ---

155 pfh->pf_ino = sb.st_ino;
156
157 return (pfh);
158}
159
160int
161pidfile_write(struct pidfh *pfh)
162{
123 }
124 free(pfh);
125 return (NULL);
126 }
127 /*
128 * Remember file information, so in pidfile_write() we are sure we write
129 * to the proper descriptor.
130 */

--- 11 unchanged lines hidden (view full) ---

142 pfh->pf_ino = sb.st_ino;
143
144 return (pfh);
145}
146
147int
148pidfile_write(struct pidfh *pfh)
149{
150 struct stat sb;
163 char pidstr[16];
164 int error, fd;
165
166 /*
167 * Check remembered descriptor, so we don't overwrite some other
168 * file if pidfile was closed and descriptor reused.
169 */
170 errno = pidfile_verify(pfh);

--- 11 unchanged lines hidden (view full) ---

182 if (ftruncate(fd, 0) == -1) {
183 error = errno;
184 _pidfile_remove(pfh, 0);
185 errno = error;
186 return (-1);
187 }
188
189 snprintf(pidstr, sizeof(pidstr), "%u", getpid());
151 char pidstr[16];
152 int error, fd;
153
154 /*
155 * Check remembered descriptor, so we don't overwrite some other
156 * file if pidfile was closed and descriptor reused.
157 */
158 errno = pidfile_verify(pfh);

--- 11 unchanged lines hidden (view full) ---

170 if (ftruncate(fd, 0) == -1) {
171 error = errno;
172 _pidfile_remove(pfh, 0);
173 errno = error;
174 return (-1);
175 }
176
177 snprintf(pidstr, sizeof(pidstr), "%u", getpid());
190 if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
178 if (write(fd, pidstr, strlen(pidstr)) != (ssize_t)strlen(pidstr)) {
191 error = errno;
192 _pidfile_remove(pfh, 0);
193 errno = error;
194 return (-1);
195 }
196
197 return (0);
198}

--- 27 unchanged lines hidden (view full) ---

226 error = pidfile_verify(pfh);
227 if (error != 0) {
228 errno = error;
229 return (-1);
230 }
231
232 if (unlink(pfh->pf_path) == -1)
233 error = errno;
179 error = errno;
180 _pidfile_remove(pfh, 0);
181 errno = error;
182 return (-1);
183 }
184
185 return (0);
186}

--- 27 unchanged lines hidden (view full) ---

214 error = pidfile_verify(pfh);
215 if (error != 0) {
216 errno = error;
217 return (-1);
218 }
219
220 if (unlink(pfh->pf_path) == -1)
221 error = errno;
222 if (flock(pfh->pf_fd, LOCK_UN) == -1) {
223 if (error == 0)
224 error = errno;
225 }
234 if (close(pfh->pf_fd) == -1) {
235 if (error == 0)
236 error = errno;
237 }
238 if (freeit)
239 free(pfh);
240 else
241 pfh->pf_fd = -1;

--- 13 unchanged lines hidden ---
226 if (close(pfh->pf_fd) == -1) {
227 if (error == 0)
228 error = errno;
229 }
230 if (freeit)
231 free(pfh);
232 else
233 pfh->pf_fd = -1;

--- 13 unchanged lines hidden ---