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 */