]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/win32lib.c
Import reconfigure cachemgr action from NT Devel branch
[thirdparty/squid.git] / lib / win32lib.c
CommitLineData
1b52df9a 1
62045984 2/*
2733d426 3 * $Id: win32lib.c,v 1.5 2007/08/17 18:56:26 serassio Exp $
62045984 4 *
1b52df9a 5 * Windows support
6 * AUTHOR: Guido Serassio <serassio@squid-cache.org>
7 * inspired by previous work by Romeo Anghelache & Eric Stern.
62045984 8 *
9 * SQUID Web Proxy Cache http://www.squid-cache.org/
10 * ----------------------------------------------------------
11 *
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.
20 *
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.
25 *
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.
30 *
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.
34 *
35 */
36
37#include "util.h"
38
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_)
42
43#undef strerror
44#define sys_nerr _sys_nerr
45
46#undef assert
47#include <assert.h>
48#include <stdio.h>
49#include <fcntl.h>
50#include "squid_windows.h"
51#include <string.h>
52#include <sys/timeb.h>
53#if HAVE_WIN32_PSAPI
54#include <psapi.h>
55#endif
56
57THREADLOCAL int ws32_result;
58LPCRITICAL_SECTION dbg_mutex = NULL;
59
60void GetProcessName(pid_t, char *);
61
62#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
63size_t
64getpagesize()
65{
66 return 4096;
67}
68#endif
69
70uid_t
71geteuid(void)
72{
73 return 100;
74}
75
76uid_t
77getuid(void)
78{
79 return 100;
80}
81
82int
83setuid(uid_t uid)
84{
85 return 0;
86}
87
88int
89seteuid(uid_t euid)
90{
91 return 0;
92}
93
94gid_t
95getegid(void)
96{
97 return 100;
98}
99
100gid_t
101getgid(void)
102{
103 return 100;
104}
105
106int
107setgid(gid_t gid)
108{
109 return 0;
110}
111
112int
113setegid(gid_t egid)
114{
115 return 0;
116}
117
118int
119chroot(const char *dirname)
120{
121 if (SetCurrentDirectory(dirname))
122 return 0;
123 else
124 return GetLastError();
125}
126
127void
128GetProcessName(pid_t pid, char *ProcessName)
129{
130 HANDLE hProcess;
131
132 strcpy(ProcessName, "unknown");
133#if HAVE_WIN32_PSAPI
134 /* Get a handle to the process. */
135 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
136 PROCESS_VM_READ,
137 FALSE, pid);
138 /* Get the process name. */
139 if (NULL != hProcess) {
140 HMODULE hMod;
141 DWORD cbNeeded;
142
143 if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
144 GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName));
145 else {
146 CloseHandle(hProcess);
147 return;
148 }
149 } else
150 return;
151 CloseHandle(hProcess);
152#endif
153}
154
155int
156kill(pid_t pid, int sig)
157{
158 HANDLE hProcess;
159 char MyProcessName[MAX_PATH];
160 char ProcessNameToCheck[MAX_PATH];
161
162 if (sig == 0) {
163 if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
164 PROCESS_VM_READ,
165 FALSE, pid)) == NULL)
166 return -1;
167 else {
168 CloseHandle(hProcess);
169 GetProcessName(getpid(), MyProcessName);
170 GetProcessName(pid, ProcessNameToCheck);
171 if (strcmp(MyProcessName, ProcessNameToCheck) == 0)
172 return 0;
173 return -1;
174 }
175 } else
176 return 0;
177}
178
379d5751 179#ifndef HAVE_GETTIMEOFDAY
62045984 180int
181gettimeofday(struct timeval *pcur_time, void *tzp)
182{
183 struct _timeb current;
184 struct timezone *tz = (struct timezone *) tzp;
185
186 _ftime(&current);
187
188 pcur_time->tv_sec = current.time;
189 pcur_time->tv_usec = current.millitm * 1000L;
190 if (tz) {
191 tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */
192 tz->tz_dsttime = current.dstflag; /* type of dst correction */
193 }
194 return 0;
195}
379d5751 196#endif
62045984 197
198int
199statfs(const char *path, struct statfs *sfs)
200{
201 char drive[4];
202 DWORD spc, bps, freec, totalc;
203 DWORD vsn, maxlen, flags;
204
205 if (!sfs) {
206 errno = EINVAL;
207 return -1;
208 }
209 strncpy(drive, path, 2);
210 drive[2] = '\0';
211 strcat(drive, "\\");
212
213 if (!GetDiskFreeSpace(drive, &spc, &bps, &freec, &totalc)) {
214 errno = ENOENT;
215 return -1;
216 }
217 if (!GetVolumeInformation(drive, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) {
218 errno = ENOENT;
219 return -1;
220 }
221 sfs->f_type = flags;
222 sfs->f_bsize = spc * bps;
223 sfs->f_blocks = totalc;
224 sfs->f_bfree = sfs->f_bavail = freec;
225 sfs->f_files = -1;
226 sfs->f_ffree = -1;
227 sfs->f_fsid = vsn;
228 sfs->f_namelen = maxlen;
229 return 0;
230}
231
232int
233WIN32_ftruncate(int fd, off_t size)
234{
235 HANDLE hfile;
236 unsigned int curpos;
237
238 if (fd < 0)
239 return -1;
240
241 hfile = (HANDLE) _get_osfhandle(fd);
242 curpos = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
243 if (curpos == 0xFFFFFFFF
244 || SetFilePointer(hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
245 || !SetEndOfFile(hfile)) {
246 int error = GetLastError();
247
248 switch (error) {
249 case ERROR_INVALID_HANDLE:
250 errno = EBADF;
251 break;
252 default:
253 errno = EIO;
254 break;
255 }
256
257 return -1;
258 }
259 return 0;
260}
261
262int
263WIN32_truncate(const char *pathname, off_t length)
264{
265 int fd;
266 int res = -1;
267
268 fd = open(pathname, O_RDWR);
269
270 if (fd == -1)
271 errno = EBADF;
272 else {
273 res = WIN32_ftruncate(fd, length);
274 _close(fd);
275 }
276
277 return res;
278}
279
280static struct _wsaerrtext {
281 int err;
282 const char *errconst;
283 const char *errdesc;
284} _wsaerrtext[] = {
285
286 {
287 WSA_E_CANCELLED, "WSA_E_CANCELLED", "Lookup cancelled."
288 },
289 {
290 WSA_E_NO_MORE, "WSA_E_NO_MORE", "No more data available."
291 },
292 {
293 WSAEACCES, "WSAEACCES", "Permission denied."
294 },
295 {
296 WSAEADDRINUSE, "WSAEADDRINUSE", "Address already in use."
297 },
298 {
299 WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", "Cannot assign requested address."
300 },
301 {
302 WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", "Address family not supported by protocol family."
303 },
304 {
305 WSAEALREADY, "WSAEALREADY", "Operation already in progress."
306 },
307 {
308 WSAEBADF, "WSAEBADF", "Bad file number."
309 },
310 {
311 WSAECANCELLED, "WSAECANCELLED", "Operation cancelled."
312 },
313 {
314 WSAECONNABORTED, "WSAECONNABORTED", "Software caused connection abort."
315 },
316 {
317 WSAECONNREFUSED, "WSAECONNREFUSED", "Connection refused."
318 },
319 {
320 WSAECONNRESET, "WSAECONNRESET", "Connection reset by peer."
321 },
322 {
323 WSAEDESTADDRREQ, "WSAEDESTADDRREQ", "Destination address required."
324 },
325 {
326 WSAEDQUOT, "WSAEDQUOT", "Disk quota exceeded."
327 },
328 {
329 WSAEFAULT, "WSAEFAULT", "Bad address."
330 },
331 {
332 WSAEHOSTDOWN, "WSAEHOSTDOWN", "Host is down."
333 },
334 {
335 WSAEHOSTUNREACH, "WSAEHOSTUNREACH", "No route to host."
336 },
337 {
338 WSAEINPROGRESS, "WSAEINPROGRESS", "Operation now in progress."
339 },
340 {
341 WSAEINTR, "WSAEINTR", "Interrupted function call."
342 },
343 {
344 WSAEINVAL, "WSAEINVAL", "Invalid argument."
345 },
346 {
347 WSAEINVALIDPROCTABLE, "WSAEINVALIDPROCTABLE", "Invalid procedure table from service provider."
348 },
349 {
350 WSAEINVALIDPROVIDER, "WSAEINVALIDPROVIDER", "Invalid service provider version number."
351 },
352 {
353 WSAEISCONN, "WSAEISCONN", "Socket is already connected."
354 },
355 {
356 WSAELOOP, "WSAELOOP", "Too many levels of symbolic links."
357 },
358 {
359 WSAEMFILE, "WSAEMFILE", "Too many open files."
360 },
361 {
362 WSAEMSGSIZE, "WSAEMSGSIZE", "Message too long."
363 },
364 {
365 WSAENAMETOOLONG, "WSAENAMETOOLONG", "File name is too long."
366 },
367 {
368 WSAENETDOWN, "WSAENETDOWN", "Network is down."
369 },
370 {
371 WSAENETRESET, "WSAENETRESET", "Network dropped connection on reset."
372 },
373 {
374 WSAENETUNREACH, "WSAENETUNREACH", "Network is unreachable."
375 },
376 {
377 WSAENOBUFS, "WSAENOBUFS", "No buffer space available."
378 },
379 {
380 WSAENOMORE, "WSAENOMORE", "No more data available."
381 },
382 {
383 WSAENOPROTOOPT, "WSAENOPROTOOPT", "Bad protocol option."
384 },
385 {
386 WSAENOTCONN, "WSAENOTCONN", "Socket is not connected."
387 },
388 {
389 WSAENOTEMPTY, "WSAENOTEMPTY", "Directory is not empty."
390 },
391 {
392 WSAENOTSOCK, "WSAENOTSOCK", "Socket operation on nonsocket."
393 },
394 {
395 WSAEOPNOTSUPP, "WSAEOPNOTSUPP", "Operation not supported."
396 },
397 {
398 WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", "Protocol family not supported."
399 },
400 {
401 WSAEPROCLIM, "WSAEPROCLIM", "Too many processes."
402 },
403 {
404 WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", "Protocol not supported."
405 },
406 {
407 WSAEPROTOTYPE, "WSAEPROTOTYPE", "Protocol wrong type for socket."
408 },
409 {
410 WSAEPROVIDERFAILEDINIT, "WSAEPROVIDERFAILEDINIT", "Unable to initialise a service provider."
411 },
412 {
413 WSAEREFUSED, "WSAEREFUSED", "Refused."
414 },
415 {
416 WSAEREMOTE, "WSAEREMOTE", "Too many levels of remote in path."
417 },
418 {
419 WSAESHUTDOWN, "WSAESHUTDOWN", "Cannot send after socket shutdown."
420 },
421 {
422 WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", "Socket type not supported."
423 },
424 {
425 WSAESTALE, "WSAESTALE", "Stale NFS file handle."
426 },
427 {
428 WSAETIMEDOUT, "WSAETIMEDOUT", "Connection timed out."
429 },
430 {
431 WSAETOOMANYREFS, "WSAETOOMANYREFS", "Too many references."
432 },
433 {
434 WSAEUSERS, "WSAEUSERS", "Too many users."
435 },
436 {
437 WSAEWOULDBLOCK, "WSAEWOULDBLOCK", "Resource temporarily unavailable."
438 },
439 {
440 WSANOTINITIALISED, "WSANOTINITIALISED", "Successful WSAStartup not yet performed."
441 },
442 {
443 WSASERVICE_NOT_FOUND, "WSASERVICE_NOT_FOUND", "Service not found."
444 },
445 {
446 WSASYSCALLFAILURE, "WSASYSCALLFAILURE", "System call failure."
447 },
448 {
449 WSASYSNOTREADY, "WSASYSNOTREADY", "Network subsystem is unavailable."
450 },
451 {
452 WSATYPE_NOT_FOUND, "WSATYPE_NOT_FOUND", "Class type not found."
453 },
454 {
455 WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED", "Winsock.dll version out of range."
456 },
457 {
458 WSAEDISCON, "WSAEDISCON", "Graceful shutdown in progress."
459 }
460};
461
462/*
463 * wsastrerror() - description of WSAGetLastError()
464 */
465const char *
466wsastrerror(int err)
467{
468 static char xwsaerror_buf[BUFSIZ];
469 int i, errind = -1;
470
471 if (err == 0)
472 return "(0) No error.";
473 for (i = 0; i < sizeof(_wsaerrtext) / sizeof(struct _wsaerrtext); i++) {
474 if (_wsaerrtext[i].err != err)
475 continue;
476 errind = i;
477 break;
478 }
479 if (errind == -1)
480 snprintf(xwsaerror_buf, BUFSIZ, "Unknown");
481 else
482 snprintf(xwsaerror_buf, BUFSIZ, "%s, %s", _wsaerrtext[errind].errconst, _wsaerrtext[errind].errdesc);
483 return xwsaerror_buf;
484}
485
486struct passwd *
487getpwnam(char *unused)
488{
489 static struct passwd pwd =
490 {NULL, NULL, 100, 100, NULL, NULL, NULL};
491 return &pwd;
492}
493
494struct group *
495getgrnam(char *unused)
496{
497 static struct group grp =
498 {NULL, NULL, 100, NULL};
499 return &grp;
500}
501
502/*
503 * WIN32_strerror with argument for late notification */
504
505const char *
506WIN32_strerror(int err)
507{
508 static char xbstrerror_buf[BUFSIZ];
509
510 if (err < 0 || err >= sys_nerr)
511 strncpy(xbstrerror_buf, wsastrerror(err), BUFSIZ);
512 else
513 strncpy(xbstrerror_buf, strerror(err), BUFSIZ);
514 return xbstrerror_buf;
515}
516
517#if defined(__MINGW32__) /* MinGW environment */
518int
519_free_osfhnd(int filehandle)
520{
521 if (((unsigned) filehandle < SQUID_MAXFD) &&
522 (_osfile(filehandle) & FOPEN) &&
523 (_osfhnd(filehandle) != (long) INVALID_HANDLE_VALUE)) {
524 switch (filehandle) {
525 case 0:
526 SetStdHandle(STD_INPUT_HANDLE, NULL);
527 break;
528 case 1:
529 SetStdHandle(STD_OUTPUT_HANDLE, NULL);
530 break;
531 case 2:
532 SetStdHandle(STD_ERROR_HANDLE, NULL);
533 break;
534 }
535 _osfhnd(filehandle) = (long) INVALID_HANDLE_VALUE;
536 return (0);
537 } else {
538 errno = EBADF; /* bad handle */
539 _doserrno = 0L; /* not an OS error */
540 return -1;
541 }
542}
543#endif
544
545struct errorentry {
546 unsigned long WIN32_code;
547 int POSIX_errno;
548};
549
550static struct errorentry errortable[] =
551{
552 {ERROR_INVALID_FUNCTION, EINVAL},
553 {ERROR_FILE_NOT_FOUND, ENOENT},
554 {ERROR_PATH_NOT_FOUND, ENOENT},
555 {ERROR_TOO_MANY_OPEN_FILES, EMFILE},
556 {ERROR_ACCESS_DENIED, EACCES},
557 {ERROR_INVALID_HANDLE, EBADF},
558 {ERROR_ARENA_TRASHED, ENOMEM},
559 {ERROR_NOT_ENOUGH_MEMORY, ENOMEM},
560 {ERROR_INVALID_BLOCK, ENOMEM},
561 {ERROR_BAD_ENVIRONMENT, E2BIG},
562 {ERROR_BAD_FORMAT, ENOEXEC},
563 {ERROR_INVALID_ACCESS, EINVAL},
564 {ERROR_INVALID_DATA, EINVAL},
565 {ERROR_INVALID_DRIVE, ENOENT},
566 {ERROR_CURRENT_DIRECTORY, EACCES},
567 {ERROR_NOT_SAME_DEVICE, EXDEV},
568 {ERROR_NO_MORE_FILES, ENOENT},
569 {ERROR_LOCK_VIOLATION, EACCES},
570 {ERROR_BAD_NETPATH, ENOENT},
571 {ERROR_NETWORK_ACCESS_DENIED, EACCES},
572 {ERROR_BAD_NET_NAME, ENOENT},
573 {ERROR_FILE_EXISTS, EEXIST},
574 {ERROR_CANNOT_MAKE, EACCES},
575 {ERROR_FAIL_I24, EACCES},
576 {ERROR_INVALID_PARAMETER, EINVAL},
577 {ERROR_NO_PROC_SLOTS, EAGAIN},
578 {ERROR_DRIVE_LOCKED, EACCES},
579 {ERROR_BROKEN_PIPE, EPIPE},
580 {ERROR_DISK_FULL, ENOSPC},
581 {ERROR_INVALID_TARGET_HANDLE, EBADF},
582 {ERROR_INVALID_HANDLE, EINVAL},
583 {ERROR_WAIT_NO_CHILDREN, ECHILD},
584 {ERROR_CHILD_NOT_COMPLETE, ECHILD},
585 {ERROR_DIRECT_ACCESS_HANDLE, EBADF},
586 {ERROR_NEGATIVE_SEEK, EINVAL},
587 {ERROR_SEEK_ON_DEVICE, EACCES},
588 {ERROR_DIR_NOT_EMPTY, ENOTEMPTY},
589 {ERROR_NOT_LOCKED, EACCES},
590 {ERROR_BAD_PATHNAME, ENOENT},
591 {ERROR_MAX_THRDS_REACHED, EAGAIN},
592 {ERROR_LOCK_FAILED, EACCES},
593 {ERROR_ALREADY_EXISTS, EEXIST},
594 {ERROR_FILENAME_EXCED_RANGE, ENOENT},
595 {ERROR_NESTING_NOT_ALLOWED, EAGAIN},
596 {ERROR_NOT_ENOUGH_QUOTA, ENOMEM}
597};
598
599#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
600#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
601
602#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
603#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
604
605void
606WIN32_maperror(unsigned long WIN32_oserrno)
607{
608 int i;
609
610 _doserrno = WIN32_oserrno;
611 for (i = 0; i < (sizeof(errortable) / sizeof(struct errorentry)); ++i) {
612 if (WIN32_oserrno == errortable[i].WIN32_code) {
613 errno = errortable[i].POSIX_errno;
614 return;
615 }
616 }
617 if (WIN32_oserrno >= MIN_EACCES_RANGE && WIN32_oserrno <= MAX_EACCES_RANGE)
618 errno = EACCES;
619 else if (WIN32_oserrno >= MIN_EXEC_ERROR && WIN32_oserrno <= MAX_EXEC_ERROR)
620 errno = ENOEXEC;
621 else
622 errno = EINVAL;
623}
624#endif