blob: 1ed098847d9d8d0cf44fa95c62a4388bf14ddb2e [file] [log] [blame]
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// read a file containing a single short integer.
long read_file_long(const char *filename) {
char buf[32] = { 0 };
ssize_t got;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror(filename);
return -1;
}
got = read(fd, buf, sizeof(buf) - 1);
close(fd);
if (got < 0) {
perror(filename);
return -1;
}
buf[got] = 0;
return strtol(buf, NULL, 10);
}
// write a file containing the given string.
int write_file_string(const char *filename, const char *content) {
int fd = open(filename, O_TRUNC|O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (fd >= 0) {
write(fd, content, strlen(content));
close(fd);
return 0;
}
perror(filename);
return -1;
}
int write_file_string_atomic(const char *filename, const char *content) {
char *tmpname = malloc(strlen(filename) + 4 + 1);
int ret;
sprintf(tmpname, "%s.tmp", filename);
ret = write_file_string(tmpname, content);
if (ret >= 0) {
ret = rename(tmpname, filename);
free(tmpname);
return ret;
}
free(tmpname);
return -1;
}
#define WRITE_TO_FILE(filename, oldv, newv, atomic, format) \
if (!oldv || *oldv != newv) { \
char buf[128]; \
snprintf(buf, sizeof(buf), format, newv); \
buf[sizeof(buf)-1] = 0; \
if (atomic) \
write_file_string_atomic(filename, buf); \
else \
write_file_string(filename, buf); \
if (oldv) \
*oldv = newv; \
}
static void __write_file_longlong(const char *filename, long long *oldv,
long long newv, int atomic) {
WRITE_TO_FILE(filename, oldv, newv, atomic, "%lld")
}
static void __write_file_int(const char *filename, int *oldv, int newv,
int atomic) {
WRITE_TO_FILE(filename, oldv, newv, atomic, "%d")
}
static void __write_file_double(const char *filename, double *oldv, double newv,
int atomic) {
WRITE_TO_FILE(filename, oldv, newv, atomic, "%.2f")
}
void write_file_longlong_atomic(const char *filename, long long *oldv,
long long newv) {
__write_file_longlong(filename, oldv, newv, 1);
}
void write_file_int_atomic(const char *filename, int *oldv, int newv) {
__write_file_int(filename, oldv, newv, 1);
}
void write_file_double_atomic(const char *filename, double *oldv, double newv) {
__write_file_double(filename, oldv, newv, 1);
}
void write_file_longlong(const char *filename, long long *oldv,
long long newv) {
__write_file_longlong(filename, oldv, newv, 0);
}
void write_file_int(const char *filename, int *oldv, int newv) {
__write_file_int(filename, oldv, newv, 0);
}
void write_file_double(const char *filename, double *oldv, double newv) {
__write_file_double(filename, oldv, newv, 0);
}