/* * Ouroboros - Copyright (C) 2016 * * Lockfile for ouroboros system * * Dimitri Staessens <dimitri.staessens@intec.ugent.be> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ouroboros/config.h> #include <ouroboros/lockfile.h> #define OUROBOROS_PREFIX "lockfile" #include <ouroboros/logs.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <signal.h> #include <sys/mman.h> #include <sys/stat.h> #define LF_SIZE (sizeof(pid_t)) struct lockfile { pid_t * api; int fd; }; struct lockfile * lockfile_create() { struct lockfile * lf = malloc(sizeof(*lf)); if (lf == NULL) return NULL; lf->fd = shm_open(LOCKFILE_NAME, O_CREAT | O_EXCL | O_RDWR, 0666); if (lf->fd == -1) { LOG_DBGF("Could not create lock file."); free(lf); return NULL; } if (fchmod(lf->fd, 0666)) { LOG_DBGF("Failed to chmod lockfile."); free(lf); return NULL; } if (lseek(lf->fd, LF_SIZE - 1, SEEK_SET) < 0) { LOG_DBGF("Failed to extend lockfile."); free(lf); return NULL; } if (write(lf->fd, "", 1) != 1) { LOG_DBGF("Failed to finalise lockfile."); free(lf); return NULL; } lf->api = mmap(NULL, LF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, lf->fd, 0); if (lf->api == MAP_FAILED) { LOG_DBGF("Failed to map lockfile."); if (shm_unlink(LOCKFILE_NAME) == -1) LOG_DBGF("Failed to remove invalid lockfile."); free(lf); return NULL; } *lf->api = getpid(); return lf; } struct lockfile * lockfile_open() { struct lockfile * lf = malloc(sizeof(*lf)); if (lf == NULL) return NULL; lf->fd = shm_open(LOCKFILE_NAME, O_RDWR, 0666); if (lf->fd == -1) { LOG_DBGF("Could not open lock file."); free(lf); return NULL; } lf->api = mmap(NULL, LF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, lf->fd, 0); if (lf->api == MAP_FAILED) { LOG_DBGF("Failed to map lockfile."); if (shm_unlink(LOCKFILE_NAME) == -1) LOG_DBGF("Failed to remove invalid lockfile."); free(lf); return NULL; } return lf; } void lockfile_close(struct lockfile * lf) { if (lf == NULL) { LOG_DBGF("Bogus input. Bugging out."); return; } if (close(lf->fd) < 0) LOG_DBGF("Couldn't close lockfile."); if (munmap(lf->api, LF_SIZE) == -1) LOG_DBGF("Couldn't unmap lockfile."); free(lf); } void lockfile_destroy(struct lockfile * lf) { if (lf == NULL) { LOG_DBGF("Bogus input. Bugging out."); return; } if (getpid() != *lf->api && kill(*lf->api, 0) == 0) { LOG_DBGF("Only IRMd can destroy %s.", LOCKFILE_NAME); return; } if (close(lf->fd) < 0) LOG_DBGF("Couldn't close lockfile."); if (munmap(lf->api, LF_SIZE) == -1) LOG_DBGF("Couldn't unmap lockfile."); if (shm_unlink(LOCKFILE_NAME) == -1) LOG_DBGF("Failed to remove lockfile."); free(lf); } pid_t lockfile_owner(struct lockfile * lf) { return *lf->api; }