qemu
1/*
2* os-win32.c
3*
4* Copyright (c) 2003-2008 Fabrice Bellard
5* Copyright (c) 2010-2016 Red Hat, Inc.
6*
7* QEMU library functions for win32 which are shared between QEMU and
8* the QEMU tools.
9*
10* Permission is hereby granted, free of charge, to any person obtaining a copy
11* of this software and associated documentation files (the "Software"), to deal
12* in the Software without restriction, including without limitation the rights
13* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14* copies of the Software, and to permit persons to whom the Software is
15* furnished to do so, subject to the following conditions:
16*
17* The above copyright notice and this permission notice shall be included in
18* all copies or substantial portions of the Software.
19*
20* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26* THE SOFTWARE.
27*/
28
29#include "qemu/osdep.h"30#include <windows.h>31#include "qapi/error.h"32#include "qemu/main-loop.h"33#include "trace.h"34#include "qemu/sockets.h"35#include "qemu/cutils.h"36#include "qemu/error-report.h"37#include <malloc.h>38
39static int get_allocation_granularity(void)40{
41SYSTEM_INFO system_info;42
43GetSystemInfo(&system_info);44return system_info.dwAllocationGranularity;45}
46
47void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,48bool noreserve)49{
50void *ptr;51
52if (noreserve) {53/*54* We need a MEM_COMMIT before accessing any memory in a MEM_RESERVE
55* area; we cannot easily mimic POSIX MAP_NORESERVE semantics.
56*/
57error_report("Skipping reservation of swap space is not supported.");58return NULL;59}60
61ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);62trace_qemu_anon_ram_alloc(size, ptr);63
64if (ptr && align) {65*align = MAX(get_allocation_granularity(), getpagesize());66}67return ptr;68}
69
70void qemu_anon_ram_free(void *ptr, size_t size)71{
72trace_qemu_anon_ram_free(ptr, size);73if (ptr) {74VirtualFree(ptr, 0, MEM_RELEASE);75}76}
77
78#ifndef _POSIX_THREAD_SAFE_FUNCTIONS79/* FIXME: add proper locking */
80struct tm *gmtime_r(const time_t *timep, struct tm *result)81{
82struct tm *p = gmtime(timep);83memset(result, 0, sizeof(*result));84if (p) {85*result = *p;86p = result;87}88return p;89}
90
91/* FIXME: add proper locking */
92struct tm *localtime_r(const time_t *timep, struct tm *result)93{
94struct tm *p = localtime(timep);95memset(result, 0, sizeof(*result));96if (p) {97*result = *p;98p = result;99}100return p;101}
102#endif /* _POSIX_THREAD_SAFE_FUNCTIONS */103
104static int socket_error(void)105{
106switch (WSAGetLastError()) {107case 0:108return 0;109case WSAEINTR:110return EINTR;111case WSAEINVAL:112return EINVAL;113case WSA_INVALID_HANDLE:114return EBADF;115case WSA_NOT_ENOUGH_MEMORY:116return ENOMEM;117case WSA_INVALID_PARAMETER:118return EINVAL;119case WSAENAMETOOLONG:120return ENAMETOOLONG;121case WSAENOTEMPTY:122return ENOTEMPTY;123case WSAEWOULDBLOCK:124/* not using EWOULDBLOCK as we don't want code to have125* to check both EWOULDBLOCK and EAGAIN */
126return EAGAIN;127case WSAEINPROGRESS:128return EINPROGRESS;129case WSAEALREADY:130return EALREADY;131case WSAENOTSOCK:132return ENOTSOCK;133case WSAEDESTADDRREQ:134return EDESTADDRREQ;135case WSAEMSGSIZE:136return EMSGSIZE;137case WSAEPROTOTYPE:138return EPROTOTYPE;139case WSAENOPROTOOPT:140return ENOPROTOOPT;141case WSAEPROTONOSUPPORT:142return EPROTONOSUPPORT;143case WSAEOPNOTSUPP:144return EOPNOTSUPP;145case WSAEAFNOSUPPORT:146return EAFNOSUPPORT;147case WSAEADDRINUSE:148return EADDRINUSE;149case WSAEADDRNOTAVAIL:150return EADDRNOTAVAIL;151case WSAENETDOWN:152return ENETDOWN;153case WSAENETUNREACH:154return ENETUNREACH;155case WSAENETRESET:156return ENETRESET;157case WSAECONNABORTED:158return ECONNABORTED;159case WSAECONNRESET:160return ECONNRESET;161case WSAENOBUFS:162return ENOBUFS;163case WSAEISCONN:164return EISCONN;165case WSAENOTCONN:166return ENOTCONN;167case WSAETIMEDOUT:168return ETIMEDOUT;169case WSAECONNREFUSED:170return ECONNREFUSED;171case WSAELOOP:172return ELOOP;173case WSAEHOSTUNREACH:174return EHOSTUNREACH;175default:176return EIO;177}178}
179
180void qemu_socket_set_block(int fd)181{
182unsigned long opt = 0;183qemu_socket_unselect(fd, NULL);184ioctlsocket(fd, FIONBIO, &opt);185}
186
187int qemu_socket_try_set_nonblock(int fd)188{
189unsigned long opt = 1;190if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {191return -socket_error();192}193return 0;194}
195
196void qemu_socket_set_nonblock(int fd)197{
198(void)qemu_socket_try_set_nonblock(fd);199}
200
201int socket_set_fast_reuse(int fd)202{
203/* Enabling the reuse of an endpoint that was used by a socket still in204* TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
205* fast reuse is the default and SO_REUSEADDR does strange things. So we
206* don't have to do anything here. More info can be found at:
207* http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
208return 0;209}
210
211int inet_aton(const char *cp, struct in_addr *ia)212{
213uint32_t addr = inet_addr(cp);214if (addr == 0xffffffff) {215return 0;216}217ia->s_addr = addr;218return 1;219}
220
221void qemu_set_cloexec(int fd)222{
223}
224
225int qemu_get_thread_id(void)226{
227return GetCurrentThreadId();228}
229
230char *231qemu_get_local_state_dir(void)232{
233const char * const *data_dirs = g_get_system_data_dirs();234
235g_assert(data_dirs && data_dirs[0]);236
237return g_strdup(data_dirs[0]);238}
239
240void qemu_set_tty_echo(int fd, bool echo)241{
242HANDLE handle = (HANDLE)_get_osfhandle(fd);243DWORD dwMode = 0;244
245if (handle == INVALID_HANDLE_VALUE) {246return;247}248
249GetConsoleMode(handle, &dwMode);250
251if (echo) {252SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);253} else {254SetConsoleMode(handle,255dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));256}257}
258
259int getpagesize(void)260{
261SYSTEM_INFO system_info;262
263GetSystemInfo(&system_info);264return system_info.dwPageSize;265}
266
267bool qemu_prealloc_mem(int fd, char *area, size_t sz, int max_threads,268ThreadContext *tc, bool async, Error **errp)269{
270int i;271size_t pagesize = qemu_real_host_page_size();272
273sz = (sz + pagesize - 1) & -pagesize;274for (i = 0; i < sz / pagesize; i++) {275memset(area + pagesize * i, 0, 1);276}277
278return true;279}
280
281bool qemu_finish_async_prealloc_mem(Error **errp)282{
283/* async prealloc not supported, there is nothing to finish */284return true;285}
286
287char *qemu_get_pid_name(pid_t pid)288{
289/* XXX Implement me */290abort();291}
292
293
294bool qemu_socket_select(int sockfd, WSAEVENT hEventObject,295long lNetworkEvents, Error **errp)296{
297SOCKET s = _get_osfhandle(sockfd);298
299if (errp == NULL) {300errp = &error_warn;301}302
303if (s == INVALID_SOCKET) {304error_setg(errp, "invalid socket fd=%d", sockfd);305return false;306}307
308if (WSAEventSelect(s, hEventObject, lNetworkEvents) != 0) {309error_setg_win32(errp, WSAGetLastError(), "failed to WSAEventSelect()");310return false;311}312
313return true;314}
315
316bool qemu_socket_unselect(int sockfd, Error **errp)317{
318return qemu_socket_select(sockfd, NULL, 0, errp);319}
320
321int qemu_socketpair(int domain, int type, int protocol, int sv[2])322{
323struct sockaddr_un addr = {3240,325};326socklen_t socklen;327int listener = -1;328int client = -1;329int server = -1;330g_autofree char *path = NULL;331int tmpfd;332u_long arg;333int ret = -1;334
335g_return_val_if_fail(sv != NULL, -1);336
337addr.sun_family = AF_UNIX;338socklen = sizeof(addr);339
340tmpfd = g_file_open_tmp(NULL, &path, NULL);341if (tmpfd == -1 || !path) {342errno = EACCES;343goto out;344}345
346close(tmpfd);347
348if (strlen(path) >= sizeof(addr.sun_path)) {349errno = EINVAL;350goto out;351}352
353strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);354
355listener = socket(domain, type, protocol);356if (listener == -1) {357goto out;358}359
360if (DeleteFile(path) == 0 && GetLastError() != ERROR_FILE_NOT_FOUND) {361errno = EACCES;362goto out;363}364g_clear_pointer(&path, g_free);365
366if (bind(listener, (struct sockaddr *)&addr, socklen) == -1) {367goto out;368}369
370if (listen(listener, 1) == -1) {371goto out;372}373
374client = socket(domain, type, protocol);375if (client == -1) {376goto out;377}378
379arg = 1;380if (ioctlsocket(client, FIONBIO, &arg) != NO_ERROR) {381goto out;382}383
384if (connect(client, (struct sockaddr *)&addr, socklen) == -1 &&385WSAGetLastError() != WSAEWOULDBLOCK) {386goto out;387}388
389server = accept(listener, NULL, NULL);390if (server == -1) {391goto out;392}393
394arg = 0;395if (ioctlsocket(client, FIONBIO, &arg) != NO_ERROR) {396goto out;397}398
399arg = 0;400if (ioctlsocket(client, SIO_AF_UNIX_GETPEERPID, &arg) != NO_ERROR) {401goto out;402}403
404if (arg != GetCurrentProcessId()) {405errno = EPERM;406goto out;407}408
409sv[0] = server;410server = -1;411sv[1] = client;412client = -1;413ret = 0;414
415out:416if (listener != -1) {417close(listener);418}419if (client != -1) {420close(client);421}422if (server != -1) {423close(server);424}425if (path) {426DeleteFile(path);427}428return ret;429}
430
431#undef connect432int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,433socklen_t addrlen)434{
435int ret;436SOCKET s = _get_osfhandle(sockfd);437
438if (s == INVALID_SOCKET) {439return -1;440}441
442ret = connect(s, addr, addrlen);443if (ret < 0) {444if (WSAGetLastError() == WSAEWOULDBLOCK) {445errno = EINPROGRESS;446} else {447errno = socket_error();448}449}450return ret;451}
452
453
454#undef listen455int qemu_listen_wrap(int sockfd, int backlog)456{
457int ret;458SOCKET s = _get_osfhandle(sockfd);459
460if (s == INVALID_SOCKET) {461return -1;462}463
464ret = listen(s, backlog);465if (ret < 0) {466errno = socket_error();467}468return ret;469}
470
471
472#undef bind473int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,474socklen_t addrlen)475{
476int ret;477SOCKET s = _get_osfhandle(sockfd);478
479if (s == INVALID_SOCKET) {480return -1;481}482
483ret = bind(s, addr, addrlen);484if (ret < 0) {485errno = socket_error();486}487return ret;488}
489
490QEMU_USED EXCEPTION_DISPOSITION
491win32_close_exception_handler(struct _EXCEPTION_RECORD *exception_record,492void *registration, struct _CONTEXT *context,493void *dispatcher)494{
495return EXCEPTION_EXECUTE_HANDLER;496}
497
498#undef close499int qemu_close_socket_osfhandle(int fd)500{
501SOCKET s = _get_osfhandle(fd);502DWORD flags = 0;503
504/*505* If we were to just call _close on the descriptor, it would close the
506* HANDLE, but it wouldn't free any of the resources associated to the
507* SOCKET, and we can't call _close after calling closesocket, because
508* closesocket has already closed the HANDLE, and _close would attempt to
509* close the HANDLE again, resulting in a double free. We can however
510* protect the HANDLE from actually being closed long enough to close the
511* file descriptor, then close the socket itself.
512*/
513if (!GetHandleInformation((HANDLE)s, &flags)) {514errno = EACCES;515return -1;516}517
518if (!SetHandleInformation((HANDLE)s, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE)) {519errno = EACCES;520return -1;521}522
523__try1(win32_close_exception_handler) {524/*525* close() returns EBADF since we PROTECT_FROM_CLOSE the underlying
526* handle, but the FD is actually freed
527*/
528if (close(fd) < 0 && errno != EBADF) {529return -1;530}531}532__except1 {533}534
535if (!SetHandleInformation((HANDLE)s, flags, flags)) {536errno = EACCES;537return -1;538}539
540return 0;541}
542
543int qemu_close_wrap(int fd)544{
545SOCKET s = INVALID_SOCKET;546int ret = -1;547
548if (!fd_is_socket(fd)) {549return close(fd);550}551
552s = _get_osfhandle(fd);553qemu_close_socket_osfhandle(fd);554
555ret = closesocket(s);556if (ret < 0) {557errno = socket_error();558}559
560return ret;561}
562
563
564#undef socket565int qemu_socket_wrap(int domain, int type, int protocol)566{
567SOCKET s;568int fd;569
570s = socket(domain, type, protocol);571if (s == -1) {572errno = socket_error();573return -1;574}575
576fd = _open_osfhandle(s, _O_BINARY);577if (fd < 0) {578closesocket(s);579/* _open_osfhandle may not set errno, and closesocket() may override it */580errno = ENOMEM;581}582
583return fd;584}
585
586
587#undef accept588int qemu_accept_wrap(int sockfd, struct sockaddr *addr,589socklen_t *addrlen)590{
591int fd;592SOCKET s = _get_osfhandle(sockfd);593
594if (s == INVALID_SOCKET) {595return -1;596}597
598s = accept(s, addr, addrlen);599if (s == -1) {600errno = socket_error();601return -1;602}603
604fd = _open_osfhandle(s, _O_BINARY);605if (fd < 0) {606closesocket(s);607/* _open_osfhandle may not set errno, and closesocket() may override it */608errno = ENOMEM;609}610
611return fd;612}
613
614
615#undef shutdown616int qemu_shutdown_wrap(int sockfd, int how)617{
618int ret;619SOCKET s = _get_osfhandle(sockfd);620
621if (s == INVALID_SOCKET) {622return -1;623}624
625ret = shutdown(s, how);626if (ret < 0) {627errno = socket_error();628}629return ret;630}
631
632
633#undef ioctlsocket634int qemu_ioctlsocket_wrap(int fd, int req, void *val)635{
636int ret;637SOCKET s = _get_osfhandle(fd);638
639if (s == INVALID_SOCKET) {640return -1;641}642
643ret = ioctlsocket(s, req, val);644if (ret < 0) {645errno = socket_error();646}647return ret;648}
649
650
651#undef getsockopt652int qemu_getsockopt_wrap(int sockfd, int level, int optname,653void *optval, socklen_t *optlen)654{
655int ret;656SOCKET s = _get_osfhandle(sockfd);657
658if (s == INVALID_SOCKET) {659return -1;660}661
662ret = getsockopt(s, level, optname, optval, optlen);663if (ret < 0) {664errno = socket_error();665}666return ret;667}
668
669
670#undef setsockopt671int qemu_setsockopt_wrap(int sockfd, int level, int optname,672const void *optval, socklen_t optlen)673{
674int ret;675SOCKET s = _get_osfhandle(sockfd);676
677if (s == INVALID_SOCKET) {678return -1;679}680
681ret = setsockopt(s, level, optname, optval, optlen);682if (ret < 0) {683errno = socket_error();684}685return ret;686}
687
688
689#undef getpeername690int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,691socklen_t *addrlen)692{
693int ret;694SOCKET s = _get_osfhandle(sockfd);695
696if (s == INVALID_SOCKET) {697return -1;698}699
700ret = getpeername(s, addr, addrlen);701if (ret < 0) {702errno = socket_error();703}704return ret;705}
706
707
708#undef getsockname709int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,710socklen_t *addrlen)711{
712int ret;713SOCKET s = _get_osfhandle(sockfd);714
715if (s == INVALID_SOCKET) {716return -1;717}718
719ret = getsockname(s, addr, addrlen);720if (ret < 0) {721errno = socket_error();722}723return ret;724}
725
726
727#undef send728ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)729{
730int ret;731SOCKET s = _get_osfhandle(sockfd);732
733if (s == INVALID_SOCKET) {734return -1;735}736
737ret = send(s, buf, len, flags);738if (ret < 0) {739errno = socket_error();740}741return ret;742}
743
744
745#undef sendto746ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,747const struct sockaddr *addr, socklen_t addrlen)748{
749int ret;750SOCKET s = _get_osfhandle(sockfd);751
752if (s == INVALID_SOCKET) {753return -1;754}755
756ret = sendto(s, buf, len, flags, addr, addrlen);757if (ret < 0) {758errno = socket_error();759}760return ret;761}
762
763
764#undef recv765ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)766{
767int ret;768SOCKET s = _get_osfhandle(sockfd);769
770if (s == INVALID_SOCKET) {771return -1;772}773
774ret = recv(s, buf, len, flags);775if (ret < 0) {776errno = socket_error();777}778return ret;779}
780
781
782#undef recvfrom783ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,784struct sockaddr *addr, socklen_t *addrlen)785{
786int ret;787SOCKET s = _get_osfhandle(sockfd);788
789if (s == INVALID_SOCKET) {790return -1;791}792
793ret = recvfrom(s, buf, len, flags, addr, addrlen);794if (ret < 0) {795errno = socket_error();796}797return ret;798}
799
800bool qemu_write_pidfile(const char *filename, Error **errp)801{
802char buffer[128];803int len;804HANDLE file;805OVERLAPPED overlap;806BOOL ret;807memset(&overlap, 0, sizeof(overlap));808
809file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,810OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);811
812if (file == INVALID_HANDLE_VALUE) {813error_setg(errp, "Failed to create PID file");814return false;815}816len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", (pid_t)getpid());817ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len,818NULL, &overlap);819CloseHandle(file);820if (ret == 0) {821error_setg(errp, "Failed to write PID file");822return false;823}824return true;825}
826
827size_t qemu_get_host_physmem(void)828{
829MEMORYSTATUSEX statex;830statex.dwLength = sizeof(statex);831
832if (GlobalMemoryStatusEx(&statex)) {833return statex.ullTotalPhys;834}835return 0;836}
837
838int qemu_msync(void *addr, size_t length, int fd)839{
840/**841* Perform the sync based on the file descriptor
842* The sync range will most probably be wider than the one
843* requested - but it will still get the job done
844*/
845return qemu_fdatasync(fd);846}
847
848void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp)849{
850void *bits;851
852trace_win32_map_alloc(size);853
854*h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,855size, NULL);856if (*h == NULL) {857error_setg_win32(errp, GetLastError(), "Failed to CreateFileMapping");858return NULL;859}860
861bits = MapViewOfFile(*h, FILE_MAP_ALL_ACCESS, 0, 0, size);862if (bits == NULL) {863error_setg_win32(errp, GetLastError(), "Failed to MapViewOfFile");864CloseHandle(*h);865return NULL;866}867
868return bits;869}
870
871void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp)872{
873trace_win32_map_free(ptr, h);874
875if (UnmapViewOfFile(ptr) == 0) {876error_setg_win32(errp, GetLastError(), "Failed to UnmapViewOfFile");877}878CloseHandle(h);879}
880