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