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