Mercurial > notdcc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcclib/win32.c Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,421 @@ +/* Distributed Checksum Clearinghouse + * + * routines to make WIN32 look sort of reasonable + * + * Copyright (c) 2008 by Rhyolite Software, LLC + * + * This agreement is not applicable to any entity which sells anti-spam + * solutions to others or provides an anti-spam solution as part of a + * security solution sold to other entities, or to a private network + * which employs the DCC or uses data provided by operation of the DCC + * but does not provide corresponding data to other users. + * + * Permission to use, copy, modify, and distribute this software without + * changes for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice appear in all + * copies and any distributed versions or copies are either unchanged + * or not called anything similar to "DCC" or "Distributed Checksum + * Clearinghouse". + * + * Parties not eligible to receive a license under this agreement can + * obtain a commercial license to use DCC by contacting Rhyolite Software + * at sales@rhyolite.com. + * + * A commercial license would be for Distributed Checksum and Reputation + * Clearinghouse software. That software includes additional features. This + * free license for Distributed ChecksumClearinghouse Software does not in any + * way grant permision to use Distributed Checksum and Reputation Clearinghouse + * software + * + * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC + * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Rhyolite Software DCC 1.3.103-1.23 $Revision$ + */ + + +#include "dcc_defs.h" + +#ifdef DCC_WIN32 + +static DCC_PATH path_tmp; +const char *_PATH_TMP = path_tmp; + +static u_char is_nt; + + +void +win32_init(void) +{ + OSVERSIONINFO ver; + WSADATA WSAData; + + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ver); + is_nt = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT); + + if (WSAStartup(MAKEWORD(2, 0), &WSAData)) + dcc_logbad(EX_SOFTWARE, "WSAStartup(): %s", ERROR_STR()); + + atexit((void(*)(void))WSACleanup); + + GetTempPath(sizeof(path_tmp), path_tmp); + +#ifdef __BORLANDC__ + _fmode = O_BINARY; +#endif +} + + + +int +gettimeofday(struct timeval *tv, struct timezone *tzp) +{ + static SYSTEMTIME epoch_st = {1970, 1, 0, 1, 0, 0, 0, 0}; + static LONGLONG epoch; /* the first second of the UNIX epoch */ + LONGLONG now; + + if (epoch == 0) + SystemTimeToFileTime(&epoch_st, (FILETIME *)&epoch); + GetSystemTimeAsFileTime((FILETIME *)&now); + now -= epoch; + now /= 10; + tv->tv_sec = now/(1000*1000); + tv->tv_usec = now%(1000*1000); + return 0; +} + + + +void +win32_unmap(HANDLE *hp, void *p, const char *nm) +{ + if (!UnmapViewOfFile(p)) + dcc_error_msg("UnmapViewOfFile(%s): %s", nm, ERROR_STR()); + if (!CloseHandle(*hp)) + dcc_error_msg("CloseHandle(%s): %s", nm, ERROR_STR()); + *hp = INVALID_HANDLE_VALUE; +} + + + +void * +win32_map(DCC_EMSG emsg, + HANDLE *map_handle, /* put handle for the map here */ + const char *nm, /* for this resolved path name */ + int fd, /* with this C style file descriptor */ + int size) /* with this size (to extend file) */ +{ + static char junk; /* foil optimizer */ + DCC_PATH map_nm; + HANDLE h; + void *p; + int i; + + /* make a name for the mapping */ + if (!fnm2abs(map_nm, nm, 0)) + STRLCPY(map_nm, nm, sizeof(DCC_PATH)); + for (i = 0; i < sizeof(DCC_PATH) && map_nm[i] != '\0'; ++i) { + if (map_nm[i] == '/' || map_nm[i] == '\\') + map_nm[i] = '-'; + } + + h = CreateFileMapping((HANDLE)_get_osfhandle(fd), + 0, PAGE_READWRITE, 0, size, map_nm); + if (!h) { + dcc_pemsg(EX_IOERR, emsg, "CreateFileMapping(%s): %s", + nm, ERROR_STR()); + *map_handle = INVALID_HANDLE_VALUE; + return 0; + } + p = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0,0, size); + if (!p) { + dcc_pemsg(EX_IOERR, emsg, "MapViewOfFile(%s): %s", + nm, ERROR_STR()); + CloseHandle(h); + *map_handle = INVALID_HANDLE_VALUE; + return 0; + } + + /* If you immediately lock the file, the mapping is garbage on Win98. + * It seems to help to poke at the mapping. + * One theory is that a page fault on a locked file fails */ + for (i = 0; i < size; i += 512) + junk += ((char *)p)[i]; + + *map_handle = h; + return p; +} + + + +/* get an exclusive lock on a file */ +u_char +win32_lock(HANDLE h, DWORD flags) +{ + OVERLAPPED olap; + int e; + + if (is_nt) { + memset(&olap, 0, sizeof(olap)); + return LockFileEx(h, flags, 0, 1,0, &olap); + } + + /* this is ugly, but so is Win95 */ + for (;;) { + if (LockFile(h, 0,0, 1,0)) + return 1; + e = GetLastError(); + if (e != ERROR_LOCKED + && e != ERROR_LOCK_VIOLATION + && e != ERROR_SHARING_VIOLATION) + return 0; + Sleep(100); + } +} + + + +u_char +win32_unlock(HANDLE h) +{ + return UnlockFile(h, 0,0, 1,0); +} + + + +/* not all WIN32 systems have snprintf + * At least some versions of FormatMessage() do not understand %f + * There should be no unsafe sprintf's, so worry only a little */ +int +dcc_vsnprintf(char *tgt, int tgt_len, const char *pat, va_list args) +{ + char buf[32*1024]; + int len; + + len = vsprintf(buf, pat, args); + STRLCPY(tgt, buf, tgt_len); + return len; +} + + + +int +dcc_snprintf(char *buf, int buf_len, const char *pat, ...) +{ + int len; + va_list args; + + va_start(args, pat); + len = dcc_vsnprintf(buf, buf_len, pat, args); + va_end(args); + return len; +} + + + +/* in NT, this should probably have something to do with the event log */ + +char syslog_prefix[64]; + +#pragma argsused +void +openlog(const char *ident, int logopt, int facility) +{ + BUFCPY(syslog_prefix, ident); +} + + + +#pragma argsused +void +vsyslog(int priority, const char *msg, va_list args) +{ + struct tm tm; + char *bp, buf[sizeof(syslog_prefix)+256]; + + if (dcc_no_syslog) + return; + + strcpy(buf, syslog_prefix); + bp = buf+strlen(buf); + dcc_localtime(time(0), &tm); + bp += strftime(bp, &buf[sizeof(buf)-3]-bp, " %D %H:%M:%S ", &tm); + if (bp >= &buf[sizeof(buf)-3]) + bp = &buf[sizeof(buf)-3]; + + bp += vsnprintf(bp, &buf[sizeof(buf)-3]-bp, msg, args); + if (bp >= &buf[sizeof(buf)-3]) + bp = &buf[sizeof(buf)-3]; + strcpy(bp, "\r\n"); + + puts(buf); +} + + + +void +syslog(int priority, const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + vsyslog(priority, msg, args); + va_end(args); +} + + + +void +closelog(void) +{ + fflush(stdout); + fflush(stderr); +} + + +/* Strip any CR or LF and convert the strange, non-ASCII + * garbage from Microsoft messages + * Trim the trailing blanks and '.' from Borland messages */ +static void +ws_strip(const char *begin, char *tgt, char *end) +{ + const char *src; + char c; + + src = begin; + do { + if (tgt >= end) { + *tgt++ = '\0'; + break; + } + c = *src++; + if (c == '\r') /* skip carriage return */ + continue; + if (c == '\n') + c = ' '; + if ((c < ' ' && c != '\0') || c > 0x7e) + c = '?'; + *tgt++ = c; + } while (c != '\0'); + + /* trim trailing whitespace */ + --tgt; + while (--tgt >= begin + && ((c = *tgt) == ' ' || c == '\t' || c == '.')) { + *tgt = '\0'; + } +} + + + +/* complete the lame strerror() from Borland for WIN95 */ +const char * +ws_strerror(int eno) +{ + static struct { + char s[256]; + } ebufs[8]; + static int ebuf_num; + int bn; + const char *src; + char *begin; + + /* Borland fopen() and who knows what else does not set + * the WIN32 GetLastError() value */ +#ifdef __BORLANDC__ + /* sometimes the Borland wrapper for errno works better */ + if (eno == 0) + eno = *__errno(); +#endif + if (eno == 0) + return "unknown error"; + + /* Use an array of static buffers to kludge around problems with + * threads */ + bn = ebuf_num; + ebuf_num = (bn+1) % DIM(ebufs); + begin = ebufs[bn].s; + + /* Use the Microsoft message if it is not silly. */ + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + 0, eno, 0, begin, sizeof(ebufs[bn].s), 0)) { + + /* strip any CR or LF and convert the strange, non-ASCII + * garbage from Microsoft messages */ + ws_strip(begin, begin, begin+sizeof(ebufs[bn].s)-1); + if (strlen(begin) < 128) + return begin; + } + + /* If Microsoft fails, try the Borland messages, + * and use anything other than "unknown error" */ + src = strerror(eno); + if (strcmp(src, "Unknown error\n")) { + ws_strip(src, begin, begin+sizeof(ebufs[bn].s)-1); + return begin; + } + + /* MicroSoft has only some of the BSD standard error messages */ + switch (eno) { + case WSAEACCES: return "SO_BROADCAST not enabled"; + case WSAEADDRINUSE: return "address already in use"; + case WSAEADDRNOTAVAIL: return "address not available"; + case WSAEAFNOSUPPORT: return "Address family not supported"; + case WSAEALREADY: return "nonblocking connect in progress"; + case WSAEBADF: return "Bad file descriptor"; + case WSAECONNABORTED: return "Software caused connection abort"; + case WSAECONNREFUSED: return "Connection refused"; + case WSAECONNRESET: return "Connection reset by peer"; + case WSAEDESTADDRREQ: return "Destination address required"; + case WSAEDQUOT: return "Disc quota exceeded"; + case WSAEFAULT: return "WS bad address"; + case WSAEHOSTDOWN: return "Host is down"; + case WSAEHOSTUNREACH: return "No route to host"; + case WSAEINPROGRESS: return "winsock 1.1 call in progress"; + case WSAEINTR: return "cancelled by WSACancelBlockingCall"; + case WSAEINVAL: return "WS invalid argument"; + case WSAEISCONN: return "Socket is already connected"; + case WSAELOOP: return "Too many levels of symbolic links"; + case WSAEMFILE: return "Too many open files"; + case WSAEMSGSIZE: return "Message too long"; + case WSAENAMETOOLONG: return "File name too long"; + case WSAENETDOWN: return "network is down"; + case WSAENETRESET: return "Network dropped connection on reset"; + case WSAENETUNREACH: return "network is unreachable"; + case WSAENOBUFS: return "No buffer space available"; + case WSAENOPROTOOPT: return "Protocol not available"; + case WSAENOTCONN: return "Socket is not connected"; + case WSAENOTEMPTY: return "Directory not empty"; + case WSAENOTSOCK: return "socket operation on non-socket"; + case WSAEOPNOTSUPP: return "Operation not supported"; + case WSAEPFNOSUPPORT: return "Protocol family not supported"; + case WSAEPROCLIM: return "Too many processes"; + case WSAEPROTONOSUPPORT:return "Protocol not supported"; + case WSAEPROTOTYPE: return "Protocol wrong type for socket"; + case WSAEREMOTE: return "Too many levels of remote in path"; + case WSAESHUTDOWN: return "Can't send after socket shutdown"; + case WSAESOCKTNOSUPPORT:return "Socket type not supported"; + case WSAESTALE: return "Stale NFS file handle"; + case WSAETIMEDOUT: return "Operation timed out"; + case WSAETOOMANYREFS: return "Too many references: can't splice"; + case WSAEUSERS: return "Too many users"; + case WSAEWOULDBLOCK: return "Operation would block"; + case WSANOTINITIALISED: return "WSAStartup not done"; + case WSAHOST_NOT_FOUND: return "Unknown host"; + case WSATRY_AGAIN: return "Host name lookup failure"; + case WSANO_RECOVERY: return "Unknown server error"; + case WSANO_DATA: return "No address associated with name"; + } + + /* fall back on Borland's "unkonwn error", but admit the error # */ + snprintf(begin, sizeof(ebufs[bn].s), "Unknown error %d", eno); + return begin; +} +#endif /* !DCC_WIN32 */