#include #include #include #include #include #include #include #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; }