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