Mercurial > notdcc
comparison dcclib/win32.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c7f6b056b673 |
---|---|
1 /* Distributed Checksum Clearinghouse | |
2 * | |
3 * routines to make WIN32 look sort of reasonable | |
4 * | |
5 * Copyright (c) 2008 by Rhyolite Software, LLC | |
6 * | |
7 * This agreement is not applicable to any entity which sells anti-spam | |
8 * solutions to others or provides an anti-spam solution as part of a | |
9 * security solution sold to other entities, or to a private network | |
10 * which employs the DCC or uses data provided by operation of the DCC | |
11 * but does not provide corresponding data to other users. | |
12 * | |
13 * Permission to use, copy, modify, and distribute this software without | |
14 * changes for any purpose with or without fee is hereby granted, provided | |
15 * that the above copyright notice and this permission notice appear in all | |
16 * copies and any distributed versions or copies are either unchanged | |
17 * or not called anything similar to "DCC" or "Distributed Checksum | |
18 * Clearinghouse". | |
19 * | |
20 * Parties not eligible to receive a license under this agreement can | |
21 * obtain a commercial license to use DCC by contacting Rhyolite Software | |
22 * at sales@rhyolite.com. | |
23 * | |
24 * A commercial license would be for Distributed Checksum and Reputation | |
25 * Clearinghouse software. That software includes additional features. This | |
26 * free license for Distributed ChecksumClearinghouse Software does not in any | |
27 * way grant permision to use Distributed Checksum and Reputation Clearinghouse | |
28 * software | |
29 * | |
30 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL | |
31 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES | |
32 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC | |
33 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES | |
34 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
35 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
36 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
37 * SOFTWARE. | |
38 * | |
39 * Rhyolite Software DCC 1.3.103-1.23 $Revision$ | |
40 */ | |
41 | |
42 | |
43 #include "dcc_defs.h" | |
44 | |
45 #ifdef DCC_WIN32 | |
46 | |
47 static DCC_PATH path_tmp; | |
48 const char *_PATH_TMP = path_tmp; | |
49 | |
50 static u_char is_nt; | |
51 | |
52 | |
53 void | |
54 win32_init(void) | |
55 { | |
56 OSVERSIONINFO ver; | |
57 WSADATA WSAData; | |
58 | |
59 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
60 GetVersionEx(&ver); | |
61 is_nt = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT); | |
62 | |
63 if (WSAStartup(MAKEWORD(2, 0), &WSAData)) | |
64 dcc_logbad(EX_SOFTWARE, "WSAStartup(): %s", ERROR_STR()); | |
65 | |
66 atexit((void(*)(void))WSACleanup); | |
67 | |
68 GetTempPath(sizeof(path_tmp), path_tmp); | |
69 | |
70 #ifdef __BORLANDC__ | |
71 _fmode = O_BINARY; | |
72 #endif | |
73 } | |
74 | |
75 | |
76 | |
77 int | |
78 gettimeofday(struct timeval *tv, struct timezone *tzp) | |
79 { | |
80 static SYSTEMTIME epoch_st = {1970, 1, 0, 1, 0, 0, 0, 0}; | |
81 static LONGLONG epoch; /* the first second of the UNIX epoch */ | |
82 LONGLONG now; | |
83 | |
84 if (epoch == 0) | |
85 SystemTimeToFileTime(&epoch_st, (FILETIME *)&epoch); | |
86 GetSystemTimeAsFileTime((FILETIME *)&now); | |
87 now -= epoch; | |
88 now /= 10; | |
89 tv->tv_sec = now/(1000*1000); | |
90 tv->tv_usec = now%(1000*1000); | |
91 return 0; | |
92 } | |
93 | |
94 | |
95 | |
96 void | |
97 win32_unmap(HANDLE *hp, void *p, const char *nm) | |
98 { | |
99 if (!UnmapViewOfFile(p)) | |
100 dcc_error_msg("UnmapViewOfFile(%s): %s", nm, ERROR_STR()); | |
101 if (!CloseHandle(*hp)) | |
102 dcc_error_msg("CloseHandle(%s): %s", nm, ERROR_STR()); | |
103 *hp = INVALID_HANDLE_VALUE; | |
104 } | |
105 | |
106 | |
107 | |
108 void * | |
109 win32_map(DCC_EMSG emsg, | |
110 HANDLE *map_handle, /* put handle for the map here */ | |
111 const char *nm, /* for this resolved path name */ | |
112 int fd, /* with this C style file descriptor */ | |
113 int size) /* with this size (to extend file) */ | |
114 { | |
115 static char junk; /* foil optimizer */ | |
116 DCC_PATH map_nm; | |
117 HANDLE h; | |
118 void *p; | |
119 int i; | |
120 | |
121 /* make a name for the mapping */ | |
122 if (!fnm2abs(map_nm, nm, 0)) | |
123 STRLCPY(map_nm, nm, sizeof(DCC_PATH)); | |
124 for (i = 0; i < sizeof(DCC_PATH) && map_nm[i] != '\0'; ++i) { | |
125 if (map_nm[i] == '/' || map_nm[i] == '\\') | |
126 map_nm[i] = '-'; | |
127 } | |
128 | |
129 h = CreateFileMapping((HANDLE)_get_osfhandle(fd), | |
130 0, PAGE_READWRITE, 0, size, map_nm); | |
131 if (!h) { | |
132 dcc_pemsg(EX_IOERR, emsg, "CreateFileMapping(%s): %s", | |
133 nm, ERROR_STR()); | |
134 *map_handle = INVALID_HANDLE_VALUE; | |
135 return 0; | |
136 } | |
137 p = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0,0, size); | |
138 if (!p) { | |
139 dcc_pemsg(EX_IOERR, emsg, "MapViewOfFile(%s): %s", | |
140 nm, ERROR_STR()); | |
141 CloseHandle(h); | |
142 *map_handle = INVALID_HANDLE_VALUE; | |
143 return 0; | |
144 } | |
145 | |
146 /* If you immediately lock the file, the mapping is garbage on Win98. | |
147 * It seems to help to poke at the mapping. | |
148 * One theory is that a page fault on a locked file fails */ | |
149 for (i = 0; i < size; i += 512) | |
150 junk += ((char *)p)[i]; | |
151 | |
152 *map_handle = h; | |
153 return p; | |
154 } | |
155 | |
156 | |
157 | |
158 /* get an exclusive lock on a file */ | |
159 u_char | |
160 win32_lock(HANDLE h, DWORD flags) | |
161 { | |
162 OVERLAPPED olap; | |
163 int e; | |
164 | |
165 if (is_nt) { | |
166 memset(&olap, 0, sizeof(olap)); | |
167 return LockFileEx(h, flags, 0, 1,0, &olap); | |
168 } | |
169 | |
170 /* this is ugly, but so is Win95 */ | |
171 for (;;) { | |
172 if (LockFile(h, 0,0, 1,0)) | |
173 return 1; | |
174 e = GetLastError(); | |
175 if (e != ERROR_LOCKED | |
176 && e != ERROR_LOCK_VIOLATION | |
177 && e != ERROR_SHARING_VIOLATION) | |
178 return 0; | |
179 Sleep(100); | |
180 } | |
181 } | |
182 | |
183 | |
184 | |
185 u_char | |
186 win32_unlock(HANDLE h) | |
187 { | |
188 return UnlockFile(h, 0,0, 1,0); | |
189 } | |
190 | |
191 | |
192 | |
193 /* not all WIN32 systems have snprintf | |
194 * At least some versions of FormatMessage() do not understand %f | |
195 * There should be no unsafe sprintf's, so worry only a little */ | |
196 int | |
197 dcc_vsnprintf(char *tgt, int tgt_len, const char *pat, va_list args) | |
198 { | |
199 char buf[32*1024]; | |
200 int len; | |
201 | |
202 len = vsprintf(buf, pat, args); | |
203 STRLCPY(tgt, buf, tgt_len); | |
204 return len; | |
205 } | |
206 | |
207 | |
208 | |
209 int | |
210 dcc_snprintf(char *buf, int buf_len, const char *pat, ...) | |
211 { | |
212 int len; | |
213 va_list args; | |
214 | |
215 va_start(args, pat); | |
216 len = dcc_vsnprintf(buf, buf_len, pat, args); | |
217 va_end(args); | |
218 return len; | |
219 } | |
220 | |
221 | |
222 | |
223 /* in NT, this should probably have something to do with the event log */ | |
224 | |
225 char syslog_prefix[64]; | |
226 | |
227 #pragma argsused | |
228 void | |
229 openlog(const char *ident, int logopt, int facility) | |
230 { | |
231 BUFCPY(syslog_prefix, ident); | |
232 } | |
233 | |
234 | |
235 | |
236 #pragma argsused | |
237 void | |
238 vsyslog(int priority, const char *msg, va_list args) | |
239 { | |
240 struct tm tm; | |
241 char *bp, buf[sizeof(syslog_prefix)+256]; | |
242 | |
243 if (dcc_no_syslog) | |
244 return; | |
245 | |
246 strcpy(buf, syslog_prefix); | |
247 bp = buf+strlen(buf); | |
248 dcc_localtime(time(0), &tm); | |
249 bp += strftime(bp, &buf[sizeof(buf)-3]-bp, " %D %H:%M:%S ", &tm); | |
250 if (bp >= &buf[sizeof(buf)-3]) | |
251 bp = &buf[sizeof(buf)-3]; | |
252 | |
253 bp += vsnprintf(bp, &buf[sizeof(buf)-3]-bp, msg, args); | |
254 if (bp >= &buf[sizeof(buf)-3]) | |
255 bp = &buf[sizeof(buf)-3]; | |
256 strcpy(bp, "\r\n"); | |
257 | |
258 puts(buf); | |
259 } | |
260 | |
261 | |
262 | |
263 void | |
264 syslog(int priority, const char *msg, ...) | |
265 { | |
266 va_list args; | |
267 | |
268 va_start(args, msg); | |
269 vsyslog(priority, msg, args); | |
270 va_end(args); | |
271 } | |
272 | |
273 | |
274 | |
275 void | |
276 closelog(void) | |
277 { | |
278 fflush(stdout); | |
279 fflush(stderr); | |
280 } | |
281 | |
282 | |
283 /* Strip any CR or LF and convert the strange, non-ASCII | |
284 * garbage from Microsoft messages | |
285 * Trim the trailing blanks and '.' from Borland messages */ | |
286 static void | |
287 ws_strip(const char *begin, char *tgt, char *end) | |
288 { | |
289 const char *src; | |
290 char c; | |
291 | |
292 src = begin; | |
293 do { | |
294 if (tgt >= end) { | |
295 *tgt++ = '\0'; | |
296 break; | |
297 } | |
298 c = *src++; | |
299 if (c == '\r') /* skip carriage return */ | |
300 continue; | |
301 if (c == '\n') | |
302 c = ' '; | |
303 if ((c < ' ' && c != '\0') || c > 0x7e) | |
304 c = '?'; | |
305 *tgt++ = c; | |
306 } while (c != '\0'); | |
307 | |
308 /* trim trailing whitespace */ | |
309 --tgt; | |
310 while (--tgt >= begin | |
311 && ((c = *tgt) == ' ' || c == '\t' || c == '.')) { | |
312 *tgt = '\0'; | |
313 } | |
314 } | |
315 | |
316 | |
317 | |
318 /* complete the lame strerror() from Borland for WIN95 */ | |
319 const char * | |
320 ws_strerror(int eno) | |
321 { | |
322 static struct { | |
323 char s[256]; | |
324 } ebufs[8]; | |
325 static int ebuf_num; | |
326 int bn; | |
327 const char *src; | |
328 char *begin; | |
329 | |
330 /* Borland fopen() and who knows what else does not set | |
331 * the WIN32 GetLastError() value */ | |
332 #ifdef __BORLANDC__ | |
333 /* sometimes the Borland wrapper for errno works better */ | |
334 if (eno == 0) | |
335 eno = *__errno(); | |
336 #endif | |
337 if (eno == 0) | |
338 return "unknown error"; | |
339 | |
340 /* Use an array of static buffers to kludge around problems with | |
341 * threads */ | |
342 bn = ebuf_num; | |
343 ebuf_num = (bn+1) % DIM(ebufs); | |
344 begin = ebufs[bn].s; | |
345 | |
346 /* Use the Microsoft message if it is not silly. */ | |
347 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, | |
348 0, eno, 0, begin, sizeof(ebufs[bn].s), 0)) { | |
349 | |
350 /* strip any CR or LF and convert the strange, non-ASCII | |
351 * garbage from Microsoft messages */ | |
352 ws_strip(begin, begin, begin+sizeof(ebufs[bn].s)-1); | |
353 if (strlen(begin) < 128) | |
354 return begin; | |
355 } | |
356 | |
357 /* If Microsoft fails, try the Borland messages, | |
358 * and use anything other than "unknown error" */ | |
359 src = strerror(eno); | |
360 if (strcmp(src, "Unknown error\n")) { | |
361 ws_strip(src, begin, begin+sizeof(ebufs[bn].s)-1); | |
362 return begin; | |
363 } | |
364 | |
365 /* MicroSoft has only some of the BSD standard error messages */ | |
366 switch (eno) { | |
367 case WSAEACCES: return "SO_BROADCAST not enabled"; | |
368 case WSAEADDRINUSE: return "address already in use"; | |
369 case WSAEADDRNOTAVAIL: return "address not available"; | |
370 case WSAEAFNOSUPPORT: return "Address family not supported"; | |
371 case WSAEALREADY: return "nonblocking connect in progress"; | |
372 case WSAEBADF: return "Bad file descriptor"; | |
373 case WSAECONNABORTED: return "Software caused connection abort"; | |
374 case WSAECONNREFUSED: return "Connection refused"; | |
375 case WSAECONNRESET: return "Connection reset by peer"; | |
376 case WSAEDESTADDRREQ: return "Destination address required"; | |
377 case WSAEDQUOT: return "Disc quota exceeded"; | |
378 case WSAEFAULT: return "WS bad address"; | |
379 case WSAEHOSTDOWN: return "Host is down"; | |
380 case WSAEHOSTUNREACH: return "No route to host"; | |
381 case WSAEINPROGRESS: return "winsock 1.1 call in progress"; | |
382 case WSAEINTR: return "cancelled by WSACancelBlockingCall"; | |
383 case WSAEINVAL: return "WS invalid argument"; | |
384 case WSAEISCONN: return "Socket is already connected"; | |
385 case WSAELOOP: return "Too many levels of symbolic links"; | |
386 case WSAEMFILE: return "Too many open files"; | |
387 case WSAEMSGSIZE: return "Message too long"; | |
388 case WSAENAMETOOLONG: return "File name too long"; | |
389 case WSAENETDOWN: return "network is down"; | |
390 case WSAENETRESET: return "Network dropped connection on reset"; | |
391 case WSAENETUNREACH: return "network is unreachable"; | |
392 case WSAENOBUFS: return "No buffer space available"; | |
393 case WSAENOPROTOOPT: return "Protocol not available"; | |
394 case WSAENOTCONN: return "Socket is not connected"; | |
395 case WSAENOTEMPTY: return "Directory not empty"; | |
396 case WSAENOTSOCK: return "socket operation on non-socket"; | |
397 case WSAEOPNOTSUPP: return "Operation not supported"; | |
398 case WSAEPFNOSUPPORT: return "Protocol family not supported"; | |
399 case WSAEPROCLIM: return "Too many processes"; | |
400 case WSAEPROTONOSUPPORT:return "Protocol not supported"; | |
401 case WSAEPROTOTYPE: return "Protocol wrong type for socket"; | |
402 case WSAEREMOTE: return "Too many levels of remote in path"; | |
403 case WSAESHUTDOWN: return "Can't send after socket shutdown"; | |
404 case WSAESOCKTNOSUPPORT:return "Socket type not supported"; | |
405 case WSAESTALE: return "Stale NFS file handle"; | |
406 case WSAETIMEDOUT: return "Operation timed out"; | |
407 case WSAETOOMANYREFS: return "Too many references: can't splice"; | |
408 case WSAEUSERS: return "Too many users"; | |
409 case WSAEWOULDBLOCK: return "Operation would block"; | |
410 case WSANOTINITIALISED: return "WSAStartup not done"; | |
411 case WSAHOST_NOT_FOUND: return "Unknown host"; | |
412 case WSATRY_AGAIN: return "Host name lookup failure"; | |
413 case WSANO_RECOVERY: return "Unknown server error"; | |
414 case WSANO_DATA: return "No address associated with name"; | |
415 } | |
416 | |
417 /* fall back on Borland's "unkonwn error", but admit the error # */ | |
418 snprintf(begin, sizeof(ebufs[bn].s), "Unknown error %d", eno); | |
419 return begin; | |
420 } | |
421 #endif /* !DCC_WIN32 */ |