diff options
Diffstat (limited to 'src/gns/nss/util.c')
-rw-r--r-- | src/gns/nss/util.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/gns/nss/util.c b/src/gns/nss/util.c new file mode 100644 index 000000000..7349d6b1f --- /dev/null +++ b/src/gns/nss/util.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /*** | ||
4 | This file is part of nss-mdns. | ||
5 | |||
6 | nss-mdns is free software; you can redistribute it and/or modify it | ||
7 | under the terms of the GNU Lesser General Public License as | ||
8 | published by the Free Software Foundation; either version 2 of the | ||
9 | License, or (at your option) any later version. | ||
10 | |||
11 | nss-mdns is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Lesser General Public | ||
17 | License along with nss-mdns; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
19 | USA. | ||
20 | ***/ | ||
21 | |||
22 | #include <gnunet_config.h> | ||
23 | |||
24 | #include <sys/select.h> | ||
25 | #include <errno.h> | ||
26 | #include <string.h> | ||
27 | #include <assert.h> | ||
28 | #include <fcntl.h> | ||
29 | |||
30 | #include "util.h" | ||
31 | |||
32 | #ifdef ENABLE_LEGACY | ||
33 | |||
34 | /* Calculate the difference between the two specfified timeval | ||
35 | * timestamsps. */ | ||
36 | usec_t timeval_diff(const struct timeval *a, const struct timeval *b) { | ||
37 | usec_t r; | ||
38 | assert(a && b); | ||
39 | |||
40 | /* Check which whan is the earlier time and swap the two arguments if reuqired. */ | ||
41 | if (timeval_cmp(a, b) < 0) { | ||
42 | const struct timeval *c; | ||
43 | c = a; | ||
44 | a = b; | ||
45 | b = c; | ||
46 | } | ||
47 | |||
48 | /* Calculate the second difference*/ | ||
49 | r = ((usec_t) a->tv_sec - b->tv_sec)* 1000000; | ||
50 | |||
51 | /* Calculate the microsecond difference */ | ||
52 | if (a->tv_usec > b->tv_usec) | ||
53 | r += ((usec_t) a->tv_usec - b->tv_usec); | ||
54 | else if (a->tv_usec < b->tv_usec) | ||
55 | r -= ((usec_t) b->tv_usec - a->tv_usec); | ||
56 | |||
57 | return r; | ||
58 | } | ||
59 | |||
60 | /* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ | ||
61 | int timeval_cmp(const struct timeval *a, const struct timeval *b) { | ||
62 | assert(a && b); | ||
63 | |||
64 | if (a->tv_sec < b->tv_sec) | ||
65 | return -1; | ||
66 | |||
67 | if (a->tv_sec > b->tv_sec) | ||
68 | return 1; | ||
69 | |||
70 | if (a->tv_usec < b->tv_usec) | ||
71 | return -1; | ||
72 | |||
73 | if (a->tv_usec > b->tv_usec) | ||
74 | return 1; | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | /* Return the time difference between now and the specified timestamp */ | ||
80 | usec_t timeval_age(const struct timeval *tv) { | ||
81 | struct timeval now; | ||
82 | assert(tv); | ||
83 | gettimeofday(&now, NULL); | ||
84 | return timeval_diff(&now, tv); | ||
85 | } | ||
86 | |||
87 | /* Add the specified time inmicroseconds to the specified timeval structure */ | ||
88 | void timeval_add(struct timeval *tv, usec_t v) { | ||
89 | unsigned long secs; | ||
90 | assert(tv); | ||
91 | |||
92 | secs = (v/1000000); | ||
93 | tv->tv_sec += (unsigned long) secs; | ||
94 | v -= secs*1000000; | ||
95 | |||
96 | tv->tv_usec += v; | ||
97 | |||
98 | /* Normalize */ | ||
99 | while (tv->tv_usec >= 1000000) { | ||
100 | tv->tv_sec++; | ||
101 | tv->tv_usec -= 1000000; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | int set_nonblock(int fd) { | ||
106 | int n; | ||
107 | assert(fd >= 0); | ||
108 | |||
109 | if ((n = fcntl(fd, F_GETFL)) < 0) | ||
110 | return -1; | ||
111 | |||
112 | if (n & O_NONBLOCK) | ||
113 | return 0; | ||
114 | |||
115 | return fcntl(fd, F_SETFL, n|O_NONBLOCK); | ||
116 | } | ||
117 | |||
118 | int wait_for_write(int fd, struct timeval *end) { | ||
119 | struct timeval now; | ||
120 | |||
121 | if (end) | ||
122 | gettimeofday(&now, NULL); | ||
123 | |||
124 | for (;;) { | ||
125 | struct timeval tv; | ||
126 | fd_set fds; | ||
127 | int r; | ||
128 | |||
129 | FD_ZERO(&fds); | ||
130 | FD_SET(fd, &fds); | ||
131 | |||
132 | if (end) { | ||
133 | if (timeval_cmp(&now, end) >= 0) | ||
134 | return 1; | ||
135 | |||
136 | tv.tv_sec = tv.tv_usec = 0; | ||
137 | timeval_add(&tv, timeval_diff(end, &now)); | ||
138 | } | ||
139 | |||
140 | if ((r = select(fd+1, NULL, &fds, NULL, end ? &tv : NULL)) < 0) { | ||
141 | if (errno != EINTR) | ||
142 | return -1; | ||
143 | } else if (r == 0) | ||
144 | return 1; | ||
145 | else { | ||
146 | if (FD_ISSET(fd, &fds)) | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | if (end) | ||
151 | gettimeofday(&now, NULL); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | int wait_for_read(int fd, struct timeval *end) { | ||
156 | struct timeval now; | ||
157 | |||
158 | if (end) | ||
159 | gettimeofday(&now, NULL); | ||
160 | |||
161 | for (;;) { | ||
162 | struct timeval tv; | ||
163 | fd_set fds; | ||
164 | int r; | ||
165 | |||
166 | FD_ZERO(&fds); | ||
167 | FD_SET(fd, &fds); | ||
168 | |||
169 | if (end) { | ||
170 | if (timeval_cmp(&now, end) >= 0) | ||
171 | return 1; | ||
172 | |||
173 | tv.tv_sec = tv.tv_usec = 0; | ||
174 | timeval_add(&tv, timeval_diff(end, &now)); | ||
175 | } | ||
176 | |||
177 | if ((r = select(fd+1, &fds, NULL, NULL, end ? &tv : NULL)) < 0) { | ||
178 | if (errno != EINTR) | ||
179 | return -1; | ||
180 | } else if (r == 0) | ||
181 | return 1; | ||
182 | else { | ||
183 | |||
184 | if (FD_ISSET(fd, &fds)) | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | if (end) | ||
189 | gettimeofday(&now, NULL); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | #endif | ||
194 | |||
195 | int set_cloexec(int fd) { | ||
196 | int n; | ||
197 | assert(fd >= 0); | ||
198 | |||
199 | if ((n = fcntl(fd, F_GETFD)) < 0) | ||
200 | return -1; | ||
201 | |||
202 | if (n & FD_CLOEXEC) | ||
203 | return 0; | ||
204 | |||
205 | return fcntl(fd, F_SETFD, n|FD_CLOEXEC); | ||
206 | } | ||
207 | |||