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.
40 /* The following code section is part of an EXPERIMENTAL native */
41 /* Windows NT/2000 Squid port - Compiles only on MS Visual C++ */
42 #if defined(_SQUID_MSWIN_)
45 #define sys_nerr _sys_nerr
51 #include "squid_windows.h"
53 #include <sys/timeb.h>
58 THREADLOCAL
int ws32_result
;
59 LPCRITICAL_SECTION dbg_mutex
= NULL
;
61 void GetProcessName(pid_t
, char *);
63 #if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
67 static DWORD system_pagesize
= 0;
68 if (!system_pagesize
) {
69 SYSTEM_INFO system_info
;
70 GetSystemInfo(&system_info
);
71 system_pagesize
= system_info
.dwPageSize
;
73 return system_pagesize
;
126 chroot(const char *dirname
)
128 if (SetCurrentDirectory(dirname
))
131 return GetLastError();
135 GetProcessName(pid_t pid
, char *ProcessName
)
139 strcpy(ProcessName
, "unknown");
141 /* Get a handle to the process. */
142 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
|
145 /* Get the process name. */
146 if (NULL
!= hProcess
) {
150 if (EnumProcessModules(hProcess
, &hMod
, sizeof(hMod
), &cbNeeded
))
151 GetModuleBaseName(hProcess
, hMod
, ProcessName
, sizeof(ProcessName
));
153 CloseHandle(hProcess
);
158 CloseHandle(hProcess
);
163 kill(pid_t pid
, int sig
)
166 char MyProcessName
[MAX_PATH
];
167 char ProcessNameToCheck
[MAX_PATH
];
170 if ((hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
|
172 FALSE
, pid
)) == NULL
)
175 CloseHandle(hProcess
);
176 GetProcessName(getpid(), MyProcessName
);
177 GetProcessName(pid
, ProcessNameToCheck
);
178 if (strcmp(MyProcessName
, ProcessNameToCheck
) == 0)
186 #if !HAVE_GETTIMEOFDAY
188 gettimeofday(struct timeval
*pcur_time
, void *tzp
)
190 struct _timeb current
;
191 struct timezone
*tz
= (struct timezone
*) tzp
;
195 pcur_time
->tv_sec
= current
.time
;
196 pcur_time
->tv_usec
= current
.millitm
* 1000L;
198 tz
->tz_minuteswest
= current
.timezone
; /* minutes west of Greenwich */
199 tz
->tz_dsttime
= current
.dstflag
; /* type of dst correction */
206 statfs(const char *path
, struct statfs
*sfs
)
209 DWORD spc
, bps
, freec
, totalc
;
210 DWORD vsn
, maxlen
, flags
;
216 strncpy(drive
, path
, 2);
220 if (!GetDiskFreeSpace(drive
, &spc
, &bps
, &freec
, &totalc
)) {
224 if (!GetVolumeInformation(drive
, NULL
, 0, &vsn
, &maxlen
, &flags
, NULL
, 0)) {
229 sfs
->f_bsize
= spc
* bps
;
230 sfs
->f_blocks
= totalc
;
231 sfs
->f_bfree
= sfs
->f_bavail
= freec
;
235 sfs
->f_namelen
= maxlen
;
240 WIN32_ftruncate(int fd
, off_t size
)
248 hfile
= (HANDLE
) _get_osfhandle(fd
);
249 curpos
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
250 if (curpos
== 0xFFFFFFFF
251 || SetFilePointer(hfile
, size
, NULL
, FILE_BEGIN
) == 0xFFFFFFFF
252 || !SetEndOfFile(hfile
)) {
253 int error
= GetLastError();
256 case ERROR_INVALID_HANDLE
:
270 WIN32_truncate(const char *pathname
, off_t length
)
275 fd
= open(pathname
, O_RDWR
);
280 res
= WIN32_ftruncate(fd
, length
);
287 static struct _wsaerrtext
{
289 const char *errconst
;
294 WSA_E_CANCELLED
, "WSA_E_CANCELLED", "Lookup cancelled."
297 WSA_E_NO_MORE
, "WSA_E_NO_MORE", "No more data available."
300 WSAEACCES
, "WSAEACCES", "Permission denied."
303 WSAEADDRINUSE
, "WSAEADDRINUSE", "Address already in use."
306 WSAEADDRNOTAVAIL
, "WSAEADDRNOTAVAIL", "Cannot assign requested address."
309 WSAEAFNOSUPPORT
, "WSAEAFNOSUPPORT", "Address family not supported by protocol family."
312 WSAEALREADY
, "WSAEALREADY", "Operation already in progress."
315 WSAEBADF
, "WSAEBADF", "Bad file number."
318 WSAECANCELLED
, "WSAECANCELLED", "Operation cancelled."
321 WSAECONNABORTED
, "WSAECONNABORTED", "Software caused connection abort."
324 WSAECONNREFUSED
, "WSAECONNREFUSED", "Connection refused."
327 WSAECONNRESET
, "WSAECONNRESET", "Connection reset by peer."
330 WSAEDESTADDRREQ
, "WSAEDESTADDRREQ", "Destination address required."
333 WSAEDQUOT
, "WSAEDQUOT", "Disk quota exceeded."
336 WSAEFAULT
, "WSAEFAULT", "Bad address."
339 WSAEHOSTDOWN
, "WSAEHOSTDOWN", "Host is down."
342 WSAEHOSTUNREACH
, "WSAEHOSTUNREACH", "No route to host."
345 WSAEINPROGRESS
, "WSAEINPROGRESS", "Operation now in progress."
348 WSAEINTR
, "WSAEINTR", "Interrupted function call."
351 WSAEINVAL
, "WSAEINVAL", "Invalid argument."
354 WSAEINVALIDPROCTABLE
, "WSAEINVALIDPROCTABLE", "Invalid procedure table from service provider."
357 WSAEINVALIDPROVIDER
, "WSAEINVALIDPROVIDER", "Invalid service provider version number."
360 WSAEISCONN
, "WSAEISCONN", "Socket is already connected."
363 WSAELOOP
, "WSAELOOP", "Too many levels of symbolic links."
366 WSAEMFILE
, "WSAEMFILE", "Too many open files."
369 WSAEMSGSIZE
, "WSAEMSGSIZE", "Message too long."
372 WSAENAMETOOLONG
, "WSAENAMETOOLONG", "File name is too long."
375 WSAENETDOWN
, "WSAENETDOWN", "Network is down."
378 WSAENETRESET
, "WSAENETRESET", "Network dropped connection on reset."
381 WSAENETUNREACH
, "WSAENETUNREACH", "Network is unreachable."
384 WSAENOBUFS
, "WSAENOBUFS", "No buffer space available."
387 WSAENOMORE
, "WSAENOMORE", "No more data available."
390 WSAENOPROTOOPT
, "WSAENOPROTOOPT", "Bad protocol option."
393 WSAENOTCONN
, "WSAENOTCONN", "Socket is not connected."
396 WSAENOTEMPTY
, "WSAENOTEMPTY", "Directory is not empty."
399 WSAENOTSOCK
, "WSAENOTSOCK", "Socket operation on nonsocket."
402 WSAEOPNOTSUPP
, "WSAEOPNOTSUPP", "Operation not supported."
405 WSAEPFNOSUPPORT
, "WSAEPFNOSUPPORT", "Protocol family not supported."
408 WSAEPROCLIM
, "WSAEPROCLIM", "Too many processes."
411 WSAEPROTONOSUPPORT
, "WSAEPROTONOSUPPORT", "Protocol not supported."
414 WSAEPROTOTYPE
, "WSAEPROTOTYPE", "Protocol wrong type for socket."
417 WSAEPROVIDERFAILEDINIT
, "WSAEPROVIDERFAILEDINIT", "Unable to initialise a service provider."
420 WSAEREFUSED
, "WSAEREFUSED", "Refused."
423 WSAEREMOTE
, "WSAEREMOTE", "Too many levels of remote in path."
426 WSAESHUTDOWN
, "WSAESHUTDOWN", "Cannot send after socket shutdown."
429 WSAESOCKTNOSUPPORT
, "WSAESOCKTNOSUPPORT", "Socket type not supported."
432 WSAESTALE
, "WSAESTALE", "Stale NFS file handle."
435 WSAETIMEDOUT
, "WSAETIMEDOUT", "Connection timed out."
438 WSAETOOMANYREFS
, "WSAETOOMANYREFS", "Too many references."
441 WSAEUSERS
, "WSAEUSERS", "Too many users."
444 WSAEWOULDBLOCK
, "WSAEWOULDBLOCK", "Resource temporarily unavailable."
447 WSANOTINITIALISED
, "WSANOTINITIALISED", "Successful WSAStartup not yet performed."
450 WSASERVICE_NOT_FOUND
, "WSASERVICE_NOT_FOUND", "Service not found."
453 WSASYSCALLFAILURE
, "WSASYSCALLFAILURE", "System call failure."
456 WSASYSNOTREADY
, "WSASYSNOTREADY", "Network subsystem is unavailable."
459 WSATYPE_NOT_FOUND
, "WSATYPE_NOT_FOUND", "Class type not found."
462 WSAVERNOTSUPPORTED
, "WSAVERNOTSUPPORTED", "Winsock.dll version out of range."
465 WSAEDISCON
, "WSAEDISCON", "Graceful shutdown in progress."
470 * wsastrerror() - description of WSAGetLastError()
475 static char xwsaerror_buf
[BUFSIZ
];
479 return "(0) No error.";
480 for (i
= 0; i
< sizeof(_wsaerrtext
) / sizeof(struct _wsaerrtext
); i
++) {
481 if (_wsaerrtext
[i
].err
!= err
)
487 snprintf(xwsaerror_buf
, BUFSIZ
, "Unknown");
489 snprintf(xwsaerror_buf
, BUFSIZ
, "%s, %s", _wsaerrtext
[errind
].errconst
, _wsaerrtext
[errind
].errdesc
);
490 return xwsaerror_buf
;
494 getpwnam(char *unused
) {
495 static struct passwd pwd
= {NULL
, NULL
, 100, 100, NULL
, NULL
, NULL
};
500 getgrnam(char *unused
) {
501 static struct group grp
= {NULL
, NULL
, 100, NULL
};
506 * WIN32_strerror with argument for late notification */
509 WIN32_strerror(int err
)
511 static char xbstrerror_buf
[BUFSIZ
];
513 if (err
< 0 || err
>= sys_nerr
)
514 strncpy(xbstrerror_buf
, wsastrerror(err
), BUFSIZ
);
516 strncpy(xbstrerror_buf
, strerror(err
), BUFSIZ
);
517 return xbstrerror_buf
;
520 #if defined(__MINGW32__) /* MinGW environment */
522 _free_osfhnd(int filehandle
)
524 if (((unsigned) filehandle
< SQUID_MAXFD
) &&
525 (_osfile(filehandle
) & FOPEN
) &&
526 (_osfhnd(filehandle
) != (long) INVALID_HANDLE_VALUE
)) {
527 switch (filehandle
) {
529 SetStdHandle(STD_INPUT_HANDLE
, NULL
);
532 SetStdHandle(STD_OUTPUT_HANDLE
, NULL
);
535 SetStdHandle(STD_ERROR_HANDLE
, NULL
);
538 _osfhnd(filehandle
) = (long) INVALID_HANDLE_VALUE
;
541 errno
= EBADF
; /* bad handle */
542 _doserrno
= 0L; /* not an OS error */
549 unsigned long WIN32_code
;
553 static struct errorentry errortable
[] = {
554 {ERROR_INVALID_FUNCTION
, EINVAL
},
555 {ERROR_FILE_NOT_FOUND
, ENOENT
},
556 {ERROR_PATH_NOT_FOUND
, ENOENT
},
557 {ERROR_TOO_MANY_OPEN_FILES
, EMFILE
},
558 {ERROR_ACCESS_DENIED
, EACCES
},
559 {ERROR_INVALID_HANDLE
, EBADF
},
560 {ERROR_ARENA_TRASHED
, ENOMEM
},
561 {ERROR_NOT_ENOUGH_MEMORY
, ENOMEM
},
562 {ERROR_INVALID_BLOCK
, ENOMEM
},
563 {ERROR_BAD_ENVIRONMENT
, E2BIG
},
564 {ERROR_BAD_FORMAT
, ENOEXEC
},
565 {ERROR_INVALID_ACCESS
, EINVAL
},
566 {ERROR_INVALID_DATA
, EINVAL
},
567 {ERROR_INVALID_DRIVE
, ENOENT
},
568 {ERROR_CURRENT_DIRECTORY
, EACCES
},
569 {ERROR_NOT_SAME_DEVICE
, EXDEV
},
570 {ERROR_NO_MORE_FILES
, ENOENT
},
571 {ERROR_LOCK_VIOLATION
, EACCES
},
572 {ERROR_BAD_NETPATH
, ENOENT
},
573 {ERROR_NETWORK_ACCESS_DENIED
, EACCES
},
574 {ERROR_BAD_NET_NAME
, ENOENT
},
575 {ERROR_FILE_EXISTS
, EEXIST
},
576 {ERROR_CANNOT_MAKE
, EACCES
},
577 {ERROR_FAIL_I24
, EACCES
},
578 {ERROR_INVALID_PARAMETER
, EINVAL
},
579 {ERROR_NO_PROC_SLOTS
, EAGAIN
},
580 {ERROR_DRIVE_LOCKED
, EACCES
},
581 {ERROR_BROKEN_PIPE
, EPIPE
},
582 {ERROR_DISK_FULL
, ENOSPC
},
583 {ERROR_INVALID_TARGET_HANDLE
, EBADF
},
584 {ERROR_INVALID_HANDLE
, EINVAL
},
585 {ERROR_WAIT_NO_CHILDREN
, ECHILD
},
586 {ERROR_CHILD_NOT_COMPLETE
, ECHILD
},
587 {ERROR_DIRECT_ACCESS_HANDLE
, EBADF
},
588 {ERROR_NEGATIVE_SEEK
, EINVAL
},
589 {ERROR_SEEK_ON_DEVICE
, EACCES
},
590 {ERROR_DIR_NOT_EMPTY
, ENOTEMPTY
},
591 {ERROR_NOT_LOCKED
, EACCES
},
592 {ERROR_BAD_PATHNAME
, ENOENT
},
593 {ERROR_MAX_THRDS_REACHED
, EAGAIN
},
594 {ERROR_LOCK_FAILED
, EACCES
},
595 {ERROR_ALREADY_EXISTS
, EEXIST
},
596 {ERROR_FILENAME_EXCED_RANGE
, ENOENT
},
597 {ERROR_NESTING_NOT_ALLOWED
, EAGAIN
},
598 {ERROR_NOT_ENOUGH_QUOTA
, ENOMEM
}
601 #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
602 #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
604 #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
605 #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
608 WIN32_maperror(unsigned long WIN32_oserrno
)
612 _doserrno
= WIN32_oserrno
;
613 for (i
= 0; i
< (sizeof(errortable
) / sizeof(struct errorentry
)); ++i
) {
614 if (WIN32_oserrno
== errortable
[i
].WIN32_code
) {
615 errno
= errortable
[i
].POSIX_errno
;
619 if (WIN32_oserrno
>= MIN_EACCES_RANGE
&& WIN32_oserrno
<= MAX_EACCES_RANGE
)
621 else if (WIN32_oserrno
>= MIN_EXEC_ERROR
&& WIN32_oserrno
<= MAX_EXEC_ERROR
)