qemu/util/osdep.c
<<
>>
Prefs
   1/*
   2 * QEMU low level functions
   3 *
   4 * Copyright (c) 2003 Fabrice Bellard
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24#include <stdlib.h>
  25#include <stdio.h>
  26#include <stdarg.h>
  27#include <stdbool.h>
  28#include <string.h>
  29#include <errno.h>
  30#include <unistd.h>
  31#include <fcntl.h>
  32
  33/* Needed early for CONFIG_BSD etc. */
  34#include "config-host.h"
  35
  36#if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
  37#include <sys/mman.h>
  38#endif
  39
  40#ifdef CONFIG_SOLARIS
  41#include <sys/types.h>
  42#include <sys/statvfs.h>
  43/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
  44   discussion about Solaris header problems */
  45extern int madvise(caddr_t, size_t, int);
  46#endif
  47
  48#include "qemu-common.h"
  49#include "trace.h"
  50#include "qemu/sockets.h"
  51#include "monitor/monitor.h"
  52
  53static bool fips_enabled = false;
  54
  55static const char *qemu_version = QEMU_VERSION;
  56
  57int socket_set_cork(int fd, int v)
  58{
  59#if defined(SOL_TCP) && defined(TCP_CORK)
  60    return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
  61#else
  62    return 0;
  63#endif
  64}
  65
  66int socket_set_nodelay(int fd)
  67{
  68    int v = 1;
  69    return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
  70}
  71
  72int qemu_madvise(void *addr, size_t len, int advice)
  73{
  74    if (advice == QEMU_MADV_INVALID) {
  75        errno = EINVAL;
  76        return -1;
  77    }
  78#if defined(CONFIG_MADVISE)
  79    return madvise(addr, len, advice);
  80#elif defined(CONFIG_POSIX_MADVISE)
  81    return posix_madvise(addr, len, advice);
  82#else
  83    errno = EINVAL;
  84    return -1;
  85#endif
  86}
  87
  88#ifndef _WIN32
  89/*
  90 * Dups an fd and sets the flags
  91 */
  92static int qemu_dup_flags(int fd, int flags)
  93{
  94    int ret;
  95    int serrno;
  96    int dup_flags;
  97
  98#ifdef F_DUPFD_CLOEXEC
  99    ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
 100#else
 101    ret = dup(fd);
 102    if (ret != -1) {
 103        qemu_set_cloexec(ret);
 104    }
 105#endif
 106    if (ret == -1) {
 107        goto fail;
 108    }
 109
 110    dup_flags = fcntl(ret, F_GETFL);
 111    if (dup_flags == -1) {
 112        goto fail;
 113    }
 114
 115    if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
 116        errno = EINVAL;
 117        goto fail;
 118    }
 119
 120    /* Set/unset flags that we can with fcntl */
 121    if (fcntl(ret, F_SETFL, flags) == -1) {
 122        goto fail;
 123    }
 124
 125    /* Truncate the file in the cases that open() would truncate it */
 126    if (flags & O_TRUNC ||
 127            ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
 128        if (ftruncate(ret, 0) == -1) {
 129            goto fail;
 130        }
 131    }
 132
 133    return ret;
 134
 135fail:
 136    serrno = errno;
 137    if (ret != -1) {
 138        close(ret);
 139    }
 140    errno = serrno;
 141    return -1;
 142}
 143
 144static int qemu_parse_fdset(const char *param)
 145{
 146    return qemu_parse_fd(param);
 147}
 148#endif
 149
 150/*
 151 * Opens a file with FD_CLOEXEC set
 152 */
 153int qemu_open(const char *name, int flags, ...)
 154{
 155    int ret;
 156    int mode = 0;
 157
 158#ifndef _WIN32
 159    const char *fdset_id_str;
 160
 161    /* Attempt dup of fd from fd set */
 162    if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
 163        int64_t fdset_id;
 164        int fd, dupfd;
 165
 166        fdset_id = qemu_parse_fdset(fdset_id_str);
 167        if (fdset_id == -1) {
 168            errno = EINVAL;
 169            return -1;
 170        }
 171
 172        fd = monitor_fdset_get_fd(fdset_id, flags);
 173        if (fd == -1) {
 174            return -1;
 175        }
 176
 177        dupfd = qemu_dup_flags(fd, flags);
 178        if (dupfd == -1) {
 179            return -1;
 180        }
 181
 182        ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
 183        if (ret == -1) {
 184            close(dupfd);
 185            errno = EINVAL;
 186            return -1;
 187        }
 188
 189        return dupfd;
 190    }
 191#endif
 192
 193    if (flags & O_CREAT) {
 194        va_list ap;
 195
 196        va_start(ap, flags);
 197        mode = va_arg(ap, int);
 198        va_end(ap);
 199    }
 200
 201#ifdef O_CLOEXEC
 202    ret = open(name, flags | O_CLOEXEC, mode);
 203#else
 204    ret = open(name, flags, mode);
 205    if (ret >= 0) {
 206        qemu_set_cloexec(ret);
 207    }
 208#endif
 209
 210#ifdef O_DIRECT
 211    if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
 212        error_report("file system may not support O_DIRECT");
 213        errno = EINVAL; /* in case it was clobbered */
 214    }
 215#endif /* O_DIRECT */
 216
 217    return ret;
 218}
 219
 220int qemu_close(int fd)
 221{
 222    int64_t fdset_id;
 223
 224    /* Close fd that was dup'd from an fdset */
 225    fdset_id = monitor_fdset_dup_fd_find(fd);
 226    if (fdset_id != -1) {
 227        int ret;
 228
 229        ret = close(fd);
 230        if (ret == 0) {
 231            monitor_fdset_dup_fd_remove(fd);
 232        }
 233
 234        return ret;
 235    }
 236
 237    return close(fd);
 238}
 239
 240/*
 241 * A variant of write(2) which handles partial write.
 242 *
 243 * Return the number of bytes transferred.
 244 * Set errno if fewer than `count' bytes are written.
 245 *
 246 * This function don't work with non-blocking fd's.
 247 * Any of the possibilities with non-bloking fd's is bad:
 248 *   - return a short write (then name is wrong)
 249 *   - busy wait adding (errno == EAGAIN) to the loop
 250 */
 251ssize_t qemu_write_full(int fd, const void *buf, size_t count)
 252{
 253    ssize_t ret = 0;
 254    ssize_t total = 0;
 255
 256    while (count) {
 257        ret = write(fd, buf, count);
 258        if (ret < 0) {
 259            if (errno == EINTR)
 260                continue;
 261            break;
 262        }
 263
 264        count -= ret;
 265        buf += ret;
 266        total += ret;
 267    }
 268
 269    return total;
 270}
 271
 272/*
 273 * Opens a socket with FD_CLOEXEC set
 274 */
 275int qemu_socket(int domain, int type, int protocol)
 276{
 277    int ret;
 278
 279#ifdef SOCK_CLOEXEC
 280    ret = socket(domain, type | SOCK_CLOEXEC, protocol);
 281    if (ret != -1 || errno != EINVAL) {
 282        return ret;
 283    }
 284#endif
 285    ret = socket(domain, type, protocol);
 286    if (ret >= 0) {
 287        qemu_set_cloexec(ret);
 288    }
 289
 290    return ret;
 291}
 292
 293/*
 294 * Accept a connection and set FD_CLOEXEC
 295 */
 296int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
 297{
 298    int ret;
 299
 300#ifdef CONFIG_ACCEPT4
 301    ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
 302    if (ret != -1 || errno != ENOSYS) {
 303        return ret;
 304    }
 305#endif
 306    ret = accept(s, addr, addrlen);
 307    if (ret >= 0) {
 308        qemu_set_cloexec(ret);
 309    }
 310
 311    return ret;
 312}
 313
 314/*
 315 * A variant of send(2) which handles partial write.
 316 *
 317 * Return the number of bytes transferred, which is only
 318 * smaller than `count' if there is an error.
 319 *
 320 * This function won't work with non-blocking fd's.
 321 * Any of the possibilities with non-bloking fd's is bad:
 322 *   - return a short write (then name is wrong)
 323 *   - busy wait adding (errno == EAGAIN) to the loop
 324 */
 325ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
 326{
 327    ssize_t ret = 0;
 328    ssize_t total = 0;
 329
 330    while (count) {
 331        ret = send(fd, buf, count, flags);
 332        if (ret < 0) {
 333            if (errno == EINTR) {
 334                continue;
 335            }
 336            break;
 337        }
 338
 339        count -= ret;
 340        buf += ret;
 341        total += ret;
 342    }
 343
 344    return total;
 345}
 346
 347/*
 348 * A variant of recv(2) which handles partial write.
 349 *
 350 * Return the number of bytes transferred, which is only
 351 * smaller than `count' if there is an error.
 352 *
 353 * This function won't work with non-blocking fd's.
 354 * Any of the possibilities with non-bloking fd's is bad:
 355 *   - return a short write (then name is wrong)
 356 *   - busy wait adding (errno == EAGAIN) to the loop
 357 */
 358ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
 359{
 360    ssize_t ret = 0;
 361    ssize_t total = 0;
 362
 363    while (count) {
 364        ret = qemu_recv(fd, buf, count, flags);
 365        if (ret <= 0) {
 366            if (ret < 0 && errno == EINTR) {
 367                continue;
 368            }
 369            break;
 370        }
 371
 372        count -= ret;
 373        buf += ret;
 374        total += ret;
 375    }
 376
 377    return total;
 378}
 379
 380void qemu_set_version(const char *version)
 381{
 382    qemu_version = version;
 383}
 384
 385const char *qemu_get_version(void)
 386{
 387    return qemu_version;
 388}
 389
 390void fips_set_state(bool requested)
 391{
 392#ifdef __linux__
 393    if (requested) {
 394        FILE *fds = fopen("/proc/sys/crypto/fips_enabled", "r");
 395        if (fds != NULL) {
 396            fips_enabled = (fgetc(fds) == '1');
 397            fclose(fds);
 398        }
 399    }
 400#else
 401    fips_enabled = false;
 402#endif /* __linux__ */
 403
 404#ifdef _FIPS_DEBUG
 405    fprintf(stderr, "FIPS mode %s (requested %s)\n",
 406            (fips_enabled ? "enabled" : "disabled"),
 407            (requested ? "enabled" : "disabled"));
 408#endif
 409}
 410
 411bool fips_get_state(void)
 412{
 413    return fips_enabled;
 414}
 415
 416#ifdef _WIN32
 417static void socket_cleanup(void)
 418{
 419    WSACleanup();
 420}
 421#endif
 422
 423int socket_init(void)
 424{
 425#ifdef _WIN32
 426    WSADATA Data;
 427    int ret, err;
 428
 429    ret = WSAStartup(MAKEWORD(2, 2), &Data);
 430    if (ret != 0) {
 431        err = WSAGetLastError();
 432        fprintf(stderr, "WSAStartup: %d\n", err);
 433        return -1;
 434    }
 435    atexit(socket_cleanup);
 436#endif
 437    return 0;
 438}
 439
 440#ifndef CONFIG_IOVEC
 441/* helper function for iov_send_recv() */
 442static ssize_t
 443readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
 444{
 445    unsigned i = 0;
 446    ssize_t ret = 0;
 447    while (i < iov_cnt) {
 448        ssize_t r = do_write
 449            ? write(fd, iov[i].iov_base, iov[i].iov_len)
 450            : read(fd, iov[i].iov_base, iov[i].iov_len);
 451        if (r > 0) {
 452            ret += r;
 453        } else if (!r) {
 454            break;
 455        } else if (errno == EINTR) {
 456            continue;
 457        } else {
 458            /* else it is some "other" error,
 459             * only return if there was no data processed. */
 460            if (ret == 0) {
 461                ret = -1;
 462            }
 463            break;
 464        }
 465        i++;
 466    }
 467    return ret;
 468}
 469
 470ssize_t
 471readv(int fd, const struct iovec *iov, int iov_cnt)
 472{
 473    return readv_writev(fd, iov, iov_cnt, false);
 474}
 475
 476ssize_t
 477writev(int fd, const struct iovec *iov, int iov_cnt)
 478{
 479    return readv_writev(fd, iov, iov_cnt, true);
 480}
 481#endif
 482