Add uc_restart_counter concept
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#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, 0600);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user