samba-gpupdate: Test that sysvol paths download in case-insensitive way
[Samba.git] / lib / util / pidfile.c
blobb7daa089223d04634b1e82193e18b78786772bca
1 /*
2 Unix SMB/CIFS implementation.
3 pidfile handling
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Amitay Isaccs 2016
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "replace.h"
22 #include "system/filesys.h"
24 #include "lib/util/blocking.h"
25 #include "lib/util/debug.h"
26 #include "lib/util/samba_util.h" /* For process_exists_by_pid() */
28 #include "lib/util/pidfile.h"
30 int pidfile_path_create(const char *path, int *outfd)
32 struct flock lck;
33 char tmp[64] = { 0 };
34 pid_t pid;
35 int fd, ret = 0;
36 int len;
37 ssize_t nwritten;
39 pid = getpid();
41 fd = open(path, O_CREAT|O_WRONLY|O_NONBLOCK, 0644);
42 if (fd == -1) {
43 return errno;
46 if (! set_close_on_exec(fd)) {
47 close(fd);
48 return EIO;
51 lck = (struct flock) {
52 .l_type = F_WRLCK,
53 .l_whence = SEEK_SET,
56 do {
57 ret = fcntl(fd, F_SETLK, &lck);
58 } while ((ret == -1) && (errno == EINTR));
60 if (ret != 0) {
61 ret = errno;
62 close(fd);
63 return ret;
67 * PID file is locked by us so from here on we should unlink
68 * on failure
71 do {
72 ret = ftruncate(fd, 0);
73 } while ((ret == -1) && (errno == EINTR));
75 if (ret == -1) {
76 ret = EIO;
77 goto fail_unlink;
80 len = snprintf(tmp, sizeof(tmp), "%u\n", pid);
81 if (len < 0) {
82 ret = errno;
83 goto fail_unlink;
85 if ((size_t)len >= sizeof(tmp)) {
86 ret = ENOSPC;
87 goto fail_unlink;
90 do {
91 nwritten = write(fd, tmp, len);
92 } while ((nwritten == -1) && (errno == EINTR));
94 if ((nwritten == -1) || (nwritten != len)) {
95 ret = EIO;
96 goto fail_unlink;
99 if (outfd != NULL) {
100 *outfd = fd;
102 return 0;
104 fail_unlink:
105 unlink(path);
106 close(fd);
107 return ret;
110 void pidfile_fd_close(int fd)
112 struct flock lck = {
113 .l_type = F_UNLCK,
114 .l_whence = SEEK_SET,
116 int ret;
118 do {
119 ret = fcntl(fd, F_SETLK, &lck);
120 } while ((ret == -1) && (errno == EINTR));
122 do {
123 ret = close(fd);
124 } while ((ret == -1) && (errno == EINTR));
129 * return the pid in a pidfile. return 0 if the process (or pidfile)
130 * does not exist
132 pid_t pidfile_pid(const char *piddir, const char *name)
134 size_t len = strlen(piddir) + strlen(name) + 6;
135 char pidFile[len];
136 int fd;
137 char pidstr[20] = { 0, };
138 pid_t ret = -1;
140 snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
142 fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644);
144 if (fd == -1) {
145 return 0;
148 if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) {
149 goto noproc;
152 ret = (pid_t)atoi(pidstr);
153 if (ret <= 0) {
154 DEBUG(1, ("Could not parse contents of pidfile %s\n",
155 pidFile));
156 goto noproc;
159 if (!process_exists_by_pid(ret)) {
160 DEBUG(10, ("Process with PID=%d does not exist.\n", (int)ret));
161 goto noproc;
164 if (fcntl_lock(fd,F_SETLK,0,1,F_RDLCK)) {
165 /* we could get the lock - it can't be a Samba process */
166 DEBUG(10, ("Process with PID=%d is not a Samba process.\n",
167 (int)ret));
168 goto noproc;
171 close(fd);
172 DEBUG(10, ("Process with PID=%d is running.\n", (int)ret));
173 return ret;
175 noproc:
176 close(fd);
177 return 0;
181 * create a pid file in the pid directory. open it and leave it locked
183 void pidfile_create(const char *piddir, const char *name)
185 size_t len = strlen(piddir) + strlen(name) + 6;
186 char pidFile[len];
187 pid_t pid;
188 int ret;
190 snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
192 pid = pidfile_pid(piddir, name);
193 if (pid != 0) {
194 DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n",
195 name, pidFile, (int)pid));
196 exit(1);
199 ret = pidfile_path_create(pidFile, NULL);
200 if (ret != 0) {
201 DBG_ERR("ERROR: Failed to create PID file %s (%s)\n",
202 pidFile, strerror(ret));
203 exit(1);
206 /* Leave pid file open & locked for the duration... */
209 void pidfile_unlink(const char *piddir, const char *name)
211 size_t len = strlen(piddir) + strlen(name) + 6;
212 char pidFile[len];
213 int ret;
215 snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
217 ret = unlink(pidFile);
218 if (ret == -1) {
219 DEBUG(0,("Failed to delete pidfile %s. Error was %s\n",
220 pidFile, strerror(errno)));