]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | return 4096; | |
67 | } | |
68 | #endif | |
69 | ||
70 | uid_t | |
71 | geteuid(void) | |
72 | { | |
73 | return 100; | |
74 | } | |
75 | ||
76 | uid_t | |
77 | getuid(void) | |
78 | { | |
79 | return 100; | |
80 | } | |
81 | ||
82 | int | |
83 | setuid(uid_t uid) | |
84 | { | |
85 | return 0; | |
86 | } | |
87 | ||
88 | int | |
89 | seteuid(uid_t euid) | |
90 | { | |
91 | return 0; | |
92 | } | |
93 | ||
94 | gid_t | |
95 | getegid(void) | |
96 | { | |
97 | return 100; | |
98 | } | |
99 | ||
100 | gid_t | |
101 | getgid(void) | |
102 | { | |
103 | return 100; | |
104 | } | |
105 | ||
106 | int | |
107 | setgid(gid_t gid) | |
108 | { | |
109 | return 0; | |
110 | } | |
111 | ||
112 | int | |
113 | setegid(gid_t egid) | |
114 | { | |
115 | return 0; | |
116 | } | |
117 | ||
118 | int | |
119 | chroot(const char *dirname) | |
120 | { | |
121 | if (SetCurrentDirectory(dirname)) | |
122 | return 0; | |
123 | else | |
124 | return GetLastError(); | |
125 | } | |
126 | ||
127 | void | |
128 | GetProcessName(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 | ||
155 | int | |
156 | kill(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 | 180 | int |
181 | gettimeofday(struct timeval *pcur_time, void *tzp) | |
182 | { | |
183 | struct _timeb current; | |
184 | struct timezone *tz = (struct timezone *) tzp; | |
185 | ||
186 | _ftime(¤t); | |
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 | |
198 | int | |
199 | statfs(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 | ||
232 | int | |
233 | WIN32_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 | ||
262 | int | |
263 | WIN32_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 | ||
280 | static 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 | */ | |
465 | const char * | |
466 | wsastrerror(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 | ||
486 | struct passwd * | |
487 | getpwnam(char *unused) | |
488 | { | |
489 | static struct passwd pwd = | |
490 | {NULL, NULL, 100, 100, NULL, NULL, NULL}; | |
491 | return &pwd; | |
492 | } | |
493 | ||
494 | struct group * | |
495 | getgrnam(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 | ||
505 | const char * | |
506 | WIN32_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 */ | |
518 | int | |
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 | ||
545 | struct errorentry { | |
546 | unsigned long WIN32_code; | |
547 | int POSIX_errno; | |
548 | }; | |
549 | ||
550 | static 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 | ||
605 | void | |
606 | WIN32_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 |