#include #include #include #include "unixatomic.h" #include "sysincludes.h" int atomic_close(int fd) { while (1) { if (close(fd) < 0) { if (errno == EINTR) continue; return -1; } break; } return 0; } int atomic_dup2(int oldfd, int newfd) { while (1) { if (dup2(oldfd, newfd) < 0) { if (errno == EINTR) continue; return -1; } break; } return newfd; } size_t atomic_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { uint8_t *dest = ptr; size_t readmembers = 0; size_t ret; while (readmembers < nmemb) { ret = fread(dest + size * readmembers, size, nmemb - readmembers, stream); if (ret == 0) break; readmembers += ret; } assert(readmembers <= nmemb); return readmembers; } ssize_t atomic_read(int fd, const void *buf, size_t count) { char *b = (char *) buf; ssize_t bytes_read = 0; ssize_t ret; while (bytes_read < count) { ret = read(fd, &b[bytes_read], count - bytes_read); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) { fd_set s; FD_ZERO(&s); FD_SET(fd, &s); if (select(fd + 1, &s, NULL, NULL, NULL) == 0) fprintf(stderr, "atomic_read: very strange. infinite select() returned 0. report this!\n"); continue; } return -1; } else if (ret == 0) { return 0; } bytes_read += ret; } return bytes_read; } void *atomic_read_file(size_t *fs, const char *filename) { FILE *f; size_t off; void *mem = NULL; size_t msize; long pos; if ((f = fopen(filename, "rb")) == NULL) goto error; if (fseek(f, 0, SEEK_END)) goto error; pos = ftell(f); if (pos < 0) goto error; if (fseek(f, 0, SEEK_SET)) goto error; *fs = pos; msize = (pos > 0) ? pos : 1; if ((mem = malloc(msize)) == NULL) goto error; off = atomic_fread(mem, 1, *fs, f); if (off < *fs) { fprintf(stderr, "Not able to read the whole file %s\n", filename); goto error; } fclose(f); return mem; error: if (f) fclose(f); free(mem); *fs = 0; return NULL; } ssize_t atomic_write(int fd, const void *buf, size_t count) { char *b = (char *) buf; ssize_t bytes_written = 0; ssize_t ret; while (bytes_written < count) { ret = write(fd, &b[bytes_written], count - bytes_written); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) { fd_set s; FD_ZERO(&s); FD_SET(fd, &s); if (select(fd + 1, NULL, &s, NULL, NULL) == 0) fprintf(stderr, "atomic_write: very strange. infinite select() returned 0. report this!\n"); continue; } return -1; } bytes_written += ret; } return bytes_written; }