LCOV - code coverage report
Current view: top level - lib/util - pidfile.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 74 124 59.7 %
Date: 2024-04-13 12:30:31 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    pidfile handling
       4             :    Copyright (C) Andrew Tridgell 1998
       5             :    Copyright (C) Amitay Isaccs  2016
       6             : 
       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.
      11             : 
      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.
      16             : 
      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/>.
      19             : */
      20             : 
      21             : #include "replace.h"
      22             : #include "system/filesys.h"
      23             : 
      24             : #include "lib/util/blocking.h"
      25             : #include "lib/util/debug.h"
      26             : #include "lib/util/samba_util.h"  /* For process_exists_by_pid() */
      27             : 
      28             : #include "lib/util/pidfile.h"
      29             : 
      30         325 : int pidfile_path_create(const char *path, int *pfd, pid_t *existing_pid)
      31             : {
      32           3 :         struct flock lck;
      33         325 :         char tmp[64] = { 0 };
      34         325 :         int fd, ret = 0;
      35           3 :         int len;
      36           3 :         ssize_t nwritten;
      37         325 :         bool retried = false;
      38             : 
      39         325 :         fd = open(path, O_CREAT|O_WRONLY|O_NONBLOCK, 0644);
      40         325 :         if (fd == -1) {
      41           0 :                 return errno;
      42             :         }
      43             : 
      44         325 :         if (! set_close_on_exec(fd)) {
      45           0 :                 ret = errno;
      46           0 :                 goto fail;
      47             :         }
      48             : 
      49         325 : retry:
      50         325 :         lck = (struct flock) {
      51             :                 .l_type = F_WRLCK,
      52             :                 .l_whence = SEEK_SET,
      53             :         };
      54             : 
      55           3 :         do {
      56         325 :                 ret = fcntl(fd, F_SETLK, &lck);
      57         325 :         } while ((ret == -1) && (errno == EINTR));
      58             : 
      59         325 :         if (ret != 0) {
      60          83 :                 ret = errno;
      61             : 
      62          83 :                 if ((ret == EACCES) || (ret == EAGAIN)) {
      63           0 :                         do {
      64          83 :                                 ret = fcntl(fd, F_GETLK, &lck);
      65          83 :                         } while ((ret == -1) && (errno == EINTR));
      66             : 
      67          83 :                         if (ret == -1) {
      68           0 :                                 ret = errno;
      69           0 :                                 goto fail;
      70             :                         }
      71             : 
      72          83 :                         if (lck.l_type == F_UNLCK) {
      73           0 :                                 if (!retried) {
      74             :                                         /* Lock holder died, retry once */
      75           0 :                                         retried = true;
      76           0 :                                         goto retry;
      77             :                                 }
      78             :                                 /* Something badly wrong */
      79           0 :                                 ret = EIO;
      80           0 :                                 goto fail;
      81             :                         }
      82             : 
      83          83 :                         if (existing_pid != NULL) {
      84          83 :                                 *existing_pid = lck.l_pid;
      85             :                         }
      86          83 :                         return EAGAIN;
      87             :                 }
      88           0 :                 goto fail;
      89             :         }
      90             : 
      91             :         /*
      92             :          * PID file is locked by us so from here on we should unlink
      93             :          * on failure
      94             :          */
      95         242 :         len = snprintf(tmp, sizeof(tmp), "%u\n", getpid());
      96         242 :         if (len < 0) {
      97           0 :                 ret = errno;
      98           0 :                 goto fail_unlink;
      99             :         }
     100         242 :         if ((size_t)len >= sizeof(tmp)) {
     101           0 :                 ret = ENOSPC;
     102           0 :                 goto fail_unlink;
     103             :         }
     104             : 
     105           3 :         do {
     106         242 :                 nwritten = write(fd, tmp, len);
     107         242 :         } while ((nwritten == -1) && (errno == EINTR));
     108             : 
     109         242 :         if ((nwritten == -1) || (nwritten != len)) {
     110           0 :                 ret = errno;
     111           0 :                 goto fail_unlink;
     112             :         }
     113             : 
     114           3 :         do {
     115         242 :                 ret = ftruncate(fd, len);
     116         242 :         } while ((ret == -1) && (errno == EINTR));
     117             : 
     118         242 :         if (ret == -1) {
     119           0 :                 ret = errno;
     120           0 :                 goto fail_unlink;
     121             :         }
     122             : 
     123         242 :         *pfd = fd;
     124         242 :         return 0;
     125             : 
     126           0 : fail_unlink:
     127           0 :         unlink(path);
     128           0 : fail:
     129           0 :         close(fd);
     130           0 :         return ret;
     131             : }
     132             : 
     133           0 : void pidfile_fd_close(int fd)
     134             : {
     135           0 :         struct flock lck = {
     136             :                 .l_type = F_UNLCK,
     137             :                 .l_whence = SEEK_SET,
     138             :         };
     139           0 :         int ret;
     140             : 
     141           0 :         do {
     142           0 :                 ret = fcntl(fd, F_SETLK, &lck);
     143           0 :         } while ((ret == -1) && (errno == EINTR));
     144             : 
     145           0 :         do {
     146           0 :                 ret = close(fd);
     147           0 :         } while ((ret == -1) && (errno == EINTR));
     148           0 : }
     149             : 
     150             : 
     151             : /**
     152             :  * return the pid in a pidfile. return 0 if the process (or pidfile)
     153             :  * does not exist
     154             :  */
     155        1399 : pid_t pidfile_pid(const char *piddir, const char *name)
     156        1399 : {
     157        1399 :         size_t len = strlen(piddir) + strlen(name) + 6;
     158        1399 :         char pidFile[len];
     159           0 :         int fd;
     160        1399 :         char pidstr[20] = { 0, };
     161        1399 :         pid_t ret = -1;
     162             : 
     163        1399 :         snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
     164             : 
     165        1399 :         fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644);
     166             : 
     167        1399 :         if (fd == -1) {
     168          18 :                 return 0;
     169             :         }
     170             : 
     171        1381 :         if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) {
     172           0 :                 goto noproc;
     173             :         }
     174             : 
     175        1381 :         ret = (pid_t)atoi(pidstr);
     176        1381 :         if (ret <= 0) {
     177           0 :                 DEBUG(1, ("Could not parse contents of pidfile %s\n",
     178             :                         pidFile));
     179           0 :                 goto noproc;
     180             :         }
     181             : 
     182        1381 :         if (!process_exists_by_pid(ret)) {
     183           0 :                 DEBUG(10, ("Process with PID=%d does not exist.\n", (int)ret));
     184           0 :                 goto noproc;
     185             :         }
     186             : 
     187        1381 :         if (fcntl_lock(fd,F_SETLK,0,1,F_RDLCK)) {
     188             :                 /* we could get the lock - it can't be a Samba process */
     189           0 :                 DEBUG(10, ("Process with PID=%d is not a Samba process.\n",
     190             :                         (int)ret));
     191           0 :                 goto noproc;
     192             :         }
     193             : 
     194        1381 :         close(fd);
     195        1381 :         DEBUG(10, ("Process with PID=%d is running.\n", (int)ret));
     196        1381 :         return ret;
     197             : 
     198           0 :  noproc:
     199           0 :         close(fd);
     200           0 :         return 0;
     201             : }
     202             : 
     203             : /**
     204             :  * create a pid file in the pid directory. open it and leave it locked
     205             :  */
     206         146 : void pidfile_create(const char *piddir, const char *name)
     207         146 : {
     208         146 :         size_t len = strlen(piddir) + strlen(name) + 6;
     209         146 :         char pidFile[len];
     210         146 :         pid_t pid = (pid_t)-1;
     211           3 :         int ret, fd;
     212             : 
     213         146 :         snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
     214             : 
     215         146 :         ret = pidfile_path_create(pidFile, &fd, &pid);
     216         146 :         if (ret == EAGAIN) {
     217           0 :                 DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n",
     218             :                          name, pidFile, (int)pid));
     219           0 :                 exit(1);
     220             :         }
     221             : 
     222             :         /* Leave pid file open & locked for the duration... */
     223         146 : }
     224             : 
     225          80 : void pidfile_unlink(const char *piddir, const char *name)
     226          80 : {
     227          80 :         size_t len = strlen(piddir) + strlen(name) + 6;
     228          80 :         char pidFile[len];
     229           0 :         int ret;
     230             : 
     231          80 :         snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name);
     232             : 
     233          80 :         ret = unlink(pidFile);
     234          80 :         if (ret == -1) {
     235           0 :                 DEBUG(0,("Failed to delete pidfile %s. Error was %s\n",
     236             :                         pidFile, strerror(errno)));
     237             :         }
     238          80 : }

Generated by: LCOV version 1.14