qemu/util/oslib-win32.c
<<
>>
Prefs
   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 * The implementation of g_poll (functions poll_rest, g_poll) at the end of
  29 * this file are based on code from GNOME glib-2 and use a different license,
  30 * see the license comment there.
  31 */
  32
  33#include "qemu/osdep.h"
  34#include <windows.h>
  35#include "qemu-common.h"
  36#include "qapi/error.h"
  37#include "qemu/main-loop.h"
  38#include "trace.h"
  39#include "qemu/sockets.h"
  40#include "qemu/cutils.h"
  41#include "qemu/error-report.h"
  42#include <malloc.h>
  43
  44/* this must come after including "trace.h" */
  45#include <shlobj.h>
  46
  47static int get_allocation_granularity(void)
  48{
  49    SYSTEM_INFO system_info;
  50
  51    GetSystemInfo(&system_info);
  52    return system_info.dwAllocationGranularity;
  53}
  54
  55void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
  56                          bool noreserve)
  57{
  58    void *ptr;
  59
  60    if (noreserve) {
  61        /*
  62         * We need a MEM_COMMIT before accessing any memory in a MEM_RESERVE
  63         * area; we cannot easily mimic POSIX MAP_NORESERVE semantics.
  64         */
  65        error_report("Skipping reservation of swap space is not supported.");
  66        return NULL;
  67    }
  68
  69    ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
  70    trace_qemu_anon_ram_alloc(size, ptr);
  71
  72    if (ptr && align) {
  73        *align = MAX(get_allocation_granularity(), getpagesize());
  74    }
  75    return ptr;
  76}
  77
  78void qemu_anon_ram_free(void *ptr, size_t size)
  79{
  80    trace_qemu_anon_ram_free(ptr, size);
  81    if (ptr) {
  82        VirtualFree(ptr, 0, MEM_RELEASE);
  83    }
  84}
  85
  86#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
  87/* FIXME: add proper locking */
  88struct tm *gmtime_r(const time_t *timep, struct tm *result)
  89{
  90    struct tm *p = gmtime(timep);
  91    memset(result, 0, sizeof(*result));
  92    if (p) {
  93        *result = *p;
  94        p = result;
  95    }
  96    return p;
  97}
  98
  99/* FIXME: add proper locking */
 100struct tm *localtime_r(const time_t *timep, struct tm *result)
 101{
 102    struct tm *p = localtime(timep);
 103    memset(result, 0, sizeof(*result));
 104    if (p) {
 105        *result = *p;
 106        p = result;
 107    }
 108    return p;
 109}
 110#endif /* _POSIX_THREAD_SAFE_FUNCTIONS */
 111
 112static int socket_error(void)
 113{
 114    switch (WSAGetLastError()) {
 115    case 0:
 116        return 0;
 117    case WSAEINTR:
 118        return EINTR;
 119    case WSAEINVAL:
 120        return EINVAL;
 121    case WSA_INVALID_HANDLE:
 122        return EBADF;
 123    case WSA_NOT_ENOUGH_MEMORY:
 124        return ENOMEM;
 125    case WSA_INVALID_PARAMETER:
 126        return EINVAL;
 127    case WSAENAMETOOLONG:
 128        return ENAMETOOLONG;
 129    case WSAENOTEMPTY:
 130        return ENOTEMPTY;
 131    case WSAEWOULDBLOCK:
 132         /* not using EWOULDBLOCK as we don't want code to have
 133          * to check both EWOULDBLOCK and EAGAIN */
 134        return EAGAIN;
 135    case WSAEINPROGRESS:
 136        return EINPROGRESS;
 137    case WSAEALREADY:
 138        return EALREADY;
 139    case WSAENOTSOCK:
 140        return ENOTSOCK;
 141    case WSAEDESTADDRREQ:
 142        return EDESTADDRREQ;
 143    case WSAEMSGSIZE:
 144        return EMSGSIZE;
 145    case WSAEPROTOTYPE:
 146        return EPROTOTYPE;
 147    case WSAENOPROTOOPT:
 148        return ENOPROTOOPT;
 149    case WSAEPROTONOSUPPORT:
 150        return EPROTONOSUPPORT;
 151    case WSAEOPNOTSUPP:
 152        return EOPNOTSUPP;
 153    case WSAEAFNOSUPPORT:
 154        return EAFNOSUPPORT;
 155    case WSAEADDRINUSE:
 156        return EADDRINUSE;
 157    case WSAEADDRNOTAVAIL:
 158        return EADDRNOTAVAIL;
 159    case WSAENETDOWN:
 160        return ENETDOWN;
 161    case WSAENETUNREACH:
 162        return ENETUNREACH;
 163    case WSAENETRESET:
 164        return ENETRESET;
 165    case WSAECONNABORTED:
 166        return ECONNABORTED;
 167    case WSAECONNRESET:
 168        return ECONNRESET;
 169    case WSAENOBUFS:
 170        return ENOBUFS;
 171    case WSAEISCONN:
 172        return EISCONN;
 173    case WSAENOTCONN:
 174        return ENOTCONN;
 175    case WSAETIMEDOUT:
 176        return ETIMEDOUT;
 177    case WSAECONNREFUSED:
 178        return ECONNREFUSED;
 179    case WSAELOOP:
 180        return ELOOP;
 181    case WSAEHOSTUNREACH:
 182        return EHOSTUNREACH;
 183    default:
 184        return EIO;
 185    }
 186}
 187
 188void qemu_set_block(int fd)
 189{
 190    unsigned long opt = 0;
 191    WSAEventSelect(fd, NULL, 0);
 192    ioctlsocket(fd, FIONBIO, &opt);
 193}
 194
 195int qemu_try_set_nonblock(int fd)
 196{
 197    unsigned long opt = 1;
 198    if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
 199        return -socket_error();
 200    }
 201    return 0;
 202}
 203
 204void qemu_set_nonblock(int fd)
 205{
 206    (void)qemu_try_set_nonblock(fd);
 207}
 208
 209int socket_set_fast_reuse(int fd)
 210{
 211    /* Enabling the reuse of an endpoint that was used by a socket still in
 212     * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
 213     * fast reuse is the default and SO_REUSEADDR does strange things. So we
 214     * don't have to do anything here. More info can be found at:
 215     * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
 216    return 0;
 217}
 218
 219int inet_aton(const char *cp, struct in_addr *ia)
 220{
 221    uint32_t addr = inet_addr(cp);
 222    if (addr == 0xffffffff) {
 223        return 0;
 224    }
 225    ia->s_addr = addr;
 226    return 1;
 227}
 228
 229void qemu_set_cloexec(int fd)
 230{
 231}
 232
 233/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
 234#define _W32_FT_OFFSET (116444736000000000ULL)
 235
 236int qemu_gettimeofday(qemu_timeval *tp)
 237{
 238  union {
 239    unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
 240    FILETIME ft;
 241  }  _now;
 242
 243  if(tp) {
 244      GetSystemTimeAsFileTime (&_now.ft);
 245      tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
 246      tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
 247  }
 248  /* Always return 0 as per Open Group Base Specifications Issue 6.
 249     Do not set errno on error.  */
 250  return 0;
 251}
 252
 253int qemu_get_thread_id(void)
 254{
 255    return GetCurrentThreadId();
 256}
 257
 258char *
 259qemu_get_local_state_pathname(const char *relative_pathname)
 260{
 261    HRESULT result;
 262    char base_path[MAX_PATH+1] = "";
 263
 264    result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
 265                             /* SHGFP_TYPE_CURRENT */ 0, base_path);
 266    if (result != S_OK) {
 267        /* misconfigured environment */
 268        g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result);
 269        abort();
 270    }
 271    return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
 272                           relative_pathname);
 273}
 274
 275void qemu_set_tty_echo(int fd, bool echo)
 276{
 277    HANDLE handle = (HANDLE)_get_osfhandle(fd);
 278    DWORD dwMode = 0;
 279
 280    if (handle == INVALID_HANDLE_VALUE) {
 281        return;
 282    }
 283
 284    GetConsoleMode(handle, &dwMode);
 285
 286    if (echo) {
 287        SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
 288    } else {
 289        SetConsoleMode(handle,
 290                       dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
 291    }
 292}
 293
 294static const char *exec_dir;
 295
 296void qemu_init_exec_dir(const char *argv0)
 297{
 298
 299    char *p;
 300    char buf[MAX_PATH];
 301    DWORD len;
 302
 303    if (exec_dir) {
 304        return;
 305    }
 306
 307    len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
 308    if (len == 0) {
 309        return;
 310    }
 311
 312    buf[len] = 0;
 313    p = buf + len - 1;
 314    while (p != buf && *p != '\\') {
 315        p--;
 316    }
 317    *p = 0;
 318    if (access(buf, R_OK) == 0) {
 319        exec_dir = g_strdup(buf);
 320    } else {
 321        exec_dir = CONFIG_BINDIR;
 322    }
 323}
 324
 325const char *qemu_get_exec_dir(void)
 326{
 327    return exec_dir;
 328}
 329
 330int getpagesize(void)
 331{
 332    SYSTEM_INFO system_info;
 333
 334    GetSystemInfo(&system_info);
 335    return system_info.dwPageSize;
 336}
 337
 338void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
 339                     Error **errp)
 340{
 341    int i;
 342    size_t pagesize = qemu_real_host_page_size;
 343
 344    memory = (memory + pagesize - 1) & -pagesize;
 345    for (i = 0; i < memory / pagesize; i++) {
 346        memset(area + pagesize * i, 0, 1);
 347    }
 348}
 349
 350char *qemu_get_pid_name(pid_t pid)
 351{
 352    /* XXX Implement me */
 353    abort();
 354}
 355
 356
 357pid_t qemu_fork(Error **errp)
 358{
 359    errno = ENOSYS;
 360    error_setg_errno(errp, errno,
 361                     "cannot fork child process");
 362    return -1;
 363}
 364
 365
 366#undef connect
 367int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
 368                      socklen_t addrlen)
 369{
 370    int ret;
 371    ret = connect(sockfd, addr, addrlen);
 372    if (ret < 0) {
 373        if (WSAGetLastError() == WSAEWOULDBLOCK) {
 374            errno = EINPROGRESS;
 375        } else {
 376            errno = socket_error();
 377        }
 378    }
 379    return ret;
 380}
 381
 382
 383#undef listen
 384int qemu_listen_wrap(int sockfd, int backlog)
 385{
 386    int ret;
 387    ret = listen(sockfd, backlog);
 388    if (ret < 0) {
 389        errno = socket_error();
 390    }
 391    return ret;
 392}
 393
 394
 395#undef bind
 396int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
 397                   socklen_t addrlen)
 398{
 399    int ret;
 400    ret = bind(sockfd, addr, addrlen);
 401    if (ret < 0) {
 402        errno = socket_error();
 403    }
 404    return ret;
 405}
 406
 407
 408#undef socket
 409int qemu_socket_wrap(int domain, int type, int protocol)
 410{
 411    int ret;
 412    ret = socket(domain, type, protocol);
 413    if (ret < 0) {
 414        errno = socket_error();
 415    }
 416    return ret;
 417}
 418
 419
 420#undef accept
 421int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
 422                     socklen_t *addrlen)
 423{
 424    int ret;
 425    ret = accept(sockfd, addr, addrlen);
 426    if (ret < 0) {
 427        errno = socket_error();
 428    }
 429    return ret;
 430}
 431
 432
 433#undef shutdown
 434int qemu_shutdown_wrap(int sockfd, int how)
 435{
 436    int ret;
 437    ret = shutdown(sockfd, how);
 438    if (ret < 0) {
 439        errno = socket_error();
 440    }
 441    return ret;
 442}
 443
 444
 445#undef ioctlsocket
 446int qemu_ioctlsocket_wrap(int fd, int req, void *val)
 447{
 448    int ret;
 449    ret = ioctlsocket(fd, req, val);
 450    if (ret < 0) {
 451        errno = socket_error();
 452    }
 453    return ret;
 454}
 455
 456
 457#undef closesocket
 458int qemu_closesocket_wrap(int fd)
 459{
 460    int ret;
 461    ret = closesocket(fd);
 462    if (ret < 0) {
 463        errno = socket_error();
 464    }
 465    return ret;
 466}
 467
 468
 469#undef getsockopt
 470int qemu_getsockopt_wrap(int sockfd, int level, int optname,
 471                         void *optval, socklen_t *optlen)
 472{
 473    int ret;
 474    ret = getsockopt(sockfd, level, optname, optval, optlen);
 475    if (ret < 0) {
 476        errno = socket_error();
 477    }
 478    return ret;
 479}
 480
 481
 482#undef setsockopt
 483int qemu_setsockopt_wrap(int sockfd, int level, int optname,
 484                         const void *optval, socklen_t optlen)
 485{
 486    int ret;
 487    ret = setsockopt(sockfd, level, optname, optval, optlen);
 488    if (ret < 0) {
 489        errno = socket_error();
 490    }
 491    return ret;
 492}
 493
 494
 495#undef getpeername
 496int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,
 497                          socklen_t *addrlen)
 498{
 499    int ret;
 500    ret = getpeername(sockfd, addr, addrlen);
 501    if (ret < 0) {
 502        errno = socket_error();
 503    }
 504    return ret;
 505}
 506
 507
 508#undef getsockname
 509int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,
 510                          socklen_t *addrlen)
 511{
 512    int ret;
 513    ret = getsockname(sockfd, addr, addrlen);
 514    if (ret < 0) {
 515        errno = socket_error();
 516    }
 517    return ret;
 518}
 519
 520
 521#undef send
 522ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)
 523{
 524    int ret;
 525    ret = send(sockfd, buf, len, flags);
 526    if (ret < 0) {
 527        errno = socket_error();
 528    }
 529    return ret;
 530}
 531
 532
 533#undef sendto
 534ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
 535                         const struct sockaddr *addr, socklen_t addrlen)
 536{
 537    int ret;
 538    ret = sendto(sockfd, buf, len, flags, addr, addrlen);
 539    if (ret < 0) {
 540        errno = socket_error();
 541    }
 542    return ret;
 543}
 544
 545
 546#undef recv
 547ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)
 548{
 549    int ret;
 550    ret = recv(sockfd, buf, len, flags);
 551    if (ret < 0) {
 552        errno = socket_error();
 553    }
 554    return ret;
 555}
 556
 557
 558#undef recvfrom
 559ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
 560                           struct sockaddr *addr, socklen_t *addrlen)
 561{
 562    int ret;
 563    ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);
 564    if (ret < 0) {
 565        errno = socket_error();
 566    }
 567    return ret;
 568}
 569
 570bool qemu_write_pidfile(const char *filename, Error **errp)
 571{
 572    char buffer[128];
 573    int len;
 574    HANDLE file;
 575    OVERLAPPED overlap;
 576    BOOL ret;
 577    memset(&overlap, 0, sizeof(overlap));
 578
 579    file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
 580                      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 581
 582    if (file == INVALID_HANDLE_VALUE) {
 583        error_setg(errp, "Failed to create PID file");
 584        return false;
 585    }
 586    len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", (pid_t)getpid());
 587    ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len,
 588                    NULL, &overlap);
 589    CloseHandle(file);
 590    if (ret == 0) {
 591        error_setg(errp, "Failed to write PID file");
 592        return false;
 593    }
 594    return true;
 595}
 596
 597char *qemu_get_host_name(Error **errp)
 598{
 599    wchar_t tmp[MAX_COMPUTERNAME_LENGTH + 1];
 600    DWORD size = G_N_ELEMENTS(tmp);
 601
 602    if (GetComputerNameW(tmp, &size) == 0) {
 603        error_setg_win32(errp, GetLastError(), "failed close handle");
 604        return NULL;
 605    }
 606
 607    return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL);
 608}
 609
 610size_t qemu_get_host_physmem(void)
 611{
 612    MEMORYSTATUSEX statex;
 613    statex.dwLength = sizeof(statex);
 614
 615    if (GlobalMemoryStatusEx(&statex)) {
 616        return statex.ullTotalPhys;
 617    }
 618    return 0;
 619}
 620