6
* AUTHOR: Guido Serassio <serassio@squid-cache.org>
7
* inspired by previous work by Romeo Anghelache & Eric Stern.
9
* SQUID Web Proxy Cache http://www.squid-cache.org/
10
* ----------------------------------------------------------
12
* Squid is the result of efforts by numerous individuals from
13
* the Internet community; see the CONTRIBUTORS file for full
14
* details. Many organizations have provided support for Squid's
15
* development; see the SPONSORS file for full details. Squid is
16
* Copyrighted (C) 2001 by the Regents of the University of
17
* California; see the COPYRIGHT file for full details. Squid
18
* incorporates software developed and/or copyrighted by other
19
* sources; see the CREDITS file for full details.
21
* This program is free software; you can redistribute it and/or modify
22
* it under the terms of the GNU General Public License as published by
23
* the Free Software Foundation; either version 2 of the License, or
24
* (at your option) any later version.
26
* This program is distributed in the hope that it will be useful,
27
* but WITHOUT ANY WARRANTY; without even the implied warranty of
28
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
* GNU General Public License for more details.
31
* You should have received a copy of the GNU General Public License
32
* along with this program; if not, write to the Free Software
33
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39
/* The following code section is part of an EXPERIMENTAL native */
40
/* Windows NT/2000 Squid port - Compiles only on MS Visual C++ */
41
#if defined(_SQUID_MSWIN_)
44
#define sys_nerr _sys_nerr
50
#include "squid_windows.h"
52
#include <sys/timeb.h>
57
THREADLOCAL int ws32_result;
58
LPCRITICAL_SECTION dbg_mutex = NULL;
60
void GetProcessName(pid_t, char *);
62
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
66
static DWORD system_pagesize = 0;
67
if (!system_pagesize) {
68
SYSTEM_INFO system_info;
69
GetSystemInfo(&system_info);
70
system_pagesize = system_info.dwPageSize;
72
return system_pagesize;
125
chroot(const char *dirname)
127
if (SetCurrentDirectory(dirname))
130
return GetLastError();
134
GetProcessName(pid_t pid, char *ProcessName)
138
strcpy(ProcessName, "unknown");
140
/* Get a handle to the process. */
141
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
144
/* Get the process name. */
145
if (NULL != hProcess) {
149
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
150
GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName));
152
CloseHandle(hProcess);
157
CloseHandle(hProcess);
162
kill(pid_t pid, int sig)
165
char MyProcessName[MAX_PATH];
166
char ProcessNameToCheck[MAX_PATH];
169
if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
171
FALSE, pid)) == NULL)
174
CloseHandle(hProcess);
175
GetProcessName(getpid(), MyProcessName);
176
GetProcessName(pid, ProcessNameToCheck);
177
if (strcmp(MyProcessName, ProcessNameToCheck) == 0)
185
#ifndef HAVE_GETTIMEOFDAY
187
gettimeofday(struct timeval *pcur_time, void *tzp)
189
struct _timeb current;
190
struct timezone *tz = (struct timezone *) tzp;
194
pcur_time->tv_sec = current.time;
195
pcur_time->tv_usec = current.millitm * 1000L;
197
tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */
198
tz->tz_dsttime = current.dstflag; /* type of dst correction */
205
statfs(const char *path, struct statfs *sfs)
208
DWORD spc, bps, freec, totalc;
209
DWORD vsn, maxlen, flags;
215
strncpy(drive, path, 2);
219
if (!GetDiskFreeSpace(drive, &spc, &bps, &freec, &totalc)) {
223
if (!GetVolumeInformation(drive, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) {
228
sfs->f_bsize = spc * bps;
229
sfs->f_blocks = totalc;
230
sfs->f_bfree = sfs->f_bavail = freec;
234
sfs->f_namelen = maxlen;
239
WIN32_ftruncate(int fd, off_t size)
247
hfile = (HANDLE) _get_osfhandle(fd);
248
curpos = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
249
if (curpos == 0xFFFFFFFF
250
|| SetFilePointer(hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
251
|| !SetEndOfFile(hfile)) {
252
int error = GetLastError();
255
case ERROR_INVALID_HANDLE:
269
WIN32_truncate(const char *pathname, off_t length)
274
fd = open(pathname, O_RDWR);
279
res = WIN32_ftruncate(fd, length);
286
static struct _wsaerrtext {
288
const char *errconst;
293
WSA_E_CANCELLED, "WSA_E_CANCELLED", "Lookup cancelled."
296
WSA_E_NO_MORE, "WSA_E_NO_MORE", "No more data available."
299
WSAEACCES, "WSAEACCES", "Permission denied."
302
WSAEADDRINUSE, "WSAEADDRINUSE", "Address already in use."
305
WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", "Cannot assign requested address."
308
WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", "Address family not supported by protocol family."
311
WSAEALREADY, "WSAEALREADY", "Operation already in progress."
314
WSAEBADF, "WSAEBADF", "Bad file number."
317
WSAECANCELLED, "WSAECANCELLED", "Operation cancelled."
320
WSAECONNABORTED, "WSAECONNABORTED", "Software caused connection abort."
323
WSAECONNREFUSED, "WSAECONNREFUSED", "Connection refused."
326
WSAECONNRESET, "WSAECONNRESET", "Connection reset by peer."
329
WSAEDESTADDRREQ, "WSAEDESTADDRREQ", "Destination address required."
332
WSAEDQUOT, "WSAEDQUOT", "Disk quota exceeded."
335
WSAEFAULT, "WSAEFAULT", "Bad address."
338
WSAEHOSTDOWN, "WSAEHOSTDOWN", "Host is down."
341
WSAEHOSTUNREACH, "WSAEHOSTUNREACH", "No route to host."
344
WSAEINPROGRESS, "WSAEINPROGRESS", "Operation now in progress."
347
WSAEINTR, "WSAEINTR", "Interrupted function call."
350
WSAEINVAL, "WSAEINVAL", "Invalid argument."
353
WSAEINVALIDPROCTABLE, "WSAEINVALIDPROCTABLE", "Invalid procedure table from service provider."
356
WSAEINVALIDPROVIDER, "WSAEINVALIDPROVIDER", "Invalid service provider version number."
359
WSAEISCONN, "WSAEISCONN", "Socket is already connected."
362
WSAELOOP, "WSAELOOP", "Too many levels of symbolic links."
365
WSAEMFILE, "WSAEMFILE", "Too many open files."
368
WSAEMSGSIZE, "WSAEMSGSIZE", "Message too long."
371
WSAENAMETOOLONG, "WSAENAMETOOLONG", "File name is too long."
374
WSAENETDOWN, "WSAENETDOWN", "Network is down."
377
WSAENETRESET, "WSAENETRESET", "Network dropped connection on reset."
380
WSAENETUNREACH, "WSAENETUNREACH", "Network is unreachable."
383
WSAENOBUFS, "WSAENOBUFS", "No buffer space available."
386
WSAENOMORE, "WSAENOMORE", "No more data available."
389
WSAENOPROTOOPT, "WSAENOPROTOOPT", "Bad protocol option."
392
WSAENOTCONN, "WSAENOTCONN", "Socket is not connected."
395
WSAENOTEMPTY, "WSAENOTEMPTY", "Directory is not empty."
398
WSAENOTSOCK, "WSAENOTSOCK", "Socket operation on nonsocket."
401
WSAEOPNOTSUPP, "WSAEOPNOTSUPP", "Operation not supported."
404
WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", "Protocol family not supported."
407
WSAEPROCLIM, "WSAEPROCLIM", "Too many processes."
410
WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", "Protocol not supported."
413
WSAEPROTOTYPE, "WSAEPROTOTYPE", "Protocol wrong type for socket."
416
WSAEPROVIDERFAILEDINIT, "WSAEPROVIDERFAILEDINIT", "Unable to initialise a service provider."
419
WSAEREFUSED, "WSAEREFUSED", "Refused."
422
WSAEREMOTE, "WSAEREMOTE", "Too many levels of remote in path."
425
WSAESHUTDOWN, "WSAESHUTDOWN", "Cannot send after socket shutdown."
428
WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", "Socket type not supported."
431
WSAESTALE, "WSAESTALE", "Stale NFS file handle."
434
WSAETIMEDOUT, "WSAETIMEDOUT", "Connection timed out."
437
WSAETOOMANYREFS, "WSAETOOMANYREFS", "Too many references."
440
WSAEUSERS, "WSAEUSERS", "Too many users."
443
WSAEWOULDBLOCK, "WSAEWOULDBLOCK", "Resource temporarily unavailable."
446
WSANOTINITIALISED, "WSANOTINITIALISED", "Successful WSAStartup not yet performed."
449
WSASERVICE_NOT_FOUND, "WSASERVICE_NOT_FOUND", "Service not found."
452
WSASYSCALLFAILURE, "WSASYSCALLFAILURE", "System call failure."
455
WSASYSNOTREADY, "WSASYSNOTREADY", "Network subsystem is unavailable."
458
WSATYPE_NOT_FOUND, "WSATYPE_NOT_FOUND", "Class type not found."
461
WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED", "Winsock.dll version out of range."
464
WSAEDISCON, "WSAEDISCON", "Graceful shutdown in progress."
469
* wsastrerror() - description of WSAGetLastError()
474
static char xwsaerror_buf[BUFSIZ];
478
return "(0) No error.";
479
for (i = 0; i < sizeof(_wsaerrtext) / sizeof(struct _wsaerrtext); i++) {
480
if (_wsaerrtext[i].err != err)
486
snprintf(xwsaerror_buf, BUFSIZ, "Unknown");
488
snprintf(xwsaerror_buf, BUFSIZ, "%s, %s", _wsaerrtext[errind].errconst, _wsaerrtext[errind].errdesc);
489
return xwsaerror_buf;
493
getpwnam(char *unused) {
494
static struct passwd pwd = {NULL, NULL, 100, 100, NULL, NULL, NULL};
499
getgrnam(char *unused) {
500
static struct group grp = {NULL, NULL, 100, NULL};
505
* WIN32_strerror with argument for late notification */
508
WIN32_strerror(int err)
510
static char xbstrerror_buf[BUFSIZ];
512
if (err < 0 || err >= sys_nerr)
513
strncpy(xbstrerror_buf, wsastrerror(err), BUFSIZ);
515
strncpy(xbstrerror_buf, strerror(err), BUFSIZ);
516
return xbstrerror_buf;
519
#if defined(__MINGW32__) /* MinGW environment */
521
_free_osfhnd(int filehandle)
523
if (((unsigned) filehandle < SQUID_MAXFD) &&
524
(_osfile(filehandle) & FOPEN) &&
525
(_osfhnd(filehandle) != (long) INVALID_HANDLE_VALUE)) {
526
switch (filehandle) {
528
SetStdHandle(STD_INPUT_HANDLE, NULL);
531
SetStdHandle(STD_OUTPUT_HANDLE, NULL);
534
SetStdHandle(STD_ERROR_HANDLE, NULL);
537
_osfhnd(filehandle) = (long) INVALID_HANDLE_VALUE;
540
errno = EBADF; /* bad handle */
541
_doserrno = 0L; /* not an OS error */
548
unsigned long WIN32_code;
552
static struct errorentry errortable[] = {
553
{ERROR_INVALID_FUNCTION, EINVAL},
554
{ERROR_FILE_NOT_FOUND, ENOENT},
555
{ERROR_PATH_NOT_FOUND, ENOENT},
556
{ERROR_TOO_MANY_OPEN_FILES, EMFILE},
557
{ERROR_ACCESS_DENIED, EACCES},
558
{ERROR_INVALID_HANDLE, EBADF},
559
{ERROR_ARENA_TRASHED, ENOMEM},
560
{ERROR_NOT_ENOUGH_MEMORY, ENOMEM},
561
{ERROR_INVALID_BLOCK, ENOMEM},
562
{ERROR_BAD_ENVIRONMENT, E2BIG},
563
{ERROR_BAD_FORMAT, ENOEXEC},
564
{ERROR_INVALID_ACCESS, EINVAL},
565
{ERROR_INVALID_DATA, EINVAL},
566
{ERROR_INVALID_DRIVE, ENOENT},
567
{ERROR_CURRENT_DIRECTORY, EACCES},
568
{ERROR_NOT_SAME_DEVICE, EXDEV},
569
{ERROR_NO_MORE_FILES, ENOENT},
570
{ERROR_LOCK_VIOLATION, EACCES},
571
{ERROR_BAD_NETPATH, ENOENT},
572
{ERROR_NETWORK_ACCESS_DENIED, EACCES},
573
{ERROR_BAD_NET_NAME, ENOENT},
574
{ERROR_FILE_EXISTS, EEXIST},
575
{ERROR_CANNOT_MAKE, EACCES},
576
{ERROR_FAIL_I24, EACCES},
577
{ERROR_INVALID_PARAMETER, EINVAL},
578
{ERROR_NO_PROC_SLOTS, EAGAIN},
579
{ERROR_DRIVE_LOCKED, EACCES},
580
{ERROR_BROKEN_PIPE, EPIPE},
581
{ERROR_DISK_FULL, ENOSPC},
582
{ERROR_INVALID_TARGET_HANDLE, EBADF},
583
{ERROR_INVALID_HANDLE, EINVAL},
584
{ERROR_WAIT_NO_CHILDREN, ECHILD},
585
{ERROR_CHILD_NOT_COMPLETE, ECHILD},
586
{ERROR_DIRECT_ACCESS_HANDLE, EBADF},
587
{ERROR_NEGATIVE_SEEK, EINVAL},
588
{ERROR_SEEK_ON_DEVICE, EACCES},
589
{ERROR_DIR_NOT_EMPTY, ENOTEMPTY},
590
{ERROR_NOT_LOCKED, EACCES},
591
{ERROR_BAD_PATHNAME, ENOENT},
592
{ERROR_MAX_THRDS_REACHED, EAGAIN},
593
{ERROR_LOCK_FAILED, EACCES},
594
{ERROR_ALREADY_EXISTS, EEXIST},
595
{ERROR_FILENAME_EXCED_RANGE, ENOENT},
596
{ERROR_NESTING_NOT_ALLOWED, EAGAIN},
597
{ERROR_NOT_ENOUGH_QUOTA, ENOMEM}
600
#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
601
#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
603
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
604
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
607
WIN32_maperror(unsigned long WIN32_oserrno)
611
_doserrno = WIN32_oserrno;
612
for (i = 0; i < (sizeof(errortable) / sizeof(struct errorentry)); ++i) {
613
if (WIN32_oserrno == errortable[i].WIN32_code) {
614
errno = errortable[i].POSIX_errno;
618
if (WIN32_oserrno >= MIN_EACCES_RANGE && WIN32_oserrno <= MAX_EACCES_RANGE)
620
else if (WIN32_oserrno >= MIN_EXEC_ERROR && WIN32_oserrno <= MAX_EXEC_ERROR)