1 #include <errno.h>
2 #include <stdint.h>
3 #include <assert.h>
4
5 #include "unixatomic.h"
6 #include "sysincludes.h"
7
atomic_close(int fd)8 int atomic_close(int fd)
9 {
10 while (1) {
11 if (close(fd) < 0) {
12 if (errno == EINTR)
13 continue;
14 return -1;
15 }
16 break;
17 }
18 return 0;
19 }
20
21
atomic_dup2(int oldfd,int newfd)22 int atomic_dup2(int oldfd, int newfd)
23 {
24 while (1) {
25 if (dup2(oldfd, newfd) < 0) {
26 if (errno == EINTR)
27 continue;
28 return -1;
29 }
30 break;
31 }
32 return newfd;
33 }
34
35
atomic_fread(void * ptr,size_t size,size_t nmemb,FILE * stream)36 size_t atomic_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
37 {
38 uint8_t *dest = ptr;
39 size_t readmembers = 0;
40 size_t ret;
41
42 while (readmembers < nmemb) {
43 ret = fread(dest + size * readmembers, size, nmemb - readmembers, stream);
44 if (ret == 0)
45 break;
46 readmembers += ret;
47 }
48
49 assert(readmembers <= nmemb);
50
51 return readmembers;
52 }
53
54
atomic_read(int fd,const void * buf,size_t count)55 ssize_t atomic_read(int fd, const void *buf, size_t count)
56 {
57 char *b = (char *) buf;
58 ssize_t bytes_read = 0;
59 ssize_t ret;
60 while (bytes_read < count) {
61 ret = read(fd, &b[bytes_read], count - bytes_read);
62 if (ret < 0) {
63 if (errno == EINTR)
64 continue;
65 if (errno == EAGAIN) {
66 fd_set s;
67 FD_ZERO(&s);
68 FD_SET(fd, &s);
69 if (select(fd + 1, &s, NULL, NULL, NULL) == 0)
70 fprintf(stderr, "atomic_read: very strange. infinite select() returned 0. report this!\n");
71 continue;
72 }
73 return -1;
74 } else if (ret == 0) {
75 return 0;
76 }
77 bytes_read += ret;
78 }
79 return bytes_read;
80 }
81
82
atomic_read_file(size_t * fs,const char * filename)83 void *atomic_read_file(size_t *fs, const char *filename)
84 {
85 FILE *f;
86 size_t off;
87 void *mem = NULL;
88 size_t msize;
89 long pos;
90
91 if ((f = fopen(filename, "rb")) == NULL)
92 goto error;
93
94 if (fseek(f, 0, SEEK_END))
95 goto error;
96 pos = ftell(f);
97 if (pos < 0)
98 goto error;
99 if (fseek(f, 0, SEEK_SET))
100 goto error;
101
102 *fs = pos;
103 msize = (pos > 0) ? pos : 1;
104
105 if ((mem = malloc(msize)) == NULL)
106 goto error;
107
108 off = atomic_fread(mem, 1, *fs, f);
109 if (off < *fs) {
110 fprintf(stderr, "Not able to read the whole file %s\n", filename);
111 goto error;
112 }
113
114 fclose(f);
115 return mem;
116
117 error:
118 if (f)
119 fclose(f);
120 free(mem);
121 *fs = 0;
122 return NULL;
123 }
124
125
atomic_write(int fd,const void * buf,size_t count)126 ssize_t atomic_write(int fd, const void *buf, size_t count)
127 {
128 char *b = (char *) buf;
129 ssize_t bytes_written = 0;
130 ssize_t ret;
131 while (bytes_written < count) {
132 ret = write(fd, &b[bytes_written], count - bytes_written);
133 if (ret < 0) {
134 if (errno == EINTR)
135 continue;
136 if (errno == EAGAIN) {
137 fd_set s;
138 FD_ZERO(&s);
139 FD_SET(fd, &s);
140 if (select(fd + 1, NULL, &s, NULL, NULL) == 0)
141 fprintf(stderr, "atomic_write: very strange. infinite select() returned 0. report this!\n");
142 continue;
143 }
144 return -1;
145 }
146 bytes_written += ret;
147 }
148 return bytes_written;
149 }
150