]>
Commit | Line | Data |
---|---|---|
62045984 | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
62045984 | 3 | * |
37be9888 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
62045984 | 7 | */ |
8 | ||
37be9888 | 9 | /* Windows support |
37be9888 AJ |
10 | * Inspired by previous work by Romeo Anghelache & Eric Stern. */ |
11 | ||
f7f3304a | 12 | #include "squid.h" |
62045984 | 13 | |
3f5727dc AJ |
14 | // The following code section is part of an EXPERIMENTAL native Windows NT/2000 Squid port. |
15 | // Compiles only on MS Visual C++ or MinGW | |
16 | // CygWin appears not to need any of these | |
7aa9bb3e | 17 | #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_ |
62045984 | 18 | |
62045984 | 19 | #define sys_nerr _sys_nerr |
20 | ||
21 | #undef assert | |
074d6a40 AJ |
22 | #include <cassert> |
23 | #include <cstring> | |
62045984 | 24 | #include <fcntl.h> |
62045984 | 25 | #include <sys/timeb.h> |
26 | #if HAVE_WIN32_PSAPI | |
27 | #include <psapi.h> | |
28 | #endif | |
3f5727dc AJ |
29 | #ifndef _MSWSOCK_ |
30 | #include <mswsock.h> | |
31 | #endif | |
32 | ||
62045984 | 33 | THREADLOCAL int ws32_result; |
34 | LPCRITICAL_SECTION dbg_mutex = NULL; | |
35 | ||
36 | void GetProcessName(pid_t, char *); | |
37 | ||
3f5727dc | 38 | #if HAVE_GETPAGESIZE > 1 |
26ac0430 | 39 | size_t |
62045984 | 40 | getpagesize() |
41 | { | |
97fee6b1 GS |
42 | static DWORD system_pagesize = 0; |
43 | if (!system_pagesize) { | |
26ac0430 AJ |
44 | SYSTEM_INFO system_info; |
45 | GetSystemInfo(&system_info); | |
46 | system_pagesize = system_info.dwPageSize; | |
97fee6b1 GS |
47 | } |
48 | return system_pagesize; | |
62045984 | 49 | } |
3f5727dc | 50 | #endif /* HAVE_GETPAGESIZE > 1 */ |
62045984 | 51 | |
26ac0430 | 52 | int |
62045984 | 53 | chroot(const char *dirname) |
54 | { | |
55 | if (SetCurrentDirectory(dirname)) | |
26ac0430 | 56 | return 0; |
62045984 | 57 | else |
26ac0430 | 58 | return GetLastError(); |
62045984 | 59 | } |
60 | ||
26ac0430 | 61 | void |
62045984 | 62 | GetProcessName(pid_t pid, char *ProcessName) |
63 | { | |
62045984 | 64 | strcpy(ProcessName, "unknown"); |
65 | #if HAVE_WIN32_PSAPI | |
66 | /* Get a handle to the process. */ | |
3f5727dc | 67 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); |
62045984 | 68 | /* Get the process name. */ |
69 | if (NULL != hProcess) { | |
26ac0430 AJ |
70 | HMODULE hMod; |
71 | DWORD cbNeeded; | |
72 | ||
73 | if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) | |
74 | GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName)); | |
75 | else { | |
76 | CloseHandle(hProcess); | |
77 | return; | |
78 | } | |
62045984 | 79 | } else |
26ac0430 | 80 | return; |
62045984 | 81 | CloseHandle(hProcess); |
3f5727dc | 82 | #endif /* HAVE_WIN32_PSAPI */ |
62045984 | 83 | } |
84 | ||
26ac0430 | 85 | int |
62045984 | 86 | kill(pid_t pid, int sig) |
87 | { | |
88 | HANDLE hProcess; | |
89 | char MyProcessName[MAX_PATH]; | |
90 | char ProcessNameToCheck[MAX_PATH]; | |
91 | ||
92 | if (sig == 0) { | |
26ac0430 AJ |
93 | if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | |
94 | PROCESS_VM_READ, | |
95 | FALSE, pid)) == NULL) | |
96 | return -1; | |
97 | else { | |
98 | CloseHandle(hProcess); | |
99 | GetProcessName(getpid(), MyProcessName); | |
100 | GetProcessName(pid, ProcessNameToCheck); | |
101 | if (strcmp(MyProcessName, ProcessNameToCheck) == 0) | |
102 | return 0; | |
103 | return -1; | |
104 | } | |
62045984 | 105 | } else |
26ac0430 | 106 | return 0; |
62045984 | 107 | } |
108 | ||
32d002cb | 109 | #if !HAVE_GETTIMEOFDAY |
26ac0430 | 110 | int |
62045984 | 111 | gettimeofday(struct timeval *pcur_time, void *tzp) |
112 | { | |
113 | struct _timeb current; | |
114 | struct timezone *tz = (struct timezone *) tzp; | |
115 | ||
116 | _ftime(¤t); | |
117 | ||
118 | pcur_time->tv_sec = current.time; | |
119 | pcur_time->tv_usec = current.millitm * 1000L; | |
120 | if (tz) { | |
3f5727dc AJ |
121 | tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */ |
122 | tz->tz_dsttime = current.dstflag; /* type of dst correction */ | |
62045984 | 123 | } |
124 | return 0; | |
125 | } | |
3f5727dc | 126 | #endif /* !HAVE_GETTIMEOFDAY */ |
62045984 | 127 | |
3bfe9ee7 | 128 | #if !_SQUID_MINGW_ |
62045984 | 129 | int |
130 | WIN32_ftruncate(int fd, off_t size) | |
131 | { | |
132 | HANDLE hfile; | |
133 | unsigned int curpos; | |
134 | ||
135 | if (fd < 0) | |
26ac0430 | 136 | return -1; |
62045984 | 137 | |
138 | hfile = (HANDLE) _get_osfhandle(fd); | |
139 | curpos = SetFilePointer(hfile, 0, NULL, FILE_CURRENT); | |
140 | if (curpos == 0xFFFFFFFF | |
26ac0430 AJ |
141 | || SetFilePointer(hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF |
142 | || !SetEndOfFile(hfile)) { | |
143 | int error = GetLastError(); | |
144 | ||
145 | switch (error) { | |
146 | case ERROR_INVALID_HANDLE: | |
147 | errno = EBADF; | |
148 | break; | |
149 | default: | |
150 | errno = EIO; | |
151 | break; | |
152 | } | |
153 | ||
154 | return -1; | |
62045984 | 155 | } |
156 | return 0; | |
157 | } | |
158 | ||
26ac0430 | 159 | int |
62045984 | 160 | WIN32_truncate(const char *pathname, off_t length) |
161 | { | |
162 | int fd; | |
163 | int res = -1; | |
164 | ||
165 | fd = open(pathname, O_RDWR); | |
166 | ||
167 | if (fd == -1) | |
26ac0430 | 168 | errno = EBADF; |
62045984 | 169 | else { |
26ac0430 AJ |
170 | res = WIN32_ftruncate(fd, length); |
171 | _close(fd); | |
62045984 | 172 | } |
173 | ||
174 | return res; | |
175 | } | |
3bfe9ee7 | 176 | #endif /* !_SQUID_MINGW_ */ |
62045984 | 177 | |
62045984 | 178 | struct passwd * |
e1381638 | 179 | getpwnam(char *unused) { |
26ac0430 | 180 | static struct passwd pwd = {NULL, NULL, 100, 100, NULL, NULL, NULL}; |
62045984 | 181 | return &pwd; |
182 | } | |
183 | ||
184 | struct group * | |
e1381638 | 185 | getgrnam(char *unused) { |
26ac0430 | 186 | static struct group grp = {NULL, NULL, 100, NULL}; |
62045984 | 187 | return &grp; |
188 | } | |
189 | ||
d305c51d | 190 | #if _SQUID_MINGW_ |
26ac0430 | 191 | int |
62045984 | 192 | _free_osfhnd(int filehandle) |
193 | { | |
194 | if (((unsigned) filehandle < SQUID_MAXFD) && | |
26ac0430 AJ |
195 | (_osfile(filehandle) & FOPEN) && |
196 | (_osfhnd(filehandle) != (long) INVALID_HANDLE_VALUE)) { | |
197 | switch (filehandle) { | |
198 | case 0: | |
199 | SetStdHandle(STD_INPUT_HANDLE, NULL); | |
200 | break; | |
201 | case 1: | |
202 | SetStdHandle(STD_OUTPUT_HANDLE, NULL); | |
203 | break; | |
204 | case 2: | |
205 | SetStdHandle(STD_ERROR_HANDLE, NULL); | |
206 | break; | |
207 | } | |
208 | _osfhnd(filehandle) = (long) INVALID_HANDLE_VALUE; | |
209 | return (0); | |
62045984 | 210 | } else { |
f53969cc SM |
211 | errno = EBADF; /* bad handle */ |
212 | _doserrno = 0L; /* not an OS error */ | |
26ac0430 | 213 | return -1; |
62045984 | 214 | } |
215 | } | |
3f5727dc | 216 | #endif /* _SQUID_MINGW_ */ |
62045984 | 217 | |
218 | struct errorentry { | |
219 | unsigned long WIN32_code; | |
220 | int POSIX_errno; | |
221 | }; | |
222 | ||
26ac0430 | 223 | static struct errorentry errortable[] = { |
62045984 | 224 | {ERROR_INVALID_FUNCTION, EINVAL}, |
225 | {ERROR_FILE_NOT_FOUND, ENOENT}, | |
226 | {ERROR_PATH_NOT_FOUND, ENOENT}, | |
227 | {ERROR_TOO_MANY_OPEN_FILES, EMFILE}, | |
228 | {ERROR_ACCESS_DENIED, EACCES}, | |
229 | {ERROR_INVALID_HANDLE, EBADF}, | |
230 | {ERROR_ARENA_TRASHED, ENOMEM}, | |
231 | {ERROR_NOT_ENOUGH_MEMORY, ENOMEM}, | |
232 | {ERROR_INVALID_BLOCK, ENOMEM}, | |
233 | {ERROR_BAD_ENVIRONMENT, E2BIG}, | |
234 | {ERROR_BAD_FORMAT, ENOEXEC}, | |
235 | {ERROR_INVALID_ACCESS, EINVAL}, | |
236 | {ERROR_INVALID_DATA, EINVAL}, | |
237 | {ERROR_INVALID_DRIVE, ENOENT}, | |
238 | {ERROR_CURRENT_DIRECTORY, EACCES}, | |
239 | {ERROR_NOT_SAME_DEVICE, EXDEV}, | |
240 | {ERROR_NO_MORE_FILES, ENOENT}, | |
241 | {ERROR_LOCK_VIOLATION, EACCES}, | |
242 | {ERROR_BAD_NETPATH, ENOENT}, | |
243 | {ERROR_NETWORK_ACCESS_DENIED, EACCES}, | |
244 | {ERROR_BAD_NET_NAME, ENOENT}, | |
245 | {ERROR_FILE_EXISTS, EEXIST}, | |
246 | {ERROR_CANNOT_MAKE, EACCES}, | |
247 | {ERROR_FAIL_I24, EACCES}, | |
248 | {ERROR_INVALID_PARAMETER, EINVAL}, | |
249 | {ERROR_NO_PROC_SLOTS, EAGAIN}, | |
250 | {ERROR_DRIVE_LOCKED, EACCES}, | |
251 | {ERROR_BROKEN_PIPE, EPIPE}, | |
252 | {ERROR_DISK_FULL, ENOSPC}, | |
253 | {ERROR_INVALID_TARGET_HANDLE, EBADF}, | |
254 | {ERROR_INVALID_HANDLE, EINVAL}, | |
255 | {ERROR_WAIT_NO_CHILDREN, ECHILD}, | |
256 | {ERROR_CHILD_NOT_COMPLETE, ECHILD}, | |
257 | {ERROR_DIRECT_ACCESS_HANDLE, EBADF}, | |
258 | {ERROR_NEGATIVE_SEEK, EINVAL}, | |
259 | {ERROR_SEEK_ON_DEVICE, EACCES}, | |
260 | {ERROR_DIR_NOT_EMPTY, ENOTEMPTY}, | |
261 | {ERROR_NOT_LOCKED, EACCES}, | |
262 | {ERROR_BAD_PATHNAME, ENOENT}, | |
263 | {ERROR_MAX_THRDS_REACHED, EAGAIN}, | |
264 | {ERROR_LOCK_FAILED, EACCES}, | |
265 | {ERROR_ALREADY_EXISTS, EEXIST}, | |
266 | {ERROR_FILENAME_EXCED_RANGE, ENOENT}, | |
267 | {ERROR_NESTING_NOT_ALLOWED, EAGAIN}, | |
268 | {ERROR_NOT_ENOUGH_QUOTA, ENOMEM} | |
269 | }; | |
270 | ||
271 | #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG | |
272 | #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN | |
273 | ||
274 | #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT | |
275 | #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED | |
276 | ||
26ac0430 | 277 | void |
62045984 | 278 | WIN32_maperror(unsigned long WIN32_oserrno) |
279 | { | |
62045984 | 280 | _doserrno = WIN32_oserrno; |
3f5727dc | 281 | for (size_t i = 0; i < (sizeof(errortable) / sizeof(struct errorentry)); ++i) { |
26ac0430 AJ |
282 | if (WIN32_oserrno == errortable[i].WIN32_code) { |
283 | errno = errortable[i].POSIX_errno; | |
284 | return; | |
285 | } | |
62045984 | 286 | } |
287 | if (WIN32_oserrno >= MIN_EACCES_RANGE && WIN32_oserrno <= MAX_EACCES_RANGE) | |
26ac0430 | 288 | errno = EACCES; |
62045984 | 289 | else if (WIN32_oserrno >= MIN_EXEC_ERROR && WIN32_oserrno <= MAX_EXEC_ERROR) |
26ac0430 | 290 | errno = ENOEXEC; |
62045984 | 291 | else |
26ac0430 | 292 | errno = EINVAL; |
62045984 | 293 | } |
3f5727dc AJ |
294 | |
295 | /* syslog emulation layer derived from git */ | |
296 | static HANDLE ms_eventlog; | |
297 | ||
298 | void | |
299 | openlog(const char *ident, int logopt, int facility) | |
300 | { | |
ec6d36d2 A |
301 | if (ms_eventlog) |
302 | return; | |
3f5727dc | 303 | |
ec6d36d2 | 304 | ms_eventlog = RegisterEventSourceA(NULL, ident); |
3f5727dc | 305 | |
ec6d36d2 A |
306 | // note: RegisterEventAtSourceA may fail and return NULL. |
307 | // in that case we'll just retry at the next message or not log | |
3f5727dc AJ |
308 | } |
309 | #define SYSLOG_MAX_MSG_SIZE 1024 | |
310 | ||
311 | void | |
312 | syslog(int priority, const char *fmt, ...) | |
313 | { | |
ec6d36d2 A |
314 | WORD logtype; |
315 | char *str=static_cast<char *>(xmalloc(SYSLOG_MAX_MSG_SIZE)); | |
316 | int str_len; | |
317 | va_list ap; | |
3f5727dc | 318 | |
ec6d36d2 A |
319 | if (!ms_eventlog) |
320 | return; | |
3f5727dc | 321 | |
ec6d36d2 A |
322 | va_start(ap, fmt); |
323 | str_len = vsnprintf(str, SYSLOG_MAX_MSG_SIZE-1, fmt, ap); | |
324 | va_end(ap); | |
3f5727dc | 325 | |
ec6d36d2 A |
326 | if (str_len < 0) { |
327 | /* vsnprintf failed */ | |
328 | return; | |
329 | } | |
3f5727dc | 330 | |
ec6d36d2 A |
331 | switch (priority) { |
332 | case LOG_EMERG: | |
333 | case LOG_ALERT: | |
334 | case LOG_CRIT: | |
335 | case LOG_ERR: | |
336 | logtype = EVENTLOG_ERROR_TYPE; | |
337 | break; | |
338 | ||
339 | case LOG_WARNING: | |
340 | logtype = EVENTLOG_WARNING_TYPE; | |
341 | break; | |
342 | ||
343 | case LOG_NOTICE: | |
344 | case LOG_INFO: | |
345 | case LOG_DEBUG: | |
346 | default: | |
347 | logtype = EVENTLOG_INFORMATION_TYPE; | |
348 | break; | |
349 | } | |
3f5727dc | 350 | |
ec6d36d2 A |
351 | //Windows API suck. They are overengineered |
352 | ReportEventA(ms_eventlog, logtype, 0, 0, NULL, 1, 0, | |
353 | const_cast<const char **>(&str), NULL); | |
3f5727dc AJ |
354 | } |
355 | ||
356 | /* note: this is all MSWindows-specific code; all of it should be conditional */ | |
357 | #endif /* _SQUID_WINDOWS_ */ | |
f53969cc | 358 |