]> git.ipfire.org Git - thirdparty/squid.git/blame - compat/mswindows.cc
SourceFormat Enforcement
[thirdparty/squid.git] / compat / mswindows.cc
CommitLineData
62045984 1/*
4ac4a490 2 * Copyright (C) 1996-2017 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 33THREADLOCAL int ws32_result;
34LPCRITICAL_SECTION dbg_mutex = NULL;
35
36void GetProcessName(pid_t, char *);
37
3f5727dc 38#if HAVE_GETPAGESIZE > 1
26ac0430 39size_t
62045984 40getpagesize()
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 52int
62045984 53chroot(const char *dirname)
54{
55 if (SetCurrentDirectory(dirname))
26ac0430 56 return 0;
62045984 57 else
26ac0430 58 return GetLastError();
62045984 59}
60
26ac0430 61void
62045984 62GetProcessName(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 85int
62045984 86kill(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 110int
62045984 111gettimeofday(struct timeval *pcur_time, void *tzp)
112{
113 struct _timeb current;
114 struct timezone *tz = (struct timezone *) tzp;
115
116 _ftime(&current);
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 129int
130WIN32_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 159int
62045984 160WIN32_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 178struct passwd *
e1381638 179getpwnam(char *unused) {
26ac0430 180 static struct passwd pwd = {NULL, NULL, 100, 100, NULL, NULL, NULL};
62045984 181 return &pwd;
182}
183
184struct group *
e1381638 185getgrnam(char *unused) {
26ac0430 186 static struct group grp = {NULL, NULL, 100, NULL};
62045984 187 return &grp;
188}
189
d305c51d 190#if _SQUID_MINGW_
26ac0430 191int
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
218struct errorentry {
219 unsigned long WIN32_code;
220 int POSIX_errno;
221};
222
26ac0430 223static 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 277void
62045984 278WIN32_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 */
296static HANDLE ms_eventlog;
297
298void
299openlog(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
311void
312syslog(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