andre@1160: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
andre@1160:  * Software engineering by Intevation GmbH
andre@1160:  *
andre@1160:  * This file is Free Software under the GNU GPL (v>=2)
andre@1160:  * and comes with ABSOLUTELY NO WARRANTY!
andre@1160:  * See LICENSE.txt for details.
andre@1160:  */
andre@1160: 
wilde@782: #ifndef WIN32
wilde@782: 
wilde@782: #include <fcntl.h>
wilde@782: #include <stdio.h>
wilde@782: #include <sys/types.h>
wilde@782: #include <unistd.h>
wilde@782: 
wilde@782: #include "logging.h"
wilde@782: 
wilde@782: int
wilde@782: open_lockfile(char *path)
wilde@782: {
wilde@782:   int fd;
wilde@782:   char pidstr[20];
wilde@782:   size_t pidstrlen;
wilde@782:   struct flock lk;
wilde@782:   fd = open(path, O_RDWR | O_CREAT, 0600);
wilde@782:   if (fd != -1)
wilde@782:     {
wilde@782:       /* Get an exclusive lock on the whole file. */
wilde@782:       lk.l_type = F_WRLCK;
wilde@782:       lk.l_whence = SEEK_SET;
wilde@782:       lk.l_start = 0;
wilde@782:       lk.l_len = 0;
wilde@782:       if (fcntl(fd, F_SETLK, &lk) != -1)
wilde@782:         {
andre@1162:           /* FIXME (issue139): For extra security we should check if there is
wilde@782:              already a pid in the file.  If so we should check in
wilde@782:              /proc/$PID if there is still a process of the same name
wilde@782:              as ours running... */
wilde@782:           ftruncate(fd, 0);
wilde@782:           pidstrlen = (size_t)snprintf(pidstr, sizeof(pidstr), "%d", getpid());
wilde@782:           write(fd, pidstr, pidstrlen);
wilde@782:         }
wilde@782:       else
wilde@782:         {
wilde@782:           /* Lock can not be acquired.  Bail out... */
wilde@782:           close(fd);
wilde@782:           DEBUGPRINTF("Could not get an exclusive lock on %s.\n", path);
wilde@782:           return -1;
wilde@782:         }
wilde@782:     }
wilde@782:   else
wilde@782:     {
wilde@782:       DEBUGPRINTF("Failed to open lock file: %s.\n", path);
wilde@782:     }
wilde@782:   return fd;
wilde@782: }
wilde@782: 
wilde@782: void
wilde@782: close_lockfile(int fd)
wilde@782: {
wilde@782:   struct flock lk;
wilde@782: 
wilde@782:   /* Delete the PID from file. */
wilde@782:   /* We do this instead of trying to unlink the file. */
wilde@782:   ftruncate(fd, 0);
wilde@782: 
wilde@782:   /* Remove lock from the file. */
wilde@782:   lk.l_type = F_UNLCK;
wilde@782:   lk.l_whence = SEEK_SET;
wilde@782:   lk.l_start = 0;
wilde@782:   lk.l_len = 0;
wilde@782:   if (fcntl(fd, F_SETLK, &lk) == -1)
wilde@782:     {
andre@1250:       /* Lock can not be removed */
andre@1250:       DEBUGPRINTF("Could not remove lock from pid file.\n");
wilde@782:     }
wilde@782:   close(fd);
wilde@782: }
wilde@782: 
wilde@782: #endif /* Not WIN32 */