711d734998
write to file if seek/truncate failed
105 lines
2.3 KiB
C
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;
|
|
}
|