Files
libucore/src/restart_counter.c
T
Nils O. Selåsdal 711d734998 Open restart file in 0644 mode, fsync the file, don't
write to file if seek/truncate failed
2014-09-12 01:11:41 +02:00

105 lines
2.3 KiB
C

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ucore/restart_counter.h"
static UCRCResult uc_restart_counter_lock(int fd)
{
int rc = lockf(fd, F_TLOCK, 0);
if (rc == -1 && (errno == EACCES || errno == EAGAIN)) {
return UC_RC_ERR_FILE_LOCKED;
} else if (rc == -1) {
return UC_RC_ERR_UNSPECIFIED;
}
return UC_RC_OK;
}
UCRCResult uc_restart_counter_init(
struct UCRestartCounter *counter,
const char *filename,
unsigned int flags)
{
int fd;
UCRCResult rc = UC_RC_OK;
char buf[64];
ssize_t n;
counter->counter = 0;
counter->fd = -1;
fd = open(filename, O_CREAT|O_RDWR, 0644);
if (fd == -1) {
return UC_RC_ERR_FILE_ACCESS_ERROR;
}
if (flags & UC_RC_FL_LOCK_FILE) {
rc = uc_restart_counter_lock(fd);
if (rc != UC_RC_OK) {
close(fd);
return rc;
}
counter->fd = fd;
}
buf[0] = 0;
n = read(fd, buf, sizeof buf - 1);
if (n > 0) {
buf[n] = 0;
if (sscanf(buf, "%u", &counter->counter) == 1) {
counter->counter++;
rc = UC_RC_OK;
} else {
rc = UC_RC_ERR_FILE_CONTENT_ERROR;
}
if (lseek(fd, 0, SEEK_SET) != 0 ||
ftruncate(fd,0) != 0) {
rc = UC_RC_ERR_UNSPECIFIED;
goto done;
}
} else if (n < 0) {
rc = UC_RC_ERR_FILE_ACCESS_ERROR;
} //if n is 0, we act as we created the file for the 1. time
snprintf(buf, sizeof buf, "%u\n", counter->counter);
n = strlen(buf);
if (write(fd, buf, n) != n) {
rc = UC_RC_ERR_UNSPECIFIED;
}
fsync(fd);
done:
if ((flags & UC_RC_FL_LOCK_FILE) == 0) {
close(fd);
}
return rc;
}
UCRCResult uc_restart_counter_close(struct UCRestartCounter *counter)
{
if (counter->fd < 0) {
return UC_RC_ERR_NOT_OPENED;
}
close(counter->fd); //also releases the lock
counter->fd = -1;
return UC_RC_OK;
}
unsigned int uc_restart_counter_get(const struct UCRestartCounter *counter)
{
return counter->counter;
}