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
)