diff options
Diffstat (limited to 'libdm/libdm-file.c')
-rw-r--r-- | libdm/libdm-file.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/libdm/libdm-file.c b/libdm/libdm-file.c index 749ee4f6..ae2da76d 100644 --- a/libdm/libdm-file.c +++ b/libdm/libdm-file.c @@ -84,3 +84,85 @@ int dm_fclose(FILE *stream) return prev_fail || fclose_fail ? EOF : 0; } + +int dm_create_lockfile(const char *lockfile) +{ + int fd, value; + size_t bufferlen; + ssize_t write_out; + struct flock lock; + char buffer[50]; + + if((fd = open(lockfile, O_CREAT | O_WRONLY, + (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) { + log_error("Cannot open lockfile [%s], error was [%s]", + lockfile, strerror(errno)); + return 0; + } + + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + if (fcntl(fd, F_SETLK, &lock) < 0) { + if (errno != EACCES && errno != EAGAIN) + log_error("Cannot lock lockfile [%s], error was [%s]", + lockfile, strerror(errno)); + else + log_error("process is already running"); + + goto fail; + } + + if (ftruncate(fd, 0) < 0) { + log_error("Cannot truncate pidfile [%s], error was [%s]", + lockfile, strerror(errno)); + + goto fail; + } + + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer)-1, "%u\n", getpid()); + + bufferlen = strlen(buffer); + write_out = write(fd, buffer, bufferlen); + + if ((write_out < 0) || (write_out == 0 && errno)) { + log_error("Cannot write pid to pidfile [%s], error was [%s]", + lockfile, strerror(errno)); + + goto fail; + } + + if ((write_out == 0) || (write_out < bufferlen)) { + log_error("Cannot write pid to pidfile [%s], shortwrite of" + "[%" PRIsize_t "] bytes, expected [%" PRIsize_t "]\n", + lockfile, write_out, bufferlen); + + goto fail; + } + + if ((value = fcntl(fd, F_GETFD, 0)) < 0) { + log_error("Cannot get close-on-exec flag from pidfile [%s], " + "error was [%s]", lockfile, strerror(errno)); + + goto fail; + } + value |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, value) < 0) { + log_error("Cannot set close-on-exec flag from pidfile [%s], " + "error was [%s]", lockfile, strerror(errno)); + + goto fail; + } + + return 1; + +fail: + if (close(fd)) + stack; + if (unlink(lockfile)) + stack; + + return 0; +} |