summaryrefslogtreecommitdiffstats
path: root/qemu/util
diff options
context:
space:
mode:
authorRajithaY <rajithax.yerrumsetty@intel.com>2017-04-25 03:31:15 -0700
committerRajitha Yerrumchetty <rajithax.yerrumsetty@intel.com>2017-05-22 06:48:08 +0000
commitbb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch)
treeca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/util
parenta14b48d18a9ed03ec191cf16b162206998a895ce (diff)
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/util')
-rw-r--r--qemu/util/Makefile.objs34
-rw-r--r--qemu/util/acl.c188
-rw-r--r--qemu/util/base64.c60
-rw-r--r--qemu/util/bitmap.c340
-rw-r--r--qemu/util/bitops.c159
-rw-r--r--qemu/util/buffer.c172
-rw-r--r--qemu/util/compatfd.c111
-rw-r--r--qemu/util/coroutine-gthread.c199
-rw-r--r--qemu/util/coroutine-sigaltstack.c290
-rw-r--r--qemu/util/coroutine-ucontext.c192
-rw-r--r--qemu/util/coroutine-win32.c102
-rw-r--r--qemu/util/crc32c.c116
-rw-r--r--qemu/util/cutils.c839
-rw-r--r--qemu/util/envlist.c242
-rw-r--r--qemu/util/error.c273
-rw-r--r--qemu/util/event_notifier-posix.c132
-rw-r--r--qemu/util/event_notifier-win32.c61
-rw-r--r--qemu/util/fifo8.c126
-rw-r--r--qemu/util/getauxval.c109
-rw-r--r--qemu/util/hbitmap.c493
-rw-r--r--qemu/util/hexdump.c49
-rw-r--r--qemu/util/host-utils.c161
-rw-r--r--qemu/util/id.c67
-rw-r--r--qemu/util/iov.c580
-rw-r--r--qemu/util/log.c313
-rw-r--r--qemu/util/memfd.c162
-rw-r--r--qemu/util/mmap-alloc.c110
-rw-r--r--qemu/util/module.c219
-rw-r--r--qemu/util/notify.c72
-rw-r--r--qemu/util/osdep.c429
-rw-r--r--qemu/util/oslib-posix.c513
-rw-r--r--qemu/util/oslib-win32.c786
-rw-r--r--qemu/util/path.c178
-rw-r--r--qemu/util/qemu-config.c573
-rw-r--r--qemu/util/qemu-coroutine-io.c90
-rw-r--r--qemu/util/qemu-coroutine-lock.c187
-rw-r--r--qemu/util/qemu-coroutine-sleep.c42
-rw-r--r--qemu/util/qemu-coroutine.c147
-rw-r--r--qemu/util/qemu-error.c239
-rw-r--r--qemu/util/qemu-openpty.c137
-rw-r--r--qemu/util/qemu-option.c1207
-rw-r--r--qemu/util/qemu-progress.c159
-rw-r--r--qemu/util/qemu-sockets.c1153
-rw-r--r--qemu/util/qemu-thread-posix.c509
-rw-r--r--qemu/util/qemu-thread-win32.c478
-rw-r--r--qemu/util/qemu-timer-common.c62
-rw-r--r--qemu/util/rcu.c348
-rw-r--r--qemu/util/readline.c517
-rw-r--r--qemu/util/rfifolock.c78
-rw-r--r--qemu/util/throttle.c489
-rw-r--r--qemu/util/timed-average.c231
-rw-r--r--qemu/util/unicode.c101
-rw-r--r--qemu/util/uri.c2203
53 files changed, 0 insertions, 16827 deletions
diff --git a/qemu/util/Makefile.objs b/qemu/util/Makefile.objs
deleted file mode 100644
index a8a777ec4..000000000
--- a/qemu/util/Makefile.objs
+++ /dev/null
@@ -1,34 +0,0 @@
-util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
-util-obj-$(CONFIG_POSIX) += compatfd.o
-util-obj-$(CONFIG_POSIX) += event_notifier-posix.o
-util-obj-$(CONFIG_POSIX) += mmap-alloc.o
-util-obj-$(CONFIG_POSIX) += oslib-posix.o
-util-obj-$(CONFIG_POSIX) += qemu-openpty.o
-util-obj-$(CONFIG_POSIX) += qemu-thread-posix.o
-util-obj-$(CONFIG_WIN32) += event_notifier-win32.o
-util-obj-$(CONFIG_POSIX) += memfd.o
-util-obj-$(CONFIG_WIN32) += oslib-win32.o
-util-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
-util-obj-y += envlist.o path.o module.o
-util-obj-$(call lnot,$(CONFIG_INT128)) += host-utils.o
-util-obj-y += bitmap.o bitops.o hbitmap.o
-util-obj-y += fifo8.o
-util-obj-y += acl.o
-util-obj-y += error.o qemu-error.o
-util-obj-y += id.o
-util-obj-y += iov.o qemu-config.o qemu-sockets.o uri.o notify.o
-util-obj-y += qemu-option.o qemu-progress.o
-util-obj-y += hexdump.o
-util-obj-y += crc32c.o
-util-obj-y += throttle.o
-util-obj-y += getauxval.o
-util-obj-y += readline.o
-util-obj-y += rfifolock.o
-util-obj-y += rcu.o
-util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
-util-obj-y += qemu-coroutine-sleep.o
-util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
-util-obj-y += buffer.o
-util-obj-y += timed-average.o
-util-obj-y += base64.o
-util-obj-y += log.o
diff --git a/qemu/util/acl.c b/qemu/util/acl.c
deleted file mode 100644
index 723b6a89b..000000000
--- a/qemu/util/acl.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * QEMU access control list management
- *
- * Copyright (C) 2009 Red Hat, Inc
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/acl.h"
-
-#ifdef CONFIG_FNMATCH
-#include <fnmatch.h>
-#endif
-
-
-static unsigned int nacls = 0;
-static qemu_acl **acls = NULL;
-
-
-
-qemu_acl *qemu_acl_find(const char *aclname)
-{
- int i;
- for (i = 0 ; i < nacls ; i++) {
- if (strcmp(acls[i]->aclname, aclname) == 0)
- return acls[i];
- }
-
- return NULL;
-}
-
-qemu_acl *qemu_acl_init(const char *aclname)
-{
- qemu_acl *acl;
-
- acl = qemu_acl_find(aclname);
- if (acl)
- return acl;
-
- acl = g_malloc(sizeof(*acl));
- acl->aclname = g_strdup(aclname);
- /* Deny by default, so there is no window of "open
- * access" between QEMU starting, and the user setting
- * up ACLs in the monitor */
- acl->defaultDeny = 1;
-
- acl->nentries = 0;
- QTAILQ_INIT(&acl->entries);
-
- acls = g_realloc(acls, sizeof(*acls) * (nacls +1));
- acls[nacls] = acl;
- nacls++;
-
- return acl;
-}
-
-int qemu_acl_party_is_allowed(qemu_acl *acl,
- const char *party)
-{
- qemu_acl_entry *entry;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
-#ifdef CONFIG_FNMATCH
- if (fnmatch(entry->match, party, 0) == 0)
- return entry->deny ? 0 : 1;
-#else
- /* No fnmatch, so fallback to exact string matching
- * instead of allowing wildcards */
- if (strcmp(entry->match, party) == 0)
- return entry->deny ? 0 : 1;
-#endif
- }
-
- return acl->defaultDeny ? 0 : 1;
-}
-
-
-void qemu_acl_reset(qemu_acl *acl)
-{
- qemu_acl_entry *entry, *next_entry;
-
- /* Put back to deny by default, so there is no window
- * of "open access" while the user re-initializes the
- * access control list */
- acl->defaultDeny = 1;
- QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- g_free(entry->match);
- g_free(entry);
- }
- acl->nentries = 0;
-}
-
-
-int qemu_acl_append(qemu_acl *acl,
- int deny,
- const char *match)
-{
- qemu_acl_entry *entry;
-
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
- acl->nentries++;
-
- return acl->nentries;
-}
-
-
-int qemu_acl_insert(qemu_acl *acl,
- int deny,
- const char *match,
- int index)
-{
- qemu_acl_entry *tmp;
- int i = 0;
-
- if (index <= 0)
- return -1;
- if (index > acl->nentries) {
- return qemu_acl_append(acl, deny, match);
- }
-
- QTAILQ_FOREACH(tmp, &acl->entries, next) {
- i++;
- if (i == index) {
- qemu_acl_entry *entry;
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_BEFORE(tmp, entry, next);
- acl->nentries++;
- break;
- }
- }
-
- return i;
-}
-
-int qemu_acl_remove(qemu_acl *acl,
- const char *match)
-{
- qemu_acl_entry *entry;
- int i = 0;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
- i++;
- if (strcmp(entry->match, match) == 0) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- acl->nentries--;
- g_free(entry->match);
- g_free(entry);
- return i;
- }
- }
- return -1;
-}
-
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
diff --git a/qemu/util/base64.c b/qemu/util/base64.c
deleted file mode 100644
index 9d3c46cbc..000000000
--- a/qemu/util/base64.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * QEMU base64 helpers
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu/base64.h"
-
-static const char *base64_valid_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
-
-uint8_t *qbase64_decode(const char *input,
- size_t in_len,
- size_t *out_len,
- Error **errp)
-{
- *out_len = 0;
-
- if (in_len != -1) {
- /* Lack of NUL terminator is an error */
- if (input[in_len] != '\0') {
- error_setg(errp, "Base64 data is not NUL terminated");
- return NULL;
- }
- /* Check there's no NULs embedded since we expect
- * this to be valid base64 data */
- if (memchr(input, '\0', in_len) != NULL) {
- error_setg(errp, "Base64 data contains embedded NUL characters");
- return NULL;
- }
-
- /* Now we know its a valid nul terminated string
- * strspn is safe to use... */
- } else {
- in_len = strlen(input);
- }
-
- if (strspn(input, base64_valid_chars) != in_len) {
- error_setg(errp, "Base64 data contains invalid characters");
- return NULL;
- }
-
- return g_base64_decode(input, out_len);
-}
diff --git a/qemu/util/bitmap.c b/qemu/util/bitmap.c
deleted file mode 100644
index 40aadfb4f..000000000
--- a/qemu/util/bitmap.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Bitmap Module
- *
- * Stolen from linux/src/lib/bitmap.c
- *
- * Copyright (C) 2010 Corentin Chary
- *
- * This source code is licensed under the GNU General Public License,
- * Version 2.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/bitops.h"
-#include "qemu/bitmap.h"
-#include "qemu/atomic.h"
-
-/*
- * bitmaps provide an array of bits, implemented using an
- * array of unsigned longs. The number of valid bits in a
- * given bitmap does _not_ need to be an exact multiple of
- * BITS_PER_LONG.
- *
- * The possible unused bits in the last, partially used word
- * of a bitmap are 'don't care'. The implementation makes
- * no particular effort to keep them zero. It ensures that
- * their value will not affect the results of any operation.
- * The bitmap operations that return Boolean (bitmap_empty,
- * for example) or scalar (bitmap_weight, for example) results
- * carefully filter out these unused bits from impacting their
- * results.
- *
- * These operations actually hold to a slightly stronger rule:
- * if you don't input any bitmaps to these ops that have some
- * unused bits set, then they won't output any set unused bits
- * in output bitmaps.
- *
- * The byte ordering of bitmaps is more natural on little
- * endian architectures.
- */
-
-int slow_bitmap_empty(const unsigned long *bitmap, long bits)
-{
- long k, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; ++k) {
- if (bitmap[k]) {
- return 0;
- }
- }
- if (bits % BITS_PER_LONG) {
- if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-int slow_bitmap_full(const unsigned long *bitmap, long bits)
-{
- long k, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; ++k) {
- if (~bitmap[k]) {
- return 0;
- }
- }
-
- if (bits % BITS_PER_LONG) {
- if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-int slow_bitmap_equal(const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; ++k) {
- if (bitmap1[k] != bitmap2[k]) {
- return 0;
- }
- }
-
- if (bits % BITS_PER_LONG) {
- if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
- long bits)
-{
- long k, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; ++k) {
- dst[k] = ~src[k];
- }
-
- if (bits % BITS_PER_LONG) {
- dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
- }
-}
-
-int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k;
- long nr = BITS_TO_LONGS(bits);
- unsigned long result = 0;
-
- for (k = 0; k < nr; k++) {
- result |= (dst[k] = bitmap1[k] & bitmap2[k]);
- }
- return result != 0;
-}
-
-void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k;
- long nr = BITS_TO_LONGS(bits);
-
- for (k = 0; k < nr; k++) {
- dst[k] = bitmap1[k] | bitmap2[k];
- }
-}
-
-void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k;
- long nr = BITS_TO_LONGS(bits);
-
- for (k = 0; k < nr; k++) {
- dst[k] = bitmap1[k] ^ bitmap2[k];
- }
-}
-
-int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k;
- long nr = BITS_TO_LONGS(bits);
- unsigned long result = 0;
-
- for (k = 0; k < nr; k++) {
- result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
- }
- return result != 0;
-}
-
-#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
-
-void bitmap_set(unsigned long *map, long start, long nr)
-{
- unsigned long *p = map + BIT_WORD(start);
- const long size = start + nr;
- int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
- unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
-
- while (nr - bits_to_set >= 0) {
- *p |= mask_to_set;
- nr -= bits_to_set;
- bits_to_set = BITS_PER_LONG;
- mask_to_set = ~0UL;
- p++;
- }
- if (nr) {
- mask_to_set &= BITMAP_LAST_WORD_MASK(size);
- *p |= mask_to_set;
- }
-}
-
-void bitmap_set_atomic(unsigned long *map, long start, long nr)
-{
- unsigned long *p = map + BIT_WORD(start);
- const long size = start + nr;
- int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
- unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
-
- /* First word */
- if (nr - bits_to_set > 0) {
- atomic_or(p, mask_to_set);
- nr -= bits_to_set;
- bits_to_set = BITS_PER_LONG;
- mask_to_set = ~0UL;
- p++;
- }
-
- /* Full words */
- if (bits_to_set == BITS_PER_LONG) {
- while (nr >= BITS_PER_LONG) {
- *p = ~0UL;
- nr -= BITS_PER_LONG;
- p++;
- }
- }
-
- /* Last word */
- if (nr) {
- mask_to_set &= BITMAP_LAST_WORD_MASK(size);
- atomic_or(p, mask_to_set);
- } else {
- /* If we avoided the full barrier in atomic_or(), issue a
- * barrier to account for the assignments in the while loop.
- */
- smp_mb();
- }
-}
-
-void bitmap_clear(unsigned long *map, long start, long nr)
-{
- unsigned long *p = map + BIT_WORD(start);
- const long size = start + nr;
- int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
- unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
-
- while (nr - bits_to_clear >= 0) {
- *p &= ~mask_to_clear;
- nr -= bits_to_clear;
- bits_to_clear = BITS_PER_LONG;
- mask_to_clear = ~0UL;
- p++;
- }
- if (nr) {
- mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
- *p &= ~mask_to_clear;
- }
-}
-
-bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr)
-{
- unsigned long *p = map + BIT_WORD(start);
- const long size = start + nr;
- int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
- unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
- unsigned long dirty = 0;
- unsigned long old_bits;
-
- /* First word */
- if (nr - bits_to_clear > 0) {
- old_bits = atomic_fetch_and(p, ~mask_to_clear);
- dirty |= old_bits & mask_to_clear;
- nr -= bits_to_clear;
- bits_to_clear = BITS_PER_LONG;
- mask_to_clear = ~0UL;
- p++;
- }
-
- /* Full words */
- if (bits_to_clear == BITS_PER_LONG) {
- while (nr >= BITS_PER_LONG) {
- if (*p) {
- old_bits = atomic_xchg(p, 0);
- dirty |= old_bits;
- }
- nr -= BITS_PER_LONG;
- p++;
- }
- }
-
- /* Last word */
- if (nr) {
- mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
- old_bits = atomic_fetch_and(p, ~mask_to_clear);
- dirty |= old_bits & mask_to_clear;
- } else {
- if (!dirty) {
- smp_mb();
- }
- }
-
- return dirty != 0;
-}
-
-#define ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
-
-/**
- * bitmap_find_next_zero_area - find a contiguous aligned zero area
- * @map: The address to base the search on
- * @size: The bitmap size in bits
- * @start: The bitnumber to start searching at
- * @nr: The number of zeroed bits we're looking for
- * @align_mask: Alignment mask for zero area
- *
- * The @align_mask should be one less than a power of 2; the effect is that
- * the bit offset of all zero areas this function finds is multiples of that
- * power of 2. A @align_mask of 0 means no alignment is required.
- */
-unsigned long bitmap_find_next_zero_area(unsigned long *map,
- unsigned long size,
- unsigned long start,
- unsigned long nr,
- unsigned long align_mask)
-{
- unsigned long index, end, i;
-again:
- index = find_next_zero_bit(map, size, start);
-
- /* Align allocation */
- index = ALIGN_MASK(index, align_mask);
-
- end = index + nr;
- if (end > size) {
- return end;
- }
- i = find_next_bit(map, end, index);
- if (i < end) {
- start = i + 1;
- goto again;
- }
- return index;
-}
-
-int slow_bitmap_intersects(const unsigned long *bitmap1,
- const unsigned long *bitmap2, long bits)
-{
- long k, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; ++k) {
- if (bitmap1[k] & bitmap2[k]) {
- return 1;
- }
- }
-
- if (bits % BITS_PER_LONG) {
- if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
- return 1;
- }
- }
- return 0;
-}
diff --git a/qemu/util/bitops.c b/qemu/util/bitops.c
deleted file mode 100644
index b0c35dd5f..000000000
--- a/qemu/util/bitops.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- * Copyright (C) 2008 IBM Corporation
- * Written by Rusty Russell <rusty@rustcorp.com.au>
- * (Inspired by David Howell's find_next_bit implementation)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/bitops.h"
-
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
-/*
- * Find the next set bit in a memory region.
- */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = addr + BITOP_WORD(offset);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size) {
- return size;
- }
- size -= result;
- offset %= BITS_PER_LONG;
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < BITS_PER_LONG) {
- goto found_first;
- }
- if (tmp) {
- goto found_middle;
- }
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size >= 4*BITS_PER_LONG) {
- unsigned long d1, d2, d3;
- tmp = *p;
- d1 = *(p+1);
- d2 = *(p+2);
- d3 = *(p+3);
- if (tmp) {
- goto found_middle;
- }
- if (d1 | d2 | d3) {
- break;
- }
- p += 4;
- result += 4*BITS_PER_LONG;
- size -= 4*BITS_PER_LONG;
- }
- while (size >= BITS_PER_LONG) {
- if ((tmp = *(p++))) {
- goto found_middle;
- }
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size) {
- return result;
- }
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) { /* Are any bits set? */
- return result + size; /* Nope. */
- }
-found_middle:
- return result + ctzl(tmp);
-}
-
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = addr + BITOP_WORD(offset);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size) {
- return size;
- }
- size -= result;
- offset %= BITS_PER_LONG;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (BITS_PER_LONG - offset);
- if (size < BITS_PER_LONG) {
- goto found_first;
- }
- if (~tmp) {
- goto found_middle;
- }
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1)) {
- if (~(tmp = *(p++))) {
- goto found_middle;
- }
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size) {
- return result;
- }
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) { /* Are any bits zero? */
- return result + size; /* Nope. */
- }
-found_middle:
- return result + ctzl(~tmp);
-}
-
-unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
-{
- unsigned long words;
- unsigned long tmp;
-
- /* Start at final word. */
- words = size / BITS_PER_LONG;
-
- /* Partial final word? */
- if (size & (BITS_PER_LONG-1)) {
- tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
- - (size & (BITS_PER_LONG-1)))));
- if (tmp) {
- goto found;
- }
- }
-
- while (words) {
- tmp = addr[--words];
- if (tmp) {
- found:
- return words * BITS_PER_LONG + BITS_PER_LONG - 1 - clzl(tmp);
- }
- }
-
- /* Not found */
- return size;
-}
diff --git a/qemu/util/buffer.c b/qemu/util/buffer.c
deleted file mode 100644
index a6118bf5b..000000000
--- a/qemu/util/buffer.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * QEMU generic buffers
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/buffer.h"
-#include "trace.h"
-
-#define BUFFER_MIN_INIT_SIZE 4096
-#define BUFFER_MIN_SHRINK_SIZE 65536
-
-/* define the factor alpha for the expentional smoothing
- * that is used in the average size calculation. a shift
- * of 7 results in an alpha of 1/2^7. */
-#define BUFFER_AVG_SIZE_SHIFT 7
-
-static size_t buffer_req_size(Buffer *buffer, size_t len)
-{
- return MAX(BUFFER_MIN_INIT_SIZE,
- pow2ceil(buffer->offset + len));
-}
-
-static void buffer_adj_size(Buffer *buffer, size_t len)
-{
- size_t old = buffer->capacity;
- buffer->capacity = buffer_req_size(buffer, len);
- buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
- trace_buffer_resize(buffer->name ?: "unnamed",
- old, buffer->capacity);
-
- /* make it even harder for the buffer to shrink, reset average size
- * to currenty capacity if it is larger than the average. */
- buffer->avg_size = MAX(buffer->avg_size,
- buffer->capacity << BUFFER_AVG_SIZE_SHIFT);
-}
-
-void buffer_init(Buffer *buffer, const char *name, ...)
-{
- va_list ap;
-
- va_start(ap, name);
- buffer->name = g_strdup_vprintf(name, ap);
- va_end(ap);
-}
-
-static uint64_t buffer_get_avg_size(Buffer *buffer)
-{
- return buffer->avg_size >> BUFFER_AVG_SIZE_SHIFT;
-}
-
-void buffer_shrink(Buffer *buffer)
-{
- size_t new;
-
- /* Calculate the average size of the buffer as
- * avg_size = avg_size * ( 1 - a ) + required_size * a
- * where a is 1 / 2 ^ BUFFER_AVG_SIZE_SHIFT. */
- buffer->avg_size *= (1 << BUFFER_AVG_SIZE_SHIFT) - 1;
- buffer->avg_size >>= BUFFER_AVG_SIZE_SHIFT;
- buffer->avg_size += buffer_req_size(buffer, 0);
-
- /* And then only shrink if the average size of the buffer is much
- * too big, to avoid bumping up & down the buffers all the time.
- * realloc() isn't exactly cheap ... */
- new = buffer_req_size(buffer, buffer_get_avg_size(buffer));
- if (new < buffer->capacity >> 3 &&
- new >= BUFFER_MIN_SHRINK_SIZE) {
- buffer_adj_size(buffer, buffer_get_avg_size(buffer));
- }
-
- buffer_adj_size(buffer, 0);
-}
-
-void buffer_reserve(Buffer *buffer, size_t len)
-{
- if ((buffer->capacity - buffer->offset) < len) {
- buffer_adj_size(buffer, len);
- }
-}
-
-gboolean buffer_empty(Buffer *buffer)
-{
- return buffer->offset == 0;
-}
-
-uint8_t *buffer_end(Buffer *buffer)
-{
- return buffer->buffer + buffer->offset;
-}
-
-void buffer_reset(Buffer *buffer)
-{
- buffer->offset = 0;
- buffer_shrink(buffer);
-}
-
-void buffer_free(Buffer *buffer)
-{
- trace_buffer_free(buffer->name ?: "unnamed", buffer->capacity);
- g_free(buffer->buffer);
- g_free(buffer->name);
- buffer->offset = 0;
- buffer->capacity = 0;
- buffer->buffer = NULL;
- buffer->name = NULL;
-}
-
-void buffer_append(Buffer *buffer, const void *data, size_t len)
-{
- memcpy(buffer->buffer + buffer->offset, data, len);
- buffer->offset += len;
-}
-
-void buffer_advance(Buffer *buffer, size_t len)
-{
- memmove(buffer->buffer, buffer->buffer + len,
- (buffer->offset - len));
- buffer->offset -= len;
- buffer_shrink(buffer);
-}
-
-void buffer_move_empty(Buffer *to, Buffer *from)
-{
- trace_buffer_move_empty(to->name ?: "unnamed",
- from->offset,
- from->name ?: "unnamed");
- assert(to->offset == 0);
-
- g_free(to->buffer);
- to->offset = from->offset;
- to->capacity = from->capacity;
- to->buffer = from->buffer;
-
- from->offset = 0;
- from->capacity = 0;
- from->buffer = NULL;
-}
-
-void buffer_move(Buffer *to, Buffer *from)
-{
- if (to->offset == 0) {
- buffer_move_empty(to, from);
- return;
- }
-
- trace_buffer_move(to->name ?: "unnamed",
- from->offset,
- from->name ?: "unnamed");
- buffer_reserve(to, from->offset);
- buffer_append(to, from->buffer, from->offset);
-
- g_free(from->buffer);
- from->offset = 0;
- from->capacity = 0;
- from->buffer = NULL;
-}
diff --git a/qemu/util/compatfd.c b/qemu/util/compatfd.c
deleted file mode 100644
index 9a43042ae..000000000
--- a/qemu/util/compatfd.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * signalfd/eventfd compatibility
- *
- * Copyright IBM, Corp. 2008
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/compatfd.h"
-#include "qemu/thread.h"
-
-#include <sys/syscall.h>
-
-struct sigfd_compat_info
-{
- sigset_t mask;
- int fd;
-};
-
-static void *sigwait_compat(void *opaque)
-{
- struct sigfd_compat_info *info = opaque;
-
- while (1) {
- int sig;
- int err;
-
- err = sigwait(&info->mask, &sig);
- if (err != 0) {
- if (errno == EINTR) {
- continue;
- } else {
- return NULL;
- }
- } else {
- struct qemu_signalfd_siginfo buffer;
- size_t offset = 0;
-
- memset(&buffer, 0, sizeof(buffer));
- buffer.ssi_signo = sig;
-
- while (offset < sizeof(buffer)) {
- ssize_t len;
-
- len = write(info->fd, (char *)&buffer + offset,
- sizeof(buffer) - offset);
- if (len == -1 && errno == EINTR)
- continue;
-
- if (len <= 0) {
- return NULL;
- }
-
- offset += len;
- }
- }
- }
-}
-
-static int qemu_signalfd_compat(const sigset_t *mask)
-{
- struct sigfd_compat_info *info;
- QemuThread thread;
- int fds[2];
-
- info = malloc(sizeof(*info));
- if (info == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- if (pipe(fds) == -1) {
- free(info);
- return -1;
- }
-
- qemu_set_cloexec(fds[0]);
- qemu_set_cloexec(fds[1]);
-
- memcpy(&info->mask, mask, sizeof(*mask));
- info->fd = fds[1];
-
- qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info,
- QEMU_THREAD_DETACHED);
-
- return fds[0];
-}
-
-int qemu_signalfd(const sigset_t *mask)
-{
-#if defined(CONFIG_SIGNALFD)
- int ret;
-
- ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
- if (ret != -1) {
- qemu_set_cloexec(ret);
- return ret;
- }
-#endif
-
- return qemu_signalfd_compat(mask);
-}
diff --git a/qemu/util/coroutine-gthread.c b/qemu/util/coroutine-gthread.c
deleted file mode 100644
index fb697eb0b..000000000
--- a/qemu/util/coroutine-gthread.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * GThread coroutine initialization code
- *
- * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
- * Copyright (C) 2011 Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "qemu-common.h"
-#include "qemu/coroutine_int.h"
-
-typedef struct {
- Coroutine base;
- GThread *thread;
- bool runnable;
- bool free_on_thread_exit;
- CoroutineAction action;
-} CoroutineGThread;
-
-static CompatGMutex coroutine_lock;
-static CompatGCond coroutine_cond;
-
-/* GLib 2.31 and beyond deprecated various parts of the thread API,
- * but the new interfaces are not available in older GLib versions
- * so we have to cope with both.
- */
-#if GLIB_CHECK_VERSION(2, 31, 0)
-/* Awkwardly, the GPrivate API doesn't provide a way to update the
- * GDestroyNotify handler for the coroutine key dynamically. So instead
- * we track whether or not the CoroutineGThread should be freed on
- * thread exit / coroutine key update using the free_on_thread_exit
- * field.
- */
-static void coroutine_destroy_notify(gpointer data)
-{
- CoroutineGThread *co = data;
- if (co && co->free_on_thread_exit) {
- g_free(co);
- }
-}
-
-static GPrivate coroutine_key = G_PRIVATE_INIT(coroutine_destroy_notify);
-
-static inline CoroutineGThread *get_coroutine_key(void)
-{
- return g_private_get(&coroutine_key);
-}
-
-static inline void set_coroutine_key(CoroutineGThread *co,
- bool free_on_thread_exit)
-{
- /* Unlike g_static_private_set() this does not call the GDestroyNotify
- * if the previous value of the key was NULL. Fortunately we only need
- * the GDestroyNotify in the non-NULL key case.
- */
- co->free_on_thread_exit = free_on_thread_exit;
- g_private_replace(&coroutine_key, co);
-}
-
-static inline GThread *create_thread(GThreadFunc func, gpointer data)
-{
- return g_thread_new("coroutine", func, data);
-}
-
-#else
-
-/* Handle older GLib versions */
-
-static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
-
-static inline CoroutineGThread *get_coroutine_key(void)
-{
- return g_static_private_get(&coroutine_key);
-}
-
-static inline void set_coroutine_key(CoroutineGThread *co,
- bool free_on_thread_exit)
-{
- g_static_private_set(&coroutine_key, co,
- free_on_thread_exit ? (GDestroyNotify)g_free : NULL);
-}
-
-static inline GThread *create_thread(GThreadFunc func, gpointer data)
-{
- return g_thread_create_full(func, data, 0, TRUE, TRUE,
- G_THREAD_PRIORITY_NORMAL, NULL);
-}
-
-#endif
-
-
-static void __attribute__((constructor)) coroutine_init(void)
-{
-#if !GLIB_CHECK_VERSION(2, 31, 0)
- if (!g_thread_supported()) {
- g_thread_init(NULL);
- }
-#endif
-}
-
-static void coroutine_wait_runnable_locked(CoroutineGThread *co)
-{
- while (!co->runnable) {
- g_cond_wait(&coroutine_cond, &coroutine_lock);
- }
-}
-
-static void coroutine_wait_runnable(CoroutineGThread *co)
-{
- g_mutex_lock(&coroutine_lock);
- coroutine_wait_runnable_locked(co);
- g_mutex_unlock(&coroutine_lock);
-}
-
-static gpointer coroutine_thread(gpointer opaque)
-{
- CoroutineGThread *co = opaque;
-
- set_coroutine_key(co, false);
- coroutine_wait_runnable(co);
- co->base.entry(co->base.entry_arg);
- qemu_coroutine_switch(&co->base, co->base.caller, COROUTINE_TERMINATE);
- return NULL;
-}
-
-Coroutine *qemu_coroutine_new(void)
-{
- CoroutineGThread *co;
-
- co = g_malloc0(sizeof(*co));
- co->thread = create_thread(coroutine_thread, co);
- if (!co->thread) {
- g_free(co);
- return NULL;
- }
- return &co->base;
-}
-
-void qemu_coroutine_delete(Coroutine *co_)
-{
- CoroutineGThread *co = DO_UPCAST(CoroutineGThread, base, co_);
-
- g_thread_join(co->thread);
- g_free(co);
-}
-
-CoroutineAction qemu_coroutine_switch(Coroutine *from_,
- Coroutine *to_,
- CoroutineAction action)
-{
- CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
- CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
-
- g_mutex_lock(&coroutine_lock);
- from->runnable = false;
- from->action = action;
- to->runnable = true;
- to->action = action;
- g_cond_broadcast(&coroutine_cond);
-
- if (action != COROUTINE_TERMINATE) {
- coroutine_wait_runnable_locked(from);
- }
- g_mutex_unlock(&coroutine_lock);
- return from->action;
-}
-
-Coroutine *qemu_coroutine_self(void)
-{
- CoroutineGThread *co = get_coroutine_key();
- if (!co) {
- co = g_malloc0(sizeof(*co));
- co->runnable = true;
- set_coroutine_key(co, true);
- }
-
- return &co->base;
-}
-
-bool qemu_in_coroutine(void)
-{
- CoroutineGThread *co = get_coroutine_key();
-
- return co && co->base.caller;
-}
diff --git a/qemu/util/coroutine-sigaltstack.c b/qemu/util/coroutine-sigaltstack.c
deleted file mode 100644
index a7c336655..000000000
--- a/qemu/util/coroutine-sigaltstack.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * sigaltstack coroutine initialization code
- *
- * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
- * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com>
- * Copyright (C) 2012 Alex Barcelo <abarcelo@ac.upc.edu>
-** This file is partly based on pth_mctx.c, from the GNU Portable Threads
-** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
-#ifdef _FORTIFY_SOURCE
-#undef _FORTIFY_SOURCE
-#endif
-#include "qemu/osdep.h"
-#include <pthread.h>
-#include "qemu-common.h"
-#include "qemu/coroutine_int.h"
-
-typedef struct {
- Coroutine base;
- void *stack;
- sigjmp_buf env;
-} CoroutineUContext;
-
-/**
- * Per-thread coroutine bookkeeping
- */
-typedef struct {
- /** Currently executing coroutine */
- Coroutine *current;
-
- /** The default coroutine */
- CoroutineUContext leader;
-
- /** Information for the signal handler (trampoline) */
- sigjmp_buf tr_reenter;
- volatile sig_atomic_t tr_called;
- void *tr_handler;
-} CoroutineThreadState;
-
-static pthread_key_t thread_state_key;
-
-static CoroutineThreadState *coroutine_get_thread_state(void)
-{
- CoroutineThreadState *s = pthread_getspecific(thread_state_key);
-
- if (!s) {
- s = g_malloc0(sizeof(*s));
- s->current = &s->leader.base;
- pthread_setspecific(thread_state_key, s);
- }
- return s;
-}
-
-static void qemu_coroutine_thread_cleanup(void *opaque)
-{
- CoroutineThreadState *s = opaque;
-
- g_free(s);
-}
-
-static void __attribute__((constructor)) coroutine_init(void)
-{
- int ret;
-
- ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup);
- if (ret != 0) {
- fprintf(stderr, "unable to create leader key: %s\n", strerror(errno));
- abort();
- }
-}
-
-/* "boot" function
- * This is what starts the coroutine, is called from the trampoline
- * (from the signal handler when it is not signal handling, read ahead
- * for more information).
- */
-static void coroutine_bootstrap(CoroutineUContext *self, Coroutine *co)
-{
- /* Initialize longjmp environment and switch back the caller */
- if (!sigsetjmp(self->env, 0)) {
- siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
- }
-
- while (true) {
- co->entry(co->entry_arg);
- qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
- }
-}
-
-/*
- * This is used as the signal handler. This is called with the brand new stack
- * (thanks to sigaltstack). We have to return, given that this is a signal
- * handler and the sigmask and some other things are changed.
- */
-static void coroutine_trampoline(int signal)
-{
- CoroutineUContext *self;
- Coroutine *co;
- CoroutineThreadState *coTS;
-
- /* Get the thread specific information */
- coTS = coroutine_get_thread_state();
- self = coTS->tr_handler;
- coTS->tr_called = 1;
- co = &self->base;
-
- /*
- * Here we have to do a bit of a ping pong between the caller, given that
- * this is a signal handler and we have to do a return "soon". Then the
- * caller can reestablish everything and do a siglongjmp here again.
- */
- if (!sigsetjmp(coTS->tr_reenter, 0)) {
- return;
- }
-
- /*
- * Ok, the caller has siglongjmp'ed back to us, so now prepare
- * us for the real machine state switching. We have to jump
- * into another function here to get a new stack context for
- * the auto variables (which have to be auto-variables
- * because the start of the thread happens later). Else with
- * PIC (i.e. Position Independent Code which is used when PTH
- * is built as a shared library) most platforms would
- * horrible core dump as experience showed.
- */
- coroutine_bootstrap(self, co);
-}
-
-Coroutine *qemu_coroutine_new(void)
-{
- const size_t stack_size = 1 << 20;
- CoroutineUContext *co;
- CoroutineThreadState *coTS;
- struct sigaction sa;
- struct sigaction osa;
- stack_t ss;
- stack_t oss;
- sigset_t sigs;
- sigset_t osigs;
- sigjmp_buf old_env;
-
- /* The way to manipulate stack is with the sigaltstack function. We
- * prepare a stack, with it delivering a signal to ourselves and then
- * put sigsetjmp/siglongjmp where needed.
- * This has been done keeping coroutine-ucontext as a model and with the
- * pth ideas (GNU Portable Threads). See coroutine-ucontext for the basics
- * of the coroutines and see pth_mctx.c (from the pth project) for the
- * sigaltstack way of manipulating stacks.
- */
-
- co = g_malloc0(sizeof(*co));
- co->stack = g_malloc(stack_size);
- co->base.entry_arg = &old_env; /* stash away our jmp_buf */
-
- coTS = coroutine_get_thread_state();
- coTS->tr_handler = co;
-
- /*
- * Preserve the SIGUSR2 signal state, block SIGUSR2,
- * and establish our signal handler. The signal will
- * later transfer control onto the signal stack.
- */
- sigemptyset(&sigs);
- sigaddset(&sigs, SIGUSR2);
- pthread_sigmask(SIG_BLOCK, &sigs, &osigs);
- sa.sa_handler = coroutine_trampoline;
- sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK;
- if (sigaction(SIGUSR2, &sa, &osa) != 0) {
- abort();
- }
-
- /*
- * Set the new stack.
- */
- ss.ss_sp = co->stack;
- ss.ss_size = stack_size;
- ss.ss_flags = 0;
- if (sigaltstack(&ss, &oss) < 0) {
- abort();
- }
-
- /*
- * Now transfer control onto the signal stack and set it up.
- * It will return immediately via "return" after the sigsetjmp()
- * was performed. Be careful here with race conditions. The
- * signal can be delivered the first time sigsuspend() is
- * called.
- */
- coTS->tr_called = 0;
- pthread_kill(pthread_self(), SIGUSR2);
- sigfillset(&sigs);
- sigdelset(&sigs, SIGUSR2);
- while (!coTS->tr_called) {
- sigsuspend(&sigs);
- }
-
- /*
- * Inform the system that we are back off the signal stack by
- * removing the alternative signal stack. Be careful here: It
- * first has to be disabled, before it can be removed.
- */
- sigaltstack(NULL, &ss);
- ss.ss_flags = SS_DISABLE;
- if (sigaltstack(&ss, NULL) < 0) {
- abort();
- }
- sigaltstack(NULL, &ss);
- if (!(oss.ss_flags & SS_DISABLE)) {
- sigaltstack(&oss, NULL);
- }
-
- /*
- * Restore the old SIGUSR2 signal handler and mask
- */
- sigaction(SIGUSR2, &osa, NULL);
- pthread_sigmask(SIG_SETMASK, &osigs, NULL);
-
- /*
- * Now enter the trampoline again, but this time not as a signal
- * handler. Instead we jump into it directly. The functionally
- * redundant ping-pong pointer arithmetic is necessary to avoid
- * type-conversion warnings related to the `volatile' qualifier and
- * the fact that `jmp_buf' usually is an array type.
- */
- if (!sigsetjmp(old_env, 0)) {
- siglongjmp(coTS->tr_reenter, 1);
- }
-
- /*
- * Ok, we returned again, so now we're finished
- */
-
- return &co->base;
-}
-
-void qemu_coroutine_delete(Coroutine *co_)
-{
- CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
-
- g_free(co->stack);
- g_free(co);
-}
-
-CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
- CoroutineAction action)
-{
- CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
- CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
- CoroutineThreadState *s = coroutine_get_thread_state();
- int ret;
-
- s->current = to_;
-
- ret = sigsetjmp(from->env, 0);
- if (ret == 0) {
- siglongjmp(to->env, action);
- }
- return ret;
-}
-
-Coroutine *qemu_coroutine_self(void)
-{
- CoroutineThreadState *s = coroutine_get_thread_state();
-
- return s->current;
-}
-
-bool qemu_in_coroutine(void)
-{
- CoroutineThreadState *s = pthread_getspecific(thread_state_key);
-
- return s && s->current->caller;
-}
-
diff --git a/qemu/util/coroutine-ucontext.c b/qemu/util/coroutine-ucontext.c
deleted file mode 100644
index 2bb7e10d4..000000000
--- a/qemu/util/coroutine-ucontext.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * ucontext coroutine initialization code
- *
- * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
- * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
-#ifdef _FORTIFY_SOURCE
-#undef _FORTIFY_SOURCE
-#endif
-#include "qemu/osdep.h"
-#include <ucontext.h>
-#include "qemu-common.h"
-#include "qemu/coroutine_int.h"
-
-#ifdef CONFIG_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
-
-typedef struct {
- Coroutine base;
- void *stack;
- sigjmp_buf env;
-
-#ifdef CONFIG_VALGRIND_H
- unsigned int valgrind_stack_id;
-#endif
-
-} CoroutineUContext;
-
-/**
- * Per-thread coroutine bookkeeping
- */
-static __thread CoroutineUContext leader;
-static __thread Coroutine *current;
-
-/*
- * va_args to makecontext() must be type 'int', so passing
- * the pointer we need may require several int args. This
- * union is a quick hack to let us do that
- */
-union cc_arg {
- void *p;
- int i[2];
-};
-
-static void coroutine_trampoline(int i0, int i1)
-{
- union cc_arg arg;
- CoroutineUContext *self;
- Coroutine *co;
-
- arg.i[0] = i0;
- arg.i[1] = i1;
- self = arg.p;
- co = &self->base;
-
- /* Initialize longjmp environment and switch back the caller */
- if (!sigsetjmp(self->env, 0)) {
- siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
- }
-
- while (true) {
- co->entry(co->entry_arg);
- qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
- }
-}
-
-Coroutine *qemu_coroutine_new(void)
-{
- const size_t stack_size = 1 << 20;
- CoroutineUContext *co;
- ucontext_t old_uc, uc;
- sigjmp_buf old_env;
- union cc_arg arg = {0};
-
- /* The ucontext functions preserve signal masks which incurs a
- * system call overhead. sigsetjmp(buf, 0)/siglongjmp() does not
- * preserve signal masks but only works on the current stack.
- * Since we need a way to create and switch to a new stack, use
- * the ucontext functions for that but sigsetjmp()/siglongjmp() for
- * everything else.
- */
-
- if (getcontext(&uc) == -1) {
- abort();
- }
-
- co = g_malloc0(sizeof(*co));
- co->stack = g_malloc(stack_size);
- co->base.entry_arg = &old_env; /* stash away our jmp_buf */
-
- uc.uc_link = &old_uc;
- uc.uc_stack.ss_sp = co->stack;
- uc.uc_stack.ss_size = stack_size;
- uc.uc_stack.ss_flags = 0;
-
-#ifdef CONFIG_VALGRIND_H
- co->valgrind_stack_id =
- VALGRIND_STACK_REGISTER(co->stack, co->stack + stack_size);
-#endif
-
- arg.p = co;
-
- makecontext(&uc, (void (*)(void))coroutine_trampoline,
- 2, arg.i[0], arg.i[1]);
-
- /* swapcontext() in, siglongjmp() back out */
- if (!sigsetjmp(old_env, 0)) {
- swapcontext(&old_uc, &uc);
- }
- return &co->base;
-}
-
-#ifdef CONFIG_VALGRIND_H
-#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
-/* Work around an unused variable in the valgrind.h macro... */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
-#endif
-static inline void valgrind_stack_deregister(CoroutineUContext *co)
-{
- VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
-}
-#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
-#pragma GCC diagnostic pop
-#endif
-#endif
-
-void qemu_coroutine_delete(Coroutine *co_)
-{
- CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
-
-#ifdef CONFIG_VALGRIND_H
- valgrind_stack_deregister(co);
-#endif
-
- g_free(co->stack);
- g_free(co);
-}
-
-/* This function is marked noinline to prevent GCC from inlining it
- * into coroutine_trampoline(). If we allow it to do that then it
- * hoists the code to get the address of the TLS variable "current"
- * out of the while() loop. This is an invalid transformation because
- * the sigsetjmp() call may be called when running thread A but
- * return in thread B, and so we might be in a different thread
- * context each time round the loop.
- */
-CoroutineAction __attribute__((noinline))
-qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
- CoroutineAction action)
-{
- CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
- CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
- int ret;
-
- current = to_;
-
- ret = sigsetjmp(from->env, 0);
- if (ret == 0) {
- siglongjmp(to->env, action);
- }
- return ret;
-}
-
-Coroutine *qemu_coroutine_self(void)
-{
- if (!current) {
- current = &leader.base;
- }
- return current;
-}
-
-bool qemu_in_coroutine(void)
-{
- return current && current->caller;
-}
diff --git a/qemu/util/coroutine-win32.c b/qemu/util/coroutine-win32.c
deleted file mode 100644
index 02e28e825..000000000
--- a/qemu/util/coroutine-win32.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Win32 coroutine initialization code
- *
- * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/coroutine_int.h"
-
-typedef struct
-{
- Coroutine base;
-
- LPVOID fiber;
- CoroutineAction action;
-} CoroutineWin32;
-
-static __thread CoroutineWin32 leader;
-static __thread Coroutine *current;
-
-/* This function is marked noinline to prevent GCC from inlining it
- * into coroutine_trampoline(). If we allow it to do that then it
- * hoists the code to get the address of the TLS variable "current"
- * out of the while() loop. This is an invalid transformation because
- * the SwitchToFiber() call may be called when running thread A but
- * return in thread B, and so we might be in a different thread
- * context each time round the loop.
- */
-CoroutineAction __attribute__((noinline))
-qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
- CoroutineAction action)
-{
- CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
- CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
-
- current = to_;
-
- to->action = action;
- SwitchToFiber(to->fiber);
- return from->action;
-}
-
-static void CALLBACK coroutine_trampoline(void *co_)
-{
- Coroutine *co = co_;
-
- while (true) {
- co->entry(co->entry_arg);
- qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
- }
-}
-
-Coroutine *qemu_coroutine_new(void)
-{
- const size_t stack_size = 1 << 20;
- CoroutineWin32 *co;
-
- co = g_malloc0(sizeof(*co));
- co->fiber = CreateFiber(stack_size, coroutine_trampoline, &co->base);
- return &co->base;
-}
-
-void qemu_coroutine_delete(Coroutine *co_)
-{
- CoroutineWin32 *co = DO_UPCAST(CoroutineWin32, base, co_);
-
- DeleteFiber(co->fiber);
- g_free(co);
-}
-
-Coroutine *qemu_coroutine_self(void)
-{
- if (!current) {
- current = &leader.base;
- leader.fiber = ConvertThreadToFiber(NULL);
- }
- return current;
-}
-
-bool qemu_in_coroutine(void)
-{
- return current && current->caller;
-}
diff --git a/qemu/util/crc32c.c b/qemu/util/crc32c.c
deleted file mode 100644
index 7e99555c1..000000000
--- a/qemu/util/crc32c.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Castagnoli CRC32C Checksum Algorithm
- *
- * Polynomial: 0x11EDC6F41
- *
- * Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
- * "Optimization of Cyclic Redundancy-Check Codes with 24
- * and 32 Parity Bits",IEEE Transactions on Communication,
- * Volume 41, Number 6, June 1993
- *
- * Copyright (c) 2013 Red Hat, Inc.,
- *
- * Authors:
- * Jeff Cody <jcody@redhat.com>
- *
- * Based on the Linux kernel cryptographic crc32c module,
- *
- * Copyright (c) 2004 Cisco Systems, Inc.
- * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/crc32c.h"
-
-/*
- * This is the CRC-32C table
- * Generated with:
- * width = 32 bits
- * poly = 0x1EDC6F41
- * reflect input bytes = true
- * reflect output bytes = true
- */
-
-static const uint32_t crc32c_table[256] = {
- 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
- 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
- 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
- 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
- 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
- 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
- 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
- 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
- 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
- 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
- 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
- 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
- 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
- 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
- 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
- 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
- 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
- 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
- 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
- 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
- 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
- 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
- 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
- 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
- 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
- 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
- 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
- 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
- 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
- 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
- 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
- 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
- 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
- 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
- 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
- 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
- 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
- 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
- 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
- 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
- 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
- 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
- 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
- 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
- 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
- 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
- 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
- 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
- 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
- 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
- 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
- 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
- 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
- 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
- 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
- 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
- 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
- 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
- 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
- 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
- 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
- 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
- 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
- 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
-};
-
-
-uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length)
-{
- while (length--) {
- crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
- }
- return crc^0xffffffff;
-}
-
diff --git a/qemu/util/cutils.c b/qemu/util/cutils.c
deleted file mode 100644
index 43d1afbbe..000000000
--- a/qemu/util/cutils.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Simple C functions to supplement the C library
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/host-utils.h"
-#include <math.h>
-
-#include "qemu/sockets.h"
-#include "qemu/iov.h"
-#include "net/net.h"
-#include "qemu/cutils.h"
-
-void strpadcpy(char *buf, int buf_size, const char *str, char pad)
-{
- int len = qemu_strnlen(str, buf_size);
- memcpy(buf, str, len);
- memset(buf + len, pad, buf_size - len);
-}
-
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
- int c;
- char *q = buf;
-
- if (buf_size <= 0)
- return;
-
- for(;;) {
- c = *str++;
- if (c == 0 || q >= buf + buf_size - 1)
- break;
- *q++ = c;
- }
- *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
- int len;
- len = strlen(buf);
- if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
- return buf;
-}
-
-int strstart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
-int stristart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (qemu_toupper(*p) != qemu_toupper(*q))
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
-/* XXX: use host strnlen if available ? */
-int qemu_strnlen(const char *s, int max_len)
-{
- int i;
-
- for(i = 0; i < max_len; i++) {
- if (s[i] == '\0') {
- break;
- }
- }
- return i;
-}
-
-char *qemu_strsep(char **input, const char *delim)
-{
- char *result = *input;
- if (result != NULL) {
- char *p;
-
- for (p = result; *p != '\0'; p++) {
- if (strchr(delim, *p)) {
- break;
- }
- }
- if (*p == '\0') {
- *input = NULL;
- } else {
- *p = '\0';
- *input = p + 1;
- }
- }
- return result;
-}
-
-time_t mktimegm(struct tm *tm)
-{
- time_t t;
- int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
- if (m < 3) {
- m += 12;
- y--;
- }
- t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
- y / 400 - 719469);
- t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
- return t;
-}
-
-/*
- * Make sure data goes on disk, but if possible do not bother to
- * write out the inode just for timestamp updates.
- *
- * Unfortunately even in 2009 many operating systems do not support
- * fdatasync and have to fall back to fsync.
- */
-int qemu_fdatasync(int fd)
-{
-#ifdef CONFIG_FDATASYNC
- return fdatasync(fd);
-#else
- return fsync(fd);
-#endif
-}
-
-/* vector definitions */
-#ifdef __ALTIVEC__
-#include <altivec.h>
-/* The altivec.h header says we're allowed to undef these for
- * C++ compatibility. Here we don't care about C++, but we
- * undef them anyway to avoid namespace pollution.
- */
-#undef vector
-#undef pixel
-#undef bool
-#define VECTYPE __vector unsigned char
-#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
-#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
-#define VEC_OR(v1, v2) ((v1) | (v2))
-/* altivec.h may redefine the bool macro as vector type.
- * Reset it to POSIX semantics. */
-#define bool _Bool
-#elif defined __SSE2__
-#include <emmintrin.h>
-#define VECTYPE __m128i
-#define SPLAT(p) _mm_set1_epi8(*(p))
-#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
-#define VEC_OR(v1, v2) (_mm_or_si128(v1, v2))
-#else
-#define VECTYPE unsigned long
-#define SPLAT(p) (*(p) * (~0UL / 255))
-#define ALL_EQ(v1, v2) ((v1) == (v2))
-#define VEC_OR(v1, v2) ((v1) | (v2))
-#endif
-
-#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8
-
-static bool
-can_use_buffer_find_nonzero_offset_inner(const void *buf, size_t len)
-{
- return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR
- * sizeof(VECTYPE)) == 0
- && ((uintptr_t) buf) % sizeof(VECTYPE) == 0);
-}
-
-/*
- * Searches for an area with non-zero content in a buffer
- *
- * Attention! The len must be a multiple of
- * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
- * and addr must be a multiple of sizeof(VECTYPE) due to
- * restriction of optimizations in this function.
- *
- * can_use_buffer_find_nonzero_offset_inner() can be used to
- * check these requirements.
- *
- * The return value is the offset of the non-zero area rounded
- * down to a multiple of sizeof(VECTYPE) for the first
- * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR chunks and down to
- * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
- * afterwards.
- *
- * If the buffer is all zero the return value is equal to len.
- */
-
-static size_t buffer_find_nonzero_offset_inner(const void *buf, size_t len)
-{
- const VECTYPE *p = buf;
- const VECTYPE zero = (VECTYPE){0};
- size_t i;
-
- assert(can_use_buffer_find_nonzero_offset_inner(buf, len));
-
- if (!len) {
- return 0;
- }
-
- for (i = 0; i < BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; i++) {
- if (!ALL_EQ(p[i], zero)) {
- return i * sizeof(VECTYPE);
- }
- }
-
- for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
- i < len / sizeof(VECTYPE);
- i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
- VECTYPE tmp0 = VEC_OR(p[i + 0], p[i + 1]);
- VECTYPE tmp1 = VEC_OR(p[i + 2], p[i + 3]);
- VECTYPE tmp2 = VEC_OR(p[i + 4], p[i + 5]);
- VECTYPE tmp3 = VEC_OR(p[i + 6], p[i + 7]);
- VECTYPE tmp01 = VEC_OR(tmp0, tmp1);
- VECTYPE tmp23 = VEC_OR(tmp2, tmp3);
- if (!ALL_EQ(VEC_OR(tmp01, tmp23), zero)) {
- break;
- }
- }
-
- return i * sizeof(VECTYPE);
-}
-
-/*
- * GCC before version 4.9 has a bug which will cause the target
- * attribute work incorrectly and failed to compile in some case,
- * restrict the gcc version to 4.9+ to prevent the failure.
- */
-
-#if defined CONFIG_AVX2_OPT && QEMU_GNUC_PREREQ(4, 9)
-#pragma GCC push_options
-#pragma GCC target("avx2")
-#include <cpuid.h>
-#include <immintrin.h>
-
-#define AVX2_VECTYPE __m256i
-#define AVX2_SPLAT(p) _mm256_set1_epi8(*(p))
-#define AVX2_ALL_EQ(v1, v2) \
- (_mm256_movemask_epi8(_mm256_cmpeq_epi8(v1, v2)) == 0xFFFFFFFF)
-#define AVX2_VEC_OR(v1, v2) (_mm256_or_si256(v1, v2))
-
-static bool
-can_use_buffer_find_nonzero_offset_avx2(const void *buf, size_t len)
-{
- return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR
- * sizeof(AVX2_VECTYPE)) == 0
- && ((uintptr_t) buf) % sizeof(AVX2_VECTYPE) == 0);
-}
-
-static size_t buffer_find_nonzero_offset_avx2(const void *buf, size_t len)
-{
- const AVX2_VECTYPE *p = buf;
- const AVX2_VECTYPE zero = (AVX2_VECTYPE){0};
- size_t i;
-
- assert(can_use_buffer_find_nonzero_offset_avx2(buf, len));
-
- if (!len) {
- return 0;
- }
-
- for (i = 0; i < BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; i++) {
- if (!AVX2_ALL_EQ(p[i], zero)) {
- return i * sizeof(AVX2_VECTYPE);
- }
- }
-
- for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
- i < len / sizeof(AVX2_VECTYPE);
- i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
- AVX2_VECTYPE tmp0 = AVX2_VEC_OR(p[i + 0], p[i + 1]);
- AVX2_VECTYPE tmp1 = AVX2_VEC_OR(p[i + 2], p[i + 3]);
- AVX2_VECTYPE tmp2 = AVX2_VEC_OR(p[i + 4], p[i + 5]);
- AVX2_VECTYPE tmp3 = AVX2_VEC_OR(p[i + 6], p[i + 7]);
- AVX2_VECTYPE tmp01 = AVX2_VEC_OR(tmp0, tmp1);
- AVX2_VECTYPE tmp23 = AVX2_VEC_OR(tmp2, tmp3);
- if (!AVX2_ALL_EQ(AVX2_VEC_OR(tmp01, tmp23), zero)) {
- break;
- }
- }
-
- return i * sizeof(AVX2_VECTYPE);
-}
-
-static bool avx2_support(void)
-{
- int a, b, c, d;
-
- if (__get_cpuid_max(0, NULL) < 7) {
- return false;
- }
-
- __cpuid_count(7, 0, a, b, c, d);
-
- return b & bit_AVX2;
-}
-
-bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) \
- __attribute__ ((ifunc("can_use_buffer_find_nonzero_offset_ifunc")));
-size_t buffer_find_nonzero_offset(const void *buf, size_t len) \
- __attribute__ ((ifunc("buffer_find_nonzero_offset_ifunc")));
-
-static void *buffer_find_nonzero_offset_ifunc(void)
-{
- typeof(buffer_find_nonzero_offset) *func = (avx2_support()) ?
- buffer_find_nonzero_offset_avx2 : buffer_find_nonzero_offset_inner;
-
- return func;
-}
-
-static void *can_use_buffer_find_nonzero_offset_ifunc(void)
-{
- typeof(can_use_buffer_find_nonzero_offset) *func = (avx2_support()) ?
- can_use_buffer_find_nonzero_offset_avx2 :
- can_use_buffer_find_nonzero_offset_inner;
-
- return func;
-}
-#pragma GCC pop_options
-#else
-bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len)
-{
- return can_use_buffer_find_nonzero_offset_inner(buf, len);
-}
-
-size_t buffer_find_nonzero_offset(const void *buf, size_t len)
-{
- return buffer_find_nonzero_offset_inner(buf, len);
-}
-#endif
-
-/*
- * Checks if a buffer is all zeroes
- *
- * Attention! The len must be a multiple of 4 * sizeof(long) due to
- * restriction of optimizations in this function.
- */
-bool buffer_is_zero(const void *buf, size_t len)
-{
- /*
- * Use long as the biggest available internal data type that fits into the
- * CPU register and unroll the loop to smooth out the effect of memory
- * latency.
- */
-
- size_t i;
- long d0, d1, d2, d3;
- const long * const data = buf;
-
- /* use vector optimized zero check if possible */
- if (can_use_buffer_find_nonzero_offset(buf, len)) {
- return buffer_find_nonzero_offset(buf, len) == len;
- }
-
- assert(len % (4 * sizeof(long)) == 0);
- len /= sizeof(long);
-
- for (i = 0; i < len; i += 4) {
- d0 = data[i + 0];
- d1 = data[i + 1];
- d2 = data[i + 2];
- d3 = data[i + 3];
-
- if (d0 || d1 || d2 || d3) {
- return false;
- }
- }
-
- return true;
-}
-
-#ifndef _WIN32
-/* Sets a specific flag */
-int fcntl_setfl(int fd, int flag)
-{
- int flags;
-
- flags = fcntl(fd, F_GETFL);
- if (flags == -1)
- return -errno;
-
- if (fcntl(fd, F_SETFL, flags | flag) == -1)
- return -errno;
-
- return 0;
-}
-#endif
-
-static int64_t suffix_mul(char suffix, int64_t unit)
-{
- switch (qemu_toupper(suffix)) {
- case QEMU_STRTOSZ_DEFSUFFIX_B:
- return 1;
- case QEMU_STRTOSZ_DEFSUFFIX_KB:
- return unit;
- case QEMU_STRTOSZ_DEFSUFFIX_MB:
- return unit * unit;
- case QEMU_STRTOSZ_DEFSUFFIX_GB:
- return unit * unit * unit;
- case QEMU_STRTOSZ_DEFSUFFIX_TB:
- return unit * unit * unit * unit;
- case QEMU_STRTOSZ_DEFSUFFIX_PB:
- return unit * unit * unit * unit * unit;
- case QEMU_STRTOSZ_DEFSUFFIX_EB:
- return unit * unit * unit * unit * unit * unit;
- }
- return -1;
-}
-
-/*
- * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
- * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
- * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
- * other error.
- */
-int64_t qemu_strtosz_suffix_unit(const char *nptr, char **end,
- const char default_suffix, int64_t unit)
-{
- int64_t retval = -EINVAL;
- char *endptr;
- unsigned char c;
- int mul_required = 0;
- double val, mul, integral, fraction;
-
- errno = 0;
- val = strtod(nptr, &endptr);
- if (isnan(val) || endptr == nptr || errno != 0) {
- goto fail;
- }
- fraction = modf(val, &integral);
- if (fraction != 0) {
- mul_required = 1;
- }
- c = *endptr;
- mul = suffix_mul(c, unit);
- if (mul >= 0) {
- endptr++;
- } else {
- mul = suffix_mul(default_suffix, unit);
- assert(mul >= 0);
- }
- if (mul == 1 && mul_required) {
- goto fail;
- }
- if ((val * mul >= INT64_MAX) || val < 0) {
- retval = -ERANGE;
- goto fail;
- }
- retval = val * mul;
-
-fail:
- if (end) {
- *end = endptr;
- }
-
- return retval;
-}
-
-int64_t qemu_strtosz_suffix(const char *nptr, char **end,
- const char default_suffix)
-{
- return qemu_strtosz_suffix_unit(nptr, end, default_suffix, 1024);
-}
-
-int64_t qemu_strtosz(const char *nptr, char **end)
-{
- return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
-}
-
-/**
- * Helper function for qemu_strto*l() functions.
- */
-static int check_strtox_error(const char *p, char *endptr, const char **next,
- int err)
-{
- /* If no conversion was performed, prefer BSD behavior over glibc
- * behavior.
- */
- if (err == 0 && endptr == p) {
- err = EINVAL;
- }
- if (!next && *endptr) {
- return -EINVAL;
- }
- if (next) {
- *next = endptr;
- }
- return -err;
-}
-
-/**
- * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
- *
- * Convert ASCII string @nptr to a long integer value
- * from the given @base. Parameters @nptr, @endptr, @base
- * follows same semantics as strtol() C function.
- *
- * Unlike from strtol() function, if @endptr is not NULL, this
- * function will return -EINVAL whenever it cannot fully convert
- * the string in @nptr with given @base to a long. This function returns
- * the result of the conversion only through the @result parameter.
- *
- * If NULL is passed in @endptr, then the whole string in @ntpr
- * is a number otherwise it returns -EINVAL.
- *
- * RETURN VALUE
- * Unlike from strtol() function, this wrapper returns either
- * -EINVAL or the errno set by strtol() function (e.g -ERANGE).
- * If the conversion overflows, -ERANGE is returned, and @result
- * is set to the max value of the desired type
- * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case
- * of underflow, -ERANGE is returned, and @result is set to the min
- * value of the desired type. For strtol(), strtoll(), @result is set to
- * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it
- * is set to 0.
- */
-int qemu_strtol(const char *nptr, const char **endptr, int base,
- long *result)
-{
- char *p;
- int err = 0;
- if (!nptr) {
- if (endptr) {
- *endptr = nptr;
- }
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtol(nptr, &p, base);
- err = check_strtox_error(nptr, p, endptr, errno);
- }
- return err;
-}
-
-/**
- * Converts ASCII string to an unsigned long integer.
- *
- * If string contains a negative number, value will be converted to
- * the unsigned representation of the signed value, unless the original
- * (nonnegated) value would overflow, in this case, it will set @result
- * to ULONG_MAX, and return ERANGE.
- *
- * The same behavior holds, for qemu_strtoull() but sets @result to
- * ULLONG_MAX instead of ULONG_MAX.
- *
- * See qemu_strtol() documentation for more info.
- */
-int qemu_strtoul(const char *nptr, const char **endptr, int base,
- unsigned long *result)
-{
- char *p;
- int err = 0;
- if (!nptr) {
- if (endptr) {
- *endptr = nptr;
- }
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoul(nptr, &p, base);
- /* Windows returns 1 for negative out-of-range values. */
- if (errno == ERANGE) {
- *result = -1;
- }
- err = check_strtox_error(nptr, p, endptr, errno);
- }
- return err;
-}
-
-/**
- * Converts ASCII string to a long long integer.
- *
- * See qemu_strtol() documentation for more info.
- */
-int qemu_strtoll(const char *nptr, const char **endptr, int base,
- int64_t *result)
-{
- char *p;
- int err = 0;
- if (!nptr) {
- if (endptr) {
- *endptr = nptr;
- }
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoll(nptr, &p, base);
- err = check_strtox_error(nptr, p, endptr, errno);
- }
- return err;
-}
-
-/**
- * Converts ASCII string to an unsigned long long integer.
- *
- * See qemu_strtol() documentation for more info.
- */
-int qemu_strtoull(const char *nptr, const char **endptr, int base,
- uint64_t *result)
-{
- char *p;
- int err = 0;
- if (!nptr) {
- if (endptr) {
- *endptr = nptr;
- }
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoull(nptr, &p, base);
- /* Windows returns 1 for negative out-of-range values. */
- if (errno == ERANGE) {
- *result = -1;
- }
- err = check_strtox_error(nptr, p, endptr, errno);
- }
- return err;
-}
-
-/**
- * parse_uint:
- *
- * @s: String to parse
- * @value: Destination for parsed integer value
- * @endptr: Destination for pointer to first character not consumed
- * @base: integer base, between 2 and 36 inclusive, or 0
- *
- * Parse unsigned integer
- *
- * Parsed syntax is like strtoull()'s: arbitrary whitespace, a single optional
- * '+' or '-', an optional "0x" if @base is 0 or 16, one or more digits.
- *
- * If @s is null, or @base is invalid, or @s doesn't start with an
- * integer in the syntax above, set *@value to 0, *@endptr to @s, and
- * return -EINVAL.
- *
- * Set *@endptr to point right beyond the parsed integer (even if the integer
- * overflows or is negative, all digits will be parsed and *@endptr will
- * point right beyond them).
- *
- * If the integer is negative, set *@value to 0, and return -ERANGE.
- *
- * If the integer overflows unsigned long long, set *@value to
- * ULLONG_MAX, and return -ERANGE.
- *
- * Else, set *@value to the parsed integer, and return 0.
- */
-int parse_uint(const char *s, unsigned long long *value, char **endptr,
- int base)
-{
- int r = 0;
- char *endp = (char *)s;
- unsigned long long val = 0;
-
- if (!s) {
- r = -EINVAL;
- goto out;
- }
-
- errno = 0;
- val = strtoull(s, &endp, base);
- if (errno) {
- r = -errno;
- goto out;
- }
-
- if (endp == s) {
- r = -EINVAL;
- goto out;
- }
-
- /* make sure we reject negative numbers: */
- while (isspace((unsigned char)*s)) {
- s++;
- }
- if (*s == '-') {
- val = 0;
- r = -ERANGE;
- goto out;
- }
-
-out:
- *value = val;
- *endptr = endp;
- return r;
-}
-
-/**
- * parse_uint_full:
- *
- * @s: String to parse
- * @value: Destination for parsed integer value
- * @base: integer base, between 2 and 36 inclusive, or 0
- *
- * Parse unsigned integer from entire string
- *
- * Have the same behavior of parse_uint(), but with an additional check
- * for additional data after the parsed number. If extra characters are present
- * after the parsed number, the function will return -EINVAL, and *@v will
- * be set to 0.
- */
-int parse_uint_full(const char *s, unsigned long long *value, int base)
-{
- char *endp;
- int r;
-
- r = parse_uint(s, value, &endp, base);
- if (r < 0) {
- return r;
- }
- if (*endp) {
- *value = 0;
- return -EINVAL;
- }
-
- return 0;
-}
-
-int qemu_parse_fd(const char *param)
-{
- long fd;
- char *endptr;
-
- errno = 0;
- fd = strtol(param, &endptr, 10);
- if (param == endptr /* no conversion performed */ ||
- errno != 0 /* not representable as long; possibly others */ ||
- *endptr != '\0' /* final string not empty */ ||
- fd < 0 /* invalid as file descriptor */ ||
- fd > INT_MAX /* not representable as int */) {
- return -1;
- }
- return fd;
-}
-
-/*
- * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128)
- * Input is limited to 14-bit numbers
- */
-int uleb128_encode_small(uint8_t *out, uint32_t n)
-{
- g_assert(n <= 0x3fff);
- if (n < 0x80) {
- *out++ = n;
- return 1;
- } else {
- *out++ = (n & 0x7f) | 0x80;
- *out++ = n >> 7;
- return 2;
- }
-}
-
-int uleb128_decode_small(const uint8_t *in, uint32_t *n)
-{
- if (!(*in & 0x80)) {
- *n = *in++;
- return 1;
- } else {
- *n = *in++ & 0x7f;
- /* we exceed 14 bit number */
- if (*in & 0x80) {
- return -1;
- }
- *n |= *in++ << 7;
- return 2;
- }
-}
-
-/*
- * helper to parse debug environment variables
- */
-int parse_debug_env(const char *name, int max, int initial)
-{
- char *debug_env = getenv(name);
- char *inv = NULL;
- long debug;
-
- if (!debug_env) {
- return initial;
- }
- errno = 0;
- debug = strtol(debug_env, &inv, 10);
- if (inv == debug_env) {
- return initial;
- }
- if (debug < 0 || debug > max || errno != 0) {
- fprintf(stderr, "warning: %s not in [0, %d]", name, max);
- return initial;
- }
- return debug;
-}
-
-/*
- * Helper to print ethernet mac address
- */
-const char *qemu_ether_ntoa(const MACAddr *mac)
-{
- static char ret[18];
-
- snprintf(ret, sizeof(ret), "%02x:%02x:%02x:%02x:%02x:%02x",
- mac->a[0], mac->a[1], mac->a[2], mac->a[3], mac->a[4], mac->a[5]);
-
- return ret;
-}
diff --git a/qemu/util/envlist.c b/qemu/util/envlist.c
deleted file mode 100644
index e86857e70..000000000
--- a/qemu/util/envlist.c
+++ /dev/null
@@ -1,242 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/queue.h"
-#include "qemu/envlist.h"
-
-struct envlist_entry {
- const char *ev_var; /* actual env value */
- QLIST_ENTRY(envlist_entry) ev_link;
-};
-
-struct envlist {
- QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
- size_t el_count; /* number of entries */
-};
-
-static int envlist_parse(envlist_t *envlist,
- const char *env, int (*)(envlist_t *, const char *));
-
-/*
- * Allocates new envlist and returns pointer to that or
- * NULL in case of error.
- */
-envlist_t *
-envlist_create(void)
-{
- envlist_t *envlist;
-
- if ((envlist = malloc(sizeof (*envlist))) == NULL)
- return (NULL);
-
- QLIST_INIT(&envlist->el_entries);
- envlist->el_count = 0;
-
- return (envlist);
-}
-
-/*
- * Releases given envlist and its entries.
- */
-void
-envlist_free(envlist_t *envlist)
-{
- struct envlist_entry *entry;
-
- assert(envlist != NULL);
-
- while (envlist->el_entries.lh_first != NULL) {
- entry = envlist->el_entries.lh_first;
- QLIST_REMOVE(entry, ev_link);
-
- free((char *)entry->ev_var);
- free(entry);
- }
- free(envlist);
-}
-
-/*
- * Parses comma separated list of set/modify environment
- * variable entries and updates given enlist accordingly.
- *
- * For example:
- * envlist_parse(el, "HOME=foo,SHELL=/bin/sh");
- *
- * inserts/sets environment variables HOME and SHELL.
- *
- * Returns 0 on success, errno otherwise.
- */
-int
-envlist_parse_set(envlist_t *envlist, const char *env)
-{
- return (envlist_parse(envlist, env, &envlist_setenv));
-}
-
-/*
- * Parses comma separated list of unset environment variable
- * entries and removes given variables from given envlist.
- *
- * Returns 0 on success, errno otherwise.
- */
-int
-envlist_parse_unset(envlist_t *envlist, const char *env)
-{
- return (envlist_parse(envlist, env, &envlist_unsetenv));
-}
-
-/*
- * Parses comma separated list of set, modify or unset entries
- * and calls given callback for each entry.
- *
- * Returns 0 in case of success, errno otherwise.
- */
-static int
-envlist_parse(envlist_t *envlist, const char *env,
- int (*callback)(envlist_t *, const char *))
-{
- char *tmpenv, *envvar;
- char *envsave = NULL;
- int ret = 0;
- assert(callback != NULL);
-
- if ((envlist == NULL) || (env == NULL))
- return (EINVAL);
-
- if ((tmpenv = strdup(env)) == NULL)
- return (errno);
- envsave = tmpenv;
-
- do {
- envvar = strchr(tmpenv, ',');
- if (envvar != NULL) {
- *envvar = '\0';
- }
- if ((*callback)(envlist, tmpenv) != 0) {
- ret = errno;
- break;
- }
- tmpenv = envvar + 1;
- } while (envvar != NULL);
-
- free(envsave);
- return ret;
-}
-
-/*
- * Sets environment value to envlist in similar manner
- * than putenv(3).
- *
- * Returns 0 in success, errno otherwise.
- */
-int
-envlist_setenv(envlist_t *envlist, const char *env)
-{
- struct envlist_entry *entry = NULL;
- const char *eq_sign;
- size_t envname_len;
-
- if ((envlist == NULL) || (env == NULL))
- return (EINVAL);
-
- /* find out first equals sign in given env */
- if ((eq_sign = strchr(env, '=')) == NULL)
- return (EINVAL);
- envname_len = eq_sign - env + 1;
-
- /*
- * If there already exists variable with given name
- * we remove and release it before allocating a whole
- * new entry.
- */
- for (entry = envlist->el_entries.lh_first; entry != NULL;
- entry = entry->ev_link.le_next) {
- if (strncmp(entry->ev_var, env, envname_len) == 0)
- break;
- }
-
- if (entry != NULL) {
- QLIST_REMOVE(entry, ev_link);
- free((char *)entry->ev_var);
- free(entry);
- } else {
- envlist->el_count++;
- }
-
- if ((entry = malloc(sizeof (*entry))) == NULL)
- return (errno);
- if ((entry->ev_var = strdup(env)) == NULL) {
- free(entry);
- return (errno);
- }
- QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
-
- return (0);
-}
-
-/*
- * Removes given env value from envlist in similar manner
- * than unsetenv(3). Returns 0 in success, errno otherwise.
- */
-int
-envlist_unsetenv(envlist_t *envlist, const char *env)
-{
- struct envlist_entry *entry;
- size_t envname_len;
-
- if ((envlist == NULL) || (env == NULL))
- return (EINVAL);
-
- /* env is not allowed to contain '=' */
- if (strchr(env, '=') != NULL)
- return (EINVAL);
-
- /*
- * Find out the requested entry and remove
- * it from the list.
- */
- envname_len = strlen(env);
- for (entry = envlist->el_entries.lh_first; entry != NULL;
- entry = entry->ev_link.le_next) {
- if (strncmp(entry->ev_var, env, envname_len) == 0)
- break;
- }
- if (entry != NULL) {
- QLIST_REMOVE(entry, ev_link);
- free((char *)entry->ev_var);
- free(entry);
-
- envlist->el_count--;
- }
- return (0);
-}
-
-/*
- * Returns given envlist as array of strings (in same form that
- * global variable environ is). Caller must free returned memory
- * by calling free(3) for each element and for the array. Returned
- * array and given envlist are not related (no common references).
- *
- * If caller provides count pointer, number of items in array is
- * stored there. In case of error, NULL is returned and no memory
- * is allocated.
- */
-char **
-envlist_to_environ(const envlist_t *envlist, size_t *count)
-{
- struct envlist_entry *entry;
- char **env, **penv;
-
- penv = env = malloc((envlist->el_count + 1) * sizeof (char *));
- if (env == NULL)
- return (NULL);
-
- for (entry = envlist->el_entries.lh_first; entry != NULL;
- entry = entry->ev_link.le_next) {
- *(penv++) = strdup(entry->ev_var);
- }
- *penv = NULL; /* NULL terminate the list */
-
- if (count != NULL)
- *count = envlist->el_count;
-
- return (env);
-}
diff --git a/qemu/util/error.c b/qemu/util/error.c
deleted file mode 100644
index cae251173..000000000
--- a/qemu/util/error.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * QEMU Error Objects
- *
- * Copyright IBM, Corp. 2011
- * Copyright (C) 2011-2015 Red Hat, Inc.
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- * Markus Armbruster <armbru@redhat.com>,
- *
- * This work is licensed under the terms of the GNU LGPL, version 2. See
- * the COPYING.LIB file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-
-struct Error
-{
- char *msg;
- ErrorClass err_class;
- const char *src, *func;
- int line;
- GString *hint;
-};
-
-Error *error_abort;
-Error *error_fatal;
-
-static void error_handle_fatal(Error **errp, Error *err)
-{
- if (errp == &error_abort) {
- fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
- err->func, err->src, err->line);
- error_report_err(err);
- abort();
- }
- if (errp == &error_fatal) {
- error_report_err(err);
- exit(1);
- }
-}
-
-static void error_setv(Error **errp,
- const char *src, int line, const char *func,
- ErrorClass err_class, const char *fmt, va_list ap,
- const char *suffix)
-{
- Error *err;
- int saved_errno = errno;
-
- if (errp == NULL) {
- return;
- }
- assert(*errp == NULL);
-
- err = g_malloc0(sizeof(*err));
- err->msg = g_strdup_vprintf(fmt, ap);
- if (suffix) {
- char *msg = err->msg;
- err->msg = g_strdup_printf("%s: %s", msg, suffix);
- g_free(msg);
- }
- err->err_class = err_class;
- err->src = src;
- err->line = line;
- err->func = func;
-
- error_handle_fatal(errp, err);
- *errp = err;
-
- errno = saved_errno;
-}
-
-void error_set_internal(Error **errp,
- const char *src, int line, const char *func,
- ErrorClass err_class, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
- va_end(ap);
-}
-
-void error_setg_internal(Error **errp,
- const char *src, int line, const char *func,
- const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
- va_end(ap);
-}
-
-void error_setg_errno_internal(Error **errp,
- const char *src, int line, const char *func,
- int os_errno, const char *fmt, ...)
-{
- va_list ap;
- int saved_errno = errno;
-
- if (errp == NULL) {
- return;
- }
-
- va_start(ap, fmt);
- error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
- os_errno != 0 ? strerror(os_errno) : NULL);
- va_end(ap);
-
- errno = saved_errno;
-}
-
-void error_setg_file_open_internal(Error **errp,
- const char *src, int line, const char *func,
- int os_errno, const char *filename)
-{
- error_setg_errno_internal(errp, src, line, func, os_errno,
- "Could not open '%s'", filename);
-}
-
-void error_vprepend(Error **errp, const char *fmt, va_list ap)
-{
- GString *newmsg;
-
- if (!errp) {
- return;
- }
-
- newmsg = g_string_new(NULL);
- g_string_vprintf(newmsg, fmt, ap);
- g_string_append(newmsg, (*errp)->msg);
- (*errp)->msg = g_string_free(newmsg, 0);
-}
-
-void error_prepend(Error **errp, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_vprepend(errp, fmt, ap);
- va_end(ap);
-}
-
-void error_append_hint(Error **errp, const char *fmt, ...)
-{
- va_list ap;
- int saved_errno = errno;
- Error *err;
-
- if (!errp) {
- return;
- }
- err = *errp;
- assert(err && errp != &error_abort && errp != &error_fatal);
-
- if (!err->hint) {
- err->hint = g_string_new(NULL);
- }
- va_start(ap, fmt);
- g_string_append_vprintf(err->hint, fmt, ap);
- va_end(ap);
-
- errno = saved_errno;
-}
-
-#ifdef _WIN32
-
-void error_setg_win32_internal(Error **errp,
- const char *src, int line, const char *func,
- int win32_err, const char *fmt, ...)
-{
- va_list ap;
- char *suffix = NULL;
-
- if (errp == NULL) {
- return;
- }
-
- if (win32_err != 0) {
- suffix = g_win32_error_message(win32_err);
- }
-
- va_start(ap, fmt);
- error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
- fmt, ap, suffix);
- va_end(ap);
-
- g_free(suffix);
-}
-
-#endif
-
-Error *error_copy(const Error *err)
-{
- Error *err_new;
-
- err_new = g_malloc0(sizeof(*err));
- err_new->msg = g_strdup(err->msg);
- err_new->err_class = err->err_class;
- err_new->src = err->src;
- err_new->line = err->line;
- err_new->func = err->func;
- if (err->hint) {
- err_new->hint = g_string_new(err->hint->str);
- }
-
- return err_new;
-}
-
-ErrorClass error_get_class(const Error *err)
-{
- return err->err_class;
-}
-
-const char *error_get_pretty(Error *err)
-{
- return err->msg;
-}
-
-void error_report_err(Error *err)
-{
- error_report("%s", error_get_pretty(err));
- if (err->hint) {
- error_printf_unless_qmp("%s", err->hint->str);
- }
- error_free(err);
-}
-
-void error_reportf_err(Error *err, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_vprepend(&err, fmt, ap);
- va_end(ap);
- error_report_err(err);
-}
-
-void error_free(Error *err)
-{
- if (err) {
- g_free(err->msg);
- if (err->hint) {
- g_string_free(err->hint, true);
- }
- g_free(err);
- }
-}
-
-void error_free_or_abort(Error **errp)
-{
- assert(errp && *errp);
- error_free(*errp);
- *errp = NULL;
-}
-
-void error_propagate(Error **dst_errp, Error *local_err)
-{
- if (!local_err) {
- return;
- }
- error_handle_fatal(dst_errp, local_err);
- if (dst_errp && !*dst_errp) {
- *dst_errp = local_err;
- } else {
- error_free(local_err);
- }
-}
diff --git a/qemu/util/event_notifier-posix.c b/qemu/util/event_notifier-posix.c
deleted file mode 100644
index c1f0d79b3..000000000
--- a/qemu/util/event_notifier-posix.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * event notifier support
- *
- * Copyright Red Hat, Inc. 2010
- *
- * Authors:
- * Michael S. Tsirkin <mst@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "qemu/event_notifier.h"
-#include "sysemu/char.h"
-#include "qemu/main-loop.h"
-
-#ifdef CONFIG_EVENTFD
-#include <sys/eventfd.h>
-#endif
-
-#ifdef CONFIG_EVENTFD
-/*
- * Initialize @e with existing file descriptor @fd.
- * @fd must be a genuine eventfd object, emulation with pipe won't do.
- */
-void event_notifier_init_fd(EventNotifier *e, int fd)
-{
- e->rfd = fd;
- e->wfd = fd;
-}
-#endif
-
-int event_notifier_init(EventNotifier *e, int active)
-{
- int fds[2];
- int ret;
-
-#ifdef CONFIG_EVENTFD
- ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-#else
- ret = -1;
- errno = ENOSYS;
-#endif
- if (ret >= 0) {
- e->rfd = e->wfd = ret;
- } else {
- if (errno != ENOSYS) {
- return -errno;
- }
- if (qemu_pipe(fds) < 0) {
- return -errno;
- }
- ret = fcntl_setfl(fds[0], O_NONBLOCK);
- if (ret < 0) {
- ret = -errno;
- goto fail;
- }
- ret = fcntl_setfl(fds[1], O_NONBLOCK);
- if (ret < 0) {
- ret = -errno;
- goto fail;
- }
- e->rfd = fds[0];
- e->wfd = fds[1];
- }
- if (active) {
- event_notifier_set(e);
- }
- return 0;
-
-fail:
- close(fds[0]);
- close(fds[1]);
- return ret;
-}
-
-void event_notifier_cleanup(EventNotifier *e)
-{
- if (e->rfd != e->wfd) {
- close(e->rfd);
- }
- close(e->wfd);
-}
-
-int event_notifier_get_fd(const EventNotifier *e)
-{
- return e->rfd;
-}
-
-int event_notifier_set_handler(EventNotifier *e,
- bool is_external,
- EventNotifierHandler *handler)
-{
- aio_set_fd_handler(iohandler_get_aio_context(), e->rfd, is_external,
- (IOHandler *)handler, NULL, e);
- return 0;
-}
-
-int event_notifier_set(EventNotifier *e)
-{
- static const uint64_t value = 1;
- ssize_t ret;
-
- do {
- ret = write(e->wfd, &value, sizeof(value));
- } while (ret < 0 && errno == EINTR);
-
- /* EAGAIN is fine, a read must be pending. */
- if (ret < 0 && errno != EAGAIN) {
- return -errno;
- }
- return 0;
-}
-
-int event_notifier_test_and_clear(EventNotifier *e)
-{
- int value;
- ssize_t len;
- char buffer[512];
-
- /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
- value = 0;
- do {
- len = read(e->rfd, buffer, sizeof(buffer));
- value |= (len > 0);
- } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
-
- return value;
-}
diff --git a/qemu/util/event_notifier-win32.c b/qemu/util/event_notifier-win32.c
deleted file mode 100644
index de87df02d..000000000
--- a/qemu/util/event_notifier-win32.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * event notifier support
- *
- * Copyright Red Hat, Inc. 2010
- *
- * Authors:
- * Michael S. Tsirkin <mst@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/event_notifier.h"
-#include "qemu/main-loop.h"
-
-int event_notifier_init(EventNotifier *e, int active)
-{
- e->event = CreateEvent(NULL, TRUE, FALSE, NULL);
- assert(e->event);
- return 0;
-}
-
-void event_notifier_cleanup(EventNotifier *e)
-{
- CloseHandle(e->event);
-}
-
-HANDLE event_notifier_get_handle(EventNotifier *e)
-{
- return e->event;
-}
-
-int event_notifier_set_handler(EventNotifier *e,
- bool is_external,
- EventNotifierHandler *handler)
-{
- if (handler) {
- return qemu_add_wait_object(e->event, (IOHandler *)handler, e);
- } else {
- qemu_del_wait_object(e->event, (IOHandler *)handler, e);
- return 0;
- }
-}
-
-int event_notifier_set(EventNotifier *e)
-{
- SetEvent(e->event);
- return 0;
-}
-
-int event_notifier_test_and_clear(EventNotifier *e)
-{
- int ret = WaitForSingleObject(e->event, 0);
- if (ret == WAIT_OBJECT_0) {
- ResetEvent(e->event);
- return true;
- }
- return false;
-}
diff --git a/qemu/util/fifo8.c b/qemu/util/fifo8.c
deleted file mode 100644
index 5c64101b3..000000000
--- a/qemu/util/fifo8.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Generic FIFO component, implemented as a circular buffer.
- *
- * Copyright (c) 2012 Peter A. G. Crosthwaite
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/fifo8.h"
-
-void fifo8_create(Fifo8 *fifo, uint32_t capacity)
-{
- fifo->data = g_new(uint8_t, capacity);
- fifo->capacity = capacity;
- fifo->head = 0;
- fifo->num = 0;
-}
-
-void fifo8_destroy(Fifo8 *fifo)
-{
- g_free(fifo->data);
-}
-
-void fifo8_push(Fifo8 *fifo, uint8_t data)
-{
- if (fifo->num == fifo->capacity) {
- abort();
- }
- fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
- fifo->num++;
-}
-
-void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num)
-{
- uint32_t start, avail;
-
- if (fifo->num + num > fifo->capacity) {
- abort();
- }
-
- start = (fifo->head + fifo->num) % fifo->capacity;
-
- if (start + num <= fifo->capacity) {
- memcpy(&fifo->data[start], data, num);
- } else {
- avail = fifo->capacity - start;
- memcpy(&fifo->data[start], data, avail);
- memcpy(&fifo->data[0], &data[avail], num - avail);
- }
-
- fifo->num += num;
-}
-
-uint8_t fifo8_pop(Fifo8 *fifo)
-{
- uint8_t ret;
-
- if (fifo->num == 0) {
- abort();
- }
- ret = fifo->data[fifo->head++];
- fifo->head %= fifo->capacity;
- fifo->num--;
- return ret;
-}
-
-const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num)
-{
- uint8_t *ret;
-
- if (max == 0 || max > fifo->num) {
- abort();
- }
- *num = MIN(fifo->capacity - fifo->head, max);
- ret = &fifo->data[fifo->head];
- fifo->head += *num;
- fifo->head %= fifo->capacity;
- fifo->num -= *num;
- return ret;
-}
-
-void fifo8_reset(Fifo8 *fifo)
-{
- fifo->num = 0;
- fifo->head = 0;
-}
-
-bool fifo8_is_empty(Fifo8 *fifo)
-{
- return (fifo->num == 0);
-}
-
-bool fifo8_is_full(Fifo8 *fifo)
-{
- return (fifo->num == fifo->capacity);
-}
-
-uint32_t fifo8_num_free(Fifo8 *fifo)
-{
- return fifo->capacity - fifo->num;
-}
-
-uint32_t fifo8_num_used(Fifo8 *fifo)
-{
- return fifo->num;
-}
-
-const VMStateDescription vmstate_fifo8 = {
- .name = "Fifo8",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
- VMSTATE_UINT32(head, Fifo8),
- VMSTATE_UINT32(num, Fifo8),
- VMSTATE_END_OF_LIST()
- }
-};
diff --git a/qemu/util/getauxval.c b/qemu/util/getauxval.c
deleted file mode 100644
index 0b3bae2dc..000000000
--- a/qemu/util/getauxval.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * QEMU access to the auxiliary vector
- *
- * Copyright (C) 2013 Red Hat, Inc
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-
-#ifdef CONFIG_GETAUXVAL
-/* Don't inline this in qemu/osdep.h, because pulling in <sys/auxv.h> for
- the system declaration of getauxval pulls in the system <elf.h>, which
- conflicts with qemu's version. */
-
-#include <sys/auxv.h>
-
-unsigned long qemu_getauxval(unsigned long key)
-{
- return getauxval(key);
-}
-#elif defined(__linux__)
-#include "elf.h"
-
-/* Our elf.h doesn't contain Elf32_auxv_t and Elf64_auxv_t, which is ok because
- that just makes it easier to define it properly for the host here. */
-typedef struct {
- unsigned long a_type;
- unsigned long a_val;
-} ElfW_auxv_t;
-
-static const ElfW_auxv_t *auxv;
-
-static const ElfW_auxv_t *qemu_init_auxval(void)
-{
- ElfW_auxv_t *a;
- ssize_t size = 512, r, ofs;
- int fd;
-
- /* Allocate some initial storage. Make sure the first entry is set
- to end-of-list, so that we've got a valid list in case of error. */
- auxv = a = g_malloc(size);
- a[0].a_type = 0;
- a[0].a_val = 0;
-
- fd = open("/proc/self/auxv", O_RDONLY);
- if (fd < 0) {
- return a;
- }
-
- /* Read the first SIZE bytes. Hopefully, this covers everything. */
- r = read(fd, a, size);
-
- if (r == size) {
- /* Continue to expand until we do get a partial read. */
- do {
- ofs = size;
- size *= 2;
- auxv = a = g_realloc(a, size);
- r = read(fd, (char *)a + ofs, ofs);
- } while (r == ofs);
- }
-
- close(fd);
- return a;
-}
-
-unsigned long qemu_getauxval(unsigned long type)
-{
- const ElfW_auxv_t *a = auxv;
-
- if (unlikely(a == NULL)) {
- a = qemu_init_auxval();
- }
-
- for (; a->a_type != 0; a++) {
- if (a->a_type == type) {
- return a->a_val;
- }
- }
-
- return 0;
-}
-
-#else
-
-unsigned long qemu_getauxval(unsigned long type)
-{
- return 0;
-}
-
-#endif
diff --git a/qemu/util/hbitmap.c b/qemu/util/hbitmap.c
deleted file mode 100644
index b22b87d0a..000000000
--- a/qemu/util/hbitmap.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Hierarchical Bitmap Data Type
- *
- * Copyright Red Hat, Inc., 2012
- *
- * Author: Paolo Bonzini <pbonzini@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * later. See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "qemu/hbitmap.h"
-#include "qemu/host-utils.h"
-#include "trace.h"
-
-/* HBitmaps provides an array of bits. The bits are stored as usual in an
- * array of unsigned longs, but HBitmap is also optimized to provide fast
- * iteration over set bits; going from one bit to the next is O(logB n)
- * worst case, with B = sizeof(long) * CHAR_BIT: the result is low enough
- * that the number of levels is in fact fixed.
- *
- * In order to do this, it stacks multiple bitmaps with progressively coarser
- * granularity; in all levels except the last, bit N is set iff the N-th
- * unsigned long is nonzero in the immediately next level. When iteration
- * completes on the last level it can examine the 2nd-last level to quickly
- * skip entire words, and even do so recursively to skip blocks of 64 words or
- * powers thereof (32 on 32-bit machines).
- *
- * Given an index in the bitmap, it can be split in group of bits like
- * this (for the 64-bit case):
- *
- * bits 0-57 => word in the last bitmap | bits 58-63 => bit in the word
- * bits 0-51 => word in the 2nd-last bitmap | bits 52-57 => bit in the word
- * bits 0-45 => word in the 3rd-last bitmap | bits 46-51 => bit in the word
- *
- * So it is easy to move up simply by shifting the index right by
- * log2(BITS_PER_LONG) bits. To move down, you shift the index left
- * similarly, and add the word index within the group. Iteration uses
- * ffs (find first set bit) to find the next word to examine; this
- * operation can be done in constant time in most current architectures.
- *
- * Setting or clearing a range of m bits on all levels, the work to perform
- * is O(m + m/W + m/W^2 + ...), which is O(m) like on a regular bitmap.
- *
- * When iterating on a bitmap, each bit (on any level) is only visited
- * once. Hence, The total cost of visiting a bitmap with m bits in it is
- * the number of bits that are set in all bitmaps. Unless the bitmap is
- * extremely sparse, this is also O(m + m/W + m/W^2 + ...), so the amortized
- * cost of advancing from one bit to the next is usually constant (worst case
- * O(logB n) as in the non-amortized complexity).
- */
-
-struct HBitmap {
- /* Number of total bits in the bottom level. */
- uint64_t size;
-
- /* Number of set bits in the bottom level. */
- uint64_t count;
-
- /* A scaling factor. Given a granularity of G, each bit in the bitmap will
- * will actually represent a group of 2^G elements. Each operation on a
- * range of bits first rounds the bits to determine which group they land
- * in, and then affect the entire page; iteration will only visit the first
- * bit of each group. Here is an example of operations in a size-16,
- * granularity-1 HBitmap:
- *
- * initial state 00000000
- * set(start=0, count=9) 11111000 (iter: 0, 2, 4, 6, 8)
- * reset(start=1, count=3) 00111000 (iter: 4, 6, 8)
- * set(start=9, count=2) 00111100 (iter: 4, 6, 8, 10)
- * reset(start=5, count=5) 00000000
- *
- * From an implementation point of view, when setting or resetting bits,
- * the bitmap will scale bit numbers right by this amount of bits. When
- * iterating, the bitmap will scale bit numbers left by this amount of
- * bits.
- */
- int granularity;
-
- /* A number of progressively less coarse bitmaps (i.e. level 0 is the
- * coarsest). Each bit in level N represents a word in level N+1 that
- * has a set bit, except the last level where each bit represents the
- * actual bitmap.
- *
- * Note that all bitmaps have the same number of levels. Even a 1-bit
- * bitmap will still allocate HBITMAP_LEVELS arrays.
- */
- unsigned long *levels[HBITMAP_LEVELS];
-
- /* The length of each levels[] array. */
- uint64_t sizes[HBITMAP_LEVELS];
-};
-
-/* Advance hbi to the next nonzero word and return it. hbi->pos
- * is updated. Returns zero if we reach the end of the bitmap.
- */
-unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi)
-{
- size_t pos = hbi->pos;
- const HBitmap *hb = hbi->hb;
- unsigned i = HBITMAP_LEVELS - 1;
-
- unsigned long cur;
- do {
- cur = hbi->cur[--i];
- pos >>= BITS_PER_LEVEL;
- } while (cur == 0);
-
- /* Check for end of iteration. We always use fewer than BITS_PER_LONG
- * bits in the level 0 bitmap; thus we can repurpose the most significant
- * bit as a sentinel. The sentinel is set in hbitmap_alloc and ensures
- * that the above loop ends even without an explicit check on i.
- */
-
- if (i == 0 && cur == (1UL << (BITS_PER_LONG - 1))) {
- return 0;
- }
- for (; i < HBITMAP_LEVELS - 1; i++) {
- /* Shift back pos to the left, matching the right shifts above.
- * The index of this word's least significant set bit provides
- * the low-order bits.
- */
- assert(cur);
- pos = (pos << BITS_PER_LEVEL) + ctzl(cur);
- hbi->cur[i] = cur & (cur - 1);
-
- /* Set up next level for iteration. */
- cur = hb->levels[i + 1][pos];
- }
-
- hbi->pos = pos;
- trace_hbitmap_iter_skip_words(hbi->hb, hbi, pos, cur);
-
- assert(cur);
- return cur;
-}
-
-void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first)
-{
- unsigned i, bit;
- uint64_t pos;
-
- hbi->hb = hb;
- pos = first >> hb->granularity;
- assert(pos < hb->size);
- hbi->pos = pos >> BITS_PER_LEVEL;
- hbi->granularity = hb->granularity;
-
- for (i = HBITMAP_LEVELS; i-- > 0; ) {
- bit = pos & (BITS_PER_LONG - 1);
- pos >>= BITS_PER_LEVEL;
-
- /* Drop bits representing items before first. */
- hbi->cur[i] = hb->levels[i][pos] & ~((1UL << bit) - 1);
-
- /* We have already added level i+1, so the lowest set bit has
- * been processed. Clear it.
- */
- if (i != HBITMAP_LEVELS - 1) {
- hbi->cur[i] &= ~(1UL << bit);
- }
- }
-}
-
-bool hbitmap_empty(const HBitmap *hb)
-{
- return hb->count == 0;
-}
-
-int hbitmap_granularity(const HBitmap *hb)
-{
- return hb->granularity;
-}
-
-uint64_t hbitmap_count(const HBitmap *hb)
-{
- return hb->count << hb->granularity;
-}
-
-/* Count the number of set bits between start and end, not accounting for
- * the granularity. Also an example of how to use hbitmap_iter_next_word.
- */
-static uint64_t hb_count_between(HBitmap *hb, uint64_t start, uint64_t last)
-{
- HBitmapIter hbi;
- uint64_t count = 0;
- uint64_t end = last + 1;
- unsigned long cur;
- size_t pos;
-
- hbitmap_iter_init(&hbi, hb, start << hb->granularity);
- for (;;) {
- pos = hbitmap_iter_next_word(&hbi, &cur);
- if (pos >= (end >> BITS_PER_LEVEL)) {
- break;
- }
- count += ctpopl(cur);
- }
-
- if (pos == (end >> BITS_PER_LEVEL)) {
- /* Drop bits representing the END-th and subsequent items. */
- int bit = end & (BITS_PER_LONG - 1);
- cur &= (1UL << bit) - 1;
- count += ctpopl(cur);
- }
-
- return count;
-}
-
-/* Setting starts at the last layer and propagates up if an element
- * changes from zero to non-zero.
- */
-static inline bool hb_set_elem(unsigned long *elem, uint64_t start, uint64_t last)
-{
- unsigned long mask;
- bool changed;
-
- assert((last >> BITS_PER_LEVEL) == (start >> BITS_PER_LEVEL));
- assert(start <= last);
-
- mask = 2UL << (last & (BITS_PER_LONG - 1));
- mask -= 1UL << (start & (BITS_PER_LONG - 1));
- changed = (*elem == 0);
- *elem |= mask;
- return changed;
-}
-
-/* The recursive workhorse (the depth is limited to HBITMAP_LEVELS)... */
-static void hb_set_between(HBitmap *hb, int level, uint64_t start, uint64_t last)
-{
- size_t pos = start >> BITS_PER_LEVEL;
- size_t lastpos = last >> BITS_PER_LEVEL;
- bool changed = false;
- size_t i;
-
- i = pos;
- if (i < lastpos) {
- uint64_t next = (start | (BITS_PER_LONG - 1)) + 1;
- changed |= hb_set_elem(&hb->levels[level][i], start, next - 1);
- for (;;) {
- start = next;
- next += BITS_PER_LONG;
- if (++i == lastpos) {
- break;
- }
- changed |= (hb->levels[level][i] == 0);
- hb->levels[level][i] = ~0UL;
- }
- }
- changed |= hb_set_elem(&hb->levels[level][i], start, last);
-
- /* If there was any change in this layer, we may have to update
- * the one above.
- */
- if (level > 0 && changed) {
- hb_set_between(hb, level - 1, pos, lastpos);
- }
-}
-
-void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count)
-{
- /* Compute range in the last layer. */
- uint64_t last = start + count - 1;
-
- trace_hbitmap_set(hb, start, count,
- start >> hb->granularity, last >> hb->granularity);
-
- start >>= hb->granularity;
- last >>= hb->granularity;
- count = last - start + 1;
-
- hb->count += count - hb_count_between(hb, start, last);
- hb_set_between(hb, HBITMAP_LEVELS - 1, start, last);
-}
-
-/* Resetting works the other way round: propagate up if the new
- * value is zero.
- */
-static inline bool hb_reset_elem(unsigned long *elem, uint64_t start, uint64_t last)
-{
- unsigned long mask;
- bool blanked;
-
- assert((last >> BITS_PER_LEVEL) == (start >> BITS_PER_LEVEL));
- assert(start <= last);
-
- mask = 2UL << (last & (BITS_PER_LONG - 1));
- mask -= 1UL << (start & (BITS_PER_LONG - 1));
- blanked = *elem != 0 && ((*elem & ~mask) == 0);
- *elem &= ~mask;
- return blanked;
-}
-
-/* The recursive workhorse (the depth is limited to HBITMAP_LEVELS)... */
-static void hb_reset_between(HBitmap *hb, int level, uint64_t start, uint64_t last)
-{
- size_t pos = start >> BITS_PER_LEVEL;
- size_t lastpos = last >> BITS_PER_LEVEL;
- bool changed = false;
- size_t i;
-
- i = pos;
- if (i < lastpos) {
- uint64_t next = (start | (BITS_PER_LONG - 1)) + 1;
-
- /* Here we need a more complex test than when setting bits. Even if
- * something was changed, we must not blank bits in the upper level
- * unless the lower-level word became entirely zero. So, remove pos
- * from the upper-level range if bits remain set.
- */
- if (hb_reset_elem(&hb->levels[level][i], start, next - 1)) {
- changed = true;
- } else {
- pos++;
- }
-
- for (;;) {
- start = next;
- next += BITS_PER_LONG;
- if (++i == lastpos) {
- break;
- }
- changed |= (hb->levels[level][i] != 0);
- hb->levels[level][i] = 0UL;
- }
- }
-
- /* Same as above, this time for lastpos. */
- if (hb_reset_elem(&hb->levels[level][i], start, last)) {
- changed = true;
- } else {
- lastpos--;
- }
-
- if (level > 0 && changed) {
- hb_reset_between(hb, level - 1, pos, lastpos);
- }
-}
-
-void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count)
-{
- /* Compute range in the last layer. */
- uint64_t last = start + count - 1;
-
- trace_hbitmap_reset(hb, start, count,
- start >> hb->granularity, last >> hb->granularity);
-
- start >>= hb->granularity;
- last >>= hb->granularity;
-
- hb->count -= hb_count_between(hb, start, last);
- hb_reset_between(hb, HBITMAP_LEVELS - 1, start, last);
-}
-
-void hbitmap_reset_all(HBitmap *hb)
-{
- unsigned int i;
-
- /* Same as hbitmap_alloc() except for memset() instead of malloc() */
- for (i = HBITMAP_LEVELS; --i >= 1; ) {
- memset(hb->levels[i], 0, hb->sizes[i] * sizeof(unsigned long));
- }
-
- hb->levels[0][0] = 1UL << (BITS_PER_LONG - 1);
- hb->count = 0;
-}
-
-bool hbitmap_get(const HBitmap *hb, uint64_t item)
-{
- /* Compute position and bit in the last layer. */
- uint64_t pos = item >> hb->granularity;
- unsigned long bit = 1UL << (pos & (BITS_PER_LONG - 1));
-
- return (hb->levels[HBITMAP_LEVELS - 1][pos >> BITS_PER_LEVEL] & bit) != 0;
-}
-
-void hbitmap_free(HBitmap *hb)
-{
- unsigned i;
- for (i = HBITMAP_LEVELS; i-- > 0; ) {
- g_free(hb->levels[i]);
- }
- g_free(hb);
-}
-
-HBitmap *hbitmap_alloc(uint64_t size, int granularity)
-{
- HBitmap *hb = g_new0(struct HBitmap, 1);
- unsigned i;
-
- assert(granularity >= 0 && granularity < 64);
- size = (size + (1ULL << granularity) - 1) >> granularity;
- assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE));
-
- hb->size = size;
- hb->granularity = granularity;
- for (i = HBITMAP_LEVELS; i-- > 0; ) {
- size = MAX((size + BITS_PER_LONG - 1) >> BITS_PER_LEVEL, 1);
- hb->sizes[i] = size;
- hb->levels[i] = g_new0(unsigned long, size);
- }
-
- /* We necessarily have free bits in level 0 due to the definition
- * of HBITMAP_LEVELS, so use one for a sentinel. This speeds up
- * hbitmap_iter_skip_words.
- */
- assert(size == 1);
- hb->levels[0][0] |= 1UL << (BITS_PER_LONG - 1);
- return hb;
-}
-
-void hbitmap_truncate(HBitmap *hb, uint64_t size)
-{
- bool shrink;
- unsigned i;
- uint64_t num_elements = size;
- uint64_t old;
-
- /* Size comes in as logical elements, adjust for granularity. */
- size = (size + (1ULL << hb->granularity) - 1) >> hb->granularity;
- assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE));
- shrink = size < hb->size;
-
- /* bit sizes are identical; nothing to do. */
- if (size == hb->size) {
- return;
- }
-
- /* If we're losing bits, let's clear those bits before we invalidate all of
- * our invariants. This helps keep the bitcount consistent, and will prevent
- * us from carrying around garbage bits beyond the end of the map.
- */
- if (shrink) {
- /* Don't clear partial granularity groups;
- * start at the first full one. */
- uint64_t start = QEMU_ALIGN_UP(num_elements, 1 << hb->granularity);
- uint64_t fix_count = (hb->size << hb->granularity) - start;
-
- assert(fix_count);
- hbitmap_reset(hb, start, fix_count);
- }
-
- hb->size = size;
- for (i = HBITMAP_LEVELS; i-- > 0; ) {
- size = MAX(BITS_TO_LONGS(size), 1);
- if (hb->sizes[i] == size) {
- break;
- }
- old = hb->sizes[i];
- hb->sizes[i] = size;
- hb->levels[i] = g_realloc(hb->levels[i], size * sizeof(unsigned long));
- if (!shrink) {
- memset(&hb->levels[i][old], 0x00,
- (size - old) * sizeof(*hb->levels[i]));
- }
- }
-}
-
-
-/**
- * Given HBitmaps A and B, let A := A (BITOR) B.
- * Bitmap B will not be modified.
- *
- * @return true if the merge was successful,
- * false if it was not attempted.
- */
-bool hbitmap_merge(HBitmap *a, const HBitmap *b)
-{
- int i;
- uint64_t j;
-
- if ((a->size != b->size) || (a->granularity != b->granularity)) {
- return false;
- }
-
- if (hbitmap_count(b) == 0) {
- return true;
- }
-
- /* This merge is O(size), as BITS_PER_LONG and HBITMAP_LEVELS are constant.
- * It may be possible to improve running times for sparsely populated maps
- * by using hbitmap_iter_next, but this is suboptimal for dense maps.
- */
- for (i = HBITMAP_LEVELS - 1; i >= 0; i--) {
- for (j = 0; j < a->sizes[i]; j++) {
- a->levels[i][j] |= b->levels[i][j];
- }
- }
-
- return true;
-}
diff --git a/qemu/util/hexdump.c b/qemu/util/hexdump.c
deleted file mode 100644
index f879ff0ad..000000000
--- a/qemu/util/hexdump.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Helper to hexdump a buffer
- *
- * Copyright (c) 2013 Red Hat, Inc.
- * Copyright (c) 2013 Gerd Hoffmann <kraxel@redhat.com>
- * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
- * Copyright (c) 2013 Xilinx, Inc
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-
-void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size)
-{
- unsigned int b, len, i, c;
-
- for (b = 0; b < size; b += 16) {
- len = size - b;
- if (len > 16) {
- len = 16;
- }
- fprintf(fp, "%s: %04x:", prefix, b);
- for (i = 0; i < 16; i++) {
- if ((i % 4) == 0) {
- fprintf(fp, " ");
- }
- if (i < len) {
- fprintf(fp, " %02x", (unsigned char)buf[b + i]);
- } else {
- fprintf(fp, " ");
- }
- }
- fprintf(fp, " ");
- for (i = 0; i < len; i++) {
- c = buf[b + i];
- if (c < ' ' || c > '~') {
- c = '.';
- }
- fprintf(fp, "%c", c);
- }
- fprintf(fp, "\n");
- }
-}
diff --git a/qemu/util/host-utils.c b/qemu/util/host-utils.c
deleted file mode 100644
index b166e5758..000000000
--- a/qemu/util/host-utils.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Utility compute operations used by translated code.
- *
- * Copyright (c) 2003 Fabrice Bellard
- * Copyright (c) 2007 Aurelien Jarno
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/host-utils.h"
-
-/* Long integer helpers */
-static inline void mul64(uint64_t *plow, uint64_t *phigh,
- uint64_t a, uint64_t b)
-{
- typedef union {
- uint64_t ll;
- struct {
-#ifdef HOST_WORDS_BIGENDIAN
- uint32_t high, low;
-#else
- uint32_t low, high;
-#endif
- } l;
- } LL;
- LL rl, rm, rn, rh, a0, b0;
- uint64_t c;
-
- a0.ll = a;
- b0.ll = b;
-
- rl.ll = (uint64_t)a0.l.low * b0.l.low;
- rm.ll = (uint64_t)a0.l.low * b0.l.high;
- rn.ll = (uint64_t)a0.l.high * b0.l.low;
- rh.ll = (uint64_t)a0.l.high * b0.l.high;
-
- c = (uint64_t)rl.l.high + rm.l.low + rn.l.low;
- rl.l.high = c;
- c >>= 32;
- c = c + rm.l.high + rn.l.high + rh.l.low;
- rh.l.low = c;
- rh.l.high += (uint32_t)(c >> 32);
-
- *plow = rl.ll;
- *phigh = rh.ll;
-}
-
-/* Unsigned 64x64 -> 128 multiplication */
-void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
-{
- mul64(plow, phigh, a, b);
-}
-
-/* Signed 64x64 -> 128 multiplication */
-void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
-{
- uint64_t rh;
-
- mul64(plow, &rh, a, b);
-
- /* Adjust for signs. */
- if (b < 0) {
- rh -= a;
- }
- if (a < 0) {
- rh -= b;
- }
- *phigh = rh;
-}
-
-/* Unsigned 128x64 division. Returns 1 if overflow (divide by zero or */
-/* quotient exceeds 64 bits). Otherwise returns quotient via plow and */
-/* remainder via phigh. */
-int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
-{
- uint64_t dhi = *phigh;
- uint64_t dlo = *plow;
- unsigned i;
- uint64_t carry = 0;
-
- if (divisor == 0) {
- return 1;
- } else if (dhi == 0) {
- *plow = dlo / divisor;
- *phigh = dlo % divisor;
- return 0;
- } else if (dhi > divisor) {
- return 1;
- } else {
-
- for (i = 0; i < 64; i++) {
- carry = dhi >> 63;
- dhi = (dhi << 1) | (dlo >> 63);
- if (carry || (dhi >= divisor)) {
- dhi -= divisor;
- carry = 1;
- } else {
- carry = 0;
- }
- dlo = (dlo << 1) | carry;
- }
-
- *plow = dlo;
- *phigh = dhi;
- return 0;
- }
-}
-
-int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
-{
- int sgn_dvdnd = *phigh < 0;
- int sgn_divsr = divisor < 0;
- int overflow = 0;
-
- if (sgn_dvdnd) {
- *plow = ~(*plow);
- *phigh = ~(*phigh);
- if (*plow == (int64_t)-1) {
- *plow = 0;
- (*phigh)++;
- } else {
- (*plow)++;
- }
- }
-
- if (sgn_divsr) {
- divisor = 0 - divisor;
- }
-
- overflow = divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor);
-
- if (sgn_dvdnd ^ sgn_divsr) {
- *plow = 0 - *plow;
- }
-
- if (!overflow) {
- if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) {
- overflow = 1;
- }
- }
-
- return overflow;
-}
-
diff --git a/qemu/util/id.c b/qemu/util/id.c
deleted file mode 100644
index 614135295..000000000
--- a/qemu/util/id.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Dealing with identifiers
- *
- * Copyright (C) 2014 Red Hat, Inc.
- *
- * Authors:
- * Markus Armbruster <armbru@redhat.com>,
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1
- * or later. See the COPYING.LIB file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/id.h"
-
-bool id_wellformed(const char *id)
-{
- int i;
-
- if (!qemu_isalpha(id[0])) {
- return false;
- }
- for (i = 1; id[i]; i++) {
- if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
- return false;
- }
- }
- return true;
-}
-
-#define ID_SPECIAL_CHAR '#'
-
-static const char *const id_subsys_str[ID_MAX] = {
- [ID_QDEV] = "qdev",
- [ID_BLOCK] = "block",
-};
-
-/*
- * Generates an ID of the form PREFIX SUBSYSTEM NUMBER
- * where:
- *
- * - PREFIX is the reserved character '#'
- * - SUBSYSTEM identifies the subsystem creating the ID
- * - NUMBER is a decimal number unique within SUBSYSTEM.
- *
- * Example: "#block146"
- *
- * Note that these IDs do not satisfy id_wellformed().
- *
- * The caller is responsible for freeing the returned string with g_free()
- */
-char *id_generate(IdSubSystems id)
-{
- static uint64_t id_counters[ID_MAX];
- uint32_t rnd;
-
- assert(id < ARRAY_SIZE(id_subsys_str));
- assert(id_subsys_str[id]);
-
- rnd = g_random_int_range(0, 100);
-
- return g_strdup_printf("%c%s%" PRIu64 "%02" PRId32, ID_SPECIAL_CHAR,
- id_subsys_str[id],
- id_counters[id]++,
- rnd);
-}
diff --git a/qemu/util/iov.c b/qemu/util/iov.c
deleted file mode 100644
index 003fcce66..000000000
--- a/qemu/util/iov.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Helpers for getting linearized buffers from iov / filling buffers into iovs
- *
- * Copyright IBM, Corp. 2007, 2008
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * Author(s):
- * Anthony Liguori <aliguori@us.ibm.com>
- * Amit Shah <amit.shah@redhat.com>
- * Michael Tokarev <mjt@tls.msk.ru>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/iov.h"
-#include "qemu/sockets.h"
-#include "qemu/cutils.h"
-
-size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
- size_t offset, const void *buf, size_t bytes)
-{
- size_t done;
- unsigned int i;
- for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
- if (offset < iov[i].iov_len) {
- size_t len = MIN(iov[i].iov_len - offset, bytes - done);
- memcpy(iov[i].iov_base + offset, buf + done, len);
- done += len;
- offset = 0;
- } else {
- offset -= iov[i].iov_len;
- }
- }
- assert(offset == 0);
- return done;
-}
-
-size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
- size_t offset, void *buf, size_t bytes)
-{
- size_t done;
- unsigned int i;
- for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
- if (offset < iov[i].iov_len) {
- size_t len = MIN(iov[i].iov_len - offset, bytes - done);
- memcpy(buf + done, iov[i].iov_base + offset, len);
- done += len;
- offset = 0;
- } else {
- offset -= iov[i].iov_len;
- }
- }
- assert(offset == 0);
- return done;
-}
-
-size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
- size_t offset, int fillc, size_t bytes)
-{
- size_t done;
- unsigned int i;
- for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
- if (offset < iov[i].iov_len) {
- size_t len = MIN(iov[i].iov_len - offset, bytes - done);
- memset(iov[i].iov_base + offset, fillc, len);
- done += len;
- offset = 0;
- } else {
- offset -= iov[i].iov_len;
- }
- }
- assert(offset == 0);
- return done;
-}
-
-size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
-{
- size_t len;
- unsigned int i;
-
- len = 0;
- for (i = 0; i < iov_cnt; i++) {
- len += iov[i].iov_len;
- }
- return len;
-}
-
-/* helper function for iov_send_recv() */
-static ssize_t
-do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
-{
-#ifdef CONFIG_POSIX
- ssize_t ret;
- struct msghdr msg;
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = iov;
- msg.msg_iovlen = iov_cnt;
- do {
- ret = do_send
- ? sendmsg(sockfd, &msg, 0)
- : recvmsg(sockfd, &msg, 0);
- } while (ret < 0 && errno == EINTR);
- return ret;
-#else
- /* else send piece-by-piece */
- /*XXX Note: windows has WSASend() and WSARecv() */
- unsigned i = 0;
- ssize_t ret = 0;
- while (i < iov_cnt) {
- ssize_t r = do_send
- ? send(sockfd, iov[i].iov_base, iov[i].iov_len, 0)
- : recv(sockfd, iov[i].iov_base, iov[i].iov_len, 0);
- if (r > 0) {
- ret += r;
- } else if (!r) {
- break;
- } else if (errno == EINTR) {
- continue;
- } else {
- /* else it is some "other" error,
- * only return if there was no data processed. */
- if (ret == 0) {
- ret = -1;
- }
- break;
- }
- i++;
- }
- return ret;
-#endif
-}
-
-ssize_t iov_send_recv(int sockfd, const struct iovec *_iov, unsigned iov_cnt,
- size_t offset, size_t bytes,
- bool do_send)
-{
- ssize_t total = 0;
- ssize_t ret;
- size_t orig_len, tail;
- unsigned niov;
- struct iovec *local_iov, *iov;
-
- if (bytes <= 0) {
- return 0;
- }
-
- local_iov = g_new0(struct iovec, iov_cnt);
- iov_copy(local_iov, iov_cnt, _iov, iov_cnt, offset, bytes);
- offset = 0;
- iov = local_iov;
-
- while (bytes > 0) {
- /* Find the start position, skipping `offset' bytes:
- * first, skip all full-sized vector elements, */
- for (niov = 0; niov < iov_cnt && offset >= iov[niov].iov_len; ++niov) {
- offset -= iov[niov].iov_len;
- }
-
- /* niov == iov_cnt would only be valid if bytes == 0, which
- * we already ruled out in the loop condition. */
- assert(niov < iov_cnt);
- iov += niov;
- iov_cnt -= niov;
-
- if (offset) {
- /* second, skip `offset' bytes from the (now) first element,
- * undo it on exit */
- iov[0].iov_base += offset;
- iov[0].iov_len -= offset;
- }
- /* Find the end position skipping `bytes' bytes: */
- /* first, skip all full-sized elements */
- tail = bytes;
- for (niov = 0; niov < iov_cnt && iov[niov].iov_len <= tail; ++niov) {
- tail -= iov[niov].iov_len;
- }
- if (tail) {
- /* second, fixup the last element, and remember the original
- * length */
- assert(niov < iov_cnt);
- assert(iov[niov].iov_len > tail);
- orig_len = iov[niov].iov_len;
- iov[niov++].iov_len = tail;
- ret = do_send_recv(sockfd, iov, niov, do_send);
- /* Undo the changes above before checking for errors */
- iov[niov-1].iov_len = orig_len;
- } else {
- ret = do_send_recv(sockfd, iov, niov, do_send);
- }
- if (offset) {
- iov[0].iov_base -= offset;
- iov[0].iov_len += offset;
- }
-
- if (ret < 0) {
- assert(errno != EINTR);
- g_free(local_iov);
- if (errno == EAGAIN && total > 0) {
- return total;
- }
- return -1;
- }
-
- if (ret == 0 && !do_send) {
- /* recv returns 0 when the peer has performed an orderly
- * shutdown. */
- break;
- }
-
- /* Prepare for the next iteration */
- offset += ret;
- total += ret;
- bytes -= ret;
- }
-
- g_free(local_iov);
- return total;
-}
-
-
-void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
- FILE *fp, const char *prefix, size_t limit)
-{
- int v;
- size_t size = 0;
- char *buf;
-
- for (v = 0; v < iov_cnt; v++) {
- size += iov[v].iov_len;
- }
- size = size > limit ? limit : size;
- buf = g_malloc(size);
- iov_to_buf(iov, iov_cnt, 0, buf, size);
- qemu_hexdump(buf, fp, prefix, size);
- g_free(buf);
-}
-
-unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
- const struct iovec *iov, unsigned int iov_cnt,
- size_t offset, size_t bytes)
-{
- size_t len;
- unsigned int i, j;
- for (i = 0, j = 0; i < iov_cnt && j < dst_iov_cnt && bytes; i++) {
- if (offset >= iov[i].iov_len) {
- offset -= iov[i].iov_len;
- continue;
- }
- len = MIN(bytes, iov[i].iov_len - offset);
-
- dst_iov[j].iov_base = iov[i].iov_base + offset;
- dst_iov[j].iov_len = len;
- j++;
- bytes -= len;
- offset = 0;
- }
- assert(offset == 0);
- return j;
-}
-
-/* io vectors */
-
-void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
-{
- qiov->iov = g_new(struct iovec, alloc_hint);
- qiov->niov = 0;
- qiov->nalloc = alloc_hint;
- qiov->size = 0;
-}
-
-void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
-{
- int i;
-
- qiov->iov = iov;
- qiov->niov = niov;
- qiov->nalloc = -1;
- qiov->size = 0;
- for (i = 0; i < niov; i++)
- qiov->size += iov[i].iov_len;
-}
-
-void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
-{
- assert(qiov->nalloc != -1);
-
- if (qiov->niov == qiov->nalloc) {
- qiov->nalloc = 2 * qiov->nalloc + 1;
- qiov->iov = g_renew(struct iovec, qiov->iov, qiov->nalloc);
- }
- qiov->iov[qiov->niov].iov_base = base;
- qiov->iov[qiov->niov].iov_len = len;
- qiov->size += len;
- ++qiov->niov;
-}
-
-/*
- * Concatenates (partial) iovecs from src_iov to the end of dst.
- * It starts copying after skipping `soffset' bytes at the
- * beginning of src and adds individual vectors from src to
- * dst copies up to `sbytes' bytes total, or up to the end
- * of src_iov if it comes first. This way, it is okay to specify
- * very large value for `sbytes' to indicate "up to the end
- * of src".
- * Only vector pointers are processed, not the actual data buffers.
- */
-size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
- struct iovec *src_iov, unsigned int src_cnt,
- size_t soffset, size_t sbytes)
-{
- int i;
- size_t done;
-
- if (!sbytes) {
- return 0;
- }
- assert(dst->nalloc != -1);
- for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) {
- if (soffset < src_iov[i].iov_len) {
- size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done);
- qemu_iovec_add(dst, src_iov[i].iov_base + soffset, len);
- done += len;
- soffset = 0;
- } else {
- soffset -= src_iov[i].iov_len;
- }
- }
- assert(soffset == 0); /* offset beyond end of src */
-
- return done;
-}
-
-/*
- * Concatenates (partial) iovecs from src to the end of dst.
- * It starts copying after skipping `soffset' bytes at the
- * beginning of src and adds individual vectors from src to
- * dst copies up to `sbytes' bytes total, or up to the end
- * of src if it comes first. This way, it is okay to specify
- * very large value for `sbytes' to indicate "up to the end
- * of src".
- * Only vector pointers are processed, not the actual data buffers.
- */
-void qemu_iovec_concat(QEMUIOVector *dst,
- QEMUIOVector *src, size_t soffset, size_t sbytes)
-{
- qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
-}
-
-/*
- * Check if the contents of the iovecs are all zero
- */
-bool qemu_iovec_is_zero(QEMUIOVector *qiov)
-{
- int i;
- for (i = 0; i < qiov->niov; i++) {
- size_t offs = QEMU_ALIGN_DOWN(qiov->iov[i].iov_len, 4 * sizeof(long));
- uint8_t *ptr = qiov->iov[i].iov_base;
- if (offs && !buffer_is_zero(qiov->iov[i].iov_base, offs)) {
- return false;
- }
- for (; offs < qiov->iov[i].iov_len; offs++) {
- if (ptr[offs]) {
- return false;
- }
- }
- }
- return true;
-}
-
-void qemu_iovec_destroy(QEMUIOVector *qiov)
-{
- assert(qiov->nalloc != -1);
-
- qemu_iovec_reset(qiov);
- g_free(qiov->iov);
- qiov->nalloc = 0;
- qiov->iov = NULL;
-}
-
-void qemu_iovec_reset(QEMUIOVector *qiov)
-{
- assert(qiov->nalloc != -1);
-
- qiov->niov = 0;
- qiov->size = 0;
-}
-
-size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
- void *buf, size_t bytes)
-{
- return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
-}
-
-size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
- const void *buf, size_t bytes)
-{
- return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
-}
-
-size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
- int fillc, size_t bytes)
-{
- return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
-}
-
-/**
- * Check that I/O vector contents are identical
- *
- * The IO vectors must have the same structure (same length of all parts).
- * A typical usage is to compare vectors created with qemu_iovec_clone().
- *
- * @a: I/O vector
- * @b: I/O vector
- * @ret: Offset to first mismatching byte or -1 if match
- */
-ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
-{
- int i;
- ssize_t offset = 0;
-
- assert(a->niov == b->niov);
- for (i = 0; i < a->niov; i++) {
- size_t len = 0;
- uint8_t *p = (uint8_t *)a->iov[i].iov_base;
- uint8_t *q = (uint8_t *)b->iov[i].iov_base;
-
- assert(a->iov[i].iov_len == b->iov[i].iov_len);
- while (len < a->iov[i].iov_len && *p++ == *q++) {
- len++;
- }
-
- offset += len;
-
- if (len != a->iov[i].iov_len) {
- return offset;
- }
- }
- return -1;
-}
-
-typedef struct {
- int src_index;
- struct iovec *src_iov;
- void *dest_base;
-} IOVectorSortElem;
-
-static int sortelem_cmp_src_base(const void *a, const void *b)
-{
- const IOVectorSortElem *elem_a = a;
- const IOVectorSortElem *elem_b = b;
-
- /* Don't overflow */
- if (elem_a->src_iov->iov_base < elem_b->src_iov->iov_base) {
- return -1;
- } else if (elem_a->src_iov->iov_base > elem_b->src_iov->iov_base) {
- return 1;
- } else {
- return 0;
- }
-}
-
-static int sortelem_cmp_src_index(const void *a, const void *b)
-{
- const IOVectorSortElem *elem_a = a;
- const IOVectorSortElem *elem_b = b;
-
- return elem_a->src_index - elem_b->src_index;
-}
-
-/**
- * Copy contents of I/O vector
- *
- * The relative relationships of overlapping iovecs are preserved. This is
- * necessary to ensure identical semantics in the cloned I/O vector.
- */
-void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf)
-{
- IOVectorSortElem sortelems[src->niov];
- void *last_end;
- int i;
-
- /* Sort by source iovecs by base address */
- for (i = 0; i < src->niov; i++) {
- sortelems[i].src_index = i;
- sortelems[i].src_iov = &src->iov[i];
- }
- qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_base);
-
- /* Allocate buffer space taking into account overlapping iovecs */
- last_end = NULL;
- for (i = 0; i < src->niov; i++) {
- struct iovec *cur = sortelems[i].src_iov;
- ptrdiff_t rewind = 0;
-
- /* Detect overlap */
- if (last_end && last_end > cur->iov_base) {
- rewind = last_end - cur->iov_base;
- }
-
- sortelems[i].dest_base = buf - rewind;
- buf += cur->iov_len - MIN(rewind, cur->iov_len);
- last_end = MAX(cur->iov_base + cur->iov_len, last_end);
- }
-
- /* Sort by source iovec index and build destination iovec */
- qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_index);
- for (i = 0; i < src->niov; i++) {
- qemu_iovec_add(dest, sortelems[i].dest_base, src->iov[i].iov_len);
- }
-}
-
-size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt,
- size_t bytes)
-{
- size_t total = 0;
- struct iovec *cur;
-
- for (cur = *iov; *iov_cnt > 0; cur++) {
- if (cur->iov_len > bytes) {
- cur->iov_base += bytes;
- cur->iov_len -= bytes;
- total += bytes;
- break;
- }
-
- bytes -= cur->iov_len;
- total += cur->iov_len;
- *iov_cnt -= 1;
- }
-
- *iov = cur;
- return total;
-}
-
-size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
- size_t bytes)
-{
- size_t total = 0;
- struct iovec *cur;
-
- if (*iov_cnt == 0) {
- return 0;
- }
-
- cur = iov + (*iov_cnt - 1);
-
- while (*iov_cnt > 0) {
- if (cur->iov_len > bytes) {
- cur->iov_len -= bytes;
- total += bytes;
- break;
- }
-
- bytes -= cur->iov_len;
- total += cur->iov_len;
- cur--;
- *iov_cnt -= 1;
- }
-
- return total;
-}
-
-void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes)
-{
- size_t total;
- unsigned int niov = qiov->niov;
-
- assert(qiov->size >= bytes);
- total = iov_discard_back(qiov->iov, &niov, bytes);
- assert(total == bytes);
-
- qiov->niov = niov;
- qiov->size -= bytes;
-}
diff --git a/qemu/util/log.c b/qemu/util/log.c
deleted file mode 100644
index 1857730dc..000000000
--- a/qemu/util/log.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Logging support
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/log.h"
-#include "qemu/range.h"
-#include "qemu/error-report.h"
-#include "qemu/cutils.h"
-#include "trace/control.h"
-
-static char *logfilename;
-FILE *qemu_logfile;
-int qemu_loglevel;
-static int log_append = 0;
-static GArray *debug_regions;
-
-void qemu_log(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- if (qemu_logfile) {
- vfprintf(qemu_logfile, fmt, ap);
- }
- va_end(ap);
-}
-
-/* enable or disable low levels log */
-void do_qemu_set_log(int log_flags, bool use_own_buffers)
-{
- qemu_loglevel = log_flags;
-#ifdef CONFIG_TRACE_LOG
- qemu_loglevel |= LOG_TRACE;
-#endif
- if (!qemu_logfile &&
- (is_daemonized() ? logfilename != NULL : qemu_loglevel)) {
- if (logfilename) {
- qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
- if (!qemu_logfile) {
- perror(logfilename);
- _exit(1);
- }
- /* In case we are a daemon redirect stderr to logfile */
- if (is_daemonized()) {
- dup2(fileno(qemu_logfile), STDERR_FILENO);
- fclose(qemu_logfile);
- /* This will skip closing logfile in qemu_log_close() */
- qemu_logfile = stderr;
- }
- } else {
- /* Default to stderr if no log file specified */
- assert(!is_daemonized());
- qemu_logfile = stderr;
- }
- /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
- if (use_own_buffers) {
- static char logfile_buf[4096];
-
- setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
- } else {
-#if defined(_WIN32)
- /* Win32 doesn't support line-buffering, so use unbuffered output. */
- setvbuf(qemu_logfile, NULL, _IONBF, 0);
-#else
- setvbuf(qemu_logfile, NULL, _IOLBF, 0);
-#endif
- log_append = 1;
- }
- }
- if (qemu_logfile &&
- (is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
- qemu_log_close();
- }
-}
-/*
- * Allow the user to include %d in their logfile which will be
- * substituted with the current PID. This is useful for debugging many
- * nested linux-user tasks but will result in lots of logs.
- */
-void qemu_set_log_filename(const char *filename)
-{
- char *pidstr;
- g_free(logfilename);
-
- pidstr = strstr(filename, "%");
- if (pidstr) {
- /* We only accept one %d, no other format strings */
- if (pidstr[1] != 'd' || strchr(pidstr + 2, '%')) {
- error_report("Bad logfile format: %s", filename);
- logfilename = NULL;
- } else {
- logfilename = g_strdup_printf(filename, getpid());
- }
- } else {
- logfilename = g_strdup(filename);
- }
- qemu_log_close();
- qemu_set_log(qemu_loglevel);
-}
-
-/* Returns true if addr is in our debug filter or no filter defined
- */
-bool qemu_log_in_addr_range(uint64_t addr)
-{
- if (debug_regions) {
- int i = 0;
- for (i = 0; i < debug_regions->len; i++) {
- struct Range *range = &g_array_index(debug_regions, Range, i);
- if (addr >= range->begin && addr <= range->end) {
- return true;
- }
- }
- return false;
- } else {
- return true;
- }
-}
-
-
-void qemu_set_dfilter_ranges(const char *filter_spec)
-{
- gchar **ranges = g_strsplit(filter_spec, ",", 0);
- if (ranges) {
- gchar **next = ranges;
- gchar *r = *next++;
- debug_regions = g_array_sized_new(FALSE, FALSE,
- sizeof(Range), g_strv_length(ranges));
- while (r) {
- char *range_op = strstr(r, "-");
- char *r2 = range_op ? range_op + 1 : NULL;
- if (!range_op) {
- range_op = strstr(r, "+");
- r2 = range_op ? range_op + 1 : NULL;
- }
- if (!range_op) {
- range_op = strstr(r, "..");
- r2 = range_op ? range_op + 2 : NULL;
- }
- if (range_op) {
- const char *e = NULL;
- uint64_t r1val, r2val;
-
- if ((qemu_strtoull(r, &e, 0, &r1val) == 0) &&
- (qemu_strtoull(r2, NULL, 0, &r2val) == 0) &&
- r2val > 0) {
- struct Range range;
-
- g_assert(e == range_op);
-
- switch (*range_op) {
- case '+':
- {
- range.begin = r1val;
- range.end = r1val + (r2val - 1);
- break;
- }
- case '-':
- {
- range.end = r1val;
- range.begin = r1val - (r2val - 1);
- break;
- }
- case '.':
- range.begin = r1val;
- range.end = r2val;
- break;
- default:
- g_assert_not_reached();
- }
- g_array_append_val(debug_regions, range);
-
- } else {
- g_error("Failed to parse range in: %s", r);
- }
- } else {
- g_error("Bad range specifier in: %s", r);
- }
- r = *next++;
- }
- g_strfreev(ranges);
- }
-}
-
-/* fflush() the log file */
-void qemu_log_flush(void)
-{
- fflush(qemu_logfile);
-}
-
-/* Close the log file */
-void qemu_log_close(void)
-{
- if (qemu_logfile) {
- if (qemu_logfile != stderr) {
- fclose(qemu_logfile);
- }
- qemu_logfile = NULL;
- }
-}
-
-const QEMULogItem qemu_log_items[] = {
- { CPU_LOG_TB_OUT_ASM, "out_asm",
- "show generated host assembly code for each compiled TB" },
- { CPU_LOG_TB_IN_ASM, "in_asm",
- "show target assembly code for each compiled TB" },
- { CPU_LOG_TB_OP, "op",
- "show micro ops for each compiled TB" },
- { CPU_LOG_TB_OP_OPT, "op_opt",
- "show micro ops (x86 only: before eflags optimization) and\n"
- "after liveness analysis" },
- { CPU_LOG_INT, "int",
- "show interrupts/exceptions in short format" },
- { CPU_LOG_EXEC, "exec",
- "show trace before each executed TB (lots of logs)" },
- { CPU_LOG_TB_CPU, "cpu",
- "show CPU registers before entering a TB (lots of logs)" },
- { CPU_LOG_MMU, "mmu",
- "log MMU-related activities" },
- { CPU_LOG_PCALL, "pcall",
- "x86 only: show protected mode far calls/returns/exceptions" },
- { CPU_LOG_RESET, "cpu_reset",
- "show CPU state before CPU resets" },
- { LOG_UNIMP, "unimp",
- "log unimplemented functionality" },
- { LOG_GUEST_ERROR, "guest_errors",
- "log when the guest OS does something invalid (eg accessing a\n"
- "non-existent register)" },
- { CPU_LOG_PAGE, "page",
- "dump pages at beginning of user mode emulation" },
- { CPU_LOG_TB_NOCHAIN, "nochain",
- "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n"
- "complete traces" },
- { 0, NULL, NULL },
-};
-
-static int cmp1(const char *s1, int n, const char *s2)
-{
- if (strlen(s2) != n) {
- return 0;
- }
- return memcmp(s1, s2, n) == 0;
-}
-
-/* takes a comma separated list of log masks. Return 0 if error. */
-int qemu_str_to_log_mask(const char *str)
-{
- const QEMULogItem *item;
- int mask;
- const char *p, *p1;
-
- p = str;
- mask = 0;
- for (;;) {
- p1 = strchr(p, ',');
- if (!p1) {
- p1 = p + strlen(p);
- }
- if (cmp1(p,p1-p,"all")) {
- for (item = qemu_log_items; item->mask != 0; item++) {
- mask |= item->mask;
- }
-#ifdef CONFIG_TRACE_LOG
- } else if (strncmp(p, "trace:", 6) == 0 && p + 6 != p1) {
- trace_enable_events(p + 6);
- mask |= LOG_TRACE;
-#endif
- } else {
- for (item = qemu_log_items; item->mask != 0; item++) {
- if (cmp1(p, p1 - p, item->name)) {
- goto found;
- }
- }
- return 0;
- found:
- mask |= item->mask;
- }
- if (*p1 != ',') {
- break;
- }
- p = p1 + 1;
- }
- return mask;
-}
-
-void qemu_print_log_usage(FILE *f)
-{
- const QEMULogItem *item;
- fprintf(f, "Log items (comma separated):\n");
- for (item = qemu_log_items; item->mask != 0; item++) {
- fprintf(f, "%-15s %s\n", item->name, item->help);
- }
-#ifdef CONFIG_TRACE_LOG
- fprintf(f, "trace:PATTERN enable trace events\n");
- fprintf(f, "\nUse \"-d trace:help\" to get a list of trace events.\n\n");
-#endif
-}
diff --git a/qemu/util/memfd.c b/qemu/util/memfd.c
deleted file mode 100644
index 7c406914c..000000000
--- a/qemu/util/memfd.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * memfd.c
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * QEMU library functions on POSIX which are shared between QEMU and
- * the QEMU tools.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-
-#include <glib.h>
-#include <glib/gprintf.h>
-
-#include <sys/mman.h>
-
-#include "qemu/memfd.h"
-
-#ifdef CONFIG_MEMFD
-#include <sys/memfd.h>
-#elif defined CONFIG_LINUX
-#include <sys/syscall.h>
-#include <asm/unistd.h>
-
-static int memfd_create(const char *name, unsigned int flags)
-{
-#ifdef __NR_memfd_create
- return syscall(__NR_memfd_create, name, flags);
-#else
- return -1;
-#endif
-}
-#endif
-
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-
-#ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
-#endif
-
-/*
- * This is a best-effort helper for shared memory allocation, with
- * optional sealing. The helper will do his best to allocate using
- * memfd with sealing, but may fallback on other methods without
- * sealing.
- */
-void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
- int *fd)
-{
- void *ptr;
- int mfd = -1;
-
- *fd = -1;
-
-#ifdef CONFIG_LINUX
- if (seals) {
- mfd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
- }
-
- if (mfd == -1) {
- /* some systems have memfd without sealing */
- mfd = memfd_create(name, MFD_CLOEXEC);
- seals = 0;
- }
-#endif
-
- if (mfd != -1) {
- if (ftruncate(mfd, size) == -1) {
- perror("ftruncate");
- close(mfd);
- return NULL;
- }
-
- if (seals && fcntl(mfd, F_ADD_SEALS, seals) == -1) {
- perror("fcntl");
- close(mfd);
- return NULL;
- }
- } else {
- const char *tmpdir = g_get_tmp_dir();
- gchar *fname;
-
- fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir);
- mfd = mkstemp(fname);
- unlink(fname);
- g_free(fname);
-
- if (mfd == -1) {
- perror("mkstemp");
- return NULL;
- }
-
- if (ftruncate(mfd, size) == -1) {
- perror("ftruncate");
- close(mfd);
- return NULL;
- }
- }
-
- ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0);
- if (ptr == MAP_FAILED) {
- perror("mmap");
- close(mfd);
- return NULL;
- }
-
- *fd = mfd;
- return ptr;
-}
-
-void qemu_memfd_free(void *ptr, size_t size, int fd)
-{
- if (ptr) {
- munmap(ptr, size);
- }
-
- if (fd != -1) {
- close(fd);
- }
-}
-
-enum {
- MEMFD_KO,
- MEMFD_OK,
- MEMFD_TODO
-};
-
-bool qemu_memfd_check(void)
-{
- static int memfd_check = MEMFD_TODO;
-
- if (memfd_check == MEMFD_TODO) {
- int fd;
- void *ptr;
-
- ptr = qemu_memfd_alloc("test", 4096, 0, &fd);
- memfd_check = ptr ? MEMFD_OK : MEMFD_KO;
- qemu_memfd_free(ptr, 4096, fd);
- }
-
- return memfd_check == MEMFD_OK;
-}
diff --git a/qemu/util/mmap-alloc.c b/qemu/util/mmap-alloc.c
deleted file mode 100644
index 0b4cc7f7f..000000000
--- a/qemu/util/mmap-alloc.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Support for RAM backed by mmaped host memory.
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * Authors:
- * Michael S. Tsirkin <mst@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * later. See the COPYING file in the top-level directory.
- */
-#include "qemu/osdep.h"
-#include <qemu/mmap-alloc.h>
-#include <sys/mman.h>
-
-#define HUGETLBFS_MAGIC 0x958458f6
-
-#ifdef CONFIG_LINUX
-#include <sys/vfs.h>
-#endif
-
-size_t qemu_fd_getpagesize(int fd)
-{
-#ifdef CONFIG_LINUX
- struct statfs fs;
- int ret;
-
- if (fd != -1) {
- do {
- ret = fstatfs(fd, &fs);
- } while (ret != 0 && errno == EINTR);
-
- if (ret == 0 && fs.f_type == HUGETLBFS_MAGIC) {
- return fs.f_bsize;
- }
- }
-#endif
-
- return getpagesize();
-}
-
-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
-{
- /*
- * Note: this always allocates at least one extra page of virtual address
- * space, even if size is already aligned.
- */
- size_t total = size + align;
-#if defined(__powerpc64__) && defined(__linux__)
- /* On ppc64 mappings in the same segment (aka slice) must share the same
- * page size. Since we will be re-allocating part of this segment
- * from the supplied fd, we should make sure to use the same page size, to
- * this end we mmap the supplied fd. In this case, set MAP_NORESERVE to
- * avoid allocating backing store memory.
- * We do this unless we are using the system page size, in which case
- * anonymous memory is OK.
- */
- int anonfd = fd == -1 || qemu_fd_getpagesize(fd) == getpagesize() ? -1 : fd;
- int flags = anonfd == -1 ? MAP_ANONYMOUS : MAP_NORESERVE;
- void *ptr = mmap(0, total, PROT_NONE, flags | MAP_PRIVATE, anonfd, 0);
-#else
- void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-#endif
- size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
- void *ptr1;
-
- if (ptr == MAP_FAILED) {
- return MAP_FAILED;
- }
-
- /* Make sure align is a power of 2 */
- assert(!(align & (align - 1)));
- /* Always align to host page size */
- assert(align >= getpagesize());
-
- ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE,
- MAP_FIXED |
- (fd == -1 ? MAP_ANONYMOUS : 0) |
- (shared ? MAP_SHARED : MAP_PRIVATE),
- fd, 0);
- if (ptr1 == MAP_FAILED) {
- munmap(ptr, total);
- return MAP_FAILED;
- }
-
- ptr += offset;
- total -= offset;
-
- if (offset > 0) {
- munmap(ptr - offset, offset);
- }
-
- /*
- * Leave a single PROT_NONE page allocated after the RAM block, to serve as
- * a guard page guarding against potential buffer overflows.
- */
- if (total > size + getpagesize()) {
- munmap(ptr + size + getpagesize(), total - size - getpagesize());
- }
-
- return ptr;
-}
-
-void qemu_ram_munmap(void *ptr, size_t size)
-{
- if (ptr) {
- /* Unmap both the RAM block and the guard page */
- munmap(ptr, size + getpagesize());
- }
-}
diff --git a/qemu/util/module.c b/qemu/util/module.c
deleted file mode 100644
index ce058aef6..000000000
--- a/qemu/util/module.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * QEMU Module Infrastructure
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#ifdef CONFIG_MODULES
-#include <gmodule.h>
-#endif
-#include "qemu/queue.h"
-#include "qemu/module.h"
-
-typedef struct ModuleEntry
-{
- void (*init)(void);
- QTAILQ_ENTRY(ModuleEntry) node;
- module_init_type type;
-} ModuleEntry;
-
-typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
-
-static ModuleTypeList init_type_list[MODULE_INIT_MAX];
-
-static ModuleTypeList dso_init_list;
-
-static void init_lists(void)
-{
- static int inited;
- int i;
-
- if (inited) {
- return;
- }
-
- for (i = 0; i < MODULE_INIT_MAX; i++) {
- QTAILQ_INIT(&init_type_list[i]);
- }
-
- QTAILQ_INIT(&dso_init_list);
-
- inited = 1;
-}
-
-
-static ModuleTypeList *find_type(module_init_type type)
-{
- ModuleTypeList *l;
-
- init_lists();
-
- l = &init_type_list[type];
-
- return l;
-}
-
-void register_module_init(void (*fn)(void), module_init_type type)
-{
- ModuleEntry *e;
- ModuleTypeList *l;
-
- e = g_malloc0(sizeof(*e));
- e->init = fn;
- e->type = type;
-
- l = find_type(type);
-
- QTAILQ_INSERT_TAIL(l, e, node);
-}
-
-void register_dso_module_init(void (*fn)(void), module_init_type type)
-{
- ModuleEntry *e;
-
- init_lists();
-
- e = g_malloc0(sizeof(*e));
- e->init = fn;
- e->type = type;
-
- QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
-}
-
-static void module_load(module_init_type type);
-
-void module_call_init(module_init_type type)
-{
- ModuleTypeList *l;
- ModuleEntry *e;
-
- module_load(type);
- l = find_type(type);
-
- QTAILQ_FOREACH(e, l, node) {
- e->init();
- }
-}
-
-#ifdef CONFIG_MODULES
-static int module_load_file(const char *fname)
-{
- GModule *g_module;
- void (*sym)(void);
- const char *dsosuf = HOST_DSOSUF;
- int len = strlen(fname);
- int suf_len = strlen(dsosuf);
- ModuleEntry *e, *next;
- int ret;
-
- if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) {
- /* wrong suffix */
- ret = -EINVAL;
- goto out;
- }
- if (access(fname, F_OK)) {
- ret = -ENOENT;
- goto out;
- }
-
- assert(QTAILQ_EMPTY(&dso_init_list));
-
- g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
- if (!g_module) {
- fprintf(stderr, "Failed to open module: %s\n",
- g_module_error());
- ret = -EINVAL;
- goto out;
- }
- if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
- fprintf(stderr, "Failed to initialize module: %s\n",
- fname);
- /* Print some info if this is a QEMU module (but from different build),
- * this will make debugging user problems easier. */
- if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
- fprintf(stderr,
- "Note: only modules from the same build can be loaded.\n");
- }
- g_module_close(g_module);
- ret = -EINVAL;
- } else {
- QTAILQ_FOREACH(e, &dso_init_list, node) {
- register_module_init(e->init, e->type);
- }
- ret = 0;
- }
-
- QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
- QTAILQ_REMOVE(&dso_init_list, e, node);
- g_free(e);
- }
-out:
- return ret;
-}
-#endif
-
-static void module_load(module_init_type type)
-{
-#ifdef CONFIG_MODULES
- char *fname = NULL;
- const char **mp;
- static const char *block_modules[] = {
- CONFIG_BLOCK_MODULES
- };
- char *exec_dir;
- char *dirs[3];
- int i = 0;
- int ret;
-
- if (!g_module_supported()) {
- fprintf(stderr, "Module is not supported by system.\n");
- return;
- }
-
- switch (type) {
- case MODULE_INIT_BLOCK:
- mp = block_modules;
- break;
- default:
- /* no other types have dynamic modules for now*/
- return;
- }
-
- exec_dir = qemu_get_exec_dir();
- dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
- dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
- dirs[i++] = g_strdup_printf("%s", exec_dir ? : "");
- assert(i == ARRAY_SIZE(dirs));
- g_free(exec_dir);
- exec_dir = NULL;
-
- for ( ; *mp; mp++) {
- for (i = 0; i < ARRAY_SIZE(dirs); i++) {
- fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF);
- ret = module_load_file(fname);
- g_free(fname);
- fname = NULL;
- /* Try loading until loaded a module file */
- if (!ret) {
- break;
- }
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(dirs); i++) {
- g_free(dirs[i]);
- }
-
-#endif
-}
diff --git a/qemu/util/notify.c b/qemu/util/notify.c
deleted file mode 100644
index 06de63a83..000000000
--- a/qemu/util/notify.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Notifier lists
- *
- * Copyright IBM, Corp. 2010
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/notify.h"
-
-void notifier_list_init(NotifierList *list)
-{
- QLIST_INIT(&list->notifiers);
-}
-
-void notifier_list_add(NotifierList *list, Notifier *notifier)
-{
- QLIST_INSERT_HEAD(&list->notifiers, notifier, node);
-}
-
-void notifier_remove(Notifier *notifier)
-{
- QLIST_REMOVE(notifier, node);
-}
-
-void notifier_list_notify(NotifierList *list, void *data)
-{
- Notifier *notifier, *next;
-
- QLIST_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
- notifier->notify(notifier, data);
- }
-}
-
-void notifier_with_return_list_init(NotifierWithReturnList *list)
-{
- QLIST_INIT(&list->notifiers);
-}
-
-void notifier_with_return_list_add(NotifierWithReturnList *list,
- NotifierWithReturn *notifier)
-{
- QLIST_INSERT_HEAD(&list->notifiers, notifier, node);
-}
-
-void notifier_with_return_remove(NotifierWithReturn *notifier)
-{
- QLIST_REMOVE(notifier, node);
-}
-
-int notifier_with_return_list_notify(NotifierWithReturnList *list, void *data)
-{
- NotifierWithReturn *notifier, *next;
- int ret = 0;
-
- QLIST_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
- ret = notifier->notify(notifier, data);
- if (ret != 0) {
- break;
- }
- }
- return ret;
-}
diff --git a/qemu/util/osdep.c b/qemu/util/osdep.c
deleted file mode 100644
index d56d07111..000000000
--- a/qemu/util/osdep.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * QEMU low level functions
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu/osdep.h"
-
-/* Needed early for CONFIG_BSD etc. */
-
-#if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
-#include <sys/mman.h>
-#endif
-
-#ifdef CONFIG_SOLARIS
-#include <sys/statvfs.h>
-/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
- discussion about Solaris header problems */
-extern int madvise(caddr_t, size_t, int);
-#endif
-
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "qemu/sockets.h"
-#include "qemu/error-report.h"
-#include "monitor/monitor.h"
-
-static bool fips_enabled = false;
-
-/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default
- * instead of QEMU_VERSION, so setting hw_version on MachineClass
- * is no longer mandatory.
- *
- * Do NOT change this string, or it will break compatibility on all
- * machine classes that don't set hw_version.
- */
-static const char *hw_version = "2.5+";
-
-int socket_set_cork(int fd, int v)
-{
-#if defined(SOL_TCP) && defined(TCP_CORK)
- return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
-#else
- return 0;
-#endif
-}
-
-int socket_set_nodelay(int fd)
-{
- int v = 1;
- return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
-}
-
-int qemu_madvise(void *addr, size_t len, int advice)
-{
- if (advice == QEMU_MADV_INVALID) {
- errno = EINVAL;
- return -1;
- }
-#if defined(CONFIG_MADVISE)
- return madvise(addr, len, advice);
-#elif defined(CONFIG_POSIX_MADVISE)
- return posix_madvise(addr, len, advice);
-#else
- errno = EINVAL;
- return -1;
-#endif
-}
-
-#ifndef _WIN32
-/*
- * Dups an fd and sets the flags
- */
-static int qemu_dup_flags(int fd, int flags)
-{
- int ret;
- int serrno;
- int dup_flags;
-
-#ifdef F_DUPFD_CLOEXEC
- ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
-#else
- ret = dup(fd);
- if (ret != -1) {
- qemu_set_cloexec(ret);
- }
-#endif
- if (ret == -1) {
- goto fail;
- }
-
- dup_flags = fcntl(ret, F_GETFL);
- if (dup_flags == -1) {
- goto fail;
- }
-
- if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
- errno = EINVAL;
- goto fail;
- }
-
- /* Set/unset flags that we can with fcntl */
- if (fcntl(ret, F_SETFL, flags) == -1) {
- goto fail;
- }
-
- /* Truncate the file in the cases that open() would truncate it */
- if (flags & O_TRUNC ||
- ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
- if (ftruncate(ret, 0) == -1) {
- goto fail;
- }
- }
-
- return ret;
-
-fail:
- serrno = errno;
- if (ret != -1) {
- close(ret);
- }
- errno = serrno;
- return -1;
-}
-
-static int qemu_parse_fdset(const char *param)
-{
- return qemu_parse_fd(param);
-}
-#endif
-
-/*
- * Opens a file with FD_CLOEXEC set
- */
-int qemu_open(const char *name, int flags, ...)
-{
- int ret;
- int mode = 0;
-
-#ifndef _WIN32
- const char *fdset_id_str;
-
- /* Attempt dup of fd from fd set */
- if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
- int64_t fdset_id;
- int fd, dupfd;
-
- fdset_id = qemu_parse_fdset(fdset_id_str);
- if (fdset_id == -1) {
- errno = EINVAL;
- return -1;
- }
-
- fd = monitor_fdset_get_fd(fdset_id, flags);
- if (fd == -1) {
- return -1;
- }
-
- dupfd = qemu_dup_flags(fd, flags);
- if (dupfd == -1) {
- return -1;
- }
-
- ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
- if (ret == -1) {
- close(dupfd);
- errno = EINVAL;
- return -1;
- }
-
- return dupfd;
- }
-#endif
-
- if (flags & O_CREAT) {
- va_list ap;
-
- va_start(ap, flags);
- mode = va_arg(ap, int);
- va_end(ap);
- }
-
-#ifdef O_CLOEXEC
- ret = open(name, flags | O_CLOEXEC, mode);
-#else
- ret = open(name, flags, mode);
- if (ret >= 0) {
- qemu_set_cloexec(ret);
- }
-#endif
-
-#ifdef O_DIRECT
- if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
- error_report("file system may not support O_DIRECT");
- errno = EINVAL; /* in case it was clobbered */
- }
-#endif /* O_DIRECT */
-
- return ret;
-}
-
-int qemu_close(int fd)
-{
- int64_t fdset_id;
-
- /* Close fd that was dup'd from an fdset */
- fdset_id = monitor_fdset_dup_fd_find(fd);
- if (fdset_id != -1) {
- int ret;
-
- ret = close(fd);
- if (ret == 0) {
- monitor_fdset_dup_fd_remove(fd);
- }
-
- return ret;
- }
-
- return close(fd);
-}
-
-/*
- * A variant of write(2) which handles partial write.
- *
- * Return the number of bytes transferred.
- * Set errno if fewer than `count' bytes are written.
- *
- * This function don't work with non-blocking fd's.
- * Any of the possibilities with non-bloking fd's is bad:
- * - return a short write (then name is wrong)
- * - busy wait adding (errno == EAGAIN) to the loop
- */
-ssize_t qemu_write_full(int fd, const void *buf, size_t count)
-{
- ssize_t ret = 0;
- ssize_t total = 0;
-
- while (count) {
- ret = write(fd, buf, count);
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- break;
- }
-
- count -= ret;
- buf += ret;
- total += ret;
- }
-
- return total;
-}
-
-/*
- * Opens a socket with FD_CLOEXEC set
- */
-int qemu_socket(int domain, int type, int protocol)
-{
- int ret;
-
-#ifdef SOCK_CLOEXEC
- ret = socket(domain, type | SOCK_CLOEXEC, protocol);
- if (ret != -1 || errno != EINVAL) {
- return ret;
- }
-#endif
- ret = socket(domain, type, protocol);
- if (ret >= 0) {
- qemu_set_cloexec(ret);
- }
-
- return ret;
-}
-
-/*
- * Accept a connection and set FD_CLOEXEC
- */
-int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- int ret;
-
-#ifdef CONFIG_ACCEPT4
- ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
- if (ret != -1 || errno != ENOSYS) {
- return ret;
- }
-#endif
- ret = accept(s, addr, addrlen);
- if (ret >= 0) {
- qemu_set_cloexec(ret);
- }
-
- return ret;
-}
-
-void qemu_set_hw_version(const char *version)
-{
- hw_version = version;
-}
-
-const char *qemu_hw_version(void)
-{
- return hw_version;
-}
-
-void fips_set_state(bool requested)
-{
-#ifdef __linux__
- if (requested) {
- FILE *fds = fopen("/proc/sys/crypto/fips_enabled", "r");
- if (fds != NULL) {
- fips_enabled = (fgetc(fds) == '1');
- fclose(fds);
- }
- }
-#else
- fips_enabled = false;
-#endif /* __linux__ */
-
-#ifdef _FIPS_DEBUG
- fprintf(stderr, "FIPS mode %s (requested %s)\n",
- (fips_enabled ? "enabled" : "disabled"),
- (requested ? "enabled" : "disabled"));
-#endif
-}
-
-bool fips_get_state(void)
-{
- return fips_enabled;
-}
-
-#ifdef _WIN32
-static void socket_cleanup(void)
-{
- WSACleanup();
-}
-#endif
-
-int socket_init(void)
-{
-#ifdef _WIN32
- WSADATA Data;
- int ret, err;
-
- ret = WSAStartup(MAKEWORD(2, 2), &Data);
- if (ret != 0) {
- err = WSAGetLastError();
- fprintf(stderr, "WSAStartup: %d\n", err);
- return -1;
- }
- atexit(socket_cleanup);
-#endif
- return 0;
-}
-
-#if !GLIB_CHECK_VERSION(2, 31, 0)
-/* Ensure that glib is running in multi-threaded mode
- * Old versions of glib require explicit initialization. Failure to do
- * this results in the single-threaded code paths being taken inside
- * glib. For example, the g_slice allocator will not be thread-safe
- * and cause crashes.
- */
-static void __attribute__((constructor)) thread_init(void)
-{
- if (!g_thread_supported()) {
- g_thread_init(NULL);
- }
-}
-#endif
-
-#ifndef CONFIG_IOVEC
-/* helper function for iov_send_recv() */
-static ssize_t
-readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
-{
- unsigned i = 0;
- ssize_t ret = 0;
- while (i < iov_cnt) {
- ssize_t r = do_write
- ? write(fd, iov[i].iov_base, iov[i].iov_len)
- : read(fd, iov[i].iov_base, iov[i].iov_len);
- if (r > 0) {
- ret += r;
- } else if (!r) {
- break;
- } else if (errno == EINTR) {
- continue;
- } else {
- /* else it is some "other" error,
- * only return if there was no data processed. */
- if (ret == 0) {
- ret = -1;
- }
- break;
- }
- i++;
- }
- return ret;
-}
-
-ssize_t
-readv(int fd, const struct iovec *iov, int iov_cnt)
-{
- return readv_writev(fd, iov, iov_cnt, false);
-}
-
-ssize_t
-writev(int fd, const struct iovec *iov, int iov_cnt)
-{
- return readv_writev(fd, iov, iov_cnt, true);
-}
-#endif
diff --git a/qemu/util/oslib-posix.c b/qemu/util/oslib-posix.c
deleted file mode 100644
index 6cc4b8f00..000000000
--- a/qemu/util/oslib-posix.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * os-posix-lib.c
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- * Copyright (c) 2010 Red Hat, Inc.
- *
- * QEMU library functions on POSIX which are shared between QEMU and
- * the QEMU tools.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if defined(__linux__) && \
- (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__))
- /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
- Valgrind does not support alignments larger than 1 MiB,
- therefore we need special code which handles running on Valgrind. */
-# define QEMU_VMALLOC_ALIGN (512 * 4096)
-#elif defined(__linux__) && defined(__s390x__)
- /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
-# define QEMU_VMALLOC_ALIGN (256 * 4096)
-#else
-# define QEMU_VMALLOC_ALIGN getpagesize()
-#endif
-
-#include "qemu/osdep.h"
-#include <termios.h>
-#include <termios.h>
-
-#include <glib/gprintf.h>
-
-#include "sysemu/sysemu.h"
-#include "trace.h"
-#include "qapi/error.h"
-#include "qemu/sockets.h"
-#include <sys/mman.h>
-#include <libgen.h>
-#include <sys/signal.h>
-#include "qemu/cutils.h"
-
-#ifdef CONFIG_LINUX
-#include <sys/syscall.h>
-#endif
-
-#ifdef __FreeBSD__
-#include <sys/sysctl.h>
-#endif
-
-#include <qemu/mmap-alloc.h>
-
-int qemu_get_thread_id(void)
-{
-#if defined(__linux__)
- return syscall(SYS_gettid);
-#else
- return getpid();
-#endif
-}
-
-int qemu_daemon(int nochdir, int noclose)
-{
- return daemon(nochdir, noclose);
-}
-
-void *qemu_oom_check(void *ptr)
-{
- if (ptr == NULL) {
- fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
- abort();
- }
- return ptr;
-}
-
-void *qemu_try_memalign(size_t alignment, size_t size)
-{
- void *ptr;
-
- if (alignment < sizeof(void*)) {
- alignment = sizeof(void*);
- }
-
-#if defined(_POSIX_C_SOURCE) && !defined(__sun__)
- int ret;
- ret = posix_memalign(&ptr, alignment, size);
- if (ret != 0) {
- errno = ret;
- ptr = NULL;
- }
-#elif defined(CONFIG_BSD)
- ptr = valloc(size);
-#else
- ptr = memalign(alignment, size);
-#endif
- trace_qemu_memalign(alignment, size, ptr);
- return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
-{
- return qemu_oom_check(qemu_try_memalign(alignment, size));
-}
-
-/* alloc shared memory pages */
-void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
-{
- size_t align = QEMU_VMALLOC_ALIGN;
- void *ptr = qemu_ram_mmap(-1, size, align, false);
-
- if (ptr == MAP_FAILED) {
- return NULL;
- }
-
- if (alignment) {
- *alignment = align;
- }
-
- trace_qemu_anon_ram_alloc(size, ptr);
- return ptr;
-}
-
-void qemu_vfree(void *ptr)
-{
- trace_qemu_vfree(ptr);
- free(ptr);
-}
-
-void qemu_anon_ram_free(void *ptr, size_t size)
-{
- trace_qemu_anon_ram_free(ptr, size);
- qemu_ram_munmap(ptr, size);
-}
-
-void qemu_set_block(int fd)
-{
- int f;
- f = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
-}
-
-void qemu_set_nonblock(int fd)
-{
- int f;
- f = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, f | O_NONBLOCK);
-}
-
-int socket_set_fast_reuse(int fd)
-{
- int val = 1, ret;
-
- ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (const char *)&val, sizeof(val));
-
- assert(ret == 0);
-
- return ret;
-}
-
-void qemu_set_cloexec(int fd)
-{
- int f;
- f = fcntl(fd, F_GETFD);
- fcntl(fd, F_SETFD, f | FD_CLOEXEC);
-}
-
-/*
- * Creates a pipe with FD_CLOEXEC set on both file descriptors
- */
-int qemu_pipe(int pipefd[2])
-{
- int ret;
-
-#ifdef CONFIG_PIPE2
- ret = pipe2(pipefd, O_CLOEXEC);
- if (ret != -1 || errno != ENOSYS) {
- return ret;
- }
-#endif
- ret = pipe(pipefd);
- if (ret == 0) {
- qemu_set_cloexec(pipefd[0]);
- qemu_set_cloexec(pipefd[1]);
- }
-
- return ret;
-}
-
-int qemu_utimens(const char *path, const struct timespec *times)
-{
- struct timeval tv[2], tv_now;
- struct stat st;
- int i;
-#ifdef CONFIG_UTIMENSAT
- int ret;
-
- ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
- if (ret != -1 || errno != ENOSYS) {
- return ret;
- }
-#endif
- /* Fallback: use utimes() instead of utimensat() */
-
- /* happy if special cases */
- if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
- return 0;
- }
- if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
- return utimes(path, NULL);
- }
-
- /* prepare for hard cases */
- if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
- gettimeofday(&tv_now, NULL);
- }
- if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
- stat(path, &st);
- }
-
- for (i = 0; i < 2; i++) {
- if (times[i].tv_nsec == UTIME_NOW) {
- tv[i].tv_sec = tv_now.tv_sec;
- tv[i].tv_usec = tv_now.tv_usec;
- } else if (times[i].tv_nsec == UTIME_OMIT) {
- tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
- tv[i].tv_usec = 0;
- } else {
- tv[i].tv_sec = times[i].tv_sec;
- tv[i].tv_usec = times[i].tv_nsec / 1000;
- }
- }
-
- return utimes(path, &tv[0]);
-}
-
-char *
-qemu_get_local_state_pathname(const char *relative_pathname)
-{
- return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR,
- relative_pathname);
-}
-
-void qemu_set_tty_echo(int fd, bool echo)
-{
- struct termios tty;
-
- tcgetattr(fd, &tty);
-
- if (echo) {
- tty.c_lflag |= ECHO | ECHONL | ICANON | IEXTEN;
- } else {
- tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
- }
-
- tcsetattr(fd, TCSANOW, &tty);
-}
-
-static char exec_dir[PATH_MAX];
-
-void qemu_init_exec_dir(const char *argv0)
-{
- char *dir;
- char *p = NULL;
- char buf[PATH_MAX];
-
- assert(!exec_dir[0]);
-
-#if defined(__linux__)
- {
- int len;
- len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (len > 0) {
- buf[len] = 0;
- p = buf;
- }
- }
-#elif defined(__FreeBSD__)
- {
- static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
- size_t len = sizeof(buf) - 1;
-
- *buf = '\0';
- if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
- *buf) {
- buf[sizeof(buf) - 1] = '\0';
- p = buf;
- }
- }
-#endif
- /* If we don't have any way of figuring out the actual executable
- location then try argv[0]. */
- if (!p) {
- if (!argv0) {
- return;
- }
- p = realpath(argv0, buf);
- if (!p) {
- return;
- }
- }
- dir = dirname(p);
-
- pstrcpy(exec_dir, sizeof(exec_dir), dir);
-}
-
-char *qemu_get_exec_dir(void)
-{
- return g_strdup(exec_dir);
-}
-
-static sigjmp_buf sigjump;
-
-static void sigbus_handler(int signal)
-{
- siglongjmp(sigjump, 1);
-}
-
-void os_mem_prealloc(int fd, char *area, size_t memory)
-{
- int ret;
- struct sigaction act, oldact;
- sigset_t set, oldset;
-
- memset(&act, 0, sizeof(act));
- act.sa_handler = &sigbus_handler;
- act.sa_flags = 0;
-
- ret = sigaction(SIGBUS, &act, &oldact);
- if (ret) {
- perror("os_mem_prealloc: failed to install signal handler");
- exit(1);
- }
-
- /* unblock SIGBUS */
- sigemptyset(&set);
- sigaddset(&set, SIGBUS);
- pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
-
- if (sigsetjmp(sigjump, 1)) {
- fprintf(stderr, "os_mem_prealloc: Insufficient free host memory "
- "pages available to allocate guest RAM\n");
- exit(1);
- } else {
- int i;
- size_t hpagesize = qemu_fd_getpagesize(fd);
- size_t numpages = DIV_ROUND_UP(memory, hpagesize);
-
- /* MAP_POPULATE silently ignores failures */
- for (i = 0; i < numpages; i++) {
- memset(area + (hpagesize * i), 0, 1);
- }
-
- ret = sigaction(SIGBUS, &oldact, NULL);
- if (ret) {
- perror("os_mem_prealloc: failed to reinstall signal handler");
- exit(1);
- }
-
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
- }
-}
-
-
-static struct termios oldtty;
-
-static void term_exit(void)
-{
- tcsetattr(0, TCSANOW, &oldtty);
-}
-
-static void term_init(void)
-{
- struct termios tty;
-
- tcgetattr(0, &tty);
- oldtty = tty;
-
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
- |INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
- tty.c_cflag &= ~(CSIZE|PARENB);
- tty.c_cflag |= CS8;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VTIME] = 0;
-
- tcsetattr(0, TCSANOW, &tty);
-
- atexit(term_exit);
-}
-
-int qemu_read_password(char *buf, int buf_size)
-{
- uint8_t ch;
- int i, ret;
-
- printf("password: ");
- fflush(stdout);
- term_init();
- i = 0;
- for (;;) {
- ret = read(0, &ch, 1);
- if (ret == -1) {
- if (errno == EAGAIN || errno == EINTR) {
- continue;
- } else {
- break;
- }
- } else if (ret == 0) {
- ret = -1;
- break;
- } else {
- if (ch == '\r' ||
- ch == '\n') {
- ret = 0;
- break;
- }
- if (i < (buf_size - 1)) {
- buf[i++] = ch;
- }
- }
- }
- term_exit();
- buf[i] = '\0';
- printf("\n");
- return ret;
-}
-
-
-pid_t qemu_fork(Error **errp)
-{
- sigset_t oldmask, newmask;
- struct sigaction sig_action;
- int saved_errno;
- pid_t pid;
-
- /*
- * Need to block signals now, so that child process can safely
- * kill off caller's signal handlers without a race.
- */
- sigfillset(&newmask);
- if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
- error_setg_errno(errp, errno,
- "cannot block signals");
- return -1;
- }
-
- pid = fork();
- saved_errno = errno;
-
- if (pid < 0) {
- /* attempt to restore signal mask, but ignore failure, to
- * avoid obscuring the fork failure */
- (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
- error_setg_errno(errp, saved_errno,
- "cannot fork child process");
- errno = saved_errno;
- return -1;
- } else if (pid) {
- /* parent process */
-
- /* Restore our original signal mask now that the child is
- * safely running. Only documented failures are EFAULT (not
- * possible, since we are using just-grabbed mask) or EINVAL
- * (not possible, since we are using correct arguments). */
- (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
- } else {
- /* child process */
- size_t i;
-
- /* Clear out all signal handlers from parent so nothing
- * unexpected can happen in our child once we unblock
- * signals */
- sig_action.sa_handler = SIG_DFL;
- sig_action.sa_flags = 0;
- sigemptyset(&sig_action.sa_mask);
-
- for (i = 1; i < NSIG; i++) {
- /* Only possible errors are EFAULT or EINVAL The former
- * won't happen, the latter we expect, so no need to check
- * return value */
- (void)sigaction(i, &sig_action, NULL);
- }
-
- /* Unmask all signals in child, since we've no idea what the
- * caller's done with their signal mask and don't want to
- * propagate that to children */
- sigemptyset(&newmask);
- if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
- Error *local_err = NULL;
- error_setg_errno(&local_err, errno,
- "cannot unblock signals");
- error_report_err(local_err);
- _exit(1);
- }
- }
- return pid;
-}
diff --git a/qemu/util/oslib-win32.c b/qemu/util/oslib-win32.c
deleted file mode 100644
index c926db4a5..000000000
--- a/qemu/util/oslib-win32.c
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * os-win32.c
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- * Copyright (c) 2010-2016 Red Hat, Inc.
- *
- * QEMU library functions for win32 which are shared between QEMU and
- * the QEMU tools.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * The implementation of g_poll (functions poll_rest, g_poll) at the end of
- * this file are based on code from GNOME glib-2 and use a different license,
- * see the license comment there.
- */
-#include "qemu/osdep.h"
-#include <windows.h>
-#include <glib.h>
-#include "qapi/error.h"
-#include "sysemu/sysemu.h"
-#include "qemu/main-loop.h"
-#include "trace.h"
-#include "qemu/sockets.h"
-#include "qemu/cutils.h"
-
-/* this must come after including "trace.h" */
-#include <shlobj.h>
-
-void *qemu_oom_check(void *ptr)
-{
- if (ptr == NULL) {
- fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
- abort();
- }
- return ptr;
-}
-
-void *qemu_try_memalign(size_t alignment, size_t size)
-{
- void *ptr;
-
- if (!size) {
- abort();
- }
- ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
- trace_qemu_memalign(alignment, size, ptr);
- return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
-{
- return qemu_oom_check(qemu_try_memalign(alignment, size));
-}
-
-void *qemu_anon_ram_alloc(size_t size, uint64_t *align)
-{
- void *ptr;
-
- /* FIXME: this is not exactly optimal solution since VirtualAlloc
- has 64Kb granularity, but at least it guarantees us that the
- memory is page aligned. */
- ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
- trace_qemu_anon_ram_alloc(size, ptr);
- return ptr;
-}
-
-void qemu_vfree(void *ptr)
-{
- trace_qemu_vfree(ptr);
- if (ptr) {
- VirtualFree(ptr, 0, MEM_RELEASE);
- }
-}
-
-void qemu_anon_ram_free(void *ptr, size_t size)
-{
- trace_qemu_anon_ram_free(ptr, size);
- if (ptr) {
- VirtualFree(ptr, 0, MEM_RELEASE);
- }
-}
-
-#ifndef CONFIG_LOCALTIME_R
-/* FIXME: add proper locking */
-struct tm *gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *p = gmtime(timep);
- memset(result, 0, sizeof(*result));
- if (p) {
- *result = *p;
- p = result;
- }
- return p;
-}
-
-/* FIXME: add proper locking */
-struct tm *localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *p = localtime(timep);
- memset(result, 0, sizeof(*result));
- if (p) {
- *result = *p;
- p = result;
- }
- return p;
-}
-#endif /* CONFIG_LOCALTIME_R */
-
-void qemu_set_block(int fd)
-{
- unsigned long opt = 0;
- WSAEventSelect(fd, NULL, 0);
- ioctlsocket(fd, FIONBIO, &opt);
-}
-
-void qemu_set_nonblock(int fd)
-{
- unsigned long opt = 1;
- ioctlsocket(fd, FIONBIO, &opt);
- qemu_fd_register(fd);
-}
-
-int socket_set_fast_reuse(int fd)
-{
- /* Enabling the reuse of an endpoint that was used by a socket still in
- * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
- * fast reuse is the default and SO_REUSEADDR does strange things. So we
- * don't have to do anything here. More info can be found at:
- * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
- return 0;
-}
-
-
-static int socket_error(void)
-{
- switch (WSAGetLastError()) {
- case 0:
- return 0;
- case WSAEINTR:
- return EINTR;
- case WSAEINVAL:
- return EINVAL;
- case WSA_INVALID_HANDLE:
- return EBADF;
- case WSA_NOT_ENOUGH_MEMORY:
- return ENOMEM;
- case WSA_INVALID_PARAMETER:
- return EINVAL;
- case WSAENAMETOOLONG:
- return ENAMETOOLONG;
- case WSAENOTEMPTY:
- return ENOTEMPTY;
- case WSAEWOULDBLOCK:
- /* not using EWOULDBLOCK as we don't want code to have
- * to check both EWOULDBLOCK and EAGAIN */
- return EAGAIN;
- case WSAEINPROGRESS:
- return EINPROGRESS;
- case WSAEALREADY:
- return EALREADY;
- case WSAENOTSOCK:
- return ENOTSOCK;
- case WSAEDESTADDRREQ:
- return EDESTADDRREQ;
- case WSAEMSGSIZE:
- return EMSGSIZE;
- case WSAEPROTOTYPE:
- return EPROTOTYPE;
- case WSAENOPROTOOPT:
- return ENOPROTOOPT;
- case WSAEPROTONOSUPPORT:
- return EPROTONOSUPPORT;
- case WSAEOPNOTSUPP:
- return EOPNOTSUPP;
- case WSAEAFNOSUPPORT:
- return EAFNOSUPPORT;
- case WSAEADDRINUSE:
- return EADDRINUSE;
- case WSAEADDRNOTAVAIL:
- return EADDRNOTAVAIL;
- case WSAENETDOWN:
- return ENETDOWN;
- case WSAENETUNREACH:
- return ENETUNREACH;
- case WSAENETRESET:
- return ENETRESET;
- case WSAECONNABORTED:
- return ECONNABORTED;
- case WSAECONNRESET:
- return ECONNRESET;
- case WSAENOBUFS:
- return ENOBUFS;
- case WSAEISCONN:
- return EISCONN;
- case WSAENOTCONN:
- return ENOTCONN;
- case WSAETIMEDOUT:
- return ETIMEDOUT;
- case WSAECONNREFUSED:
- return ECONNREFUSED;
- case WSAELOOP:
- return ELOOP;
- case WSAEHOSTUNREACH:
- return EHOSTUNREACH;
- default:
- return EIO;
- }
-}
-
-int inet_aton(const char *cp, struct in_addr *ia)
-{
- uint32_t addr = inet_addr(cp);
- if (addr == 0xffffffff) {
- return 0;
- }
- ia->s_addr = addr;
- return 1;
-}
-
-void qemu_set_cloexec(int fd)
-{
-}
-
-/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
-#define _W32_FT_OFFSET (116444736000000000ULL)
-
-int qemu_gettimeofday(qemu_timeval *tp)
-{
- union {
- unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
- FILETIME ft;
- } _now;
-
- if(tp) {
- GetSystemTimeAsFileTime (&_now.ft);
- tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
- tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
- }
- /* Always return 0 as per Open Group Base Specifications Issue 6.
- Do not set errno on error. */
- return 0;
-}
-
-int qemu_get_thread_id(void)
-{
- return GetCurrentThreadId();
-}
-
-char *
-qemu_get_local_state_pathname(const char *relative_pathname)
-{
- HRESULT result;
- char base_path[MAX_PATH+1] = "";
-
- result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
- /* SHGFP_TYPE_CURRENT */ 0, base_path);
- if (result != S_OK) {
- /* misconfigured environment */
- g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result);
- abort();
- }
- return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
- relative_pathname);
-}
-
-void qemu_set_tty_echo(int fd, bool echo)
-{
- HANDLE handle = (HANDLE)_get_osfhandle(fd);
- DWORD dwMode = 0;
-
- if (handle == INVALID_HANDLE_VALUE) {
- return;
- }
-
- GetConsoleMode(handle, &dwMode);
-
- if (echo) {
- SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
- } else {
- SetConsoleMode(handle,
- dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
- }
-}
-
-static char exec_dir[PATH_MAX];
-
-void qemu_init_exec_dir(const char *argv0)
-{
-
- char *p;
- char buf[MAX_PATH];
- DWORD len;
-
- len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
- if (len == 0) {
- return;
- }
-
- buf[len] = 0;
- p = buf + len - 1;
- while (p != buf && *p != '\\') {
- p--;
- }
- *p = 0;
- if (access(buf, R_OK) == 0) {
- pstrcpy(exec_dir, sizeof(exec_dir), buf);
- }
-}
-
-char *qemu_get_exec_dir(void)
-{
- return g_strdup(exec_dir);
-}
-
-/*
- * The original implementation of g_poll from glib has a problem on Windows
- * when using timeouts < 10 ms.
- *
- * Whenever g_poll is called with timeout < 10 ms, it does a quick poll instead
- * of wait. This causes significant performance degradation of QEMU.
- *
- * The following code is a copy of the original code from glib/gpoll.c
- * (glib commit 20f4d1820b8d4d0fc4447188e33efffd6d4a88d8 from 2014-02-19).
- * Some debug code was removed and the code was reformatted.
- * All other code modifications are marked with 'QEMU'.
- */
-
-/*
- * gpoll.c: poll(2) abstraction
- * Copyright 1998 Owen Taylor
- * Copyright 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-static int poll_rest(gboolean poll_msgs, HANDLE *handles, gint nhandles,
- GPollFD *fds, guint nfds, gint timeout)
-{
- DWORD ready;
- GPollFD *f;
- int recursed_result;
-
- if (poll_msgs) {
- /* Wait for either messages or handles
- * -> Use MsgWaitForMultipleObjectsEx
- */
- ready = MsgWaitForMultipleObjectsEx(nhandles, handles, timeout,
- QS_ALLINPUT, MWMO_ALERTABLE);
-
- if (ready == WAIT_FAILED) {
- gchar *emsg = g_win32_error_message(GetLastError());
- g_warning("MsgWaitForMultipleObjectsEx failed: %s", emsg);
- g_free(emsg);
- }
- } else if (nhandles == 0) {
- /* No handles to wait for, just the timeout */
- if (timeout == INFINITE) {
- ready = WAIT_FAILED;
- } else {
- SleepEx(timeout, TRUE);
- ready = WAIT_TIMEOUT;
- }
- } else {
- /* Wait for just handles
- * -> Use WaitForMultipleObjectsEx
- */
- ready =
- WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
- if (ready == WAIT_FAILED) {
- gchar *emsg = g_win32_error_message(GetLastError());
- g_warning("WaitForMultipleObjectsEx failed: %s", emsg);
- g_free(emsg);
- }
- }
-
- if (ready == WAIT_FAILED) {
- return -1;
- } else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
- return 0;
- } else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles) {
- for (f = fds; f < &fds[nfds]; ++f) {
- if (f->fd == G_WIN32_MSG_HANDLE && f->events & G_IO_IN) {
- f->revents |= G_IO_IN;
- }
- }
-
- /* If we have a timeout, or no handles to poll, be satisfied
- * with just noticing we have messages waiting.
- */
- if (timeout != 0 || nhandles == 0) {
- return 1;
- }
-
- /* If no timeout and handles to poll, recurse to poll them,
- * too.
- */
- recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
- return (recursed_result == -1) ? -1 : 1 + recursed_result;
- } else if (/* QEMU: removed the following unneeded statement which causes
- * a compiler warning: ready >= WAIT_OBJECT_0 && */
- ready < WAIT_OBJECT_0 + nhandles) {
- for (f = fds; f < &fds[nfds]; ++f) {
- if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
- f->revents = f->events;
- }
- }
-
- /* If no timeout and polling several handles, recurse to poll
- * the rest of them.
- */
- if (timeout == 0 && nhandles > 1) {
- /* Remove the handle that fired */
- int i;
- if (ready < nhandles - 1) {
- for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
- handles[i-1] = handles[i];
- }
- }
- nhandles--;
- recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
- return (recursed_result == -1) ? -1 : 1 + recursed_result;
- }
- return 1;
- }
-
- return 0;
-}
-
-gint g_poll(GPollFD *fds, guint nfds, gint timeout)
-{
- HANDLE handles[MAXIMUM_WAIT_OBJECTS];
- gboolean poll_msgs = FALSE;
- GPollFD *f;
- gint nhandles = 0;
- int retval;
-
- for (f = fds; f < &fds[nfds]; ++f) {
- if (f->fd == G_WIN32_MSG_HANDLE && (f->events & G_IO_IN)) {
- poll_msgs = TRUE;
- } else if (f->fd > 0) {
- /* Don't add the same handle several times into the array, as
- * docs say that is not allowed, even if it actually does seem
- * to work.
- */
- gint i;
-
- for (i = 0; i < nhandles; i++) {
- if (handles[i] == (HANDLE) f->fd) {
- break;
- }
- }
-
- if (i == nhandles) {
- if (nhandles == MAXIMUM_WAIT_OBJECTS) {
- g_warning("Too many handles to wait for!\n");
- break;
- } else {
- handles[nhandles++] = (HANDLE) f->fd;
- }
- }
- }
- }
-
- for (f = fds; f < &fds[nfds]; ++f) {
- f->revents = 0;
- }
-
- if (timeout == -1) {
- timeout = INFINITE;
- }
-
- /* Polling for several things? */
- if (nhandles > 1 || (nhandles > 0 && poll_msgs)) {
- /* First check if one or several of them are immediately
- * available
- */
- retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, 0);
-
- /* If not, and we have a significant timeout, poll again with
- * timeout then. Note that this will return indication for only
- * one event, or only for messages. We ignore timeouts less than
- * ten milliseconds as they are mostly pointless on Windows, the
- * MsgWaitForMultipleObjectsEx() call will timeout right away
- * anyway.
- *
- * Modification for QEMU: replaced timeout >= 10 by timeout > 0.
- */
- if (retval == 0 && (timeout == INFINITE || timeout > 0)) {
- retval = poll_rest(poll_msgs, handles, nhandles,
- fds, nfds, timeout);
- }
- } else {
- /* Just polling for one thing, so no need to check first if
- * available immediately
- */
- retval = poll_rest(poll_msgs, handles, nhandles, fds, nfds, timeout);
- }
-
- if (retval == -1) {
- for (f = fds; f < &fds[nfds]; ++f) {
- f->revents = 0;
- }
- }
-
- return retval;
-}
-
-int getpagesize(void)
-{
- SYSTEM_INFO system_info;
-
- GetSystemInfo(&system_info);
- return system_info.dwPageSize;
-}
-
-void os_mem_prealloc(int fd, char *area, size_t memory)
-{
- int i;
- size_t pagesize = getpagesize();
-
- memory = (memory + pagesize - 1) & -pagesize;
- for (i = 0; i < memory / pagesize; i++) {
- memset(area + pagesize * i, 0, 1);
- }
-}
-
-
-/* XXX: put correct support for win32 */
-int qemu_read_password(char *buf, int buf_size)
-{
- int c, i;
-
- printf("Password: ");
- fflush(stdout);
- i = 0;
- for (;;) {
- c = getchar();
- if (c < 0) {
- buf[i] = '\0';
- return -1;
- } else if (c == '\n') {
- break;
- } else if (i < (buf_size - 1)) {
- buf[i++] = c;
- }
- }
- buf[i] = '\0';
- return 0;
-}
-
-
-pid_t qemu_fork(Error **errp)
-{
- errno = ENOSYS;
- error_setg_errno(errp, errno,
- "cannot fork child process");
- return -1;
-}
-
-
-#undef connect
-int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- int ret;
- ret = connect(sockfd, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef listen
-int qemu_listen_wrap(int sockfd, int backlog)
-{
- int ret;
- ret = listen(sockfd, backlog);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef bind
-int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- int ret;
- ret = bind(sockfd, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef socket
-int qemu_socket_wrap(int domain, int type, int protocol)
-{
- int ret;
- ret = socket(domain, type, protocol);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef accept
-int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
- socklen_t *addrlen)
-{
- int ret;
- ret = accept(sockfd, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef shutdown
-int qemu_shutdown_wrap(int sockfd, int how)
-{
- int ret;
- ret = shutdown(sockfd, how);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef ioctlsocket
-int qemu_ioctlsocket_wrap(int fd, int req, void *val)
-{
- int ret;
- ret = ioctlsocket(fd, req, val);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef closesocket
-int qemu_closesocket_wrap(int fd)
-{
- int ret;
- ret = closesocket(fd);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef getsockopt
-int qemu_getsockopt_wrap(int sockfd, int level, int optname,
- void *optval, socklen_t *optlen)
-{
- int ret;
- ret = getsockopt(sockfd, level, optname, optval, optlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef setsockopt
-int qemu_setsockopt_wrap(int sockfd, int level, int optname,
- const void *optval, socklen_t optlen)
-{
- int ret;
- ret = setsockopt(sockfd, level, optname, optval, optlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef getpeername
-int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,
- socklen_t *addrlen)
-{
- int ret;
- ret = getpeername(sockfd, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef getsockname
-int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,
- socklen_t *addrlen)
-{
- int ret;
- ret = getsockname(sockfd, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef send
-ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)
-{
- int ret;
- ret = send(sockfd, buf, len, flags);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef sendto
-ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
- const struct sockaddr *addr, socklen_t addrlen)
-{
- int ret;
- ret = sendto(sockfd, buf, len, flags, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef recv
-ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)
-{
- int ret;
- ret = recv(sockfd, buf, len, flags);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
-
-
-#undef recvfrom
-ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
- struct sockaddr *addr, socklen_t *addrlen)
-{
- int ret;
- ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);
- if (ret < 0) {
- errno = socket_error();
- }
- return ret;
-}
diff --git a/qemu/util/path.c b/qemu/util/path.c
deleted file mode 100644
index 5479f76c6..000000000
--- a/qemu/util/path.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Code to mangle pathnames into those matching a given prefix.
- eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
-
- The assumption is that this area does not change.
-*/
-#include "qemu/osdep.h"
-#include <sys/param.h>
-#include <dirent.h>
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "qemu/path.h"
-
-struct pathelem
-{
- /* Name of this, eg. lib */
- char *name;
- /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
- char *pathname;
- struct pathelem *parent;
- /* Children */
- unsigned int num_entries;
- struct pathelem *entries[0];
-};
-
-static struct pathelem *base;
-
-/* First N chars of S1 match S2, and S2 is N chars long. */
-static int strneq(const char *s1, unsigned int n, const char *s2)
-{
- unsigned int i;
-
- for (i = 0; i < n; i++)
- if (s1[i] != s2[i])
- return 0;
- return s2[i] == 0;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
- unsigned type);
-
-static struct pathelem *new_entry(const char *root,
- struct pathelem *parent,
- const char *name)
-{
- struct pathelem *new = g_malloc(sizeof(*new));
- new->name = g_strdup(name);
- new->pathname = g_strdup_printf("%s/%s", root, name);
- new->num_entries = 0;
- return new;
-}
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-/* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
-# define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type) \
- ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
-#else
-# define dirent_type(dirent) (1)
-# define is_dir_maybe(type) (type)
-#endif
-
-static struct pathelem *add_dir_maybe(struct pathelem *path)
-{
- DIR *dir;
-
- if ((dir = opendir(path->pathname)) != NULL) {
- struct dirent *dirent;
-
- while ((dirent = readdir(dir)) != NULL) {
- if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
- path = add_entry(path, dirent->d_name, dirent_type(dirent));
- }
- }
- closedir(dir);
- }
- return path;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
- unsigned type)
-{
- struct pathelem **e;
-
- root->num_entries++;
-
- root = g_realloc(root, sizeof(*root)
- + sizeof(root->entries[0])*root->num_entries);
- e = &root->entries[root->num_entries-1];
-
- *e = new_entry(root->pathname, root, name);
- if (is_dir_maybe(type)) {
- *e = add_dir_maybe(*e);
- }
-
- return root;
-}
-
-/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
-static void set_parents(struct pathelem *child, struct pathelem *parent)
-{
- unsigned int i;
-
- child->parent = parent;
- for (i = 0; i < child->num_entries; i++)
- set_parents(child->entries[i], child);
-}
-
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
-{
- unsigned int i, namelen;
-
- name += strspn(name, "/");
- namelen = strcspn(name, "/");
-
- if (namelen == 0)
- return cursor->pathname;
-
- if (strneq(name, namelen, ".."))
- return follow_path(cursor->parent, name + namelen);
-
- if (strneq(name, namelen, "."))
- return follow_path(cursor, name + namelen);
-
- for (i = 0; i < cursor->num_entries; i++)
- if (strneq(name, namelen, cursor->entries[i]->name))
- return follow_path(cursor->entries[i], name + namelen);
-
- /* Not found */
- return NULL;
-}
-
-void init_paths(const char *prefix)
-{
- char pref_buf[PATH_MAX];
-
- if (prefix[0] == '\0' ||
- !strcmp(prefix, "/"))
- return;
-
- if (prefix[0] != '/') {
- char *cwd = getcwd(NULL, 0);
- size_t pref_buf_len = sizeof(pref_buf);
-
- if (!cwd)
- abort();
- pstrcpy(pref_buf, sizeof(pref_buf), cwd);
- pstrcat(pref_buf, pref_buf_len, "/");
- pstrcat(pref_buf, pref_buf_len, prefix);
- free(cwd);
- } else
- pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
-
- base = new_entry("", NULL, pref_buf);
- base = add_dir_maybe(base);
- if (base->num_entries == 0) {
- g_free(base->pathname);
- g_free(base->name);
- g_free(base);
- base = NULL;
- } else {
- set_parents(base, base);
- }
-}
-
-/* Look for path in emulation dir, otherwise return name. */
-const char *path(const char *name)
-{
- /* Only do absolute paths: quick and dirty, but should mostly be OK.
- Could do relative by tracking cwd. */
- if (!base || !name || name[0] != '/')
- return name;
-
- return follow_path(base, name) ?: name;
-}
diff --git a/qemu/util/qemu-config.c b/qemu/util/qemu-config.c
deleted file mode 100644
index fb973074d..000000000
--- a/qemu/util/qemu-config.c
+++ /dev/null
@@ -1,573 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include "qemu/config-file.h"
-#include "qmp-commands.h"
-
-static QemuOptsList *vm_config_groups[48];
-static QemuOptsList *drive_config_groups[4];
-
-static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
- Error **errp)
-{
- int i;
-
- for (i = 0; lists[i] != NULL; i++) {
- if (strcmp(lists[i]->name, group) == 0)
- break;
- }
- if (lists[i] == NULL) {
- error_setg(errp, "There is no option group '%s'", group);
- }
- return lists[i];
-}
-
-QemuOptsList *qemu_find_opts(const char *group)
-{
- QemuOptsList *ret;
- Error *local_err = NULL;
-
- ret = find_list(vm_config_groups, group, &local_err);
- if (local_err) {
- error_report_err(local_err);
- }
-
- return ret;
-}
-
-QemuOpts *qemu_find_opts_singleton(const char *group)
-{
- QemuOptsList *list;
- QemuOpts *opts;
-
- list = qemu_find_opts(group);
- assert(list);
- opts = qemu_opts_find(list, NULL);
- if (!opts) {
- opts = qemu_opts_create(list, NULL, 0, &error_abort);
- }
- return opts;
-}
-
-static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
-{
- CommandLineParameterInfoList *param_list = NULL, *entry;
- CommandLineParameterInfo *info;
- int i;
-
- for (i = 0; desc[i].name != NULL; i++) {
- info = g_malloc0(sizeof(*info));
- info->name = g_strdup(desc[i].name);
-
- switch (desc[i].type) {
- case QEMU_OPT_STRING:
- info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
- break;
- case QEMU_OPT_BOOL:
- info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN;
- break;
- case QEMU_OPT_NUMBER:
- info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER;
- break;
- case QEMU_OPT_SIZE:
- info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE;
- break;
- }
-
- if (desc[i].help) {
- info->has_help = true;
- info->help = g_strdup(desc[i].help);
- }
- if (desc[i].def_value_str) {
- info->has_q_default = true;
- info->q_default = g_strdup(desc[i].def_value_str);
- }
-
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = param_list;
- param_list = entry;
- }
-
- return param_list;
-}
-
-/* remove repeated entry from the info list */
-static void cleanup_infolist(CommandLineParameterInfoList *head)
-{
- CommandLineParameterInfoList *pre_entry, *cur, *del_entry;
-
- cur = head;
- while (cur->next) {
- pre_entry = head;
- while (pre_entry != cur->next) {
- if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
- del_entry = cur->next;
- cur->next = cur->next->next;
- g_free(del_entry);
- break;
- }
- pre_entry = pre_entry->next;
- }
- cur = cur->next;
- }
-}
-
-/* merge the description items of two parameter infolists */
-static void connect_infolist(CommandLineParameterInfoList *head,
- CommandLineParameterInfoList *new)
-{
- CommandLineParameterInfoList *cur;
-
- cur = head;
- while (cur->next) {
- cur = cur->next;
- }
- cur->next = new;
-}
-
-/* access all the local QemuOptsLists for drive option */
-static CommandLineParameterInfoList *get_drive_infolist(void)
-{
- CommandLineParameterInfoList *head = NULL, *cur;
- int i;
-
- for (i = 0; drive_config_groups[i] != NULL; i++) {
- if (!head) {
- head = query_option_descs(drive_config_groups[i]->desc);
- } else {
- cur = query_option_descs(drive_config_groups[i]->desc);
- connect_infolist(head, cur);
- }
- }
- cleanup_infolist(head);
-
- return head;
-}
-
-/* restore machine options that are now machine's properties */
-static QemuOptsList machine_opts = {
- .merge_lists = true,
- .head = QTAILQ_HEAD_INITIALIZER(machine_opts.head),
- .desc = {
- {
- .name = "type",
- .type = QEMU_OPT_STRING,
- .help = "emulated machine"
- },{
- .name = "accel",
- .type = QEMU_OPT_STRING,
- .help = "accelerator list",
- },{
- .name = "kernel_irqchip",
- .type = QEMU_OPT_BOOL,
- .help = "use KVM in-kernel irqchip",
- },{
- .name = "kvm_shadow_mem",
- .type = QEMU_OPT_SIZE,
- .help = "KVM shadow MMU size",
- },{
- .name = "kernel",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel image file",
- },{
- .name = "initrd",
- .type = QEMU_OPT_STRING,
- .help = "Linux initial ramdisk file",
- },{
- .name = "append",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel command line",
- },{
- .name = "dtb",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel device tree file",
- },{
- .name = "dumpdtb",
- .type = QEMU_OPT_STRING,
- .help = "Dump current dtb to a file and quit",
- },{
- .name = "phandle_start",
- .type = QEMU_OPT_NUMBER,
- .help = "The first phandle ID we may generate dynamically",
- },{
- .name = "dt_compatible",
- .type = QEMU_OPT_STRING,
- .help = "Overrides the \"compatible\" property of the dt root node",
- },{
- .name = "dump-guest-core",
- .type = QEMU_OPT_BOOL,
- .help = "Include guest memory in a core dump",
- },{
- .name = "mem-merge",
- .type = QEMU_OPT_BOOL,
- .help = "enable/disable memory merge support",
- },{
- .name = "usb",
- .type = QEMU_OPT_BOOL,
- .help = "Set on/off to enable/disable usb",
- },{
- .name = "firmware",
- .type = QEMU_OPT_STRING,
- .help = "firmware image",
- },{
- .name = "iommu",
- .type = QEMU_OPT_BOOL,
- .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
- },{
- .name = "suppress-vmdesc",
- .type = QEMU_OPT_BOOL,
- .help = "Set on to disable self-describing migration",
- },{
- .name = "aes-key-wrap",
- .type = QEMU_OPT_BOOL,
- .help = "enable/disable AES key wrapping using the CPACF wrapping key",
- },{
- .name = "dea-key-wrap",
- .type = QEMU_OPT_BOOL,
- .help = "enable/disable DEA key wrapping using the CPACF wrapping key",
- },
- { /* End of list */ }
- }
-};
-
-CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
- const char *option,
- Error **errp)
-{
- CommandLineOptionInfoList *conf_list = NULL, *entry;
- CommandLineOptionInfo *info;
- int i;
-
- for (i = 0; vm_config_groups[i] != NULL; i++) {
- if (!has_option || !strcmp(option, vm_config_groups[i]->name)) {
- info = g_malloc0(sizeof(*info));
- info->option = g_strdup(vm_config_groups[i]->name);
- if (!strcmp("drive", vm_config_groups[i]->name)) {
- info->parameters = get_drive_infolist();
- } else if (!strcmp("machine", vm_config_groups[i]->name)) {
- info->parameters = query_option_descs(machine_opts.desc);
- } else {
- info->parameters =
- query_option_descs(vm_config_groups[i]->desc);
- }
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = conf_list;
- conf_list = entry;
- }
- }
-
- if (conf_list == NULL) {
- error_setg(errp, "invalid option name: %s", option);
- }
-
- return conf_list;
-}
-
-QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
-{
- return find_list(vm_config_groups, group, errp);
-}
-
-void qemu_add_drive_opts(QemuOptsList *list)
-{
- int entries, i;
-
- entries = ARRAY_SIZE(drive_config_groups);
- entries--; /* keep list NULL terminated */
- for (i = 0; i < entries; i++) {
- if (drive_config_groups[i] == NULL) {
- drive_config_groups[i] = list;
- return;
- }
- }
- fprintf(stderr, "ran out of space in drive_config_groups");
- abort();
-}
-
-void qemu_add_opts(QemuOptsList *list)
-{
- int entries, i;
-
- entries = ARRAY_SIZE(vm_config_groups);
- entries--; /* keep list NULL terminated */
- for (i = 0; i < entries; i++) {
- if (vm_config_groups[i] == NULL) {
- vm_config_groups[i] = list;
- return;
- }
- }
- fprintf(stderr, "ran out of space in vm_config_groups");
- abort();
-}
-
-int qemu_set_option(const char *str)
-{
- Error *local_err = NULL;
- char group[64], id[64], arg[64];
- QemuOptsList *list;
- QemuOpts *opts;
- int rc, offset;
-
- rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
- if (rc < 3 || str[offset] != '=') {
- error_report("can't parse: \"%s\"", str);
- return -1;
- }
-
- list = qemu_find_opts(group);
- if (list == NULL) {
- return -1;
- }
-
- opts = qemu_opts_find(list, id);
- if (!opts) {
- error_report("there is no %s \"%s\" defined",
- list->name, id);
- return -1;
- }
-
- qemu_opt_set(opts, arg, str + offset + 1, &local_err);
- if (local_err) {
- error_report_err(local_err);
- return -1;
- }
- return 0;
-}
-
-struct ConfigWriteData {
- QemuOptsList *list;
- FILE *fp;
-};
-
-static int config_write_opt(void *opaque, const char *name, const char *value,
- Error **errp)
-{
- struct ConfigWriteData *data = opaque;
-
- fprintf(data->fp, " %s = \"%s\"\n", name, value);
- return 0;
-}
-
-static int config_write_opts(void *opaque, QemuOpts *opts, Error **errp)
-{
- struct ConfigWriteData *data = opaque;
- const char *id = qemu_opts_id(opts);
-
- if (id) {
- fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
- } else {
- fprintf(data->fp, "[%s]\n", data->list->name);
- }
- qemu_opt_foreach(opts, config_write_opt, data, NULL);
- fprintf(data->fp, "\n");
- return 0;
-}
-
-void qemu_config_write(FILE *fp)
-{
- struct ConfigWriteData data = { .fp = fp };
- QemuOptsList **lists = vm_config_groups;
- int i;
-
- fprintf(fp, "# qemu config file\n\n");
- for (i = 0; lists[i] != NULL; i++) {
- data.list = lists[i];
- qemu_opts_foreach(data.list, config_write_opts, &data, NULL);
- }
-}
-
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
-{
- char line[1024], group[64], id[64], arg[64], value[1024];
- Location loc;
- QemuOptsList *list = NULL;
- Error *local_err = NULL;
- QemuOpts *opts = NULL;
- int res = -1, lno = 0;
-
- loc_push_none(&loc);
- while (fgets(line, sizeof(line), fp) != NULL) {
- loc_set_file(fname, ++lno);
- if (line[0] == '\n') {
- /* skip empty lines */
- continue;
- }
- if (line[0] == '#') {
- /* comment */
- continue;
- }
- if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
- /* group with id */
- list = find_list(lists, group, &local_err);
- if (local_err) {
- error_report_err(local_err);
- goto out;
- }
- opts = qemu_opts_create(list, id, 1, NULL);
- continue;
- }
- if (sscanf(line, "[%63[^]]]", group) == 1) {
- /* group without id */
- list = find_list(lists, group, &local_err);
- if (local_err) {
- error_report_err(local_err);
- goto out;
- }
- opts = qemu_opts_create(list, NULL, 0, &error_abort);
- continue;
- }
- value[0] = '\0';
- if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
- sscanf(line, " %63s = \"\"", arg) == 1) {
- /* arg = value */
- if (opts == NULL) {
- error_report("no group defined");
- goto out;
- }
- qemu_opt_set(opts, arg, value, &local_err);
- if (local_err) {
- error_report_err(local_err);
- goto out;
- }
- continue;
- }
- error_report("parse error");
- goto out;
- }
- if (ferror(fp)) {
- error_report("error reading file");
- goto out;
- }
- res = 0;
-out:
- loc_pop(&loc);
- return res;
-}
-
-int qemu_read_config_file(const char *filename)
-{
- FILE *f = fopen(filename, "r");
- int ret;
-
- if (f == NULL) {
- return -errno;
- }
-
- ret = qemu_config_parse(f, vm_config_groups, filename);
- fclose(f);
-
- if (ret == 0) {
- return 0;
- } else {
- return -EINVAL;
- }
-}
-
-static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
- Error **errp)
-{
- QemuOpts *subopts;
- QDict *subqdict;
- QList *list = NULL;
- Error *local_err = NULL;
- size_t orig_size, enum_size;
- char *prefix;
-
- prefix = g_strdup_printf("%s.", opts->name);
- qdict_extract_subqdict(options, &subqdict, prefix);
- g_free(prefix);
- orig_size = qdict_size(subqdict);
- if (!orig_size) {
- goto out;
- }
-
- subopts = qemu_opts_create(opts, NULL, 0, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
- }
-
- qemu_opts_absorb_qdict(subopts, subqdict, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
- }
-
- enum_size = qdict_size(subqdict);
- if (enum_size < orig_size && enum_size) {
- error_setg(errp, "Unknown option '%s' for [%s]",
- qdict_first(subqdict)->key, opts->name);
- goto out;
- }
-
- if (enum_size) {
- /* Multiple, enumerated sections */
- QListEntry *list_entry;
- unsigned i = 0;
-
- /* Not required anymore */
- qemu_opts_del(subopts);
-
- qdict_array_split(subqdict, &list);
- if (qdict_size(subqdict)) {
- error_setg(errp, "Unused option '%s' for [%s]",
- qdict_first(subqdict)->key, opts->name);
- goto out;
- }
-
- QLIST_FOREACH_ENTRY(list, list_entry) {
- QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry));
- char *opt_name;
-
- if (!section) {
- error_setg(errp, "[%s] section (index %u) does not consist of "
- "keys", opts->name, i);
- goto out;
- }
-
- opt_name = g_strdup_printf("%s.%u", opts->name, i++);
- subopts = qemu_opts_create(opts, opt_name, 1, &local_err);
- g_free(opt_name);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
- }
-
- qemu_opts_absorb_qdict(subopts, section, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opts_del(subopts);
- goto out;
- }
-
- if (qdict_size(section)) {
- error_setg(errp, "[%s] section doesn't support the option '%s'",
- opts->name, qdict_first(section)->key);
- qemu_opts_del(subopts);
- goto out;
- }
- }
- }
-
-out:
- QDECREF(subqdict);
- QDECREF(list);
-}
-
-void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
- Error **errp)
-{
- int i;
- Error *local_err = NULL;
-
- for (i = 0; lists[i]; i++) {
- config_parse_qdict_section(options, lists[i], &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
-}
diff --git a/qemu/util/qemu-coroutine-io.c b/qemu/util/qemu-coroutine-io.c
deleted file mode 100644
index 91b9357d4..000000000
--- a/qemu/util/qemu-coroutine-io.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Coroutine-aware I/O functions
- *
- * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation.
- * Copyright (c) 2011, Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/sockets.h"
-#include "qemu/coroutine.h"
-#include "qemu/iov.h"
-#include "qemu/main-loop.h"
-
-ssize_t coroutine_fn
-qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
- size_t offset, size_t bytes, bool do_send)
-{
- size_t done = 0;
- ssize_t ret;
- while (done < bytes) {
- ret = iov_send_recv(sockfd, iov, iov_cnt,
- offset + done, bytes - done, do_send);
- if (ret > 0) {
- done += ret;
- } else if (ret < 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- qemu_coroutine_yield();
- } else if (done == 0) {
- return -errno;
- } else {
- break;
- }
- } else if (ret == 0 && !do_send) {
- /* write (send) should never return 0.
- * read (recv) returns 0 for end-of-file (-data).
- * In both cases there's little point retrying,
- * but we do for write anyway, just in case */
- break;
- }
- }
- return done;
-}
-
-ssize_t coroutine_fn
-qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send)
-{
- struct iovec iov = { .iov_base = buf, .iov_len = bytes };
- return qemu_co_sendv_recvv(sockfd, &iov, 1, 0, bytes, do_send);
-}
-
-typedef struct {
- Coroutine *co;
- int fd;
-} FDYieldUntilData;
-
-static void fd_coroutine_enter(void *opaque)
-{
- FDYieldUntilData *data = opaque;
- qemu_set_fd_handler(data->fd, NULL, NULL, NULL);
- qemu_coroutine_enter(data->co, NULL);
-}
-
-void coroutine_fn yield_until_fd_readable(int fd)
-{
- FDYieldUntilData data;
-
- assert(qemu_in_coroutine());
- data.co = qemu_coroutine_self();
- data.fd = fd;
- qemu_set_fd_handler(fd, fd_coroutine_enter, NULL, &data);
- qemu_coroutine_yield();
-}
diff --git a/qemu/util/qemu-coroutine-lock.c b/qemu/util/qemu-coroutine-lock.c
deleted file mode 100644
index da37ca7f9..000000000
--- a/qemu/util/qemu-coroutine-lock.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * coroutine queues and locks
- *
- * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/coroutine.h"
-#include "qemu/coroutine_int.h"
-#include "qemu/queue.h"
-#include "trace.h"
-
-void qemu_co_queue_init(CoQueue *queue)
-{
- QTAILQ_INIT(&queue->entries);
-}
-
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
-{
- Coroutine *self = qemu_coroutine_self();
- QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
- qemu_coroutine_yield();
- assert(qemu_in_coroutine());
-}
-
-/**
- * qemu_co_queue_run_restart:
- *
- * Enter each coroutine that was previously marked for restart by
- * qemu_co_queue_next() or qemu_co_queue_restart_all(). This function is
- * invoked by the core coroutine code when the current coroutine yields or
- * terminates.
- */
-void qemu_co_queue_run_restart(Coroutine *co)
-{
- Coroutine *next;
-
- trace_qemu_co_queue_run_restart(co);
- while ((next = QTAILQ_FIRST(&co->co_queue_wakeup))) {
- QTAILQ_REMOVE(&co->co_queue_wakeup, next, co_queue_next);
- qemu_coroutine_enter(next, NULL);
- }
-}
-
-static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
-{
- Coroutine *self = qemu_coroutine_self();
- Coroutine *next;
-
- if (QTAILQ_EMPTY(&queue->entries)) {
- return false;
- }
-
- while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) {
- QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
- QTAILQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next);
- trace_qemu_co_queue_next(next);
- if (single) {
- break;
- }
- }
- return true;
-}
-
-bool coroutine_fn qemu_co_queue_next(CoQueue *queue)
-{
- assert(qemu_in_coroutine());
- return qemu_co_queue_do_restart(queue, true);
-}
-
-void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
-{
- assert(qemu_in_coroutine());
- qemu_co_queue_do_restart(queue, false);
-}
-
-bool qemu_co_enter_next(CoQueue *queue)
-{
- Coroutine *next;
-
- next = QTAILQ_FIRST(&queue->entries);
- if (!next) {
- return false;
- }
-
- QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
- qemu_coroutine_enter(next, NULL);
- return true;
-}
-
-bool qemu_co_queue_empty(CoQueue *queue)
-{
- return QTAILQ_FIRST(&queue->entries) == NULL;
-}
-
-void qemu_co_mutex_init(CoMutex *mutex)
-{
- memset(mutex, 0, sizeof(*mutex));
- qemu_co_queue_init(&mutex->queue);
-}
-
-void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
-{
- Coroutine *self = qemu_coroutine_self();
-
- trace_qemu_co_mutex_lock_entry(mutex, self);
-
- while (mutex->locked) {
- qemu_co_queue_wait(&mutex->queue);
- }
-
- mutex->locked = true;
-
- trace_qemu_co_mutex_lock_return(mutex, self);
-}
-
-void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
-{
- Coroutine *self = qemu_coroutine_self();
-
- trace_qemu_co_mutex_unlock_entry(mutex, self);
-
- assert(mutex->locked == true);
- assert(qemu_in_coroutine());
-
- mutex->locked = false;
- qemu_co_queue_next(&mutex->queue);
-
- trace_qemu_co_mutex_unlock_return(mutex, self);
-}
-
-void qemu_co_rwlock_init(CoRwlock *lock)
-{
- memset(lock, 0, sizeof(*lock));
- qemu_co_queue_init(&lock->queue);
-}
-
-void qemu_co_rwlock_rdlock(CoRwlock *lock)
-{
- while (lock->writer) {
- qemu_co_queue_wait(&lock->queue);
- }
- lock->reader++;
-}
-
-void qemu_co_rwlock_unlock(CoRwlock *lock)
-{
- assert(qemu_in_coroutine());
- if (lock->writer) {
- lock->writer = false;
- qemu_co_queue_restart_all(&lock->queue);
- } else {
- lock->reader--;
- assert(lock->reader >= 0);
- /* Wakeup only one waiting writer */
- if (!lock->reader) {
- qemu_co_queue_next(&lock->queue);
- }
- }
-}
-
-void qemu_co_rwlock_wrlock(CoRwlock *lock)
-{
- while (lock->writer || lock->reader) {
- qemu_co_queue_wait(&lock->queue);
- }
- lock->writer = true;
-}
diff --git a/qemu/util/qemu-coroutine-sleep.c b/qemu/util/qemu-coroutine-sleep.c
deleted file mode 100644
index 6966831d3..000000000
--- a/qemu/util/qemu-coroutine-sleep.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * QEMU coroutine sleep
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/coroutine.h"
-#include "qemu/timer.h"
-#include "block/aio.h"
-
-typedef struct CoSleepCB {
- QEMUTimer *ts;
- Coroutine *co;
-} CoSleepCB;
-
-static void co_sleep_cb(void *opaque)
-{
- CoSleepCB *sleep_cb = opaque;
-
- qemu_coroutine_enter(sleep_cb->co, NULL);
-}
-
-void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
- int64_t ns)
-{
- CoSleepCB sleep_cb = {
- .co = qemu_coroutine_self(),
- };
- sleep_cb.ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &sleep_cb);
- timer_mod(sleep_cb.ts, qemu_clock_get_ns(type) + ns);
- qemu_coroutine_yield();
- timer_del(sleep_cb.ts);
- timer_free(sleep_cb.ts);
-}
diff --git a/qemu/util/qemu-coroutine.c b/qemu/util/qemu-coroutine.c
deleted file mode 100644
index 5816702cc..000000000
--- a/qemu/util/qemu-coroutine.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QEMU coroutines
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
- * Kevin Wolf <kwolf@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "trace.h"
-#include "qemu-common.h"
-#include "qemu/thread.h"
-#include "qemu/atomic.h"
-#include "qemu/coroutine.h"
-#include "qemu/coroutine_int.h"
-
-enum {
- POOL_BATCH_SIZE = 64,
-};
-
-/** Free list to speed up creation */
-static QSLIST_HEAD(, Coroutine) release_pool = QSLIST_HEAD_INITIALIZER(pool);
-static unsigned int release_pool_size;
-static __thread QSLIST_HEAD(, Coroutine) alloc_pool = QSLIST_HEAD_INITIALIZER(pool);
-static __thread unsigned int alloc_pool_size;
-static __thread Notifier coroutine_pool_cleanup_notifier;
-
-static void coroutine_pool_cleanup(Notifier *n, void *value)
-{
- Coroutine *co;
- Coroutine *tmp;
-
- QSLIST_FOREACH_SAFE(co, &alloc_pool, pool_next, tmp) {
- QSLIST_REMOVE_HEAD(&alloc_pool, pool_next);
- qemu_coroutine_delete(co);
- }
-}
-
-Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
-{
- Coroutine *co = NULL;
-
- if (CONFIG_COROUTINE_POOL) {
- co = QSLIST_FIRST(&alloc_pool);
- if (!co) {
- if (release_pool_size > POOL_BATCH_SIZE) {
- /* Slow path; a good place to register the destructor, too. */
- if (!coroutine_pool_cleanup_notifier.notify) {
- coroutine_pool_cleanup_notifier.notify = coroutine_pool_cleanup;
- qemu_thread_atexit_add(&coroutine_pool_cleanup_notifier);
- }
-
- /* This is not exact; there could be a little skew between
- * release_pool_size and the actual size of release_pool. But
- * it is just a heuristic, it does not need to be perfect.
- */
- alloc_pool_size = atomic_xchg(&release_pool_size, 0);
- QSLIST_MOVE_ATOMIC(&alloc_pool, &release_pool);
- co = QSLIST_FIRST(&alloc_pool);
- }
- }
- if (co) {
- QSLIST_REMOVE_HEAD(&alloc_pool, pool_next);
- alloc_pool_size--;
- }
- }
-
- if (!co) {
- co = qemu_coroutine_new();
- }
-
- co->entry = entry;
- QTAILQ_INIT(&co->co_queue_wakeup);
- return co;
-}
-
-static void coroutine_delete(Coroutine *co)
-{
- co->caller = NULL;
-
- if (CONFIG_COROUTINE_POOL) {
- if (release_pool_size < POOL_BATCH_SIZE * 2) {
- QSLIST_INSERT_HEAD_ATOMIC(&release_pool, co, pool_next);
- atomic_inc(&release_pool_size);
- return;
- }
- if (alloc_pool_size < POOL_BATCH_SIZE) {
- QSLIST_INSERT_HEAD(&alloc_pool, co, pool_next);
- alloc_pool_size++;
- return;
- }
- }
-
- qemu_coroutine_delete(co);
-}
-
-void qemu_coroutine_enter(Coroutine *co, void *opaque)
-{
- Coroutine *self = qemu_coroutine_self();
- CoroutineAction ret;
-
- trace_qemu_coroutine_enter(self, co, opaque);
-
- if (co->caller) {
- fprintf(stderr, "Co-routine re-entered recursively\n");
- abort();
- }
-
- co->caller = self;
- co->entry_arg = opaque;
- ret = qemu_coroutine_switch(self, co, COROUTINE_ENTER);
-
- qemu_co_queue_run_restart(co);
-
- switch (ret) {
- case COROUTINE_YIELD:
- return;
- case COROUTINE_TERMINATE:
- trace_qemu_coroutine_terminate(co);
- coroutine_delete(co);
- return;
- default:
- abort();
- }
-}
-
-void coroutine_fn qemu_coroutine_yield(void)
-{
- Coroutine *self = qemu_coroutine_self();
- Coroutine *to = self->caller;
-
- trace_qemu_coroutine_yield(self, to);
-
- if (!to) {
- fprintf(stderr, "Co-routine is yielding to no one\n");
- abort();
- }
-
- self->caller = NULL;
- qemu_coroutine_switch(self, to, COROUTINE_YIELD);
-}
diff --git a/qemu/util/qemu-error.c b/qemu/util/qemu-error.c
deleted file mode 100644
index 1ef35664a..000000000
--- a/qemu/util/qemu-error.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Error reporting
- *
- * Copyright (C) 2010 Red Hat Inc.
- *
- * Authors:
- * Markus Armbruster <armbru@redhat.com>,
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "monitor/monitor.h"
-#include "qemu/error-report.h"
-
-/*
- * Print to current monitor if we have one, else to stderr.
- * TODO should return int, so callers can calculate width, but that
- * requires surgery to monitor_vprintf(). Left for another day.
- */
-void error_vprintf(const char *fmt, va_list ap)
-{
- if (cur_mon && !monitor_cur_is_qmp()) {
- monitor_vprintf(cur_mon, fmt, ap);
- } else {
- vfprintf(stderr, fmt, ap);
- }
-}
-
-/*
- * Print to current monitor if we have one, else to stderr.
- * TODO just like error_vprintf()
- */
-void error_printf(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_vprintf(fmt, ap);
- va_end(ap);
-}
-
-void error_printf_unless_qmp(const char *fmt, ...)
-{
- va_list ap;
-
- if (!monitor_cur_is_qmp()) {
- va_start(ap, fmt);
- error_vprintf(fmt, ap);
- va_end(ap);
- }
-}
-
-static Location std_loc = {
- .kind = LOC_NONE
-};
-static Location *cur_loc = &std_loc;
-
-/*
- * Push location saved in LOC onto the location stack, return it.
- * The top of that stack is the current location.
- * Needs a matching loc_pop().
- */
-Location *loc_push_restore(Location *loc)
-{
- assert(!loc->prev);
- loc->prev = cur_loc;
- cur_loc = loc;
- return loc;
-}
-
-/*
- * Initialize *LOC to "nowhere", push it onto the location stack.
- * The top of that stack is the current location.
- * Needs a matching loc_pop().
- * Return LOC.
- */
-Location *loc_push_none(Location *loc)
-{
- loc->kind = LOC_NONE;
- loc->prev = NULL;
- return loc_push_restore(loc);
-}
-
-/*
- * Pop the location stack.
- * LOC must be the current location, i.e. the top of the stack.
- */
-Location *loc_pop(Location *loc)
-{
- assert(cur_loc == loc && loc->prev);
- cur_loc = loc->prev;
- loc->prev = NULL;
- return loc;
-}
-
-/*
- * Save the current location in LOC, return LOC.
- */
-Location *loc_save(Location *loc)
-{
- *loc = *cur_loc;
- loc->prev = NULL;
- return loc;
-}
-
-/*
- * Change the current location to the one saved in LOC.
- */
-void loc_restore(Location *loc)
-{
- Location *prev = cur_loc->prev;
- assert(!loc->prev);
- *cur_loc = *loc;
- cur_loc->prev = prev;
-}
-
-/*
- * Change the current location to "nowhere in particular".
- */
-void loc_set_none(void)
-{
- cur_loc->kind = LOC_NONE;
-}
-
-/*
- * Change the current location to argument ARGV[IDX..IDX+CNT-1].
- */
-void loc_set_cmdline(char **argv, int idx, int cnt)
-{
- cur_loc->kind = LOC_CMDLINE;
- cur_loc->num = cnt;
- cur_loc->ptr = argv + idx;
-}
-
-/*
- * Change the current location to file FNAME, line LNO.
- */
-void loc_set_file(const char *fname, int lno)
-{
- assert (fname || cur_loc->kind == LOC_FILE);
- cur_loc->kind = LOC_FILE;
- cur_loc->num = lno;
- if (fname) {
- cur_loc->ptr = fname;
- }
-}
-
-static const char *progname;
-
-/*
- * Set the program name for error_print_loc().
- */
-void error_set_progname(const char *argv0)
-{
- const char *p = strrchr(argv0, '/');
- progname = p ? p + 1 : argv0;
-}
-
-const char *error_get_progname(void)
-{
- return progname;
-}
-
-/*
- * Print current location to current monitor if we have one, else to stderr.
- */
-static void error_print_loc(void)
-{
- const char *sep = "";
- int i;
- const char *const *argp;
-
- if (!cur_mon && progname) {
- fprintf(stderr, "%s:", progname);
- sep = " ";
- }
- switch (cur_loc->kind) {
- case LOC_CMDLINE:
- argp = cur_loc->ptr;
- for (i = 0; i < cur_loc->num; i++) {
- error_printf("%s%s", sep, argp[i]);
- sep = " ";
- }
- error_printf(": ");
- break;
- case LOC_FILE:
- error_printf("%s:", (const char *)cur_loc->ptr);
- if (cur_loc->num) {
- error_printf("%d:", cur_loc->num);
- }
- error_printf(" ");
- break;
- default:
- error_printf("%s", sep);
- }
-}
-
-bool enable_timestamp_msg;
-/*
- * Print an error message to current monitor if we have one, else to stderr.
- * Format arguments like vsprintf(). The resulting message should be
- * a single phrase, with no newline or trailing punctuation.
- * Prepend the current location and append a newline.
- * It's wrong to call this in a QMP monitor. Use error_setg() there.
- */
-void error_vreport(const char *fmt, va_list ap)
-{
- GTimeVal tv;
- gchar *timestr;
-
- if (enable_timestamp_msg && !cur_mon) {
- g_get_current_time(&tv);
- timestr = g_time_val_to_iso8601(&tv);
- error_printf("%s ", timestr);
- g_free(timestr);
- }
-
- error_print_loc();
- error_vprintf(fmt, ap);
- error_printf("\n");
-}
-
-/*
- * Print an error message to current monitor if we have one, else to stderr.
- * Format arguments like sprintf(). The resulting message should be a
- * single phrase, with no newline or trailing punctuation.
- * Prepend the current location and append a newline.
- * It's wrong to call this in a QMP monitor. Use error_setg() there.
- */
-void error_report(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- error_vreport(fmt, ap);
- va_end(ap);
-}
diff --git a/qemu/util/qemu-openpty.c b/qemu/util/qemu-openpty.c
deleted file mode 100644
index 2e8b43bdf..000000000
--- a/qemu/util/qemu-openpty.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * qemu-openpty.c
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- * Copyright (c) 2010 Red Hat, Inc.
- *
- * Wrapper function qemu_openpty() implementation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/*
- * This is not part of oslib-posix.c because this function
- * uses openpty() which often in -lutil, and if we add this
- * dependency to oslib-posix.o, every app will have to be
- * linked with -lutil.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-
-#if defined(__GLIBC__)
-# include <pty.h>
-#elif defined CONFIG_BSD
-# include <termios.h>
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-# include <libutil.h>
-# else
-# include <util.h>
-# endif
-#elif defined CONFIG_SOLARIS
-# include <termios.h>
-# include <stropts.h>
-#else
-# include <termios.h>
-#endif
-
-#ifdef __sun__
-/* Once Solaris has openpty(), this is going to be removed. */
-static int openpty(int *amaster, int *aslave, char *name,
- struct termios *termp, struct winsize *winp)
-{
- const char *slave;
- int mfd = -1, sfd = -1;
-
- *amaster = *aslave = -1;
-
- mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
- if (mfd < 0)
- goto err;
-
- if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
- goto err;
-
- if ((slave = ptsname(mfd)) == NULL)
- goto err;
-
- if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
- goto err;
-
- if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
- (termp != NULL && tcgetattr(sfd, termp) < 0))
- goto err;
-
- if (amaster)
- *amaster = mfd;
- if (aslave)
- *aslave = sfd;
- if (winp)
- ioctl(sfd, TIOCSWINSZ, winp);
-
- return 0;
-
-err:
- if (sfd != -1)
- close(sfd);
- close(mfd);
- return -1;
-}
-
-static void cfmakeraw (struct termios *termios_p)
-{
- termios_p->c_iflag &=
- ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- termios_p->c_oflag &= ~OPOST;
- termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
- termios_p->c_cflag &= ~(CSIZE|PARENB);
- termios_p->c_cflag |= CS8;
-
- termios_p->c_cc[VMIN] = 0;
- termios_p->c_cc[VTIME] = 0;
-}
-#endif
-
-int qemu_openpty_raw(int *aslave, char *pty_name)
-{
- int amaster;
- struct termios tty;
-#if defined(__OpenBSD__) || defined(__DragonFly__)
- char pty_buf[PATH_MAX];
-#define q_ptsname(x) pty_buf
-#else
- char *pty_buf = NULL;
-#define q_ptsname(x) ptsname(x)
-#endif
-
- if (openpty(&amaster, aslave, pty_buf, NULL, NULL) < 0) {
- return -1;
- }
-
- /* Set raw attributes on the pty. */
- tcgetattr(*aslave, &tty);
- cfmakeraw(&tty);
- tcsetattr(*aslave, TCSAFLUSH, &tty);
-
- if (pty_name) {
- strcpy(pty_name, q_ptsname(amaster));
- }
-
- return amaster;
-}
diff --git a/qemu/util/qemu-option.c b/qemu/util/qemu-option.c
deleted file mode 100644
index 3467dc239..000000000
--- a/qemu/util/qemu-option.c
+++ /dev/null
@@ -1,1207 +0,0 @@
-/*
- * Commandline option parsing functions
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-#include "qapi/qmp/types.h"
-#include "qapi/qmp/qerror.h"
-#include "qemu/option_int.h"
-#include "qemu/cutils.h"
-#include "qemu/id.h"
-#include "qemu/help_option.h"
-
-/*
- * Extracts the name of an option from the parameter string (p points at the
- * first byte of the option name)
- *
- * The option name is delimited by delim (usually , or =) or the string end
- * and is copied into buf. If the option name is longer than buf_size, it is
- * truncated. buf is always zero terminated.
- *
- * The return value is the position of the delimiter/zero byte after the option
- * name in p.
- */
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
-{
- char *q;
-
- q = buf;
- while (*p != '\0' && *p != delim) {
- if (q && (q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
- }
- if (q)
- *q = '\0';
-
- return p;
-}
-
-/*
- * Extracts the value of an option from the parameter string p (p points at the
- * first byte of the option value)
- *
- * This function is comparable to get_opt_name with the difference that the
- * delimiter is fixed to be comma which starts a new option. To specify an
- * option value that contains commas, double each comma.
- */
-const char *get_opt_value(char *buf, int buf_size, const char *p)
-{
- char *q;
-
- q = buf;
- while (*p != '\0') {
- if (*p == ',') {
- if (*(p + 1) != ',')
- break;
- p++;
- }
- if (q && (q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
- }
- if (q)
- *q = '\0';
-
- return p;
-}
-
-int get_next_param_value(char *buf, int buf_size,
- const char *tag, const char **pstr)
-{
- const char *p;
- char option[128];
-
- p = *pstr;
- for(;;) {
- p = get_opt_name(option, sizeof(option), p, '=');
- if (*p != '=')
- break;
- p++;
- if (!strcmp(tag, option)) {
- *pstr = get_opt_value(buf, buf_size, p);
- if (**pstr == ',') {
- (*pstr)++;
- }
- return strlen(buf);
- } else {
- p = get_opt_value(NULL, 0, p);
- }
- if (*p != ',')
- break;
- p++;
- }
- return 0;
-}
-
-int get_param_value(char *buf, int buf_size,
- const char *tag, const char *str)
-{
- return get_next_param_value(buf, buf_size, tag, &str);
-}
-
-static void parse_option_bool(const char *name, const char *value, bool *ret,
- Error **errp)
-{
- if (value != NULL) {
- if (!strcmp(value, "on")) {
- *ret = 1;
- } else if (!strcmp(value, "off")) {
- *ret = 0;
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name, "'on' or 'off'");
- }
- } else {
- *ret = 1;
- }
-}
-
-static void parse_option_number(const char *name, const char *value,
- uint64_t *ret, Error **errp)
-{
- char *postfix;
- uint64_t number;
-
- if (value != NULL) {
- number = strtoull(value, &postfix, 0);
- if (*postfix != '\0') {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
- return;
- }
- *ret = number;
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
- }
-}
-
-static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
- const char *name)
-{
- int i;
-
- for (i = 0; desc[i].name != NULL; i++) {
- if (strcmp(desc[i].name, name) == 0) {
- return &desc[i];
- }
- }
-
- return NULL;
-}
-
-void parse_option_size(const char *name, const char *value,
- uint64_t *ret, Error **errp)
-{
- char *postfix;
- double sizef;
-
- if (value != NULL) {
- sizef = strtod(value, &postfix);
- if (sizef < 0 || sizef > UINT64_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
- "a non-negative number below 2^64");
- return;
- }
- switch (*postfix) {
- case 'T':
- sizef *= 1024;
- /* fall through */
- case 'G':
- sizef *= 1024;
- /* fall through */
- case 'M':
- sizef *= 1024;
- /* fall through */
- case 'K':
- case 'k':
- sizef *= 1024;
- /* fall through */
- case 'b':
- case '\0':
- *ret = (uint64_t) sizef;
- break;
- default:
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
- error_append_hint(errp, "You may use k, M, G or T suffixes for "
- "kilobytes, megabytes, gigabytes and terabytes.\n");
- return;
- }
- } else {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
- }
-}
-
-bool has_help_option(const char *param)
-{
- size_t buflen = strlen(param) + 1;
- char *buf = g_malloc(buflen);
- const char *p = param;
- bool result = false;
-
- while (*p) {
- p = get_opt_value(buf, buflen, p);
- if (*p) {
- p++;
- }
-
- if (is_help_option(buf)) {
- result = true;
- goto out;
- }
- }
-
-out:
- g_free(buf);
- return result;
-}
-
-bool is_valid_option_list(const char *param)
-{
- size_t buflen = strlen(param) + 1;
- char *buf = g_malloc(buflen);
- const char *p = param;
- bool result = true;
-
- while (*p) {
- p = get_opt_value(buf, buflen, p);
- if (*p && !*++p) {
- result = false;
- goto out;
- }
-
- if (!*buf || *buf == ',') {
- result = false;
- goto out;
- }
- }
-
-out:
- g_free(buf);
- return result;
-}
-
-void qemu_opts_print_help(QemuOptsList *list)
-{
- QemuOptDesc *desc;
-
- assert(list);
- desc = list->desc;
- printf("Supported options:\n");
- while (desc && desc->name) {
- printf("%-16s %s\n", desc->name,
- desc->help ? desc->help : "No description available");
- desc++;
- }
-}
-/* ------------------------------------------------------------------ */
-
-QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
-{
- QemuOpt *opt;
-
- QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
- if (strcmp(opt->name, name) != 0)
- continue;
- return opt;
- }
- return NULL;
-}
-
-static void qemu_opt_del(QemuOpt *opt)
-{
- QTAILQ_REMOVE(&opt->opts->head, opt, next);
- g_free(opt->name);
- g_free(opt->str);
- g_free(opt);
-}
-
-/* qemu_opt_set allows many settings for the same option.
- * This function deletes all settings for an option.
- */
-static void qemu_opt_del_all(QemuOpts *opts, const char *name)
-{
- QemuOpt *opt, *next_opt;
-
- QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
- if (!strcmp(opt->name, name)) {
- qemu_opt_del(opt);
- }
- }
-}
-
-const char *qemu_opt_get(QemuOpts *opts, const char *name)
-{
- QemuOpt *opt;
-
- if (opts == NULL) {
- return NULL;
- }
-
- opt = qemu_opt_find(opts, name);
- if (!opt) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- return desc->def_value_str;
- }
- }
- return opt ? opt->str : NULL;
-}
-
-/* Get a known option (or its default) and remove it from the list
- * all in one action. Return a malloced string of the option value.
- * Result must be freed by caller with g_free().
- */
-char *qemu_opt_get_del(QemuOpts *opts, const char *name)
-{
- QemuOpt *opt;
- const QemuOptDesc *desc;
- char *str = NULL;
-
- if (opts == NULL) {
- return NULL;
- }
-
- opt = qemu_opt_find(opts, name);
- if (!opt) {
- desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- str = g_strdup(desc->def_value_str);
- }
- return str;
- }
- str = opt->str;
- opt->str = NULL;
- qemu_opt_del_all(opts, name);
- return str;
-}
-
-bool qemu_opt_has_help_opt(QemuOpts *opts)
-{
- QemuOpt *opt;
-
- QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
- if (is_help_option(opt->name)) {
- return true;
- }
- }
- return false;
-}
-
-static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
- bool defval, bool del)
-{
- QemuOpt *opt;
- bool ret = defval;
-
- if (opts == NULL) {
- return ret;
- }
-
- opt = qemu_opt_find(opts, name);
- if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
- }
- return ret;
- }
- assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
- ret = opt->value.boolean;
- if (del) {
- qemu_opt_del_all(opts, name);
- }
- return ret;
-}
-
-bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
-{
- return qemu_opt_get_bool_helper(opts, name, defval, false);
-}
-
-bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
-{
- return qemu_opt_get_bool_helper(opts, name, defval, true);
-}
-
-static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
- uint64_t defval, bool del)
-{
- QemuOpt *opt;
- uint64_t ret = defval;
-
- if (opts == NULL) {
- return ret;
- }
-
- opt = qemu_opt_find(opts, name);
- if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_number(name, desc->def_value_str, &ret, &error_abort);
- }
- return ret;
- }
- assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
- ret = opt->value.uint;
- if (del) {
- qemu_opt_del_all(opts, name);
- }
- return ret;
-}
-
-uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
-{
- return qemu_opt_get_number_helper(opts, name, defval, false);
-}
-
-uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
- uint64_t defval)
-{
- return qemu_opt_get_number_helper(opts, name, defval, true);
-}
-
-static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
- uint64_t defval, bool del)
-{
- QemuOpt *opt;
- uint64_t ret = defval;
-
- if (opts == NULL) {
- return ret;
- }
-
- opt = qemu_opt_find(opts, name);
- if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_size(name, desc->def_value_str, &ret, &error_abort);
- }
- return ret;
- }
- assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
- ret = opt->value.uint;
- if (del) {
- qemu_opt_del_all(opts, name);
- }
- return ret;
-}
-
-uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
-{
- return qemu_opt_get_size_helper(opts, name, defval, false);
-}
-
-uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
- uint64_t defval)
-{
- return qemu_opt_get_size_helper(opts, name, defval, true);
-}
-
-static void qemu_opt_parse(QemuOpt *opt, Error **errp)
-{
- if (opt->desc == NULL)
- return;
-
- switch (opt->desc->type) {
- case QEMU_OPT_STRING:
- /* nothing */
- return;
- case QEMU_OPT_BOOL:
- parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
- break;
- case QEMU_OPT_NUMBER:
- parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
- break;
- case QEMU_OPT_SIZE:
- parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
- break;
- default:
- abort();
- }
-}
-
-static bool opts_accepts_any(const QemuOpts *opts)
-{
- return opts->list->desc[0].name == NULL;
-}
-
-int qemu_opt_unset(QemuOpts *opts, const char *name)
-{
- QemuOpt *opt = qemu_opt_find(opts, name);
-
- assert(opts_accepts_any(opts));
-
- if (opt == NULL) {
- return -1;
- } else {
- qemu_opt_del(opt);
- return 0;
- }
-}
-
-static void opt_set(QemuOpts *opts, const char *name, const char *value,
- bool prepend, Error **errp)
-{
- QemuOpt *opt;
- const QemuOptDesc *desc;
- Error *local_err = NULL;
-
- desc = find_desc_by_name(opts->list->desc, name);
- if (!desc && !opts_accepts_any(opts)) {
- error_setg(errp, QERR_INVALID_PARAMETER, name);
- return;
- }
-
- opt = g_malloc0(sizeof(*opt));
- opt->name = g_strdup(name);
- opt->opts = opts;
- if (prepend) {
- QTAILQ_INSERT_HEAD(&opts->head, opt, next);
- } else {
- QTAILQ_INSERT_TAIL(&opts->head, opt, next);
- }
- opt->desc = desc;
- opt->str = g_strdup(value);
- qemu_opt_parse(opt, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opt_del(opt);
- }
-}
-
-void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
- Error **errp)
-{
- opt_set(opts, name, value, false, errp);
-}
-
-void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
- Error **errp)
-{
- QemuOpt *opt;
- const QemuOptDesc *desc = opts->list->desc;
-
- opt = g_malloc0(sizeof(*opt));
- opt->desc = find_desc_by_name(desc, name);
- if (!opt->desc && !opts_accepts_any(opts)) {
- error_setg(errp, QERR_INVALID_PARAMETER, name);
- g_free(opt);
- return;
- }
-
- opt->name = g_strdup(name);
- opt->opts = opts;
- opt->value.boolean = !!val;
- opt->str = g_strdup(val ? "on" : "off");
- QTAILQ_INSERT_TAIL(&opts->head, opt, next);
-}
-
-void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
- Error **errp)
-{
- QemuOpt *opt;
- const QemuOptDesc *desc = opts->list->desc;
-
- opt = g_malloc0(sizeof(*opt));
- opt->desc = find_desc_by_name(desc, name);
- if (!opt->desc && !opts_accepts_any(opts)) {
- error_setg(errp, QERR_INVALID_PARAMETER, name);
- g_free(opt);
- return;
- }
-
- opt->name = g_strdup(name);
- opt->opts = opts;
- opt->value.uint = val;
- opt->str = g_strdup_printf("%" PRId64, val);
- QTAILQ_INSERT_TAIL(&opts->head, opt, next);
-}
-
-/**
- * For each member of @opts, call @func(@opaque, name, value, @errp).
- * @func() may store an Error through @errp, but must return non-zero then.
- * When @func() returns non-zero, break the loop and return that value.
- * Return zero when the loop completes.
- */
-int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
- Error **errp)
-{
- QemuOpt *opt;
- int rc;
-
- QTAILQ_FOREACH(opt, &opts->head, next) {
- rc = func(opaque, opt->name, opt->str, errp);
- if (rc) {
- return rc;
- }
- assert(!errp || !*errp);
- }
- return 0;
-}
-
-QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
-{
- QemuOpts *opts;
-
- QTAILQ_FOREACH(opts, &list->head, next) {
- if (!opts->id && !id) {
- return opts;
- }
- if (opts->id && id && !strcmp(opts->id, id)) {
- return opts;
- }
- }
- return NULL;
-}
-
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
- int fail_if_exists, Error **errp)
-{
- QemuOpts *opts = NULL;
-
- if (id) {
- if (!id_wellformed(id)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
- "an identifier");
- error_append_hint(errp, "Identifiers consist of letters, digits, "
- "'-', '.', '_', starting with a letter.\n");
- return NULL;
- }
- opts = qemu_opts_find(list, id);
- if (opts != NULL) {
- if (fail_if_exists && !list->merge_lists) {
- error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
- return NULL;
- } else {
- return opts;
- }
- }
- } else if (list->merge_lists) {
- opts = qemu_opts_find(list, NULL);
- if (opts) {
- return opts;
- }
- }
- opts = g_malloc0(sizeof(*opts));
- opts->id = g_strdup(id);
- opts->list = list;
- loc_save(&opts->loc);
- QTAILQ_INIT(&opts->head);
- QTAILQ_INSERT_TAIL(&list->head, opts, next);
- return opts;
-}
-
-void qemu_opts_reset(QemuOptsList *list)
-{
- QemuOpts *opts, *next_opts;
-
- QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
- qemu_opts_del(opts);
- }
-}
-
-void qemu_opts_loc_restore(QemuOpts *opts)
-{
- loc_restore(&opts->loc);
-}
-
-void qemu_opts_set(QemuOptsList *list, const char *id,
- const char *name, const char *value, Error **errp)
-{
- QemuOpts *opts;
- Error *local_err = NULL;
-
- opts = qemu_opts_create(list, id, 1, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- qemu_opt_set(opts, name, value, errp);
-}
-
-const char *qemu_opts_id(QemuOpts *opts)
-{
- return opts->id;
-}
-
-/* The id string will be g_free()d by qemu_opts_del */
-void qemu_opts_set_id(QemuOpts *opts, char *id)
-{
- opts->id = id;
-}
-
-void qemu_opts_del(QemuOpts *opts)
-{
- QemuOpt *opt;
-
- if (opts == NULL) {
- return;
- }
-
- for (;;) {
- opt = QTAILQ_FIRST(&opts->head);
- if (opt == NULL)
- break;
- qemu_opt_del(opt);
- }
- QTAILQ_REMOVE(&opts->list->head, opts, next);
- g_free(opts->id);
- g_free(opts);
-}
-
-/* print value, escaping any commas in value */
-static void escaped_print(const char *value)
-{
- const char *ptr;
-
- for (ptr = value; *ptr; ++ptr) {
- if (*ptr == ',') {
- putchar(',');
- }
- putchar(*ptr);
- }
-}
-
-void qemu_opts_print(QemuOpts *opts, const char *separator)
-{
- QemuOpt *opt;
- QemuOptDesc *desc = opts->list->desc;
- const char *sep = "";
-
- if (opts->id) {
- printf("id=%s", opts->id); /* passed id_wellformed -> no commas */
- sep = separator;
- }
-
- if (desc[0].name == NULL) {
- QTAILQ_FOREACH(opt, &opts->head, next) {
- printf("%s%s=", sep, opt->name);
- escaped_print(opt->str);
- sep = separator;
- }
- return;
- }
- for (; desc && desc->name; desc++) {
- const char *value;
- QemuOpt *opt = qemu_opt_find(opts, desc->name);
-
- value = opt ? opt->str : desc->def_value_str;
- if (!value) {
- continue;
- }
- if (desc->type == QEMU_OPT_STRING) {
- printf("%s%s=", sep, desc->name);
- escaped_print(value);
- } else if ((desc->type == QEMU_OPT_SIZE ||
- desc->type == QEMU_OPT_NUMBER) && opt) {
- printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
- } else {
- printf("%s%s=%s", sep, desc->name, value);
- }
- sep = separator;
- }
-}
-
-static void opts_do_parse(QemuOpts *opts, const char *params,
- const char *firstname, bool prepend, Error **errp)
-{
- char option[128], value[1024];
- const char *p,*pe,*pc;
- Error *local_err = NULL;
-
- for (p = params; *p != '\0'; p++) {
- pe = strchr(p, '=');
- pc = strchr(p, ',');
- if (!pe || (pc && pc < pe)) {
- /* found "foo,more" */
- if (p == params && firstname) {
- /* implicitly named first option */
- pstrcpy(option, sizeof(option), firstname);
- p = get_opt_value(value, sizeof(value), p);
- } else {
- /* option without value, probably a flag */
- p = get_opt_name(option, sizeof(option), p, ',');
- if (strncmp(option, "no", 2) == 0) {
- memmove(option, option+2, strlen(option+2)+1);
- pstrcpy(value, sizeof(value), "off");
- } else {
- pstrcpy(value, sizeof(value), "on");
- }
- }
- } else {
- /* found "foo=bar,more" */
- p = get_opt_name(option, sizeof(option), p, '=');
- if (*p != '=') {
- break;
- }
- p++;
- p = get_opt_value(value, sizeof(value), p);
- }
- if (strcmp(option, "id") != 0) {
- /* store and parse */
- opt_set(opts, option, value, prepend, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
- if (*p != ',') {
- break;
- }
- }
-}
-
-/**
- * Store options parsed from @params into @opts.
- * If @firstname is non-null, the first key=value in @params may omit
- * key=, and is treated as if key was @firstname.
- * On error, store an error object through @errp if non-null.
- */
-void qemu_opts_do_parse(QemuOpts *opts, const char *params,
- const char *firstname, Error **errp)
-{
- opts_do_parse(opts, params, firstname, false, errp);
-}
-
-static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
- bool permit_abbrev, bool defaults, Error **errp)
-{
- const char *firstname;
- char value[1024], *id = NULL;
- const char *p;
- QemuOpts *opts;
- Error *local_err = NULL;
-
- assert(!permit_abbrev || list->implied_opt_name);
- firstname = permit_abbrev ? list->implied_opt_name : NULL;
-
- if (strncmp(params, "id=", 3) == 0) {
- get_opt_value(value, sizeof(value), params+3);
- id = value;
- } else if ((p = strstr(params, ",id=")) != NULL) {
- get_opt_value(value, sizeof(value), p+4);
- id = value;
- }
-
- /*
- * This code doesn't work for defaults && !list->merge_lists: when
- * params has no id=, and list has an element with !opts->id, it
- * appends a new element instead of returning the existing opts.
- * However, we got no use for this case. Guard against possible
- * (if unlikely) future misuse:
- */
- assert(!defaults || list->merge_lists);
- opts = qemu_opts_create(list, id, !defaults, &local_err);
- if (opts == NULL) {
- error_propagate(errp, local_err);
- return NULL;
- }
-
- opts_do_parse(opts, params, firstname, defaults, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opts_del(opts);
- return NULL;
- }
-
- return opts;
-}
-
-/**
- * Create a QemuOpts in @list and with options parsed from @params.
- * If @permit_abbrev, the first key=value in @params may omit key=,
- * and is treated as if key was @list->implied_opt_name.
- * On error, store an error object through @errp if non-null.
- * Return the new QemuOpts on success, null pointer on error.
- */
-QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
- bool permit_abbrev, Error **errp)
-{
- return opts_parse(list, params, permit_abbrev, false, errp);
-}
-
-/**
- * Create a QemuOpts in @list and with options parsed from @params.
- * If @permit_abbrev, the first key=value in @params may omit key=,
- * and is treated as if key was @list->implied_opt_name.
- * Report errors with error_report_err(). This is inappropriate in
- * QMP context. Do not use this function there!
- * Return the new QemuOpts on success, null pointer on error.
- */
-QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
- bool permit_abbrev)
-{
- Error *err = NULL;
- QemuOpts *opts;
-
- opts = opts_parse(list, params, permit_abbrev, false, &err);
- if (err) {
- error_report_err(err);
- }
- return opts;
-}
-
-void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
- int permit_abbrev)
-{
- QemuOpts *opts;
-
- opts = opts_parse(list, params, permit_abbrev, true, NULL);
- assert(opts);
-}
-
-typedef struct OptsFromQDictState {
- QemuOpts *opts;
- Error **errp;
-} OptsFromQDictState;
-
-static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
-{
- OptsFromQDictState *state = opaque;
- char buf[32];
- const char *value;
- int n;
-
- if (!strcmp(key, "id") || *state->errp) {
- return;
- }
-
- switch (qobject_type(obj)) {
- case QTYPE_QSTRING:
- value = qstring_get_str(qobject_to_qstring(obj));
- break;
- case QTYPE_QINT:
- n = snprintf(buf, sizeof(buf), "%" PRId64,
- qint_get_int(qobject_to_qint(obj)));
- assert(n < sizeof(buf));
- value = buf;
- break;
- case QTYPE_QFLOAT:
- n = snprintf(buf, sizeof(buf), "%.17g",
- qfloat_get_double(qobject_to_qfloat(obj)));
- assert(n < sizeof(buf));
- value = buf;
- break;
- case QTYPE_QBOOL:
- pstrcpy(buf, sizeof(buf),
- qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off");
- value = buf;
- break;
- default:
- return;
- }
-
- qemu_opt_set(state->opts, key, value, state->errp);
-}
-
-/*
- * Create QemuOpts from a QDict.
- * Use value of key "id" as ID if it exists and is a QString.
- * Only QStrings, QInts, QFloats and QBools are copied. Entries with
- * other types are silently ignored.
- */
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
- Error **errp)
-{
- OptsFromQDictState state;
- Error *local_err = NULL;
- QemuOpts *opts;
-
- opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return NULL;
- }
-
- assert(opts != NULL);
-
- state.errp = &local_err;
- state.opts = opts;
- qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opts_del(opts);
- return NULL;
- }
-
- return opts;
-}
-
-/*
- * Adds all QDict entries to the QemuOpts that can be added and removes them
- * from the QDict. When this function returns, the QDict contains only those
- * entries that couldn't be added to the QemuOpts.
- */
-void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
-{
- const QDictEntry *entry, *next;
-
- entry = qdict_first(qdict);
-
- while (entry != NULL) {
- Error *local_err = NULL;
- OptsFromQDictState state = {
- .errp = &local_err,
- .opts = opts,
- };
-
- next = qdict_next(qdict, entry);
-
- if (find_desc_by_name(opts->list->desc, entry->key)) {
- qemu_opts_from_qdict_1(entry->key, entry->value, &state);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- } else {
- qdict_del(qdict, entry->key);
- }
- }
-
- entry = next;
- }
-}
-
-/*
- * Convert from QemuOpts to QDict.
- * The QDict values are of type QString.
- * TODO We'll want to use types appropriate for opt->desc->type, but
- * this is enough for now.
- */
-QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
-{
- QemuOpt *opt;
- QObject *val;
-
- if (!qdict) {
- qdict = qdict_new();
- }
- if (opts->id) {
- qdict_put(qdict, "id", qstring_from_str(opts->id));
- }
- QTAILQ_FOREACH(opt, &opts->head, next) {
- val = QOBJECT(qstring_from_str(opt->str));
- qdict_put_obj(qdict, opt->name, val);
- }
- return qdict;
-}
-
-/* Validate parsed opts against descriptions where no
- * descriptions were provided in the QemuOptsList.
- */
-void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
-{
- QemuOpt *opt;
- Error *local_err = NULL;
-
- assert(opts_accepts_any(opts));
-
- QTAILQ_FOREACH(opt, &opts->head, next) {
- opt->desc = find_desc_by_name(desc, opt->name);
- if (!opt->desc) {
- error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
- return;
- }
-
- qemu_opt_parse(opt, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
-}
-
-/**
- * For each member of @list, call @func(@opaque, member, @errp).
- * Call it with the current location temporarily set to the member's.
- * @func() may store an Error through @errp, but must return non-zero then.
- * When @func() returns non-zero, break the loop and return that value.
- * Return zero when the loop completes.
- */
-int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
- void *opaque, Error **errp)
-{
- Location loc;
- QemuOpts *opts;
- int rc = 0;
-
- loc_push_none(&loc);
- QTAILQ_FOREACH(opts, &list->head, next) {
- loc_restore(&opts->loc);
- rc = func(opaque, opts, errp);
- if (rc) {
- break;
- }
- assert(!errp || !*errp);
- }
- loc_pop(&loc);
- return rc;
-}
-
-static size_t count_opts_list(QemuOptsList *list)
-{
- QemuOptDesc *desc = NULL;
- size_t num_opts = 0;
-
- if (!list) {
- return 0;
- }
-
- desc = list->desc;
- while (desc && desc->name) {
- num_opts++;
- desc++;
- }
-
- return num_opts;
-}
-
-void qemu_opts_free(QemuOptsList *list)
-{
- g_free(list);
-}
-
-/* Realloc dst option list and append options from an option list (list)
- * to it. dst could be NULL or a malloced list.
- * The lifetime of dst must be shorter than the input list because the
- * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
- */
-QemuOptsList *qemu_opts_append(QemuOptsList *dst,
- QemuOptsList *list)
-{
- size_t num_opts, num_dst_opts;
- QemuOptDesc *desc;
- bool need_init = false;
- bool need_head_update;
-
- if (!list) {
- return dst;
- }
-
- /* If dst is NULL, after realloc, some area of dst should be initialized
- * before adding options to it.
- */
- if (!dst) {
- need_init = true;
- need_head_update = true;
- } else {
- /* Moreover, even if dst is not NULL, the realloc may move it to a
- * different address in which case we may get a stale tail pointer
- * in dst->head. */
- need_head_update = QTAILQ_EMPTY(&dst->head);
- }
-
- num_opts = count_opts_list(dst);
- num_dst_opts = num_opts;
- num_opts += count_opts_list(list);
- dst = g_realloc(dst, sizeof(QemuOptsList) +
- (num_opts + 1) * sizeof(QemuOptDesc));
- if (need_init) {
- dst->name = NULL;
- dst->implied_opt_name = NULL;
- dst->merge_lists = false;
- }
- if (need_head_update) {
- QTAILQ_INIT(&dst->head);
- }
- dst->desc[num_dst_opts].name = NULL;
-
- /* append list->desc to dst->desc */
- if (list) {
- desc = list->desc;
- while (desc && desc->name) {
- if (find_desc_by_name(dst->desc, desc->name) == NULL) {
- dst->desc[num_dst_opts++] = *desc;
- dst->desc[num_dst_opts].name = NULL;
- }
- desc++;
- }
- }
-
- return dst;
-}
diff --git a/qemu/util/qemu-progress.c b/qemu/util/qemu-progress.c
deleted file mode 100644
index f74523376..000000000
--- a/qemu/util/qemu-progress.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * QEMU progress printing utility functions
- *
- * Copyright (C) 2011 Jes Sorensen <Jes.Sorensen@redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-
-struct progress_state {
- float current;
- float last_print;
- float min_skip;
- void (*print)(void);
- void (*end)(void);
-};
-
-static struct progress_state state;
-static volatile sig_atomic_t print_pending;
-
-/*
- * Simple progress print function.
- * @percent relative percent of current operation
- * @max percent of total operation
- */
-static void progress_simple_print(void)
-{
- printf(" (%3.2f/100%%)\r", state.current);
- fflush(stdout);
-}
-
-static void progress_simple_end(void)
-{
- printf("\n");
-}
-
-static void progress_simple_init(void)
-{
- state.print = progress_simple_print;
- state.end = progress_simple_end;
-}
-
-#ifdef CONFIG_POSIX
-static void sigusr_print(int signal)
-{
- print_pending = 1;
-}
-#endif
-
-static void progress_dummy_print(void)
-{
- if (print_pending) {
- fprintf(stderr, " (%3.2f/100%%)\n", state.current);
- print_pending = 0;
- }
-}
-
-static void progress_dummy_end(void)
-{
-}
-
-static void progress_dummy_init(void)
-{
-#ifdef CONFIG_POSIX
- struct sigaction action;
- sigset_t set;
-
- memset(&action, 0, sizeof(action));
- sigfillset(&action.sa_mask);
- action.sa_handler = sigusr_print;
- action.sa_flags = 0;
- sigaction(SIGUSR1, &action, NULL);
-
- /*
- * SIGUSR1 is SIG_IPI and gets blocked in qemu_init_main_loop(). In the
- * tools that use the progress report SIGUSR1 isn't used in this meaning
- * and instead should print the progress, so reenable it.
- */
- sigemptyset(&set);
- sigaddset(&set, SIGUSR1);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-#endif
-
- state.print = progress_dummy_print;
- state.end = progress_dummy_end;
-}
-
-/*
- * Initialize progress reporting.
- * If @enabled is false, actual reporting is suppressed. The user can
- * still trigger a report by sending a SIGUSR1.
- * Reports are also suppressed unless we've had at least @min_skip
- * percent progress since the last report.
- */
-void qemu_progress_init(int enabled, float min_skip)
-{
- state.min_skip = min_skip;
- if (enabled) {
- progress_simple_init();
- } else {
- progress_dummy_init();
- }
-}
-
-void qemu_progress_end(void)
-{
- state.end();
-}
-
-/*
- * Report progress.
- * @delta is how much progress we made.
- * If @max is zero, @delta is an absolut value of the total job done.
- * Else, @delta is a progress delta since the last call, as a fraction
- * of @max. I.e. the delta is @delta * @max / 100. This allows
- * relative accounting of functions which may be a different fraction of
- * the full job, depending on the context they are called in. I.e.
- * a function might be considered 40% of the full job if used from
- * bdrv_img_create() but only 20% if called from img_convert().
- */
-void qemu_progress_print(float delta, int max)
-{
- float current;
-
- if (max == 0) {
- current = delta;
- } else {
- current = state.current + delta / 100 * max;
- }
- if (current > 100) {
- current = 100;
- }
- state.current = current;
-
- if (current > (state.last_print + state.min_skip) ||
- current < (state.last_print - state.min_skip) ||
- current == 100 || current == 0) {
- state.last_print = state.current;
- state.print();
- }
-}
diff --git a/qemu/util/qemu-sockets.c b/qemu/util/qemu-sockets.c
deleted file mode 100644
index 0d536911c..000000000
--- a/qemu/util/qemu-sockets.c
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
- * inet and unix socket functions for qemu
- *
- * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "qemu/osdep.h"
-
-#include "monitor/monitor.h"
-#include "qapi/error.h"
-#include "qemu/sockets.h"
-#include "qemu/main-loop.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi-visit.h"
-#include "qemu/cutils.h"
-
-#ifndef AI_ADDRCONFIG
-# define AI_ADDRCONFIG 0
-#endif
-
-#ifndef AI_V4MAPPED
-# define AI_V4MAPPED 0
-#endif
-
-
-static int inet_getport(struct addrinfo *e)
-{
- struct sockaddr_in *i4;
- struct sockaddr_in6 *i6;
-
- switch (e->ai_family) {
- case PF_INET6:
- i6 = (void*)e->ai_addr;
- return ntohs(i6->sin6_port);
- case PF_INET:
- i4 = (void*)e->ai_addr;
- return ntohs(i4->sin_port);
- default:
- return 0;
- }
-}
-
-static void inet_setport(struct addrinfo *e, int port)
-{
- struct sockaddr_in *i4;
- struct sockaddr_in6 *i6;
-
- switch (e->ai_family) {
- case PF_INET6:
- i6 = (void*)e->ai_addr;
- i6->sin6_port = htons(port);
- break;
- case PF_INET:
- i4 = (void*)e->ai_addr;
- i4->sin_port = htons(port);
- break;
- }
-}
-
-NetworkAddressFamily inet_netfamily(int family)
-{
- switch (family) {
- case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6;
- case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4;
- case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX;
- }
- return NETWORK_ADDRESS_FAMILY_UNKNOWN;
-}
-
-/*
- * Matrix we're trying to apply
- *
- * ipv4 ipv6 family
- * - - PF_UNSPEC
- * - f PF_INET
- * - t PF_INET6
- * f - PF_INET6
- * f f <error>
- * f t PF_INET6
- * t - PF_INET
- * t f PF_INET
- * t t PF_INET6
- *
- * NB, this matrix is only about getting the neccessary results
- * from getaddrinfo(). Some of the cases require further work
- * after reading results from getaddrinfo in order to fully
- * apply the logic the end user wants. eg with the last case
- * ipv4=t + ipv6=t + PF_INET6, getaddrinfo alone can only
- * guarantee the ipv6=t part of the request - we need more
- * checks to provide ipv4=t part of the guarantee. This is
- * outside scope of this method and not currently handled by
- * callers at all.
- */
-static int inet_ai_family_from_address(InetSocketAddress *addr,
- Error **errp)
-{
- if (addr->has_ipv6 && addr->has_ipv4 &&
- !addr->ipv6 && !addr->ipv4) {
- error_setg(errp, "Cannot disable IPv4 and IPv6 at same time");
- return PF_UNSPEC;
- }
- if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) {
- return PF_INET6;
- }
- if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) {
- return PF_INET;
- }
- return PF_UNSPEC;
-}
-
-static int inet_listen_saddr(InetSocketAddress *saddr,
- int port_offset,
- bool update_addr,
- Error **errp)
-{
- struct addrinfo ai,*res,*e;
- char port[33];
- char uaddr[INET6_ADDRSTRLEN+1];
- char uport[33];
- int slisten, rc, port_min, port_max, p;
- Error *err = NULL;
-
- memset(&ai,0, sizeof(ai));
- ai.ai_flags = AI_PASSIVE;
- ai.ai_family = inet_ai_family_from_address(saddr, &err);
- ai.ai_socktype = SOCK_STREAM;
-
- if (err) {
- error_propagate(errp, err);
- return -1;
- }
-
- if (saddr->host == NULL) {
- error_setg(errp, "host not specified");
- return -1;
- }
- if (saddr->port != NULL) {
- pstrcpy(port, sizeof(port), saddr->port);
- } else {
- port[0] = '\0';
- }
-
- /* lookup */
- if (port_offset) {
- unsigned long long baseport;
- if (strlen(port) == 0) {
- error_setg(errp, "port not specified");
- return -1;
- }
- if (parse_uint_full(port, &baseport, 10) < 0) {
- error_setg(errp, "can't convert to a number: %s", port);
- return -1;
- }
- if (baseport > 65535 ||
- baseport + port_offset > 65535) {
- error_setg(errp, "port %s out of range", port);
- return -1;
- }
- snprintf(port, sizeof(port), "%d", (int)baseport + port_offset);
- }
- rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL,
- strlen(port) ? port : NULL, &ai, &res);
- if (rc != 0) {
- error_setg(errp, "address resolution failed for %s:%s: %s",
- saddr->host, port, gai_strerror(rc));
- return -1;
- }
-
- /* create socket + bind */
- for (e = res; e != NULL; e = e->ai_next) {
- getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
- uaddr,INET6_ADDRSTRLEN,uport,32,
- NI_NUMERICHOST | NI_NUMERICSERV);
- slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
- if (slisten < 0) {
- if (!e->ai_next) {
- error_setg_errno(errp, errno, "Failed to create socket");
- }
- continue;
- }
-
- socket_set_fast_reuse(slisten);
-#ifdef IPV6_V6ONLY
- if (e->ai_family == PF_INET6) {
- /* listen on both ipv4 and ipv6 */
- const int off = 0;
- qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off,
- sizeof(off));
- }
-#endif
-
- port_min = inet_getport(e);
- port_max = saddr->has_to ? saddr->to + port_offset : port_min;
- for (p = port_min; p <= port_max; p++) {
- inet_setport(e, p);
- if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
- goto listen;
- }
- if (p == port_max) {
- if (!e->ai_next) {
- error_setg_errno(errp, errno, "Failed to bind socket");
- }
- }
- }
- closesocket(slisten);
- }
- freeaddrinfo(res);
- return -1;
-
-listen:
- if (listen(slisten,1) != 0) {
- error_setg_errno(errp, errno, "Failed to listen on socket");
- closesocket(slisten);
- freeaddrinfo(res);
- return -1;
- }
- if (update_addr) {
- g_free(saddr->host);
- saddr->host = g_strdup(uaddr);
- g_free(saddr->port);
- saddr->port = g_strdup_printf("%d",
- inet_getport(e) - port_offset);
- saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6;
- saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6;
- }
- freeaddrinfo(res);
- return slisten;
-}
-
-#ifdef _WIN32
-#define QEMU_SOCKET_RC_INPROGRESS(rc) \
- ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY)
-#else
-#define QEMU_SOCKET_RC_INPROGRESS(rc) \
- ((rc) == -EINPROGRESS)
-#endif
-
-/* Struct to store connect state for non blocking connect */
-typedef struct ConnectState {
- int fd;
- struct addrinfo *addr_list;
- struct addrinfo *current_addr;
- NonBlockingConnectHandler *callback;
- void *opaque;
-} ConnectState;
-
-static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
- ConnectState *connect_state, Error **errp);
-
-static void wait_for_connect(void *opaque)
-{
- ConnectState *s = opaque;
- int val = 0, rc = 0;
- socklen_t valsize = sizeof(val);
- bool in_progress;
- Error *err = NULL;
-
- qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-
- do {
- rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
- } while (rc == -1 && errno == EINTR);
-
- /* update rc to contain error */
- if (!rc && val) {
- rc = -1;
- errno = val;
- }
-
- /* connect error */
- if (rc < 0) {
- error_setg_errno(&err, errno, "Error connecting to socket");
- closesocket(s->fd);
- s->fd = rc;
- }
-
- /* try to connect to the next address on the list */
- if (s->current_addr) {
- while (s->current_addr->ai_next != NULL && s->fd < 0) {
- s->current_addr = s->current_addr->ai_next;
- s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL);
- if (s->fd < 0) {
- error_free(err);
- err = NULL;
- error_setg_errno(&err, errno, "Unable to start socket connect");
- }
- /* connect in progress */
- if (in_progress) {
- goto out;
- }
- }
-
- freeaddrinfo(s->addr_list);
- }
-
- if (s->callback) {
- s->callback(s->fd, err, s->opaque);
- }
- g_free(s);
-out:
- error_free(err);
-}
-
-static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
- ConnectState *connect_state, Error **errp)
-{
- int sock, rc;
-
- *in_progress = false;
-
- sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
- if (sock < 0) {
- error_setg_errno(errp, errno, "Failed to create socket");
- return -1;
- }
- socket_set_fast_reuse(sock);
- if (connect_state != NULL) {
- qemu_set_nonblock(sock);
- }
- /* connect to peer */
- do {
- rc = 0;
- if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
- rc = -errno;
- }
- } while (rc == -EINTR);
-
- if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
- connect_state->fd = sock;
- qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
- *in_progress = true;
- } else if (rc < 0) {
- error_setg_errno(errp, errno, "Failed to connect socket");
- closesocket(sock);
- return -1;
- }
- return sock;
-}
-
-static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
- Error **errp)
-{
- struct addrinfo ai, *res;
- int rc;
- Error *err = NULL;
- static int useV4Mapped = 1;
-
- memset(&ai, 0, sizeof(ai));
-
- ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
- if (atomic_read(&useV4Mapped)) {
- ai.ai_flags |= AI_V4MAPPED;
- }
- ai.ai_family = inet_ai_family_from_address(saddr, &err);
- ai.ai_socktype = SOCK_STREAM;
-
- if (err) {
- error_propagate(errp, err);
- return NULL;
- }
-
- if (saddr->host == NULL || saddr->port == NULL) {
- error_setg(errp, "host and/or port not specified");
- return NULL;
- }
-
- /* lookup */
- rc = getaddrinfo(saddr->host, saddr->port, &ai, &res);
-
- /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but
- * then don't implement it in their getaddrinfo(). Detect
- * this and retry without the flag since that's preferrable
- * to a fatal error
- */
- if (rc == EAI_BADFLAGS &&
- (ai.ai_flags & AI_V4MAPPED)) {
- atomic_set(&useV4Mapped, 0);
- ai.ai_flags &= ~AI_V4MAPPED;
- rc = getaddrinfo(saddr->host, saddr->port, &ai, &res);
- }
- if (rc != 0) {
- error_setg(errp, "address resolution failed for %s:%s: %s",
- saddr->host, saddr->port, gai_strerror(rc));
- return NULL;
- }
- return res;
-}
-
-/**
- * Create a socket and connect it to an address.
- *
- * @saddr: Inet socket address specification
- * @errp: set on error
- * @callback: callback function for non-blocking connect
- * @opaque: opaque for callback function
- *
- * Returns: -1 on error, file descriptor on success.
- *
- * If @callback is non-null, the connect is non-blocking. If this
- * function succeeds, callback will be called when the connection
- * completes, with the file descriptor on success, or -1 on error.
- */
-static int inet_connect_saddr(InetSocketAddress *saddr, Error **errp,
- NonBlockingConnectHandler *callback, void *opaque)
-{
- Error *local_err = NULL;
- struct addrinfo *res, *e;
- int sock = -1;
- bool in_progress;
- ConnectState *connect_state = NULL;
-
- res = inet_parse_connect_saddr(saddr, errp);
- if (!res) {
- return -1;
- }
-
- if (callback != NULL) {
- connect_state = g_malloc0(sizeof(*connect_state));
- connect_state->addr_list = res;
- connect_state->callback = callback;
- connect_state->opaque = opaque;
- }
-
- for (e = res; e != NULL; e = e->ai_next) {
- error_free(local_err);
- local_err = NULL;
- if (connect_state != NULL) {
- connect_state->current_addr = e;
- }
- sock = inet_connect_addr(e, &in_progress, connect_state, &local_err);
- if (sock >= 0) {
- break;
- }
- }
-
- if (sock < 0) {
- error_propagate(errp, local_err);
- } else if (in_progress) {
- /* wait_for_connect() will do the rest */
- return sock;
- } else {
- if (callback) {
- callback(sock, NULL, opaque);
- }
- }
- g_free(connect_state);
- freeaddrinfo(res);
- return sock;
-}
-
-static int inet_dgram_saddr(InetSocketAddress *sraddr,
- InetSocketAddress *sladdr,
- Error **errp)
-{
- struct addrinfo ai, *peer = NULL, *local = NULL;
- const char *addr;
- const char *port;
- int sock = -1, rc;
- Error *err = NULL;
-
- /* lookup peer addr */
- memset(&ai,0, sizeof(ai));
- ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG;
- ai.ai_family = inet_ai_family_from_address(sraddr, &err);
- ai.ai_socktype = SOCK_DGRAM;
-
- if (err) {
- error_propagate(errp, err);
- goto err;
- }
-
- addr = sraddr->host;
- port = sraddr->port;
- if (addr == NULL || strlen(addr) == 0) {
- addr = "localhost";
- }
- if (port == NULL || strlen(port) == 0) {
- error_setg(errp, "remote port not specified");
- goto err;
- }
-
- if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
- error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
- gai_strerror(rc));
- goto err;
- }
-
- /* lookup local addr */
- memset(&ai,0, sizeof(ai));
- ai.ai_flags = AI_PASSIVE;
- ai.ai_family = peer->ai_family;
- ai.ai_socktype = SOCK_DGRAM;
-
- if (sladdr) {
- addr = sladdr->host;
- port = sladdr->port;
- if (addr == NULL || strlen(addr) == 0) {
- addr = NULL;
- }
- if (!port || strlen(port) == 0) {
- port = "0";
- }
- } else {
- addr = NULL;
- port = "0";
- }
-
- if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
- error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
- gai_strerror(rc));
- goto err;
- }
-
- /* create socket */
- sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
- if (sock < 0) {
- error_setg_errno(errp, errno, "Failed to create socket");
- goto err;
- }
- socket_set_fast_reuse(sock);
-
- /* bind socket */
- if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
- error_setg_errno(errp, errno, "Failed to bind socket");
- goto err;
- }
-
- /* connect to peer */
- if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
- error_setg_errno(errp, errno, "Failed to connect socket");
- goto err;
- }
-
- freeaddrinfo(local);
- freeaddrinfo(peer);
- return sock;
-
-err:
- if (-1 != sock)
- closesocket(sock);
- if (local)
- freeaddrinfo(local);
- if (peer)
- freeaddrinfo(peer);
- return -1;
-}
-
-/* compatibility wrapper */
-InetSocketAddress *inet_parse(const char *str, Error **errp)
-{
- InetSocketAddress *addr;
- const char *optstr, *h;
- char host[65];
- char port[33];
- int to;
- int pos;
-
- addr = g_new0(InetSocketAddress, 1);
-
- /* parse address */
- if (str[0] == ':') {
- /* no host given */
- host[0] = '\0';
- if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) {
- error_setg(errp, "error parsing port in address '%s'", str);
- goto fail;
- }
- } else if (str[0] == '[') {
- /* IPv6 addr */
- if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) {
- error_setg(errp, "error parsing IPv6 address '%s'", str);
- goto fail;
- }
- addr->ipv6 = addr->has_ipv6 = true;
- } else {
- /* hostname or IPv4 addr */
- if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
- error_setg(errp, "error parsing address '%s'", str);
- goto fail;
- }
- if (host[strspn(host, "0123456789.")] == '\0') {
- addr->ipv4 = addr->has_ipv4 = true;
- }
- }
-
- addr->host = g_strdup(host);
- addr->port = g_strdup(port);
-
- /* parse options */
- optstr = str + pos;
- h = strstr(optstr, ",to=");
- if (h) {
- h += 4;
- if (sscanf(h, "%d%n", &to, &pos) != 1 ||
- (h[pos] != '\0' && h[pos] != ',')) {
- error_setg(errp, "error parsing to= argument");
- goto fail;
- }
- addr->has_to = true;
- addr->to = to;
- }
- if (strstr(optstr, ",ipv4")) {
- addr->ipv4 = addr->has_ipv4 = true;
- }
- if (strstr(optstr, ",ipv6")) {
- addr->ipv6 = addr->has_ipv6 = true;
- }
- return addr;
-
-fail:
- qapi_free_InetSocketAddress(addr);
- return NULL;
-}
-
-int inet_listen(const char *str, char *ostr, int olen,
- int socktype, int port_offset, Error **errp)
-{
- char *optstr;
- int sock = -1;
- InetSocketAddress *addr;
-
- addr = inet_parse(str, errp);
- if (addr != NULL) {
- sock = inet_listen_saddr(addr, port_offset, true, errp);
- if (sock != -1 && ostr) {
- optstr = strchr(str, ',');
- if (addr->ipv6) {
- snprintf(ostr, olen, "[%s]:%s%s",
- addr->host,
- addr->port,
- optstr ? optstr : "");
- } else {
- snprintf(ostr, olen, "%s:%s%s",
- addr->host,
- addr->port,
- optstr ? optstr : "");
- }
- }
- qapi_free_InetSocketAddress(addr);
- }
- return sock;
-}
-
-/**
- * Create a blocking socket and connect it to an address.
- *
- * @str: address string
- * @errp: set in case of an error
- *
- * Returns -1 in case of error, file descriptor on success
- **/
-int inet_connect(const char *str, Error **errp)
-{
- int sock = -1;
- InetSocketAddress *addr;
-
- addr = inet_parse(str, errp);
- if (addr != NULL) {
- sock = inet_connect_saddr(addr, errp, NULL, NULL);
- qapi_free_InetSocketAddress(addr);
- }
- return sock;
-}
-
-/**
- * Create a non-blocking socket and connect it to an address.
- * Calls the callback function with fd in case of success or -1 in case of
- * error.
- *
- * @str: address string
- * @callback: callback function that is called when connect completes,
- * cannot be NULL.
- * @opaque: opaque for callback function
- * @errp: set in case of an error
- *
- * Returns: -1 on immediate error, file descriptor on success.
- **/
-int inet_nonblocking_connect(const char *str,
- NonBlockingConnectHandler *callback,
- void *opaque, Error **errp)
-{
- int sock = -1;
- InetSocketAddress *addr;
-
- g_assert(callback != NULL);
-
- addr = inet_parse(str, errp);
- if (addr != NULL) {
- sock = inet_connect_saddr(addr, errp, callback, opaque);
- qapi_free_InetSocketAddress(addr);
- }
- return sock;
-}
-
-#ifndef _WIN32
-
-static int unix_listen_saddr(UnixSocketAddress *saddr,
- bool update_addr,
- Error **errp)
-{
- struct sockaddr_un un;
- int sock, fd;
-
- sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- error_setg_errno(errp, errno, "Failed to create Unix socket");
- return -1;
- }
-
- memset(&un, 0, sizeof(un));
- un.sun_family = AF_UNIX;
- if (saddr->path && strlen(saddr->path)) {
- snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path);
- } else {
- const char *tmpdir = getenv("TMPDIR");
- tmpdir = tmpdir ? tmpdir : "/tmp";
- if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
- tmpdir) >= sizeof(un.sun_path)) {
- error_setg_errno(errp, errno,
- "TMPDIR environment variable (%s) too large", tmpdir);
- goto err;
- }
-
- /*
- * This dummy fd usage silences the mktemp() unsecure warning.
- * Using mkstemp() doesn't make things more secure here
- * though. bind() complains about existing files, so we have
- * to unlink first and thus re-open the race window. The
- * worst case possible is bind() failing, i.e. a DoS attack.
- */
- fd = mkstemp(un.sun_path);
- if (fd < 0) {
- error_setg_errno(errp, errno,
- "Failed to make a temporary socket name in %s", tmpdir);
- goto err;
- }
- close(fd);
- if (update_addr) {
- g_free(saddr->path);
- saddr->path = g_strdup(un.sun_path);
- }
- }
-
- if (unlink(un.sun_path) < 0 && errno != ENOENT) {
- error_setg_errno(errp, errno,
- "Failed to unlink socket %s", un.sun_path);
- goto err;
- }
- if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
- error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path);
- goto err;
- }
- if (listen(sock, 1) < 0) {
- error_setg_errno(errp, errno, "Failed to listen on socket");
- goto err;
- }
-
- return sock;
-
-err:
- closesocket(sock);
- return -1;
-}
-
-static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp,
- NonBlockingConnectHandler *callback, void *opaque)
-{
- struct sockaddr_un un;
- ConnectState *connect_state = NULL;
- int sock, rc;
-
- if (saddr->path == NULL) {
- error_setg(errp, "unix connect: no path specified");
- return -1;
- }
-
- sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- error_setg_errno(errp, errno, "Failed to create socket");
- return -1;
- }
- if (callback != NULL) {
- connect_state = g_malloc0(sizeof(*connect_state));
- connect_state->callback = callback;
- connect_state->opaque = opaque;
- qemu_set_nonblock(sock);
- }
-
- memset(&un, 0, sizeof(un));
- un.sun_family = AF_UNIX;
- snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path);
-
- /* connect to peer */
- do {
- rc = 0;
- if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
- rc = -errno;
- }
- } while (rc == -EINTR);
-
- if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
- connect_state->fd = sock;
- qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
- return sock;
- } else if (rc >= 0) {
- /* non blocking socket immediate success, call callback */
- if (callback != NULL) {
- callback(sock, NULL, opaque);
- }
- }
-
- if (rc < 0) {
- error_setg_errno(errp, -rc, "Failed to connect socket");
- close(sock);
- sock = -1;
- }
-
- g_free(connect_state);
- return sock;
-}
-
-#else
-
-static int unix_listen_saddr(UnixSocketAddress *saddr,
- bool update_addr,
- Error **errp)
-{
- error_setg(errp, "unix sockets are not available on windows");
- errno = ENOTSUP;
- return -1;
-}
-
-static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp,
- NonBlockingConnectHandler *callback, void *opaque)
-{
- error_setg(errp, "unix sockets are not available on windows");
- errno = ENOTSUP;
- return -1;
-}
-#endif
-
-/* compatibility wrapper */
-int unix_listen(const char *str, char *ostr, int olen, Error **errp)
-{
- char *path, *optstr;
- int sock, len;
- UnixSocketAddress *saddr;
-
- saddr = g_new0(UnixSocketAddress, 1);
-
- optstr = strchr(str, ',');
- if (optstr) {
- len = optstr - str;
- if (len) {
- path = g_malloc(len+1);
- snprintf(path, len+1, "%.*s", len, str);
- saddr->path = path;
- }
- } else {
- saddr->path = g_strdup(str);
- }
-
- sock = unix_listen_saddr(saddr, true, errp);
-
- if (sock != -1 && ostr)
- snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : "");
- qapi_free_UnixSocketAddress(saddr);
- return sock;
-}
-
-int unix_connect(const char *path, Error **errp)
-{
- UnixSocketAddress *saddr;
- int sock;
-
- saddr = g_new0(UnixSocketAddress, 1);
- saddr->path = g_strdup(path);
- sock = unix_connect_saddr(saddr, errp, NULL, NULL);
- qapi_free_UnixSocketAddress(saddr);
- return sock;
-}
-
-
-int unix_nonblocking_connect(const char *path,
- NonBlockingConnectHandler *callback,
- void *opaque, Error **errp)
-{
- UnixSocketAddress *saddr;
- int sock = -1;
-
- g_assert(callback != NULL);
-
- saddr = g_new0(UnixSocketAddress, 1);
- saddr->path = g_strdup(path);
- sock = unix_connect_saddr(saddr, errp, callback, opaque);
- qapi_free_UnixSocketAddress(saddr);
- return sock;
-}
-
-SocketAddress *socket_parse(const char *str, Error **errp)
-{
- SocketAddress *addr;
-
- addr = g_new0(SocketAddress, 1);
- if (strstart(str, "unix:", NULL)) {
- if (str[5] == '\0') {
- error_setg(errp, "invalid Unix socket address");
- goto fail;
- } else {
- addr->type = SOCKET_ADDRESS_KIND_UNIX;
- addr->u.q_unix.data = g_new(UnixSocketAddress, 1);
- addr->u.q_unix.data->path = g_strdup(str + 5);
- }
- } else if (strstart(str, "fd:", NULL)) {
- if (str[3] == '\0') {
- error_setg(errp, "invalid file descriptor address");
- goto fail;
- } else {
- addr->type = SOCKET_ADDRESS_KIND_FD;
- addr->u.fd.data = g_new(String, 1);
- addr->u.fd.data->str = g_strdup(str + 3);
- }
- } else {
- addr->type = SOCKET_ADDRESS_KIND_INET;
- addr->u.inet.data = inet_parse(str, errp);
- if (addr->u.inet.data == NULL) {
- goto fail;
- }
- }
- return addr;
-
-fail:
- qapi_free_SocketAddress(addr);
- return NULL;
-}
-
-int socket_connect(SocketAddress *addr, Error **errp,
- NonBlockingConnectHandler *callback, void *opaque)
-{
- int fd;
-
- switch (addr->type) {
- case SOCKET_ADDRESS_KIND_INET:
- fd = inet_connect_saddr(addr->u.inet.data, errp, callback, opaque);
- break;
-
- case SOCKET_ADDRESS_KIND_UNIX:
- fd = unix_connect_saddr(addr->u.q_unix.data, errp, callback, opaque);
- break;
-
- case SOCKET_ADDRESS_KIND_FD:
- fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp);
- if (fd >= 0 && callback) {
- qemu_set_nonblock(fd);
- callback(fd, NULL, opaque);
- }
- break;
-
- default:
- abort();
- }
- return fd;
-}
-
-int socket_listen(SocketAddress *addr, Error **errp)
-{
- int fd;
-
- switch (addr->type) {
- case SOCKET_ADDRESS_KIND_INET:
- fd = inet_listen_saddr(addr->u.inet.data, 0, false, errp);
- break;
-
- case SOCKET_ADDRESS_KIND_UNIX:
- fd = unix_listen_saddr(addr->u.q_unix.data, false, errp);
- break;
-
- case SOCKET_ADDRESS_KIND_FD:
- fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp);
- break;
-
- default:
- abort();
- }
- return fd;
-}
-
-int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
-{
- int fd;
-
- switch (remote->type) {
- case SOCKET_ADDRESS_KIND_INET:
- fd = inet_dgram_saddr(remote->u.inet.data,
- local ? local->u.inet.data : NULL, errp);
- break;
-
- default:
- error_setg(errp, "socket type unsupported for datagram");
- fd = -1;
- }
- return fd;
-}
-
-
-static SocketAddress *
-socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
- socklen_t salen,
- Error **errp)
-{
- char host[NI_MAXHOST];
- char serv[NI_MAXSERV];
- SocketAddress *addr;
- InetSocketAddress *inet;
- int ret;
-
- ret = getnameinfo((struct sockaddr *)sa, salen,
- host, sizeof(host),
- serv, sizeof(serv),
- NI_NUMERICHOST | NI_NUMERICSERV);
- if (ret != 0) {
- error_setg(errp, "Cannot format numeric socket address: %s",
- gai_strerror(ret));
- return NULL;
- }
-
- addr = g_new0(SocketAddress, 1);
- addr->type = SOCKET_ADDRESS_KIND_INET;
- inet = addr->u.inet.data = g_new0(InetSocketAddress, 1);
- inet->host = g_strdup(host);
- inet->port = g_strdup(serv);
- if (sa->ss_family == AF_INET) {
- inet->has_ipv4 = inet->ipv4 = true;
- } else {
- inet->has_ipv6 = inet->ipv6 = true;
- }
-
- return addr;
-}
-
-
-#ifndef WIN32
-static SocketAddress *
-socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
- socklen_t salen,
- Error **errp)
-{
- SocketAddress *addr;
- struct sockaddr_un *su = (struct sockaddr_un *)sa;
-
- addr = g_new0(SocketAddress, 1);
- addr->type = SOCKET_ADDRESS_KIND_UNIX;
- addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
- if (su->sun_path[0]) {
- addr->u.q_unix.data->path = g_strndup(su->sun_path,
- sizeof(su->sun_path));
- }
-
- return addr;
-}
-#endif /* WIN32 */
-
-SocketAddress *
-socket_sockaddr_to_address(struct sockaddr_storage *sa,
- socklen_t salen,
- Error **errp)
-{
- switch (sa->ss_family) {
- case AF_INET:
- case AF_INET6:
- return socket_sockaddr_to_address_inet(sa, salen, errp);
-
-#ifndef WIN32
- case AF_UNIX:
- return socket_sockaddr_to_address_unix(sa, salen, errp);
-#endif /* WIN32 */
-
- default:
- error_setg(errp, "socket family %d unsupported",
- sa->ss_family);
- return NULL;
- }
- return 0;
-}
-
-
-SocketAddress *socket_local_address(int fd, Error **errp)
-{
- struct sockaddr_storage ss;
- socklen_t sslen = sizeof(ss);
-
- if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
- error_setg_errno(errp, errno, "%s",
- "Unable to query local socket address");
- return NULL;
- }
-
- return socket_sockaddr_to_address(&ss, sslen, errp);
-}
-
-
-SocketAddress *socket_remote_address(int fd, Error **errp)
-{
- struct sockaddr_storage ss;
- socklen_t sslen = sizeof(ss);
-
- if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) {
- error_setg_errno(errp, errno, "%s",
- "Unable to query remote socket address");
- return NULL;
- }
-
- return socket_sockaddr_to_address(&ss, sslen, errp);
-}
-
-
-void qapi_copy_SocketAddress(SocketAddress **p_dest,
- SocketAddress *src)
-{
- QmpOutputVisitor *qov;
- QmpInputVisitor *qiv;
- Visitor *ov, *iv;
- QObject *obj;
-
- *p_dest = NULL;
-
- qov = qmp_output_visitor_new();
- ov = qmp_output_get_visitor(qov);
- visit_type_SocketAddress(ov, NULL, &src, &error_abort);
- obj = qmp_output_get_qobject(qov);
- qmp_output_visitor_cleanup(qov);
- if (!obj) {
- return;
- }
-
- qiv = qmp_input_visitor_new(obj);
- iv = qmp_input_get_visitor(qiv);
- visit_type_SocketAddress(iv, NULL, p_dest, &error_abort);
- qmp_input_visitor_cleanup(qiv);
- qobject_decref(obj);
-}
diff --git a/qemu/util/qemu-thread-posix.c b/qemu/util/qemu-thread-posix.c
deleted file mode 100644
index 74a3023f3..000000000
--- a/qemu/util/qemu-thread-posix.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Wrappers around mutex/cond/thread functions
- *
- * Copyright Red Hat, Inc. 2009
- *
- * Author:
- * Marcelo Tosatti <mtosatti@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-#include "qemu/osdep.h"
-#ifdef __linux__
-#include <sys/syscall.h>
-#include <linux/futex.h>
-#endif
-#include "qemu/thread.h"
-#include "qemu/atomic.h"
-#include "qemu/notify.h"
-
-static bool name_threads;
-
-void qemu_thread_naming(bool enable)
-{
- name_threads = enable;
-
-#ifndef CONFIG_THREAD_SETNAME_BYTHREAD
- /* This is a debugging option, not fatal */
- if (enable) {
- fprintf(stderr, "qemu: thread naming not supported on this host\n");
- }
-#endif
-}
-
-static void error_exit(int err, const char *msg)
-{
- fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
- abort();
-}
-
-void qemu_mutex_init(QemuMutex *mutex)
-{
- int err;
-
- err = pthread_mutex_init(&mutex->lock, NULL);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_mutex_destroy(QemuMutex *mutex)
-{
- int err;
-
- err = pthread_mutex_destroy(&mutex->lock);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_mutex_lock(QemuMutex *mutex)
-{
- int err;
-
- err = pthread_mutex_lock(&mutex->lock);
- if (err)
- error_exit(err, __func__);
-}
-
-int qemu_mutex_trylock(QemuMutex *mutex)
-{
- return pthread_mutex_trylock(&mutex->lock);
-}
-
-void qemu_mutex_unlock(QemuMutex *mutex)
-{
- int err;
-
- err = pthread_mutex_unlock(&mutex->lock);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_cond_init(QemuCond *cond)
-{
- int err;
-
- err = pthread_cond_init(&cond->cond, NULL);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_cond_destroy(QemuCond *cond)
-{
- int err;
-
- err = pthread_cond_destroy(&cond->cond);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_cond_signal(QemuCond *cond)
-{
- int err;
-
- err = pthread_cond_signal(&cond->cond);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_cond_broadcast(QemuCond *cond)
-{
- int err;
-
- err = pthread_cond_broadcast(&cond->cond);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
-{
- int err;
-
- err = pthread_cond_wait(&cond->cond, &mutex->lock);
- if (err)
- error_exit(err, __func__);
-}
-
-void qemu_sem_init(QemuSemaphore *sem, int init)
-{
- int rc;
-
-#if defined(__APPLE__) || defined(__NetBSD__)
- rc = pthread_mutex_init(&sem->lock, NULL);
- if (rc != 0) {
- error_exit(rc, __func__);
- }
- rc = pthread_cond_init(&sem->cond, NULL);
- if (rc != 0) {
- error_exit(rc, __func__);
- }
- if (init < 0) {
- error_exit(EINVAL, __func__);
- }
- sem->count = init;
-#else
- rc = sem_init(&sem->sem, 0, init);
- if (rc < 0) {
- error_exit(errno, __func__);
- }
-#endif
-}
-
-void qemu_sem_destroy(QemuSemaphore *sem)
-{
- int rc;
-
-#if defined(__APPLE__) || defined(__NetBSD__)
- rc = pthread_cond_destroy(&sem->cond);
- if (rc < 0) {
- error_exit(rc, __func__);
- }
- rc = pthread_mutex_destroy(&sem->lock);
- if (rc < 0) {
- error_exit(rc, __func__);
- }
-#else
- rc = sem_destroy(&sem->sem);
- if (rc < 0) {
- error_exit(errno, __func__);
- }
-#endif
-}
-
-void qemu_sem_post(QemuSemaphore *sem)
-{
- int rc;
-
-#if defined(__APPLE__) || defined(__NetBSD__)
- pthread_mutex_lock(&sem->lock);
- if (sem->count == UINT_MAX) {
- rc = EINVAL;
- } else {
- sem->count++;
- rc = pthread_cond_signal(&sem->cond);
- }
- pthread_mutex_unlock(&sem->lock);
- if (rc != 0) {
- error_exit(rc, __func__);
- }
-#else
- rc = sem_post(&sem->sem);
- if (rc < 0) {
- error_exit(errno, __func__);
- }
-#endif
-}
-
-static void compute_abs_deadline(struct timespec *ts, int ms)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
- ts->tv_sec = tv.tv_sec + ms / 1000;
- if (ts->tv_nsec >= 1000000000) {
- ts->tv_sec++;
- ts->tv_nsec -= 1000000000;
- }
-}
-
-int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
-{
- int rc;
- struct timespec ts;
-
-#if defined(__APPLE__) || defined(__NetBSD__)
- rc = 0;
- compute_abs_deadline(&ts, ms);
- pthread_mutex_lock(&sem->lock);
- while (sem->count == 0) {
- rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts);
- if (rc == ETIMEDOUT) {
- break;
- }
- if (rc != 0) {
- error_exit(rc, __func__);
- }
- }
- if (rc != ETIMEDOUT) {
- --sem->count;
- }
- pthread_mutex_unlock(&sem->lock);
- return (rc == ETIMEDOUT ? -1 : 0);
-#else
- if (ms <= 0) {
- /* This is cheaper than sem_timedwait. */
- do {
- rc = sem_trywait(&sem->sem);
- } while (rc == -1 && errno == EINTR);
- if (rc == -1 && errno == EAGAIN) {
- return -1;
- }
- } else {
- compute_abs_deadline(&ts, ms);
- do {
- rc = sem_timedwait(&sem->sem, &ts);
- } while (rc == -1 && errno == EINTR);
- if (rc == -1 && errno == ETIMEDOUT) {
- return -1;
- }
- }
- if (rc < 0) {
- error_exit(errno, __func__);
- }
- return 0;
-#endif
-}
-
-void qemu_sem_wait(QemuSemaphore *sem)
-{
- int rc;
-
-#if defined(__APPLE__) || defined(__NetBSD__)
- pthread_mutex_lock(&sem->lock);
- while (sem->count == 0) {
- rc = pthread_cond_wait(&sem->cond, &sem->lock);
- if (rc != 0) {
- error_exit(rc, __func__);
- }
- }
- --sem->count;
- pthread_mutex_unlock(&sem->lock);
-#else
- do {
- rc = sem_wait(&sem->sem);
- } while (rc == -1 && errno == EINTR);
- if (rc < 0) {
- error_exit(errno, __func__);
- }
-#endif
-}
-
-#ifdef __linux__
-#define futex(...) syscall(__NR_futex, __VA_ARGS__)
-
-static inline void futex_wake(QemuEvent *ev, int n)
-{
- futex(ev, FUTEX_WAKE, n, NULL, NULL, 0);
-}
-
-static inline void futex_wait(QemuEvent *ev, unsigned val)
-{
- while (futex(ev, FUTEX_WAIT, (int) val, NULL, NULL, 0)) {
- switch (errno) {
- case EWOULDBLOCK:
- return;
- case EINTR:
- break; /* get out of switch and retry */
- default:
- abort();
- }
- }
-}
-#else
-static inline void futex_wake(QemuEvent *ev, int n)
-{
- pthread_mutex_lock(&ev->lock);
- if (n == 1) {
- pthread_cond_signal(&ev->cond);
- } else {
- pthread_cond_broadcast(&ev->cond);
- }
- pthread_mutex_unlock(&ev->lock);
-}
-
-static inline void futex_wait(QemuEvent *ev, unsigned val)
-{
- pthread_mutex_lock(&ev->lock);
- if (ev->value == val) {
- pthread_cond_wait(&ev->cond, &ev->lock);
- }
- pthread_mutex_unlock(&ev->lock);
-}
-#endif
-
-/* Valid transitions:
- * - free->set, when setting the event
- * - busy->set, when setting the event, followed by futex_wake
- * - set->free, when resetting the event
- * - free->busy, when waiting
- *
- * set->busy does not happen (it can be observed from the outside but
- * it really is set->free->busy).
- *
- * busy->free provably cannot happen; to enforce it, the set->free transition
- * is done with an OR, which becomes a no-op if the event has concurrently
- * transitioned to free or busy.
- */
-
-#define EV_SET 0
-#define EV_FREE 1
-#define EV_BUSY -1
-
-void qemu_event_init(QemuEvent *ev, bool init)
-{
-#ifndef __linux__
- pthread_mutex_init(&ev->lock, NULL);
- pthread_cond_init(&ev->cond, NULL);
-#endif
-
- ev->value = (init ? EV_SET : EV_FREE);
-}
-
-void qemu_event_destroy(QemuEvent *ev)
-{
-#ifndef __linux__
- pthread_mutex_destroy(&ev->lock);
- pthread_cond_destroy(&ev->cond);
-#endif
-}
-
-void qemu_event_set(QemuEvent *ev)
-{
- if (atomic_mb_read(&ev->value) != EV_SET) {
- if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
- /* There were waiters, wake them up. */
- futex_wake(ev, INT_MAX);
- }
- }
-}
-
-void qemu_event_reset(QemuEvent *ev)
-{
- if (atomic_mb_read(&ev->value) == EV_SET) {
- /*
- * If there was a concurrent reset (or even reset+wait),
- * do nothing. Otherwise change EV_SET->EV_FREE.
- */
- atomic_or(&ev->value, EV_FREE);
- }
-}
-
-void qemu_event_wait(QemuEvent *ev)
-{
- unsigned value;
-
- value = atomic_mb_read(&ev->value);
- if (value != EV_SET) {
- if (value == EV_FREE) {
- /*
- * Leave the event reset and tell qemu_event_set that there
- * are waiters. No need to retry, because there cannot be
- * a concurrent busy->free transition. After the CAS, the
- * event will be either set or busy.
- */
- if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) {
- return;
- }
- }
- futex_wait(ev, EV_BUSY);
- }
-}
-
-static pthread_key_t exit_key;
-
-union NotifierThreadData {
- void *ptr;
- NotifierList list;
-};
-QEMU_BUILD_BUG_ON(sizeof(union NotifierThreadData) != sizeof(void *));
-
-void qemu_thread_atexit_add(Notifier *notifier)
-{
- union NotifierThreadData ntd;
- ntd.ptr = pthread_getspecific(exit_key);
- notifier_list_add(&ntd.list, notifier);
- pthread_setspecific(exit_key, ntd.ptr);
-}
-
-void qemu_thread_atexit_remove(Notifier *notifier)
-{
- union NotifierThreadData ntd;
- ntd.ptr = pthread_getspecific(exit_key);
- notifier_remove(notifier);
- pthread_setspecific(exit_key, ntd.ptr);
-}
-
-static void qemu_thread_atexit_run(void *arg)
-{
- union NotifierThreadData ntd = { .ptr = arg };
- notifier_list_notify(&ntd.list, NULL);
-}
-
-static void __attribute__((constructor)) qemu_thread_atexit_init(void)
-{
- pthread_key_create(&exit_key, qemu_thread_atexit_run);
-}
-
-
-/* Attempt to set the threads name; note that this is for debug, so
- * we're not going to fail if we can't set it.
- */
-static void qemu_thread_set_name(QemuThread *thread, const char *name)
-{
-#ifdef CONFIG_PTHREAD_SETNAME_NP
- pthread_setname_np(thread->thread, name);
-#endif
-}
-
-void qemu_thread_create(QemuThread *thread, const char *name,
- void *(*start_routine)(void*),
- void *arg, int mode)
-{
- sigset_t set, oldset;
- int err;
- pthread_attr_t attr;
-
- err = pthread_attr_init(&attr);
- if (err) {
- error_exit(err, __func__);
- }
- if (mode == QEMU_THREAD_DETACHED) {
- err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (err) {
- error_exit(err, __func__);
- }
- }
-
- /* Leave signal handling to the iothread. */
- sigfillset(&set);
- pthread_sigmask(SIG_SETMASK, &set, &oldset);
- err = pthread_create(&thread->thread, &attr, start_routine, arg);
- if (err)
- error_exit(err, __func__);
-
- if (name_threads) {
- qemu_thread_set_name(thread, name);
- }
-
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-
- pthread_attr_destroy(&attr);
-}
-
-void qemu_thread_get_self(QemuThread *thread)
-{
- thread->thread = pthread_self();
-}
-
-bool qemu_thread_is_self(QemuThread *thread)
-{
- return pthread_equal(pthread_self(), thread->thread);
-}
-
-void qemu_thread_exit(void *retval)
-{
- pthread_exit(retval);
-}
-
-void *qemu_thread_join(QemuThread *thread)
-{
- int err;
- void *ret;
-
- err = pthread_join(thread->thread, &ret);
- if (err) {
- error_exit(err, __func__);
- }
- return ret;
-}
diff --git a/qemu/util/qemu-thread-win32.c b/qemu/util/qemu-thread-win32.c
deleted file mode 100644
index 98a5ddff8..000000000
--- a/qemu/util/qemu-thread-win32.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Win32 implementation for mutex/cond/thread functions
- *
- * Copyright Red Hat, Inc. 2010
- *
- * Author:
- * Paolo Bonzini <pbonzini@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/thread.h"
-#include "qemu/notify.h"
-#include <process.h>
-
-static bool name_threads;
-
-void qemu_thread_naming(bool enable)
-{
- /* But note we don't actually name them on Windows yet */
- name_threads = enable;
-
- fprintf(stderr, "qemu: thread naming not supported on this host\n");
-}
-
-static void error_exit(int err, const char *msg)
-{
- char *pstr;
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
- fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
- LocalFree(pstr);
- abort();
-}
-
-void qemu_mutex_init(QemuMutex *mutex)
-{
- mutex->owner = 0;
- InitializeCriticalSection(&mutex->lock);
-}
-
-void qemu_mutex_destroy(QemuMutex *mutex)
-{
- assert(mutex->owner == 0);
- DeleteCriticalSection(&mutex->lock);
-}
-
-void qemu_mutex_lock(QemuMutex *mutex)
-{
- EnterCriticalSection(&mutex->lock);
-
- /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
- * using them as such.
- */
- assert(mutex->owner == 0);
- mutex->owner = GetCurrentThreadId();
-}
-
-int qemu_mutex_trylock(QemuMutex *mutex)
-{
- int owned;
-
- owned = TryEnterCriticalSection(&mutex->lock);
- if (owned) {
- assert(mutex->owner == 0);
- mutex->owner = GetCurrentThreadId();
- }
- return !owned;
-}
-
-void qemu_mutex_unlock(QemuMutex *mutex)
-{
- assert(mutex->owner == GetCurrentThreadId());
- mutex->owner = 0;
- LeaveCriticalSection(&mutex->lock);
-}
-
-void qemu_cond_init(QemuCond *cond)
-{
- memset(cond, 0, sizeof(*cond));
-
- cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
- if (!cond->sema) {
- error_exit(GetLastError(), __func__);
- }
- cond->continue_event = CreateEvent(NULL, /* security */
- FALSE, /* auto-reset */
- FALSE, /* not signaled */
- NULL); /* name */
- if (!cond->continue_event) {
- error_exit(GetLastError(), __func__);
- }
-}
-
-void qemu_cond_destroy(QemuCond *cond)
-{
- BOOL result;
- result = CloseHandle(cond->continue_event);
- if (!result) {
- error_exit(GetLastError(), __func__);
- }
- cond->continue_event = 0;
- result = CloseHandle(cond->sema);
- if (!result) {
- error_exit(GetLastError(), __func__);
- }
- cond->sema = 0;
-}
-
-void qemu_cond_signal(QemuCond *cond)
-{
- DWORD result;
-
- /*
- * Signal only when there are waiters. cond->waiters is
- * incremented by pthread_cond_wait under the external lock,
- * so we are safe about that.
- */
- if (cond->waiters == 0) {
- return;
- }
-
- /*
- * Waiting threads decrement it outside the external lock, but
- * only if another thread is executing pthread_cond_broadcast and
- * has the mutex. So, it also cannot be decremented concurrently
- * with this particular access.
- */
- cond->target = cond->waiters - 1;
- result = SignalObjectAndWait(cond->sema, cond->continue_event,
- INFINITE, FALSE);
- if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
- error_exit(GetLastError(), __func__);
- }
-}
-
-void qemu_cond_broadcast(QemuCond *cond)
-{
- BOOLEAN result;
- /*
- * As in pthread_cond_signal, access to cond->waiters and
- * cond->target is locked via the external mutex.
- */
- if (cond->waiters == 0) {
- return;
- }
-
- cond->target = 0;
- result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
- if (!result) {
- error_exit(GetLastError(), __func__);
- }
-
- /*
- * At this point all waiters continue. Each one takes its
- * slice of the semaphore. Now it's our turn to wait: Since
- * the external mutex is held, no thread can leave cond_wait,
- * yet. For this reason, we can be sure that no thread gets
- * a chance to eat *more* than one slice. OTOH, it means
- * that the last waiter must send us a wake-up.
- */
- WaitForSingleObject(cond->continue_event, INFINITE);
-}
-
-void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
-{
- /*
- * This access is protected under the mutex.
- */
- cond->waiters++;
-
- /*
- * Unlock external mutex and wait for signal.
- * NOTE: we've held mutex locked long enough to increment
- * waiters count above, so there's no problem with
- * leaving mutex unlocked before we wait on semaphore.
- */
- qemu_mutex_unlock(mutex);
- WaitForSingleObject(cond->sema, INFINITE);
-
- /* Now waiters must rendez-vous with the signaling thread and
- * let it continue. For cond_broadcast this has heavy contention
- * and triggers thundering herd. So goes life.
- *
- * Decrease waiters count. The mutex is not taken, so we have
- * to do this atomically.
- *
- * All waiters contend for the mutex at the end of this function
- * until the signaling thread relinquishes it. To ensure
- * each waiter consumes exactly one slice of the semaphore,
- * the signaling thread stops until it is told by the last
- * waiter that it can go on.
- */
- if (InterlockedDecrement(&cond->waiters) == cond->target) {
- SetEvent(cond->continue_event);
- }
-
- qemu_mutex_lock(mutex);
-}
-
-void qemu_sem_init(QemuSemaphore *sem, int init)
-{
- /* Manual reset. */
- sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
-}
-
-void qemu_sem_destroy(QemuSemaphore *sem)
-{
- CloseHandle(sem->sema);
-}
-
-void qemu_sem_post(QemuSemaphore *sem)
-{
- ReleaseSemaphore(sem->sema, 1, NULL);
-}
-
-int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
-{
- int rc = WaitForSingleObject(sem->sema, ms);
- if (rc == WAIT_OBJECT_0) {
- return 0;
- }
- if (rc != WAIT_TIMEOUT) {
- error_exit(GetLastError(), __func__);
- }
- return -1;
-}
-
-void qemu_sem_wait(QemuSemaphore *sem)
-{
- if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
- error_exit(GetLastError(), __func__);
- }
-}
-
-/* Wrap a Win32 manual-reset event with a fast userspace path. The idea
- * is to reset the Win32 event lazily, as part of a test-reset-test-wait
- * sequence. Such a sequence is, indeed, how QemuEvents are used by
- * RCU and other subsystems!
- *
- * Valid transitions:
- * - free->set, when setting the event
- * - busy->set, when setting the event, followed by futex_wake
- * - set->free, when resetting the event
- * - free->busy, when waiting
- *
- * set->busy does not happen (it can be observed from the outside but
- * it really is set->free->busy).
- *
- * busy->free provably cannot happen; to enforce it, the set->free transition
- * is done with an OR, which becomes a no-op if the event has concurrently
- * transitioned to free or busy (and is faster than cmpxchg).
- */
-
-#define EV_SET 0
-#define EV_FREE 1
-#define EV_BUSY -1
-
-void qemu_event_init(QemuEvent *ev, bool init)
-{
- /* Manual reset. */
- ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
- ev->value = (init ? EV_SET : EV_FREE);
-}
-
-void qemu_event_destroy(QemuEvent *ev)
-{
- CloseHandle(ev->event);
-}
-
-void qemu_event_set(QemuEvent *ev)
-{
- if (atomic_mb_read(&ev->value) != EV_SET) {
- if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
- /* There were waiters, wake them up. */
- SetEvent(ev->event);
- }
- }
-}
-
-void qemu_event_reset(QemuEvent *ev)
-{
- if (atomic_mb_read(&ev->value) == EV_SET) {
- /* If there was a concurrent reset (or even reset+wait),
- * do nothing. Otherwise change EV_SET->EV_FREE.
- */
- atomic_or(&ev->value, EV_FREE);
- }
-}
-
-void qemu_event_wait(QemuEvent *ev)
-{
- unsigned value;
-
- value = atomic_mb_read(&ev->value);
- if (value != EV_SET) {
- if (value == EV_FREE) {
- /* qemu_event_set is not yet going to call SetEvent, but we are
- * going to do another check for EV_SET below when setting EV_BUSY.
- * At that point it is safe to call WaitForSingleObject.
- */
- ResetEvent(ev->event);
-
- /* Tell qemu_event_set that there are waiters. No need to retry
- * because there cannot be a concurent busy->free transition.
- * After the CAS, the event will be either set or busy.
- */
- if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) {
- value = EV_SET;
- } else {
- value = EV_BUSY;
- }
- }
- if (value == EV_BUSY) {
- WaitForSingleObject(ev->event, INFINITE);
- }
- }
-}
-
-struct QemuThreadData {
- /* Passed to win32_start_routine. */
- void *(*start_routine)(void *);
- void *arg;
- short mode;
- NotifierList exit;
-
- /* Only used for joinable threads. */
- bool exited;
- void *ret;
- CRITICAL_SECTION cs;
-};
-
-static bool atexit_registered;
-static NotifierList main_thread_exit;
-
-static __thread QemuThreadData *qemu_thread_data;
-
-static void run_main_thread_exit(void)
-{
- notifier_list_notify(&main_thread_exit, NULL);
-}
-
-void qemu_thread_atexit_add(Notifier *notifier)
-{
- if (!qemu_thread_data) {
- if (!atexit_registered) {
- atexit_registered = true;
- atexit(run_main_thread_exit);
- }
- notifier_list_add(&main_thread_exit, notifier);
- } else {
- notifier_list_add(&qemu_thread_data->exit, notifier);
- }
-}
-
-void qemu_thread_atexit_remove(Notifier *notifier)
-{
- notifier_remove(notifier);
-}
-
-static unsigned __stdcall win32_start_routine(void *arg)
-{
- QemuThreadData *data = (QemuThreadData *) arg;
- void *(*start_routine)(void *) = data->start_routine;
- void *thread_arg = data->arg;
-
- qemu_thread_data = data;
- qemu_thread_exit(start_routine(thread_arg));
- abort();
-}
-
-void qemu_thread_exit(void *arg)
-{
- QemuThreadData *data = qemu_thread_data;
-
- notifier_list_notify(&data->exit, NULL);
- if (data->mode == QEMU_THREAD_JOINABLE) {
- data->ret = arg;
- EnterCriticalSection(&data->cs);
- data->exited = true;
- LeaveCriticalSection(&data->cs);
- } else {
- g_free(data);
- }
- _endthreadex(0);
-}
-
-void *qemu_thread_join(QemuThread *thread)
-{
- QemuThreadData *data;
- void *ret;
- HANDLE handle;
-
- data = thread->data;
- if (data->mode == QEMU_THREAD_DETACHED) {
- return NULL;
- }
-
- /*
- * Because multiple copies of the QemuThread can exist via
- * qemu_thread_get_self, we need to store a value that cannot
- * leak there. The simplest, non racy way is to store the TID,
- * discard the handle that _beginthreadex gives back, and
- * get another copy of the handle here.
- */
- handle = qemu_thread_get_handle(thread);
- if (handle) {
- WaitForSingleObject(handle, INFINITE);
- CloseHandle(handle);
- }
- ret = data->ret;
- DeleteCriticalSection(&data->cs);
- g_free(data);
- return ret;
-}
-
-void qemu_thread_create(QemuThread *thread, const char *name,
- void *(*start_routine)(void *),
- void *arg, int mode)
-{
- HANDLE hThread;
- struct QemuThreadData *data;
-
- data = g_malloc(sizeof *data);
- data->start_routine = start_routine;
- data->arg = arg;
- data->mode = mode;
- data->exited = false;
- notifier_list_init(&data->exit);
-
- if (data->mode != QEMU_THREAD_DETACHED) {
- InitializeCriticalSection(&data->cs);
- }
-
- hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
- data, 0, &thread->tid);
- if (!hThread) {
- error_exit(GetLastError(), __func__);
- }
- CloseHandle(hThread);
- thread->data = data;
-}
-
-void qemu_thread_get_self(QemuThread *thread)
-{
- thread->data = qemu_thread_data;
- thread->tid = GetCurrentThreadId();
-}
-
-HANDLE qemu_thread_get_handle(QemuThread *thread)
-{
- QemuThreadData *data;
- HANDLE handle;
-
- data = thread->data;
- if (data->mode == QEMU_THREAD_DETACHED) {
- return NULL;
- }
-
- EnterCriticalSection(&data->cs);
- if (!data->exited) {
- handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
- thread->tid);
- } else {
- handle = NULL;
- }
- LeaveCriticalSection(&data->cs);
- return handle;
-}
-
-bool qemu_thread_is_self(QemuThread *thread)
-{
- return GetCurrentThreadId() == thread->tid;
-}
diff --git a/qemu/util/qemu-timer-common.c b/qemu/util/qemu-timer-common.c
deleted file mode 100644
index 06d084d36..000000000
--- a/qemu/util/qemu-timer-common.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu/osdep.h"
-#include "qemu/timer.h"
-
-/***********************************************************/
-/* real time host monotonic timer */
-
-#ifdef _WIN32
-
-int64_t clock_freq;
-
-static void __attribute__((constructor)) init_get_clock(void)
-{
- LARGE_INTEGER freq;
- int ret;
- ret = QueryPerformanceFrequency(&freq);
- if (ret == 0) {
- fprintf(stderr, "Could not calibrate ticks\n");
- exit(1);
- }
- clock_freq = freq.QuadPart;
-}
-
-#else
-
-int use_rt_clock;
-
-static void __attribute__((constructor)) init_get_clock(void)
-{
- use_rt_clock = 0;
-#ifdef CLOCK_MONOTONIC
- {
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
- use_rt_clock = 1;
- }
- }
-#endif
-}
-#endif
diff --git a/qemu/util/rcu.c b/qemu/util/rcu.c
deleted file mode 100644
index bceb3e472..000000000
--- a/qemu/util/rcu.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * urcu-mb.c
- *
- * Userspace RCU library with explicit memory barriers
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- * Copyright 2015 Red Hat, Inc.
- *
- * Ported to QEMU by Paolo Bonzini <pbonzini@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * IBM's contributions to this file may be relicensed under LGPLv2 or later.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/rcu.h"
-#include "qemu/atomic.h"
-#include "qemu/thread.h"
-#include "qemu/main-loop.h"
-
-/*
- * Global grace period counter. Bit 0 is always one in rcu_gp_ctr.
- * Bits 1 and above are defined in synchronize_rcu.
- */
-#define RCU_GP_LOCKED (1UL << 0)
-#define RCU_GP_CTR (1UL << 1)
-
-unsigned long rcu_gp_ctr = RCU_GP_LOCKED;
-
-QemuEvent rcu_gp_event;
-static QemuMutex rcu_registry_lock;
-static QemuMutex rcu_sync_lock;
-
-/*
- * Check whether a quiescent state was crossed between the beginning of
- * update_counter_and_wait and now.
- */
-static inline int rcu_gp_ongoing(unsigned long *ctr)
-{
- unsigned long v;
-
- v = atomic_read(ctr);
- return v && (v != rcu_gp_ctr);
-}
-
-/* Written to only by each individual reader. Read by both the reader and the
- * writers.
- */
-__thread struct rcu_reader_data rcu_reader;
-
-/* Protected by rcu_registry_lock. */
-typedef QLIST_HEAD(, rcu_reader_data) ThreadList;
-static ThreadList registry = QLIST_HEAD_INITIALIZER(registry);
-
-/* Wait for previous parity/grace period to be empty of readers. */
-static void wait_for_readers(void)
-{
- ThreadList qsreaders = QLIST_HEAD_INITIALIZER(qsreaders);
- struct rcu_reader_data *index, *tmp;
-
- for (;;) {
- /* We want to be notified of changes made to rcu_gp_ongoing
- * while we walk the list.
- */
- qemu_event_reset(&rcu_gp_event);
-
- /* Instead of using atomic_mb_set for index->waiting, and
- * atomic_mb_read for index->ctr, memory barriers are placed
- * manually since writes to different threads are independent.
- * atomic_mb_set has a smp_wmb before...
- */
- smp_wmb();
- QLIST_FOREACH(index, &registry, node) {
- atomic_set(&index->waiting, true);
- }
-
- /* ... and a smp_mb after. */
- smp_mb();
-
- QLIST_FOREACH_SAFE(index, &registry, node, tmp) {
- if (!rcu_gp_ongoing(&index->ctr)) {
- QLIST_REMOVE(index, node);
- QLIST_INSERT_HEAD(&qsreaders, index, node);
-
- /* No need for mb_set here, worst of all we
- * get some extra futex wakeups.
- */
- atomic_set(&index->waiting, false);
- }
- }
-
- /* atomic_mb_read has smp_rmb after. */
- smp_rmb();
-
- if (QLIST_EMPTY(&registry)) {
- break;
- }
-
- /* Wait for one thread to report a quiescent state and try again.
- * Release rcu_registry_lock, so rcu_(un)register_thread() doesn't
- * wait too much time.
- *
- * rcu_register_thread() may add nodes to &registry; it will not
- * wake up synchronize_rcu, but that is okay because at least another
- * thread must exit its RCU read-side critical section before
- * synchronize_rcu is done. The next iteration of the loop will
- * move the new thread's rcu_reader from &registry to &qsreaders,
- * because rcu_gp_ongoing() will return false.
- *
- * rcu_unregister_thread() may remove nodes from &qsreaders instead
- * of &registry if it runs during qemu_event_wait. That's okay;
- * the node then will not be added back to &registry by QLIST_SWAP
- * below. The invariant is that the node is part of one list when
- * rcu_registry_lock is released.
- */
- qemu_mutex_unlock(&rcu_registry_lock);
- qemu_event_wait(&rcu_gp_event);
- qemu_mutex_lock(&rcu_registry_lock);
- }
-
- /* put back the reader list in the registry */
- QLIST_SWAP(&registry, &qsreaders, node);
-}
-
-void synchronize_rcu(void)
-{
- qemu_mutex_lock(&rcu_sync_lock);
- qemu_mutex_lock(&rcu_registry_lock);
-
- if (!QLIST_EMPTY(&registry)) {
- /* In either case, the atomic_mb_set below blocks stores that free
- * old RCU-protected pointers.
- */
- if (sizeof(rcu_gp_ctr) < 8) {
- /* For architectures with 32-bit longs, a two-subphases algorithm
- * ensures we do not encounter overflow bugs.
- *
- * Switch parity: 0 -> 1, 1 -> 0.
- */
- atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR);
- wait_for_readers();
- atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR);
- } else {
- /* Increment current grace period. */
- atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR);
- }
-
- wait_for_readers();
- }
-
- qemu_mutex_unlock(&rcu_registry_lock);
- qemu_mutex_unlock(&rcu_sync_lock);
-}
-
-
-#define RCU_CALL_MIN_SIZE 30
-
-/* Multi-producer, single-consumer queue based on urcu/static/wfqueue.h
- * from liburcu. Note that head is only used by the consumer.
- */
-static struct rcu_head dummy;
-static struct rcu_head *head = &dummy, **tail = &dummy.next;
-static int rcu_call_count;
-static QemuEvent rcu_call_ready_event;
-
-static void enqueue(struct rcu_head *node)
-{
- struct rcu_head **old_tail;
-
- node->next = NULL;
- old_tail = atomic_xchg(&tail, &node->next);
- atomic_mb_set(old_tail, node);
-}
-
-static struct rcu_head *try_dequeue(void)
-{
- struct rcu_head *node, *next;
-
-retry:
- /* Test for an empty list, which we do not expect. Note that for
- * the consumer head and tail are always consistent. The head
- * is consistent because only the consumer reads/writes it.
- * The tail, because it is the first step in the enqueuing.
- * It is only the next pointers that might be inconsistent.
- */
- if (head == &dummy && atomic_mb_read(&tail) == &dummy.next) {
- abort();
- }
-
- /* If the head node has NULL in its next pointer, the value is
- * wrong and we need to wait until its enqueuer finishes the update.
- */
- node = head;
- next = atomic_mb_read(&head->next);
- if (!next) {
- return NULL;
- }
-
- /* Since we are the sole consumer, and we excluded the empty case
- * above, the queue will always have at least two nodes: the
- * dummy node, and the one being removed. So we do not need to update
- * the tail pointer.
- */
- head = next;
-
- /* If we dequeued the dummy node, add it back at the end and retry. */
- if (node == &dummy) {
- enqueue(node);
- goto retry;
- }
-
- return node;
-}
-
-static void *call_rcu_thread(void *opaque)
-{
- struct rcu_head *node;
-
- rcu_register_thread();
-
- for (;;) {
- int tries = 0;
- int n = atomic_read(&rcu_call_count);
-
- /* Heuristically wait for a decent number of callbacks to pile up.
- * Fetch rcu_call_count now, we only must process elements that were
- * added before synchronize_rcu() starts.
- */
- while (n == 0 || (n < RCU_CALL_MIN_SIZE && ++tries <= 5)) {
- g_usleep(10000);
- if (n == 0) {
- qemu_event_reset(&rcu_call_ready_event);
- n = atomic_read(&rcu_call_count);
- if (n == 0) {
- qemu_event_wait(&rcu_call_ready_event);
- }
- }
- n = atomic_read(&rcu_call_count);
- }
-
- atomic_sub(&rcu_call_count, n);
- synchronize_rcu();
- qemu_mutex_lock_iothread();
- while (n > 0) {
- node = try_dequeue();
- while (!node) {
- qemu_mutex_unlock_iothread();
- qemu_event_reset(&rcu_call_ready_event);
- node = try_dequeue();
- if (!node) {
- qemu_event_wait(&rcu_call_ready_event);
- node = try_dequeue();
- }
- qemu_mutex_lock_iothread();
- }
-
- n--;
- node->func(node);
- }
- qemu_mutex_unlock_iothread();
- }
- abort();
-}
-
-void call_rcu1(struct rcu_head *node, void (*func)(struct rcu_head *node))
-{
- node->func = func;
- enqueue(node);
- atomic_inc(&rcu_call_count);
- qemu_event_set(&rcu_call_ready_event);
-}
-
-void rcu_register_thread(void)
-{
- assert(rcu_reader.ctr == 0);
- qemu_mutex_lock(&rcu_registry_lock);
- QLIST_INSERT_HEAD(&registry, &rcu_reader, node);
- qemu_mutex_unlock(&rcu_registry_lock);
-}
-
-void rcu_unregister_thread(void)
-{
- qemu_mutex_lock(&rcu_registry_lock);
- QLIST_REMOVE(&rcu_reader, node);
- qemu_mutex_unlock(&rcu_registry_lock);
-}
-
-static void rcu_init_complete(void)
-{
- QemuThread thread;
-
- qemu_mutex_init(&rcu_registry_lock);
- qemu_mutex_init(&rcu_sync_lock);
- qemu_event_init(&rcu_gp_event, true);
-
- qemu_event_init(&rcu_call_ready_event, false);
-
- /* The caller is assumed to have iothread lock, so the call_rcu thread
- * must have been quiescent even after forking, just recreate it.
- */
- qemu_thread_create(&thread, "call_rcu", call_rcu_thread,
- NULL, QEMU_THREAD_DETACHED);
-
- rcu_register_thread();
-}
-
-#ifdef CONFIG_POSIX
-static void rcu_init_lock(void)
-{
- qemu_mutex_lock(&rcu_sync_lock);
- qemu_mutex_lock(&rcu_registry_lock);
-}
-
-static void rcu_init_unlock(void)
-{
- qemu_mutex_unlock(&rcu_registry_lock);
- qemu_mutex_unlock(&rcu_sync_lock);
-}
-#endif
-
-void rcu_after_fork(void)
-{
- memset(&registry, 0, sizeof(registry));
- rcu_init_complete();
-}
-
-static void __attribute__((__constructor__)) rcu_init(void)
-{
-#ifdef CONFIG_POSIX
- pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_unlock);
-#endif
- rcu_init_complete();
-}
diff --git a/qemu/util/readline.c b/qemu/util/readline.c
deleted file mode 100644
index bbdee790b..000000000
--- a/qemu/util/readline.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * QEMU readline utility
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/readline.h"
-#include "qemu/cutils.h"
-
-#define IS_NORM 0
-#define IS_ESC 1
-#define IS_CSI 2
-#define IS_SS3 3
-
-void readline_show_prompt(ReadLineState *rs)
-{
- rs->printf_func(rs->opaque, "%s", rs->prompt);
- rs->flush_func(rs->opaque);
- rs->last_cmd_buf_index = 0;
- rs->last_cmd_buf_size = 0;
- rs->esc_state = IS_NORM;
-}
-
-/* update the displayed command line */
-static void readline_update(ReadLineState *rs)
-{
- int i, delta, len;
-
- if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
- memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
- for(i = 0; i < rs->last_cmd_buf_index; i++) {
- rs->printf_func(rs->opaque, "\033[D");
- }
- rs->cmd_buf[rs->cmd_buf_size] = '\0';
- if (rs->read_password) {
- len = strlen(rs->cmd_buf);
- for(i = 0; i < len; i++)
- rs->printf_func(rs->opaque, "*");
- } else {
- rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
- }
- rs->printf_func(rs->opaque, "\033[K");
- memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
- rs->last_cmd_buf_size = rs->cmd_buf_size;
- rs->last_cmd_buf_index = rs->cmd_buf_size;
- }
- if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
- delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
- if (delta > 0) {
- for(i = 0;i < delta; i++) {
- rs->printf_func(rs->opaque, "\033[C");
- }
- } else {
- delta = -delta;
- for(i = 0;i < delta; i++) {
- rs->printf_func(rs->opaque, "\033[D");
- }
- }
- rs->last_cmd_buf_index = rs->cmd_buf_index;
- }
- rs->flush_func(rs->opaque);
-}
-
-static void readline_insert_char(ReadLineState *rs, int ch)
-{
- if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
- memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
- rs->cmd_buf + rs->cmd_buf_index,
- rs->cmd_buf_size - rs->cmd_buf_index);
- rs->cmd_buf[rs->cmd_buf_index] = ch;
- rs->cmd_buf_size++;
- rs->cmd_buf_index++;
- }
-}
-
-static void readline_backward_char(ReadLineState *rs)
-{
- if (rs->cmd_buf_index > 0) {
- rs->cmd_buf_index--;
- }
-}
-
-static void readline_forward_char(ReadLineState *rs)
-{
- if (rs->cmd_buf_index < rs->cmd_buf_size) {
- rs->cmd_buf_index++;
- }
-}
-
-static void readline_delete_char(ReadLineState *rs)
-{
- if (rs->cmd_buf_index < rs->cmd_buf_size) {
- memmove(rs->cmd_buf + rs->cmd_buf_index,
- rs->cmd_buf + rs->cmd_buf_index + 1,
- rs->cmd_buf_size - rs->cmd_buf_index - 1);
- rs->cmd_buf_size--;
- }
-}
-
-static void readline_backspace(ReadLineState *rs)
-{
- if (rs->cmd_buf_index > 0) {
- readline_backward_char(rs);
- readline_delete_char(rs);
- }
-}
-
-static void readline_backword(ReadLineState *rs)
-{
- int start;
-
- if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
- return;
- }
-
- start = rs->cmd_buf_index - 1;
-
- /* find first word (backwards) */
- while (start > 0) {
- if (!qemu_isspace(rs->cmd_buf[start])) {
- break;
- }
-
- --start;
- }
-
- /* find first space (backwards) */
- while (start > 0) {
- if (qemu_isspace(rs->cmd_buf[start])) {
- ++start;
- break;
- }
-
- --start;
- }
-
- /* remove word */
- if (start < rs->cmd_buf_index) {
- memmove(rs->cmd_buf + start,
- rs->cmd_buf + rs->cmd_buf_index,
- rs->cmd_buf_size - rs->cmd_buf_index);
- rs->cmd_buf_size -= rs->cmd_buf_index - start;
- rs->cmd_buf_index = start;
- }
-}
-
-static void readline_bol(ReadLineState *rs)
-{
- rs->cmd_buf_index = 0;
-}
-
-static void readline_eol(ReadLineState *rs)
-{
- rs->cmd_buf_index = rs->cmd_buf_size;
-}
-
-static void readline_up_char(ReadLineState *rs)
-{
- int idx;
-
- if (rs->hist_entry == 0)
- return;
- if (rs->hist_entry == -1) {
- /* Find latest entry */
- for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
- if (rs->history[idx] == NULL)
- break;
- }
- rs->hist_entry = idx;
- }
- rs->hist_entry--;
- if (rs->hist_entry >= 0) {
- pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
- rs->history[rs->hist_entry]);
- rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
- }
-}
-
-static void readline_down_char(ReadLineState *rs)
-{
- if (rs->hist_entry == -1)
- return;
- if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
- rs->history[++rs->hist_entry] != NULL) {
- pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
- rs->history[rs->hist_entry]);
- } else {
- rs->cmd_buf[0] = 0;
- rs->hist_entry = -1;
- }
- rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
-}
-
-static void readline_hist_add(ReadLineState *rs, const char *cmdline)
-{
- char *hist_entry, *new_entry;
- int idx;
-
- if (cmdline[0] == '\0')
- return;
- new_entry = NULL;
- if (rs->hist_entry != -1) {
- /* We were editing an existing history entry: replace it */
- hist_entry = rs->history[rs->hist_entry];
- idx = rs->hist_entry;
- if (strcmp(hist_entry, cmdline) == 0) {
- goto same_entry;
- }
- }
- /* Search cmdline in history buffers */
- for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
- hist_entry = rs->history[idx];
- if (hist_entry == NULL)
- break;
- if (strcmp(hist_entry, cmdline) == 0) {
- same_entry:
- new_entry = hist_entry;
- /* Put this entry at the end of history */
- memmove(&rs->history[idx], &rs->history[idx + 1],
- (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
- rs->history[READLINE_MAX_CMDS - 1] = NULL;
- for (; idx < READLINE_MAX_CMDS; idx++) {
- if (rs->history[idx] == NULL)
- break;
- }
- break;
- }
- }
- if (idx == READLINE_MAX_CMDS) {
- /* Need to get one free slot */
- g_free(rs->history[0]);
- memmove(rs->history, &rs->history[1],
- (READLINE_MAX_CMDS - 1) * sizeof(char *));
- rs->history[READLINE_MAX_CMDS - 1] = NULL;
- idx = READLINE_MAX_CMDS - 1;
- }
- if (new_entry == NULL)
- new_entry = g_strdup(cmdline);
- rs->history[idx] = new_entry;
- rs->hist_entry = -1;
-}
-
-/* completion support */
-
-void readline_add_completion(ReadLineState *rs, const char *str)
-{
- if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
- int i;
- for (i = 0; i < rs->nb_completions; i++) {
- if (!strcmp(rs->completions[i], str)) {
- return;
- }
- }
- rs->completions[rs->nb_completions++] = g_strdup(str);
- }
-}
-
-void readline_set_completion_index(ReadLineState *rs, int index)
-{
- rs->completion_index = index;
-}
-
-static int completion_comp(const void *a, const void *b)
-{
- return strcmp(*(const char **) a, *(const char **) b);
-}
-
-static void readline_completion(ReadLineState *rs)
-{
- int len, i, j, max_width, nb_cols, max_prefix;
- char *cmdline;
-
- rs->nb_completions = 0;
-
- cmdline = g_strndup(rs->cmd_buf, rs->cmd_buf_index);
- rs->completion_finder(rs->opaque, cmdline);
- g_free(cmdline);
-
- /* no completion found */
- if (rs->nb_completions <= 0)
- return;
- if (rs->nb_completions == 1) {
- len = strlen(rs->completions[0]);
- for(i = rs->completion_index; i < len; i++) {
- readline_insert_char(rs, rs->completions[0][i]);
- }
- /* extra space for next argument. XXX: make it more generic */
- if (len > 0 && rs->completions[0][len - 1] != '/')
- readline_insert_char(rs, ' ');
- } else {
- qsort(rs->completions, rs->nb_completions, sizeof(char *),
- completion_comp);
- rs->printf_func(rs->opaque, "\n");
- max_width = 0;
- max_prefix = 0;
- for(i = 0; i < rs->nb_completions; i++) {
- len = strlen(rs->completions[i]);
- if (i==0) {
- max_prefix = len;
- } else {
- if (len < max_prefix)
- max_prefix = len;
- for(j=0; j<max_prefix; j++) {
- if (rs->completions[i][j] != rs->completions[0][j])
- max_prefix = j;
- }
- }
- if (len > max_width)
- max_width = len;
- }
- if (max_prefix > 0)
- for(i = rs->completion_index; i < max_prefix; i++) {
- readline_insert_char(rs, rs->completions[0][i]);
- }
- max_width += 2;
- if (max_width < 10)
- max_width = 10;
- else if (max_width > 80)
- max_width = 80;
- nb_cols = 80 / max_width;
- j = 0;
- for(i = 0; i < rs->nb_completions; i++) {
- rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
- if (++j == nb_cols || i == (rs->nb_completions - 1)) {
- rs->printf_func(rs->opaque, "\n");
- j = 0;
- }
- }
- readline_show_prompt(rs);
- }
- for (i = 0; i < rs->nb_completions; i++) {
- g_free(rs->completions[i]);
- }
-}
-
-static void readline_clear_screen(ReadLineState *rs)
-{
- rs->printf_func(rs->opaque, "\033[2J\033[1;1H");
- readline_show_prompt(rs);
-}
-
-/* return true if command handled */
-void readline_handle_byte(ReadLineState *rs, int ch)
-{
- switch(rs->esc_state) {
- case IS_NORM:
- switch(ch) {
- case 1:
- readline_bol(rs);
- break;
- case 4:
- readline_delete_char(rs);
- break;
- case 5:
- readline_eol(rs);
- break;
- case 9:
- readline_completion(rs);
- break;
- case 12:
- readline_clear_screen(rs);
- break;
- case 10:
- case 13:
- rs->cmd_buf[rs->cmd_buf_size] = '\0';
- if (!rs->read_password)
- readline_hist_add(rs, rs->cmd_buf);
- rs->printf_func(rs->opaque, "\n");
- rs->cmd_buf_index = 0;
- rs->cmd_buf_size = 0;
- rs->last_cmd_buf_index = 0;
- rs->last_cmd_buf_size = 0;
- rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
- break;
- case 23:
- /* ^W */
- readline_backword(rs);
- break;
- case 27:
- rs->esc_state = IS_ESC;
- break;
- case 127:
- case 8:
- readline_backspace(rs);
- break;
- case 155:
- rs->esc_state = IS_CSI;
- break;
- default:
- if (ch >= 32) {
- readline_insert_char(rs, ch);
- }
- break;
- }
- break;
- case IS_ESC:
- if (ch == '[') {
- rs->esc_state = IS_CSI;
- rs->esc_param = 0;
- } else if (ch == 'O') {
- rs->esc_state = IS_SS3;
- rs->esc_param = 0;
- } else {
- rs->esc_state = IS_NORM;
- }
- break;
- case IS_CSI:
- switch(ch) {
- case 'A':
- case 'F':
- readline_up_char(rs);
- break;
- case 'B':
- case 'E':
- readline_down_char(rs);
- break;
- case 'D':
- readline_backward_char(rs);
- break;
- case 'C':
- readline_forward_char(rs);
- break;
- case '0' ... '9':
- rs->esc_param = rs->esc_param * 10 + (ch - '0');
- goto the_end;
- case '~':
- switch(rs->esc_param) {
- case 1:
- readline_bol(rs);
- break;
- case 3:
- readline_delete_char(rs);
- break;
- case 4:
- readline_eol(rs);
- break;
- }
- break;
- default:
- break;
- }
- rs->esc_state = IS_NORM;
- the_end:
- break;
- case IS_SS3:
- switch(ch) {
- case 'F':
- readline_eol(rs);
- break;
- case 'H':
- readline_bol(rs);
- break;
- }
- rs->esc_state = IS_NORM;
- break;
- }
- readline_update(rs);
-}
-
-void readline_start(ReadLineState *rs, const char *prompt, int read_password,
- ReadLineFunc *readline_func, void *opaque)
-{
- pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
- rs->readline_func = readline_func;
- rs->readline_opaque = opaque;
- rs->read_password = read_password;
- readline_restart(rs);
-}
-
-void readline_restart(ReadLineState *rs)
-{
- rs->cmd_buf_index = 0;
- rs->cmd_buf_size = 0;
-}
-
-const char *readline_get_history(ReadLineState *rs, unsigned int index)
-{
- if (index >= READLINE_MAX_CMDS)
- return NULL;
- return rs->history[index];
-}
-
-ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
- ReadLineFlushFunc *flush_func,
- void *opaque,
- ReadLineCompletionFunc *completion_finder)
-{
- ReadLineState *rs = g_malloc0(sizeof(*rs));
-
- rs->hist_entry = -1;
- rs->opaque = opaque;
- rs->printf_func = printf_func;
- rs->flush_func = flush_func;
- rs->completion_finder = completion_finder;
-
- return rs;
-}
diff --git a/qemu/util/rfifolock.c b/qemu/util/rfifolock.c
deleted file mode 100644
index c22f5feee..000000000
--- a/qemu/util/rfifolock.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Recursive FIFO lock
- *
- * Copyright Red Hat, Inc. 2013
- *
- * Authors:
- * Stefan Hajnoczi <stefanha@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/rfifolock.h"
-
-void rfifolock_init(RFifoLock *r, void (*cb)(void *), void *opaque)
-{
- qemu_mutex_init(&r->lock);
- r->head = 0;
- r->tail = 0;
- qemu_cond_init(&r->cond);
- r->nesting = 0;
- r->cb = cb;
- r->cb_opaque = opaque;
-}
-
-void rfifolock_destroy(RFifoLock *r)
-{
- qemu_cond_destroy(&r->cond);
- qemu_mutex_destroy(&r->lock);
-}
-
-/*
- * Theory of operation:
- *
- * In order to ensure FIFO ordering, implement a ticketlock. Threads acquiring
- * the lock enqueue themselves by incrementing the tail index. When the lock
- * is unlocked, the head is incremented and waiting threads are notified.
- *
- * Recursive locking does not take a ticket since the head is only incremented
- * when the outermost recursive caller unlocks.
- */
-void rfifolock_lock(RFifoLock *r)
-{
- qemu_mutex_lock(&r->lock);
-
- /* Take a ticket */
- unsigned int ticket = r->tail++;
-
- if (r->nesting > 0 && qemu_thread_is_self(&r->owner_thread)) {
- r->tail--; /* put ticket back, we're nesting */
- } else {
- while (ticket != r->head) {
- /* Invoke optional contention callback */
- if (r->cb) {
- r->cb(r->cb_opaque);
- }
- qemu_cond_wait(&r->cond, &r->lock);
- }
- }
-
- qemu_thread_get_self(&r->owner_thread);
- r->nesting++;
- qemu_mutex_unlock(&r->lock);
-}
-
-void rfifolock_unlock(RFifoLock *r)
-{
- qemu_mutex_lock(&r->lock);
- assert(r->nesting > 0);
- assert(qemu_thread_is_self(&r->owner_thread));
- if (--r->nesting == 0) {
- r->head++;
- qemu_cond_broadcast(&r->cond);
- }
- qemu_mutex_unlock(&r->lock);
-}
diff --git a/qemu/util/throttle.c b/qemu/util/throttle.c
deleted file mode 100644
index 71246b234..000000000
--- a/qemu/util/throttle.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * QEMU throttling infrastructure
- *
- * Copyright (C) Nodalink, EURL. 2013-2014
- * Copyright (C) Igalia, S.L. 2015
- *
- * Authors:
- * Benoît Canet <benoit.canet@nodalink.com>
- * Alberto Garcia <berto@igalia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu/throttle.h"
-#include "qemu/timer.h"
-#include "block/aio.h"
-
-/* This function make a bucket leak
- *
- * @bkt: the bucket to make leak
- * @delta_ns: the time delta
- */
-void throttle_leak_bucket(LeakyBucket *bkt, int64_t delta_ns)
-{
- double leak;
-
- /* compute how much to leak */
- leak = (bkt->avg * (double) delta_ns) / NANOSECONDS_PER_SECOND;
-
- /* make the bucket leak */
- bkt->level = MAX(bkt->level - leak, 0);
-
- /* if we allow bursts for more than one second we also need to
- * keep track of bkt->burst_level so the bkt->max goal per second
- * is attained */
- if (bkt->burst_length > 1) {
- leak = (bkt->max * (double) delta_ns) / NANOSECONDS_PER_SECOND;
- bkt->burst_level = MAX(bkt->burst_level - leak, 0);
- }
-}
-
-/* Calculate the time delta since last leak and make proportionals leaks
- *
- * @now: the current timestamp in ns
- */
-static void throttle_do_leak(ThrottleState *ts, int64_t now)
-{
- /* compute the time elapsed since the last leak */
- int64_t delta_ns = now - ts->previous_leak;
- int i;
-
- ts->previous_leak = now;
-
- if (delta_ns <= 0) {
- return;
- }
-
- /* make each bucket leak */
- for (i = 0; i < BUCKETS_COUNT; i++) {
- throttle_leak_bucket(&ts->cfg.buckets[i], delta_ns);
- }
-}
-
-/* do the real job of computing the time to wait
- *
- * @limit: the throttling limit
- * @extra: the number of operation to delay
- * @ret: the time to wait in ns
- */
-static int64_t throttle_do_compute_wait(double limit, double extra)
-{
- double wait = extra * NANOSECONDS_PER_SECOND;
- wait /= limit;
- return wait;
-}
-
-/* This function compute the wait time in ns that a leaky bucket should trigger
- *
- * @bkt: the leaky bucket we operate on
- * @ret: the resulting wait time in ns or 0 if the operation can go through
- */
-int64_t throttle_compute_wait(LeakyBucket *bkt)
-{
- double extra; /* the number of extra units blocking the io */
-
- if (!bkt->avg) {
- return 0;
- }
-
- /* If the bucket is full then we have to wait */
- extra = bkt->level - bkt->max * bkt->burst_length;
- if (extra > 0) {
- return throttle_do_compute_wait(bkt->avg, extra);
- }
-
- /* If the bucket is not full yet we have to make sure that we
- * fulfill the goal of bkt->max units per second. */
- if (bkt->burst_length > 1) {
- /* We use 1/10 of the max value to smooth the throttling.
- * See throttle_fix_bucket() for more details. */
- extra = bkt->burst_level - bkt->max / 10;
- if (extra > 0) {
- return throttle_do_compute_wait(bkt->max, extra);
- }
- }
-
- return 0;
-}
-
-/* This function compute the time that must be waited while this IO
- *
- * @is_write: true if the current IO is a write, false if it's a read
- * @ret: time to wait
- */
-static int64_t throttle_compute_wait_for(ThrottleState *ts,
- bool is_write)
-{
- BucketType to_check[2][4] = { {THROTTLE_BPS_TOTAL,
- THROTTLE_OPS_TOTAL,
- THROTTLE_BPS_READ,
- THROTTLE_OPS_READ},
- {THROTTLE_BPS_TOTAL,
- THROTTLE_OPS_TOTAL,
- THROTTLE_BPS_WRITE,
- THROTTLE_OPS_WRITE}, };
- int64_t wait, max_wait = 0;
- int i;
-
- for (i = 0; i < 4; i++) {
- BucketType index = to_check[is_write][i];
- wait = throttle_compute_wait(&ts->cfg.buckets[index]);
- if (wait > max_wait) {
- max_wait = wait;
- }
- }
-
- return max_wait;
-}
-
-/* compute the timer for this type of operation
- *
- * @is_write: the type of operation
- * @now: the current clock timestamp
- * @next_timestamp: the resulting timer
- * @ret: true if a timer must be set
- */
-static bool throttle_compute_timer(ThrottleState *ts,
- bool is_write,
- int64_t now,
- int64_t *next_timestamp)
-{
- int64_t wait;
-
- /* leak proportionally to the time elapsed */
- throttle_do_leak(ts, now);
-
- /* compute the wait time if any */
- wait = throttle_compute_wait_for(ts, is_write);
-
- /* if the code must wait compute when the next timer should fire */
- if (wait) {
- *next_timestamp = now + wait;
- return true;
- }
-
- /* else no need to wait at all */
- *next_timestamp = now;
- return false;
-}
-
-/* Add timers to event loop */
-void throttle_timers_attach_aio_context(ThrottleTimers *tt,
- AioContext *new_context)
-{
- tt->timers[0] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
- tt->read_timer_cb, tt->timer_opaque);
- tt->timers[1] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
- tt->write_timer_cb, tt->timer_opaque);
-}
-
-/*
- * Initialize the ThrottleConfig structure to a valid state
- * @cfg: the config to initialize
- */
-void throttle_config_init(ThrottleConfig *cfg)
-{
- unsigned i;
- memset(cfg, 0, sizeof(*cfg));
- for (i = 0; i < BUCKETS_COUNT; i++) {
- cfg->buckets[i].burst_length = 1;
- }
-}
-
-/* To be called first on the ThrottleState */
-void throttle_init(ThrottleState *ts)
-{
- memset(ts, 0, sizeof(ThrottleState));
- throttle_config_init(&ts->cfg);
-}
-
-/* To be called first on the ThrottleTimers */
-void throttle_timers_init(ThrottleTimers *tt,
- AioContext *aio_context,
- QEMUClockType clock_type,
- QEMUTimerCB *read_timer_cb,
- QEMUTimerCB *write_timer_cb,
- void *timer_opaque)
-{
- memset(tt, 0, sizeof(ThrottleTimers));
-
- tt->clock_type = clock_type;
- tt->read_timer_cb = read_timer_cb;
- tt->write_timer_cb = write_timer_cb;
- tt->timer_opaque = timer_opaque;
- throttle_timers_attach_aio_context(tt, aio_context);
-}
-
-/* destroy a timer */
-static void throttle_timer_destroy(QEMUTimer **timer)
-{
- assert(*timer != NULL);
-
- timer_del(*timer);
- timer_free(*timer);
- *timer = NULL;
-}
-
-/* Remove timers from event loop */
-void throttle_timers_detach_aio_context(ThrottleTimers *tt)
-{
- int i;
-
- for (i = 0; i < 2; i++) {
- throttle_timer_destroy(&tt->timers[i]);
- }
-}
-
-/* To be called last on the ThrottleTimers */
-void throttle_timers_destroy(ThrottleTimers *tt)
-{
- throttle_timers_detach_aio_context(tt);
-}
-
-/* is any throttling timer configured */
-bool throttle_timers_are_initialized(ThrottleTimers *tt)
-{
- if (tt->timers[0]) {
- return true;
- }
-
- return false;
-}
-
-/* Does any throttling must be done
- *
- * @cfg: the throttling configuration to inspect
- * @ret: true if throttling must be done else false
- */
-bool throttle_enabled(ThrottleConfig *cfg)
-{
- int i;
-
- for (i = 0; i < BUCKETS_COUNT; i++) {
- if (cfg->buckets[i].avg > 0) {
- return true;
- }
- }
-
- return false;
-}
-
-/* check if a throttling configuration is valid
- * @cfg: the throttling configuration to inspect
- * @ret: true if valid else false
- * @errp: error object
- */
-bool throttle_is_valid(ThrottleConfig *cfg, Error **errp)
-{
- int i;
- bool bps_flag, ops_flag;
- bool bps_max_flag, ops_max_flag;
-
- bps_flag = cfg->buckets[THROTTLE_BPS_TOTAL].avg &&
- (cfg->buckets[THROTTLE_BPS_READ].avg ||
- cfg->buckets[THROTTLE_BPS_WRITE].avg);
-
- ops_flag = cfg->buckets[THROTTLE_OPS_TOTAL].avg &&
- (cfg->buckets[THROTTLE_OPS_READ].avg ||
- cfg->buckets[THROTTLE_OPS_WRITE].avg);
-
- bps_max_flag = cfg->buckets[THROTTLE_BPS_TOTAL].max &&
- (cfg->buckets[THROTTLE_BPS_READ].max ||
- cfg->buckets[THROTTLE_BPS_WRITE].max);
-
- ops_max_flag = cfg->buckets[THROTTLE_OPS_TOTAL].max &&
- (cfg->buckets[THROTTLE_OPS_READ].max ||
- cfg->buckets[THROTTLE_OPS_WRITE].max);
-
- if (bps_flag || ops_flag || bps_max_flag || ops_max_flag) {
- error_setg(errp, "bps/iops/max total values and read/write values"
- " cannot be used at the same time");
- return false;
- }
-
- for (i = 0; i < BUCKETS_COUNT; i++) {
- if (cfg->buckets[i].avg < 0 ||
- cfg->buckets[i].max < 0 ||
- cfg->buckets[i].avg > THROTTLE_VALUE_MAX ||
- cfg->buckets[i].max > THROTTLE_VALUE_MAX) {
- error_setg(errp, "bps/iops/max values must be within [0, %lld]",
- THROTTLE_VALUE_MAX);
- return false;
- }
-
- if (!cfg->buckets[i].burst_length) {
- error_setg(errp, "the burst length cannot be 0");
- return false;
- }
-
- if (cfg->buckets[i].burst_length > 1 && !cfg->buckets[i].max) {
- error_setg(errp, "burst length set without burst rate");
- return false;
- }
-
- if (cfg->buckets[i].max && !cfg->buckets[i].avg) {
- error_setg(errp, "bps_max/iops_max require corresponding"
- " bps/iops values");
- return false;
- }
- }
-
- return true;
-}
-
-/* fix bucket parameters */
-static void throttle_fix_bucket(LeakyBucket *bkt)
-{
- double min;
-
- /* zero bucket level */
- bkt->level = bkt->burst_level = 0;
-
- /* The following is done to cope with the Linux CFQ block scheduler
- * which regroup reads and writes by block of 100ms in the guest.
- * When they are two process one making reads and one making writes cfq
- * make a pattern looking like the following:
- * WWWWWWWWWWWRRRRRRRRRRRRRRWWWWWWWWWWWWWwRRRRRRRRRRRRRRRRR
- * Having a max burst value of 100ms of the average will help smooth the
- * throttling
- */
- min = bkt->avg / 10;
- if (bkt->avg && !bkt->max) {
- bkt->max = min;
- }
-}
-
-/* take care of canceling a timer */
-static void throttle_cancel_timer(QEMUTimer *timer)
-{
- assert(timer != NULL);
-
- timer_del(timer);
-}
-
-/* Used to configure the throttle
- *
- * @ts: the throttle state we are working on
- * @tt: the throttle timers we use in this aio context
- * @cfg: the config to set
- */
-void throttle_config(ThrottleState *ts,
- ThrottleTimers *tt,
- ThrottleConfig *cfg)
-{
- int i;
-
- ts->cfg = *cfg;
-
- for (i = 0; i < BUCKETS_COUNT; i++) {
- throttle_fix_bucket(&ts->cfg.buckets[i]);
- }
-
- ts->previous_leak = qemu_clock_get_ns(tt->clock_type);
-
- for (i = 0; i < 2; i++) {
- throttle_cancel_timer(tt->timers[i]);
- }
-}
-
-/* used to get config
- *
- * @ts: the throttle state we are working on
- * @cfg: the config to write
- */
-void throttle_get_config(ThrottleState *ts, ThrottleConfig *cfg)
-{
- *cfg = ts->cfg;
-}
-
-
-/* Schedule the read or write timer if needed
- *
- * NOTE: this function is not unit tested due to it's usage of timer_mod
- *
- * @tt: the timers structure
- * @is_write: the type of operation (read/write)
- * @ret: true if the timer has been scheduled else false
- */
-bool throttle_schedule_timer(ThrottleState *ts,
- ThrottleTimers *tt,
- bool is_write)
-{
- int64_t now = qemu_clock_get_ns(tt->clock_type);
- int64_t next_timestamp;
- bool must_wait;
-
- must_wait = throttle_compute_timer(ts,
- is_write,
- now,
- &next_timestamp);
-
- /* request not throttled */
- if (!must_wait) {
- return false;
- }
-
- /* request throttled and timer pending -> do nothing */
- if (timer_pending(tt->timers[is_write])) {
- return true;
- }
-
- /* request throttled and timer not pending -> arm timer */
- timer_mod(tt->timers[is_write], next_timestamp);
- return true;
-}
-
-/* do the accounting for this operation
- *
- * @is_write: the type of operation (read/write)
- * @size: the size of the operation
- */
-void throttle_account(ThrottleState *ts, bool is_write, uint64_t size)
-{
- const BucketType bucket_types_size[2][2] = {
- { THROTTLE_BPS_TOTAL, THROTTLE_BPS_READ },
- { THROTTLE_BPS_TOTAL, THROTTLE_BPS_WRITE }
- };
- const BucketType bucket_types_units[2][2] = {
- { THROTTLE_OPS_TOTAL, THROTTLE_OPS_READ },
- { THROTTLE_OPS_TOTAL, THROTTLE_OPS_WRITE }
- };
- double units = 1.0;
- unsigned i;
-
- /* if cfg.op_size is defined and smaller than size we compute unit count */
- if (ts->cfg.op_size && size > ts->cfg.op_size) {
- units = (double) size / ts->cfg.op_size;
- }
-
- for (i = 0; i < 2; i++) {
- LeakyBucket *bkt;
-
- bkt = &ts->cfg.buckets[bucket_types_size[is_write][i]];
- bkt->level += size;
- if (bkt->burst_length > 1) {
- bkt->burst_level += size;
- }
-
- bkt = &ts->cfg.buckets[bucket_types_units[is_write][i]];
- bkt->level += units;
- if (bkt->burst_length > 1) {
- bkt->burst_level += units;
- }
- }
-}
-
diff --git a/qemu/util/timed-average.c b/qemu/util/timed-average.c
deleted file mode 100644
index 2eef9cbb1..000000000
--- a/qemu/util/timed-average.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * QEMU timed average computation
- *
- * Copyright (C) Nodalink, EURL. 2014
- * Copyright (C) Igalia, S.L. 2015
- *
- * Authors:
- * Benoît Canet <benoit.canet@nodalink.com>
- * Alberto Garcia <berto@igalia.com>
- *
- * This program is free sofware: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Sofware Foundation, either version 2 of the License, or
- * (at your option) version 3 or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-
-#include "qemu/timed-average.h"
-
-/* This module computes an average of a set of values within a time
- * window.
- *
- * Algorithm:
- *
- * - Create two windows with a certain expiration period, and
- * offsetted by period / 2.
- * - Each time you want to account a new value, do it in both windows.
- * - The minimum / maximum / average values are always returned from
- * the oldest window.
- *
- * Example:
- *
- * t=0 |t=0.5 |t=1 |t=1.5 |t=2
- * wnd0: [0,0.5)|wnd0: [0.5,1.5) | |wnd0: [1.5,2.5) |
- * wnd1: [0,1) | |wnd1: [1,2) | |
- *
- * Values are returned from:
- *
- * wnd0---------|wnd1------------|wnd0---------|wnd1-------------|
- */
-
-/* Update the expiration of a time window
- *
- * @w: the window used
- * @now: the current time in nanoseconds
- * @period: the expiration period in nanoseconds
- */
-static void update_expiration(TimedAverageWindow *w, int64_t now,
- int64_t period)
-{
- /* time elapsed since the last theoretical expiration */
- int64_t elapsed = (now - w->expiration) % period;
- /* time remaininging until the next expiration */
- int64_t remaining = period - elapsed;
- /* compute expiration */
- w->expiration = now + remaining;
-}
-
-/* Reset a window
- *
- * @w: the window to reset
- */
-static void window_reset(TimedAverageWindow *w)
-{
- w->min = UINT64_MAX;
- w->max = 0;
- w->sum = 0;
- w->count = 0;
-}
-
-/* Get the current window (that is, the one with the earliest
- * expiration time).
- *
- * @ta: the TimedAverage structure
- * @ret: a pointer to the current window
- */
-static TimedAverageWindow *current_window(TimedAverage *ta)
-{
- return &ta->windows[ta->current];
-}
-
-/* Initialize a TimedAverage structure
- *
- * @ta: the TimedAverage structure
- * @clock_type: the type of clock to use
- * @period: the time window period in nanoseconds
- */
-void timed_average_init(TimedAverage *ta, QEMUClockType clock_type,
- uint64_t period)
-{
- int64_t now = qemu_clock_get_ns(clock_type);
-
- /* Returned values are from the oldest window, so they belong to
- * the interval [ta->period/2,ta->period). By adjusting the
- * requested period by 4/3, we guarantee that they're in the
- * interval [2/3 period,4/3 period), closer to the requested
- * period on average */
- ta->period = (uint64_t) period * 4 / 3;
- ta->clock_type = clock_type;
- ta->current = 0;
-
- window_reset(&ta->windows[0]);
- window_reset(&ta->windows[1]);
-
- /* Both windows are offsetted by half a period */
- ta->windows[0].expiration = now + ta->period / 2;
- ta->windows[1].expiration = now + ta->period;
-}
-
-/* Check if the time windows have expired, updating their counters and
- * expiration time if that's the case.
- *
- * @ta: the TimedAverage structure
- * @elapsed: if non-NULL, the elapsed time (in ns) within the current
- * window will be stored here
- */
-static void check_expirations(TimedAverage *ta, uint64_t *elapsed)
-{
- int64_t now = qemu_clock_get_ns(ta->clock_type);
- int i;
-
- assert(ta->period != 0);
-
- /* Check if the windows have expired */
- for (i = 0; i < 2; i++) {
- TimedAverageWindow *w = &ta->windows[i];
- if (w->expiration <= now) {
- window_reset(w);
- update_expiration(w, now, ta->period);
- }
- }
-
- /* Make ta->current point to the oldest window */
- if (ta->windows[0].expiration < ta->windows[1].expiration) {
- ta->current = 0;
- } else {
- ta->current = 1;
- }
-
- /* Calculate the elapsed time within the current window */
- if (elapsed) {
- int64_t remaining = ta->windows[ta->current].expiration - now;
- *elapsed = ta->period - remaining;
- }
-}
-
-/* Account a value
- *
- * @ta: the TimedAverage structure
- * @value: the value to account
- */
-void timed_average_account(TimedAverage *ta, uint64_t value)
-{
- int i;
- check_expirations(ta, NULL);
-
- /* Do the accounting in both windows at the same time */
- for (i = 0; i < 2; i++) {
- TimedAverageWindow *w = &ta->windows[i];
-
- w->sum += value;
- w->count++;
-
- if (value < w->min) {
- w->min = value;
- }
-
- if (value > w->max) {
- w->max = value;
- }
- }
-}
-
-/* Get the minimum value
- *
- * @ta: the TimedAverage structure
- * @ret: the minimum value
- */
-uint64_t timed_average_min(TimedAverage *ta)
-{
- TimedAverageWindow *w;
- check_expirations(ta, NULL);
- w = current_window(ta);
- return w->min < UINT64_MAX ? w->min : 0;
-}
-
-/* Get the average value
- *
- * @ta: the TimedAverage structure
- * @ret: the average value
- */
-uint64_t timed_average_avg(TimedAverage *ta)
-{
- TimedAverageWindow *w;
- check_expirations(ta, NULL);
- w = current_window(ta);
- return w->count > 0 ? w->sum / w->count : 0;
-}
-
-/* Get the maximum value
- *
- * @ta: the TimedAverage structure
- * @ret: the maximum value
- */
-uint64_t timed_average_max(TimedAverage *ta)
-{
- check_expirations(ta, NULL);
- return current_window(ta)->max;
-}
-
-/* Get the sum of all accounted values
- * @ta: the TimedAverage structure
- * @elapsed: if non-NULL, the elapsed time (in ns) will be stored here
- * @ret: the sum of all accounted values
- */
-uint64_t timed_average_sum(TimedAverage *ta, uint64_t *elapsed)
-{
- TimedAverageWindow *w;
- check_expirations(ta, elapsed);
- w = current_window(ta);
- return w->sum;
-}
diff --git a/qemu/util/unicode.c b/qemu/util/unicode.c
deleted file mode 100644
index a812a3517..000000000
--- a/qemu/util/unicode.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Dealing with Unicode
- *
- * Copyright (C) 2013 Red Hat, Inc.
- *
- * Authors:
- * Markus Armbruster <armbru@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or
- * later. See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/unicode.h"
-
-/**
- * mod_utf8_codepoint:
- * @s: string encoded in modified UTF-8
- * @n: maximum number of bytes to read from @s, if less than 6
- * @end: set to end of sequence on return
- *
- * Convert the modified UTF-8 sequence at the start of @s. Modified
- * UTF-8 is exactly like UTF-8, except U+0000 is encoded as
- * "\xC0\x80".
- *
- * If @n is zero or @s points to a zero byte, the sequence is invalid,
- * and @end is set to @s.
- *
- * If @s points to an impossible byte (0xFE or 0xFF) or a continuation
- * byte, the sequence is invalid, and @end is set to @s + 1
- *
- * Else, the first byte determines how many continuation bytes are
- * expected. If there are fewer, the sequence is invalid, and @end is
- * set to @s + 1 + actual number of continuation bytes. Else, the
- * sequence is well-formed, and @end is set to @s + 1 + expected
- * number of continuation bytes.
- *
- * A well-formed sequence is valid unless it encodes a codepoint
- * outside the Unicode range U+0000..U+10FFFF, one of Unicode's 66
- * noncharacters, a surrogate codepoint, or is overlong. Except the
- * overlong sequence "\xC0\x80" is valid.
- *
- * Conversion succeeds if and only if the sequence is valid.
- *
- * Returns: the Unicode codepoint on success, -1 on failure.
- */
-int mod_utf8_codepoint(const char *s, size_t n, char **end)
-{
- static int min_cp[5] = { 0x80, 0x800, 0x10000, 0x200000, 0x4000000 };
- const unsigned char *p;
- unsigned byte, mask, len, i;
- int cp;
-
- if (n == 0 || *s == 0) {
- /* empty sequence */
- *end = (char *)s;
- return -1;
- }
-
- p = (const unsigned char *)s;
- byte = *p++;
- if (byte < 0x80) {
- cp = byte; /* one byte sequence */
- } else if (byte >= 0xFE) {
- cp = -1; /* impossible bytes 0xFE, 0xFF */
- } else if ((byte & 0x40) == 0) {
- cp = -1; /* unexpected continuation byte */
- } else {
- /* multi-byte sequence */
- len = 0;
- for (mask = 0x80; byte & mask; mask >>= 1) {
- len++;
- }
- assert(len > 1 && len < 7);
- cp = byte & (mask - 1);
- for (i = 1; i < len; i++) {
- byte = i < n ? *p : 0;
- if ((byte & 0xC0) != 0x80) {
- cp = -1; /* continuation byte missing */
- goto out;
- }
- p++;
- cp <<= 6;
- cp |= byte & 0x3F;
- }
- if (cp > 0x10FFFF) {
- cp = -1; /* beyond Unicode range */
- } else if ((cp >= 0xFDD0 && cp <= 0xFDEF)
- || (cp & 0xFFFE) == 0xFFFE) {
- cp = -1; /* noncharacter */
- } else if (cp >= 0xD800 && cp <= 0xDFFF) {
- cp = -1; /* surrogate code point */
- } else if (cp < min_cp[len - 2] && !(cp == 0 && len == 2)) {
- cp = -1; /* overlong, not \xC0\x80 */
- }
- }
-
-out:
- *end = (char *)p;
- return cp;
-}
diff --git a/qemu/util/uri.c b/qemu/util/uri.c
deleted file mode 100644
index d109d6c01..000000000
--- a/qemu/util/uri.c
+++ /dev/null
@@ -1,2203 +0,0 @@
-/**
- * uri.c: set of generic URI related routines
- *
- * Reference: RFCs 3986, 2732 and 2373
- *
- * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of Daniel Veillard shall not
- * be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from him.
- *
- * daniel@veillard.com
- *
- **
- *
- * Copyright (C) 2007, 2009-2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Richard W.M. Jones <rjones@redhat.com>
- *
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-
-#include "qemu/uri.h"
-
-static void uri_clean(URI *uri);
-
-/*
- * Old rule from 2396 used in legacy handling code
- * alpha = lowalpha | upalpha
- */
-#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
-
-
-/*
- * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
- * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
- * "u" | "v" | "w" | "x" | "y" | "z"
- */
-
-#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
-
-/*
- * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
- * "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
- * "U" | "V" | "W" | "X" | "Y" | "Z"
- */
-#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
-
-#ifdef IS_DIGIT
-#undef IS_DIGIT
-#endif
-/*
- * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- */
-#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
-
-/*
- * alphanum = alpha | digit
- */
-
-#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
-
-/*
- * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
- */
-
-#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \
- ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \
- ((x) == '(') || ((x) == ')'))
-
-/*
- * unwise = "{" | "}" | "|" | "\" | "^" | "`"
- */
-
-#define IS_UNWISE(p) \
- (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \
- ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \
- ((*(p) == ']')) || ((*(p) == '`')))
-/*
- * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
- * "[" | "]"
- */
-
-#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
- ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
- ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
- ((x) == ']'))
-
-/*
- * unreserved = alphanum | mark
- */
-
-#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
-
-/*
- * Skip to next pointer char, handle escaped sequences
- */
-
-#define NEXT(p) ((*p == '%')? p += 3 : p++)
-
-/*
- * Productions from the spec.
- *
- * authority = server | reg_name
- * reg_name = 1*( unreserved | escaped | "$" | "," |
- * ";" | ":" | "@" | "&" | "=" | "+" )
- *
- * path = [ abs_path | opaque_part ]
- */
-
-
-/************************************************************************
- * *
- * RFC 3986 parser *
- * *
- ************************************************************************/
-
-#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
-#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) || \
- ((*(p) >= 'A') && (*(p) <= 'Z')))
-#define ISA_HEXDIG(p) \
- (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) || \
- ((*(p) >= 'A') && (*(p) <= 'F')))
-
-/*
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
-#define ISA_SUB_DELIM(p) \
- (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) || \
- ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) || \
- ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) || \
- ((*(p) == '=')) || ((*(p) == '\'')))
-
-/*
- * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
- */
-#define ISA_GEN_DELIM(p) \
- (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) || \
- ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) || \
- ((*(p) == '@')))
-
-/*
- * reserved = gen-delims / sub-delims
- */
-#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p)))
-
-/*
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- */
-#define ISA_UNRESERVED(p) \
- ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \
- ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
-
-/*
- * pct-encoded = "%" HEXDIG HEXDIG
- */
-#define ISA_PCT_ENCODED(p) \
- ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
-
-/*
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- */
-#define ISA_PCHAR(p) \
- (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \
- ((*(p) == ':')) || ((*(p) == '@')))
-
-/**
- * rfc3986_parse_scheme:
- * @uri: pointer to an URI structure
- * @str: pointer to the string to analyze
- *
- * Parse an URI scheme
- *
- * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_scheme(URI *uri, const char **str) {
- const char *cur;
-
- if (str == NULL)
- return(-1);
-
- cur = *str;
- if (!ISA_ALPHA(cur))
- return(2);
- cur++;
- while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
- (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
- if (uri != NULL) {
- g_free(uri->scheme);
- uri->scheme = g_strndup(*str, cur - *str);
- }
- *str = cur;
- return(0);
-}
-
-/**
- * rfc3986_parse_fragment:
- * @uri: pointer to an URI structure
- * @str: pointer to the string to analyze
- *
- * Parse the query part of an URI
- *
- * fragment = *( pchar / "/" / "?" )
- * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
- * in the fragment identifier but this is used very broadly for
- * xpointer scheme selection, so we are allowing it here to not break
- * for example all the DocBook processing chains.
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_fragment(URI *uri, const char **str)
-{
- const char *cur;
-
- if (str == NULL)
- return (-1);
-
- cur = *str;
-
- while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
- (*cur == '[') || (*cur == ']') ||
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
- NEXT(cur);
- if (uri != NULL) {
- g_free(uri->fragment);
- if (uri->cleanup & 2)
- uri->fragment = g_strndup(*str, cur - *str);
- else
- uri->fragment = uri_string_unescape(*str, cur - *str, NULL);
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_query:
- * @uri: pointer to an URI structure
- * @str: pointer to the string to analyze
- *
- * Parse the query part of an URI
- *
- * query = *uric
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_query(URI *uri, const char **str)
-{
- const char *cur;
-
- if (str == NULL)
- return (-1);
-
- cur = *str;
-
- while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
- NEXT(cur);
- if (uri != NULL) {
- g_free(uri->query);
- uri->query = g_strndup (*str, cur - *str);
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_port:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse a port part and fills in the appropriate fields
- * of the @uri structure
- *
- * port = *DIGIT
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_port(URI *uri, const char **str)
-{
- const char *cur = *str;
- int port = 0;
-
- if (ISA_DIGIT(cur)) {
- while (ISA_DIGIT(cur)) {
- port = port * 10 + (*cur - '0');
- if (port > 65535) {
- return 1;
- }
- cur++;
- }
- if (uri) {
- uri->port = port;
- }
- *str = cur;
- return 0;
- }
- return 1;
-}
-
-/**
- * rfc3986_parse_user_info:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an user informations part and fills in the appropriate fields
- * of the @uri structure
- *
- * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_user_info(URI *uri, const char **str)
-{
- const char *cur;
-
- cur = *str;
- while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) ||
- ISA_SUB_DELIM(cur) || (*cur == ':'))
- NEXT(cur);
- if (*cur == '@') {
- if (uri != NULL) {
- g_free(uri->user);
- if (uri->cleanup & 2)
- uri->user = g_strndup(*str, cur - *str);
- else
- uri->user = uri_string_unescape(*str, cur - *str, NULL);
- }
- *str = cur;
- return(0);
- }
- return(1);
-}
-
-/**
- * rfc3986_parse_dec_octet:
- * @str: the string to analyze
- *
- * dec-octet = DIGIT ; 0-9
- * / %x31-39 DIGIT ; 10-99
- * / "1" 2DIGIT ; 100-199
- * / "2" %x30-34 DIGIT ; 200-249
- * / "25" %x30-35 ; 250-255
- *
- * Skip a dec-octet.
- *
- * Returns 0 if found and skipped, 1 otherwise
- */
-static int
-rfc3986_parse_dec_octet(const char **str) {
- const char *cur = *str;
-
- if (!(ISA_DIGIT(cur)))
- return(1);
- if (!ISA_DIGIT(cur+1))
- cur++;
- else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2)))
- cur += 2;
- else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2)))
- cur += 3;
- else if ((*cur == '2') && (*(cur + 1) >= '0') &&
- (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2)))
- cur += 3;
- else if ((*cur == '2') && (*(cur + 1) == '5') &&
- (*(cur + 2) >= '0') && (*(cur + 1) <= '5'))
- cur += 3;
- else
- return(1);
- *str = cur;
- return(0);
-}
-/**
- * rfc3986_parse_host:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an host part and fills in the appropriate fields
- * of the @uri structure
- *
- * host = IP-literal / IPv4address / reg-name
- * IP-literal = "[" ( IPv6address / IPvFuture ) "]"
- * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
- * reg-name = *( unreserved / pct-encoded / sub-delims )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_host(URI *uri, const char **str)
-{
- const char *cur = *str;
- const char *host;
-
- host = cur;
- /*
- * IPv6 and future addressing scheme are enclosed between brackets
- */
- if (*cur == '[') {
- cur++;
- while ((*cur != ']') && (*cur != 0))
- cur++;
- if (*cur != ']')
- return(1);
- cur++;
- goto found;
- }
- /*
- * try to parse an IPv4
- */
- if (ISA_DIGIT(cur)) {
- if (rfc3986_parse_dec_octet(&cur) != 0)
- goto not_ipv4;
- if (*cur != '.')
- goto not_ipv4;
- cur++;
- if (rfc3986_parse_dec_octet(&cur) != 0)
- goto not_ipv4;
- if (*cur != '.')
- goto not_ipv4;
- if (rfc3986_parse_dec_octet(&cur) != 0)
- goto not_ipv4;
- if (*cur != '.')
- goto not_ipv4;
- if (rfc3986_parse_dec_octet(&cur) != 0)
- goto not_ipv4;
- goto found;
-not_ipv4:
- cur = *str;
- }
- /*
- * then this should be a hostname which can be empty
- */
- while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
- NEXT(cur);
-found:
- if (uri != NULL) {
- g_free(uri->authority);
- uri->authority = NULL;
- g_free(uri->server);
- if (cur != host) {
- if (uri->cleanup & 2)
- uri->server = g_strndup(host, cur - host);
- else
- uri->server = uri_string_unescape(host, cur - host, NULL);
- } else
- uri->server = NULL;
- }
- *str = cur;
- return(0);
-}
-
-/**
- * rfc3986_parse_authority:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an authority part and fills in the appropriate fields
- * of the @uri structure
- *
- * authority = [ userinfo "@" ] host [ ":" port ]
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_authority(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
- /*
- * try to parse an userinfo and check for the trailing @
- */
- ret = rfc3986_parse_user_info(uri, &cur);
- if ((ret != 0) || (*cur != '@'))
- cur = *str;
- else
- cur++;
- ret = rfc3986_parse_host(uri, &cur);
- if (ret != 0) return(ret);
- if (*cur == ':') {
- cur++;
- ret = rfc3986_parse_port(uri, &cur);
- if (ret != 0) return(ret);
- }
- *str = cur;
- return(0);
-}
-
-/**
- * rfc3986_parse_segment:
- * @str: the string to analyze
- * @forbid: an optional forbidden character
- * @empty: allow an empty segment
- *
- * Parse a segment and fills in the appropriate fields
- * of the @uri structure
- *
- * segment = *pchar
- * segment-nz = 1*pchar
- * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
- * ; non-zero-length segment without any colon ":"
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_segment(const char **str, char forbid, int empty)
-{
- const char *cur;
-
- cur = *str;
- if (!ISA_PCHAR(cur)) {
- if (empty)
- return(0);
- return(1);
- }
- while (ISA_PCHAR(cur) && (*cur != forbid))
- NEXT(cur);
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_path_ab_empty:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an path absolute or empty and fills in the appropriate fields
- * of the @uri structure
- *
- * path-abempty = *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_path_ab_empty(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
-
- while (*cur == '/') {
- cur++;
- ret = rfc3986_parse_segment(&cur, 0, 1);
- if (ret != 0) return(ret);
- }
- if (uri != NULL) {
- g_free(uri->path);
- if (*str != cur) {
- if (uri->cleanup & 2)
- uri->path = g_strndup(*str, cur - *str);
- else
- uri->path = uri_string_unescape(*str, cur - *str, NULL);
- } else {
- uri->path = NULL;
- }
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_path_absolute:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an path absolute and fills in the appropriate fields
- * of the @uri structure
- *
- * path-absolute = "/" [ segment-nz *( "/" segment ) ]
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_path_absolute(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
-
- if (*cur != '/')
- return(1);
- cur++;
- ret = rfc3986_parse_segment(&cur, 0, 0);
- if (ret == 0) {
- while (*cur == '/') {
- cur++;
- ret = rfc3986_parse_segment(&cur, 0, 1);
- if (ret != 0) return(ret);
- }
- }
- if (uri != NULL) {
- g_free(uri->path);
- if (cur != *str) {
- if (uri->cleanup & 2)
- uri->path = g_strndup(*str, cur - *str);
- else
- uri->path = uri_string_unescape(*str, cur - *str, NULL);
- } else {
- uri->path = NULL;
- }
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_path_rootless:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an path without root and fills in the appropriate fields
- * of the @uri structure
- *
- * path-rootless = segment-nz *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_path_rootless(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
-
- ret = rfc3986_parse_segment(&cur, 0, 0);
- if (ret != 0) return(ret);
- while (*cur == '/') {
- cur++;
- ret = rfc3986_parse_segment(&cur, 0, 1);
- if (ret != 0) return(ret);
- }
- if (uri != NULL) {
- g_free(uri->path);
- if (cur != *str) {
- if (uri->cleanup & 2)
- uri->path = g_strndup(*str, cur - *str);
- else
- uri->path = uri_string_unescape(*str, cur - *str, NULL);
- } else {
- uri->path = NULL;
- }
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_path_no_scheme:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an path which is not a scheme and fills in the appropriate fields
- * of the @uri structure
- *
- * path-noscheme = segment-nz-nc *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_path_no_scheme(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
-
- ret = rfc3986_parse_segment(&cur, ':', 0);
- if (ret != 0) return(ret);
- while (*cur == '/') {
- cur++;
- ret = rfc3986_parse_segment(&cur, 0, 1);
- if (ret != 0) return(ret);
- }
- if (uri != NULL) {
- g_free(uri->path);
- if (cur != *str) {
- if (uri->cleanup & 2)
- uri->path = g_strndup(*str, cur - *str);
- else
- uri->path = uri_string_unescape(*str, cur - *str, NULL);
- } else {
- uri->path = NULL;
- }
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_hier_part:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an hierarchical part and fills in the appropriate fields
- * of the @uri structure
- *
- * hier-part = "//" authority path-abempty
- * / path-absolute
- * / path-rootless
- * / path-empty
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_hier_part(URI *uri, const char **str)
-{
- const char *cur;
- int ret;
-
- cur = *str;
-
- if ((*cur == '/') && (*(cur + 1) == '/')) {
- cur += 2;
- ret = rfc3986_parse_authority(uri, &cur);
- if (ret != 0) return(ret);
- ret = rfc3986_parse_path_ab_empty(uri, &cur);
- if (ret != 0) return(ret);
- *str = cur;
- return(0);
- } else if (*cur == '/') {
- ret = rfc3986_parse_path_absolute(uri, &cur);
- if (ret != 0) return(ret);
- } else if (ISA_PCHAR(cur)) {
- ret = rfc3986_parse_path_rootless(uri, &cur);
- if (ret != 0) return(ret);
- } else {
- /* path-empty is effectively empty */
- if (uri != NULL) {
- g_free(uri->path);
- uri->path = NULL;
- }
- }
- *str = cur;
- return (0);
-}
-
-/**
- * rfc3986_parse_relative_ref:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an URI string and fills in the appropriate fields
- * of the @uri structure
- *
- * relative-ref = relative-part [ "?" query ] [ "#" fragment ]
- * relative-part = "//" authority path-abempty
- * / path-absolute
- * / path-noscheme
- * / path-empty
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_relative_ref(URI *uri, const char *str) {
- int ret;
-
- if ((*str == '/') && (*(str + 1) == '/')) {
- str += 2;
- ret = rfc3986_parse_authority(uri, &str);
- if (ret != 0) return(ret);
- ret = rfc3986_parse_path_ab_empty(uri, &str);
- if (ret != 0) return(ret);
- } else if (*str == '/') {
- ret = rfc3986_parse_path_absolute(uri, &str);
- if (ret != 0) return(ret);
- } else if (ISA_PCHAR(str)) {
- ret = rfc3986_parse_path_no_scheme(uri, &str);
- if (ret != 0) return(ret);
- } else {
- /* path-empty is effectively empty */
- if (uri != NULL) {
- g_free(uri->path);
- uri->path = NULL;
- }
- }
-
- if (*str == '?') {
- str++;
- ret = rfc3986_parse_query(uri, &str);
- if (ret != 0) return(ret);
- }
- if (*str == '#') {
- str++;
- ret = rfc3986_parse_fragment(uri, &str);
- if (ret != 0) return(ret);
- }
- if (*str != 0) {
- uri_clean(uri);
- return(1);
- }
- return(0);
-}
-
-
-/**
- * rfc3986_parse:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an URI string and fills in the appropriate fields
- * of the @uri structure
- *
- * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse(URI *uri, const char *str) {
- int ret;
-
- ret = rfc3986_parse_scheme(uri, &str);
- if (ret != 0) return(ret);
- if (*str != ':') {
- return(1);
- }
- str++;
- ret = rfc3986_parse_hier_part(uri, &str);
- if (ret != 0) return(ret);
- if (*str == '?') {
- str++;
- ret = rfc3986_parse_query(uri, &str);
- if (ret != 0) return(ret);
- }
- if (*str == '#') {
- str++;
- ret = rfc3986_parse_fragment(uri, &str);
- if (ret != 0) return(ret);
- }
- if (*str != 0) {
- uri_clean(uri);
- return(1);
- }
- return(0);
-}
-
-/**
- * rfc3986_parse_uri_reference:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an URI reference string and fills in the appropriate fields
- * of the @uri structure
- *
- * URI-reference = URI / relative-ref
- *
- * Returns 0 or the error code
- */
-static int
-rfc3986_parse_uri_reference(URI *uri, const char *str) {
- int ret;
-
- if (str == NULL)
- return(-1);
- uri_clean(uri);
-
- /*
- * Try first to parse absolute refs, then fallback to relative if
- * it fails.
- */
- ret = rfc3986_parse(uri, str);
- if (ret != 0) {
- uri_clean(uri);
- ret = rfc3986_parse_relative_ref(uri, str);
- if (ret != 0) {
- uri_clean(uri);
- return(ret);
- }
- }
- return(0);
-}
-
-/**
- * uri_parse:
- * @str: the URI string to analyze
- *
- * Parse an URI based on RFC 3986
- *
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- *
- * Returns a newly built URI or NULL in case of error
- */
-URI *
-uri_parse(const char *str) {
- URI *uri;
- int ret;
-
- if (str == NULL)
- return(NULL);
- uri = uri_new();
- ret = rfc3986_parse_uri_reference(uri, str);
- if (ret) {
- uri_free(uri);
- return(NULL);
- }
- return(uri);
-}
-
-/**
- * uri_parse_into:
- * @uri: pointer to an URI structure
- * @str: the string to analyze
- *
- * Parse an URI reference string based on RFC 3986 and fills in the
- * appropriate fields of the @uri structure
- *
- * URI-reference = URI / relative-ref
- *
- * Returns 0 or the error code
- */
-int
-uri_parse_into(URI *uri, const char *str) {
- return(rfc3986_parse_uri_reference(uri, str));
-}
-
-/**
- * uri_parse_raw:
- * @str: the URI string to analyze
- * @raw: if 1 unescaping of URI pieces are disabled
- *
- * Parse an URI but allows to keep intact the original fragments.
- *
- * URI-reference = URI / relative-ref
- *
- * Returns a newly built URI or NULL in case of error
- */
-URI *
-uri_parse_raw(const char *str, int raw) {
- URI *uri;
- int ret;
-
- if (str == NULL)
- return(NULL);
- uri = uri_new();
- if (raw) {
- uri->cleanup |= 2;
- }
- ret = uri_parse_into(uri, str);
- if (ret) {
- uri_free(uri);
- return(NULL);
- }
- return(uri);
-}
-
-/************************************************************************
- * *
- * Generic URI structure functions *
- * *
- ************************************************************************/
-
-/**
- * uri_new:
- *
- * Simply creates an empty URI
- *
- * Returns the new structure or NULL in case of error
- */
-URI *
-uri_new(void) {
- URI *ret;
-
- ret = g_new0(URI, 1);
- return(ret);
-}
-
-/**
- * realloc2n:
- *
- * Function to handle properly a reallocation when saving an URI
- * Also imposes some limit on the length of an URI string output
- */
-static char *
-realloc2n(char *ret, int *max) {
- char *temp;
- int tmp;
-
- tmp = *max * 2;
- temp = g_realloc(ret, (tmp + 1));
- *max = tmp;
- return(temp);
-}
-
-/**
- * uri_to_string:
- * @uri: pointer to an URI
- *
- * Save the URI as an escaped string
- *
- * Returns a new string (to be deallocated by caller)
- */
-char *
-uri_to_string(URI *uri) {
- char *ret = NULL;
- char *temp;
- const char *p;
- int len;
- int max;
-
- if (uri == NULL) return(NULL);
-
-
- max = 80;
- ret = g_malloc(max + 1);
- len = 0;
-
- if (uri->scheme != NULL) {
- p = uri->scheme;
- while (*p != 0) {
- if (len >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = *p++;
- }
- if (len >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = ':';
- }
- if (uri->opaque != NULL) {
- p = uri->opaque;
- while (*p != 0) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
- ret[len++] = *p++;
- else {
- int val = *(unsigned char *)p++;
- int hi = val / 0x10, lo = val % 0x10;
- ret[len++] = '%';
- ret[len++] = hi + (hi > 9? 'A'-10 : '0');
- ret[len++] = lo + (lo > 9? 'A'-10 : '0');
- }
- }
- } else {
- if (uri->server != NULL) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '/';
- ret[len++] = '/';
- if (uri->user != NULL) {
- p = uri->user;
- while (*p != 0) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- if ((IS_UNRESERVED(*(p))) ||
- ((*(p) == ';')) || ((*(p) == ':')) ||
- ((*(p) == '&')) || ((*(p) == '=')) ||
- ((*(p) == '+')) || ((*(p) == '$')) ||
- ((*(p) == ',')))
- ret[len++] = *p++;
- else {
- int val = *(unsigned char *)p++;
- int hi = val / 0x10, lo = val % 0x10;
- ret[len++] = '%';
- ret[len++] = hi + (hi > 9? 'A'-10 : '0');
- ret[len++] = lo + (lo > 9? 'A'-10 : '0');
- }
- }
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '@';
- }
- p = uri->server;
- while (*p != 0) {
- if (len >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = *p++;
- }
- if (uri->port > 0) {
- if (len + 10 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- len += snprintf(&ret[len], max - len, ":%d", uri->port);
- }
- } else if (uri->authority != NULL) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '/';
- ret[len++] = '/';
- p = uri->authority;
- while (*p != 0) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- if ((IS_UNRESERVED(*(p))) ||
- ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
- ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
- ((*(p) == '=')) || ((*(p) == '+')))
- ret[len++] = *p++;
- else {
- int val = *(unsigned char *)p++;
- int hi = val / 0x10, lo = val % 0x10;
- ret[len++] = '%';
- ret[len++] = hi + (hi > 9? 'A'-10 : '0');
- ret[len++] = lo + (lo > 9? 'A'-10 : '0');
- }
- }
- } else if (uri->scheme != NULL) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '/';
- ret[len++] = '/';
- }
- if (uri->path != NULL) {
- p = uri->path;
- /*
- * the colon in file:///d: should not be escaped or
- * Windows accesses fail later.
- */
- if ((uri->scheme != NULL) &&
- (p[0] == '/') &&
- (((p[1] >= 'a') && (p[1] <= 'z')) ||
- ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
- (p[2] == ':') &&
- (!strcmp(uri->scheme, "file"))) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = *p++;
- ret[len++] = *p++;
- ret[len++] = *p++;
- }
- while (*p != 0) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
- ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
- ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
- ((*(p) == ',')))
- ret[len++] = *p++;
- else {
- int val = *(unsigned char *)p++;
- int hi = val / 0x10, lo = val % 0x10;
- ret[len++] = '%';
- ret[len++] = hi + (hi > 9? 'A'-10 : '0');
- ret[len++] = lo + (lo > 9? 'A'-10 : '0');
- }
- }
- }
- if (uri->query != NULL) {
- if (len + 1 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '?';
- p = uri->query;
- while (*p != 0) {
- if (len + 1 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = *p++;
- }
- }
- }
- if (uri->fragment != NULL) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len++] = '#';
- p = uri->fragment;
- while (*p != 0) {
- if (len + 3 >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
- ret[len++] = *p++;
- else {
- int val = *(unsigned char *)p++;
- int hi = val / 0x10, lo = val % 0x10;
- ret[len++] = '%';
- ret[len++] = hi + (hi > 9? 'A'-10 : '0');
- ret[len++] = lo + (lo > 9? 'A'-10 : '0');
- }
- }
- }
- if (len >= max) {
- temp = realloc2n(ret, &max);
- ret = temp;
- }
- ret[len] = 0;
- return(ret);
-}
-
-/**
- * uri_clean:
- * @uri: pointer to an URI
- *
- * Make sure the URI struct is free of content
- */
-static void
-uri_clean(URI *uri) {
- if (uri == NULL) return;
-
- g_free(uri->scheme);
- uri->scheme = NULL;
- g_free(uri->server);
- uri->server = NULL;
- g_free(uri->user);
- uri->user = NULL;
- g_free(uri->path);
- uri->path = NULL;
- g_free(uri->fragment);
- uri->fragment = NULL;
- g_free(uri->opaque);
- uri->opaque = NULL;
- g_free(uri->authority);
- uri->authority = NULL;
- g_free(uri->query);
- uri->query = NULL;
-}
-
-/**
- * uri_free:
- * @uri: pointer to an URI
- *
- * Free up the URI struct
- */
-void
-uri_free(URI *uri) {
- uri_clean(uri);
- g_free(uri);
-}
-
-/************************************************************************
- * *
- * Helper functions *
- * *
- ************************************************************************/
-
-/**
- * normalize_uri_path:
- * @path: pointer to the path string
- *
- * Applies the 5 normalization steps to a path string--that is, RFC 2396
- * Section 5.2, steps 6.c through 6.g.
- *
- * Normalization occurs directly on the string, no new allocation is done
- *
- * Returns 0 or an error code
- */
-static int
-normalize_uri_path(char *path) {
- char *cur, *out;
-
- if (path == NULL)
- return(-1);
-
- /* Skip all initial "/" chars. We want to get to the beginning of the
- * first non-empty segment.
- */
- cur = path;
- while (cur[0] == '/')
- ++cur;
- if (cur[0] == '\0')
- return(0);
-
- /* Keep everything we've seen so far. */
- out = cur;
-
- /*
- * Analyze each segment in sequence for cases (c) and (d).
- */
- while (cur[0] != '\0') {
- /*
- * c) All occurrences of "./", where "." is a complete path segment,
- * are removed from the buffer string.
- */
- if ((cur[0] == '.') && (cur[1] == '/')) {
- cur += 2;
- /* '//' normalization should be done at this point too */
- while (cur[0] == '/')
- cur++;
- continue;
- }
-
- /*
- * d) If the buffer string ends with "." as a complete path segment,
- * that "." is removed.
- */
- if ((cur[0] == '.') && (cur[1] == '\0'))
- break;
-
- /* Otherwise keep the segment. */
- while (cur[0] != '/') {
- if (cur[0] == '\0')
- goto done_cd;
- (out++)[0] = (cur++)[0];
- }
- /* nomalize // */
- while ((cur[0] == '/') && (cur[1] == '/'))
- cur++;
-
- (out++)[0] = (cur++)[0];
- }
- done_cd:
- out[0] = '\0';
-
- /* Reset to the beginning of the first segment for the next sequence. */
- cur = path;
- while (cur[0] == '/')
- ++cur;
- if (cur[0] == '\0')
- return(0);
-
- /*
- * Analyze each segment in sequence for cases (e) and (f).
- *
- * e) All occurrences of "<segment>/../", where <segment> is a
- * complete path segment not equal to "..", are removed from the
- * buffer string. Removal of these path segments is performed
- * iteratively, removing the leftmost matching pattern on each
- * iteration, until no matching pattern remains.
- *
- * f) If the buffer string ends with "<segment>/..", where <segment>
- * is a complete path segment not equal to "..", that
- * "<segment>/.." is removed.
- *
- * To satisfy the "iterative" clause in (e), we need to collapse the
- * string every time we find something that needs to be removed. Thus,
- * we don't need to keep two pointers into the string: we only need a
- * "current position" pointer.
- */
- while (1) {
- char *segp, *tmp;
-
- /* At the beginning of each iteration of this loop, "cur" points to
- * the first character of the segment we want to examine.
- */
-
- /* Find the end of the current segment. */
- segp = cur;
- while ((segp[0] != '/') && (segp[0] != '\0'))
- ++segp;
-
- /* If this is the last segment, we're done (we need at least two
- * segments to meet the criteria for the (e) and (f) cases).
- */
- if (segp[0] == '\0')
- break;
-
- /* If the first segment is "..", or if the next segment _isn't_ "..",
- * keep this segment and try the next one.
- */
- ++segp;
- if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3))
- || ((segp[0] != '.') || (segp[1] != '.')
- || ((segp[2] != '/') && (segp[2] != '\0')))) {
- cur = segp;
- continue;
- }
-
- /* If we get here, remove this segment and the next one and back up
- * to the previous segment (if there is one), to implement the
- * "iteratively" clause. It's pretty much impossible to back up
- * while maintaining two pointers into the buffer, so just compact
- * the whole buffer now.
- */
-
- /* If this is the end of the buffer, we're done. */
- if (segp[2] == '\0') {
- cur[0] = '\0';
- break;
- }
- /* Valgrind complained, strcpy(cur, segp + 3); */
- /* string will overlap, do not use strcpy */
- tmp = cur;
- segp += 3;
- while ((*tmp++ = *segp++) != 0)
- ;
-
- /* If there are no previous segments, then keep going from here. */
- segp = cur;
- while ((segp > path) && ((--segp)[0] == '/'))
- ;
- if (segp == path)
- continue;
-
- /* "segp" is pointing to the end of a previous segment; find it's
- * start. We need to back up to the previous segment and start
- * over with that to handle things like "foo/bar/../..". If we
- * don't do this, then on the first pass we'll remove the "bar/..",
- * but be pointing at the second ".." so we won't realize we can also
- * remove the "foo/..".
- */
- cur = segp;
- while ((cur > path) && (cur[-1] != '/'))
- --cur;
- }
- out[0] = '\0';
-
- /*
- * g) If the resulting buffer string still begins with one or more
- * complete path segments of "..", then the reference is
- * considered to be in error. Implementations may handle this
- * error by retaining these components in the resolved path (i.e.,
- * treating them as part of the final URI), by removing them from
- * the resolved path (i.e., discarding relative levels above the
- * root), or by avoiding traversal of the reference.
- *
- * We discard them from the final path.
- */
- if (path[0] == '/') {
- cur = path;
- while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.')
- && ((cur[3] == '/') || (cur[3] == '\0')))
- cur += 3;
-
- if (cur != path) {
- out = path;
- while (cur[0] != '\0')
- (out++)[0] = (cur++)[0];
- out[0] = 0;
- }
- }
-
- return(0);
-}
-
-static int is_hex(char c) {
- if (((c >= '0') && (c <= '9')) ||
- ((c >= 'a') && (c <= 'f')) ||
- ((c >= 'A') && (c <= 'F')))
- return(1);
- return(0);
-}
-
-
-/**
- * uri_string_unescape:
- * @str: the string to unescape
- * @len: the length in bytes to unescape (or <= 0 to indicate full string)
- * @target: optional destination buffer
- *
- * Unescaping routine, but does not check that the string is an URI. The
- * output is a direct unsigned char translation of %XX values (no encoding)
- * Note that the length of the result can only be smaller or same size as
- * the input string.
- *
- * Returns a copy of the string, but unescaped, will return NULL only in case
- * of error
- */
-char *
-uri_string_unescape(const char *str, int len, char *target) {
- char *ret, *out;
- const char *in;
-
- if (str == NULL)
- return(NULL);
- if (len <= 0) len = strlen(str);
- if (len < 0) return(NULL);
-
- if (target == NULL) {
- ret = g_malloc(len + 1);
- } else
- ret = target;
- in = str;
- out = ret;
- while(len > 0) {
- if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
- in++;
- if ((*in >= '0') && (*in <= '9'))
- *out = (*in - '0');
- else if ((*in >= 'a') && (*in <= 'f'))
- *out = (*in - 'a') + 10;
- else if ((*in >= 'A') && (*in <= 'F'))
- *out = (*in - 'A') + 10;
- in++;
- if ((*in >= '0') && (*in <= '9'))
- *out = *out * 16 + (*in - '0');
- else if ((*in >= 'a') && (*in <= 'f'))
- *out = *out * 16 + (*in - 'a') + 10;
- else if ((*in >= 'A') && (*in <= 'F'))
- *out = *out * 16 + (*in - 'A') + 10;
- in++;
- len -= 3;
- out++;
- } else {
- *out++ = *in++;
- len--;
- }
- }
- *out = 0;
- return(ret);
-}
-
-/**
- * uri_string_escape:
- * @str: string to escape
- * @list: exception list string of chars not to escape
- *
- * This routine escapes a string to hex, ignoring reserved characters (a-z)
- * and the characters in the exception list.
- *
- * Returns a new escaped string or NULL in case of error.
- */
-char *
-uri_string_escape(const char *str, const char *list) {
- char *ret, ch;
- char *temp;
- const char *in;
- int len, out;
-
- if (str == NULL)
- return(NULL);
- if (str[0] == 0)
- return(g_strdup(str));
- len = strlen(str);
- if (!(len > 0)) return(NULL);
-
- len += 20;
- ret = g_malloc(len);
- in = str;
- out = 0;
- while(*in != 0) {
- if (len - out <= 3) {
- temp = realloc2n(ret, &len);
- ret = temp;
- }
-
- ch = *in;
-
- if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!strchr(list, ch))) {
- unsigned char val;
- ret[out++] = '%';
- val = ch >> 4;
- if (val <= 9)
- ret[out++] = '0' + val;
- else
- ret[out++] = 'A' + val - 0xA;
- val = ch & 0xF;
- if (val <= 9)
- ret[out++] = '0' + val;
- else
- ret[out++] = 'A' + val - 0xA;
- in++;
- } else {
- ret[out++] = *in++;
- }
-
- }
- ret[out] = 0;
- return(ret);
-}
-
-/************************************************************************
- * *
- * Public functions *
- * *
- ************************************************************************/
-
-/**
- * uri_resolve:
- * @URI: the URI instance found in the document
- * @base: the base value
- *
- * Computes he final URI of the reference done by checking that
- * the given URI is valid, and building the final URI using the
- * base URI. This is processed according to section 5.2 of the
- * RFC 2396
- *
- * 5.2. Resolving Relative References to Absolute Form
- *
- * Returns a new URI string (to be freed by the caller) or NULL in case
- * of error.
- */
-char *
-uri_resolve(const char *uri, const char *base) {
- char *val = NULL;
- int ret, len, indx, cur, out;
- URI *ref = NULL;
- URI *bas = NULL;
- URI *res = NULL;
-
- /*
- * 1) The URI reference is parsed into the potential four components and
- * fragment identifier, as described in Section 4.3.
- *
- * NOTE that a completely empty URI is treated by modern browsers
- * as a reference to "." rather than as a synonym for the current
- * URI. Should we do that here?
- */
- if (uri == NULL)
- ret = -1;
- else {
- if (*uri) {
- ref = uri_new();
- ret = uri_parse_into(ref, uri);
- }
- else
- ret = 0;
- }
- if (ret != 0)
- goto done;
- if ((ref != NULL) && (ref->scheme != NULL)) {
- /*
- * The URI is absolute don't modify.
- */
- val = g_strdup(uri);
- goto done;
- }
- if (base == NULL)
- ret = -1;
- else {
- bas = uri_new();
- ret = uri_parse_into(bas, base);
- }
- if (ret != 0) {
- if (ref)
- val = uri_to_string(ref);
- goto done;
- }
- if (ref == NULL) {
- /*
- * the base fragment must be ignored
- */
- g_free(bas->fragment);
- bas->fragment = NULL;
- val = uri_to_string(bas);
- goto done;
- }
-
- /*
- * 2) If the path component is empty and the scheme, authority, and
- * query components are undefined, then it is a reference to the
- * current document and we are done. Otherwise, the reference URI's
- * query and fragment components are defined as found (or not found)
- * within the URI reference and not inherited from the base URI.
- *
- * NOTE that in modern browsers, the parsing differs from the above
- * in the following aspect: the query component is allowed to be
- * defined while still treating this as a reference to the current
- * document.
- */
- res = uri_new();
- if ((ref->scheme == NULL) && (ref->path == NULL) &&
- ((ref->authority == NULL) && (ref->server == NULL))) {
- res->scheme = g_strdup(bas->scheme);
- if (bas->authority != NULL)
- res->authority = g_strdup(bas->authority);
- else if (bas->server != NULL) {
- res->server = g_strdup(bas->server);
- res->user = g_strdup(bas->user);
- res->port = bas->port;
- }
- res->path = g_strdup(bas->path);
- if (ref->query != NULL) {
- res->query = g_strdup (ref->query);
- } else {
- res->query = g_strdup(bas->query);
- }
- res->fragment = g_strdup(ref->fragment);
- goto step_7;
- }
-
- /*
- * 3) If the scheme component is defined, indicating that the reference
- * starts with a scheme name, then the reference is interpreted as an
- * absolute URI and we are done. Otherwise, the reference URI's
- * scheme is inherited from the base URI's scheme component.
- */
- if (ref->scheme != NULL) {
- val = uri_to_string(ref);
- goto done;
- }
- res->scheme = g_strdup(bas->scheme);
-
- res->query = g_strdup(ref->query);
- res->fragment = g_strdup(ref->fragment);
-
- /*
- * 4) If the authority component is defined, then the reference is a
- * network-path and we skip to step 7. Otherwise, the reference
- * URI's authority is inherited from the base URI's authority
- * component, which will also be undefined if the URI scheme does not
- * use an authority component.
- */
- if ((ref->authority != NULL) || (ref->server != NULL)) {
- if (ref->authority != NULL)
- res->authority = g_strdup(ref->authority);
- else {
- res->server = g_strdup(ref->server);
- res->user = g_strdup(ref->user);
- res->port = ref->port;
- }
- res->path = g_strdup(ref->path);
- goto step_7;
- }
- if (bas->authority != NULL)
- res->authority = g_strdup(bas->authority);
- else if (bas->server != NULL) {
- res->server = g_strdup(bas->server);
- res->user = g_strdup(bas->user);
- res->port = bas->port;
- }
-
- /*
- * 5) If the path component begins with a slash character ("/"), then
- * the reference is an absolute-path and we skip to step 7.
- */
- if ((ref->path != NULL) && (ref->path[0] == '/')) {
- res->path = g_strdup(ref->path);
- goto step_7;
- }
-
-
- /*
- * 6) If this step is reached, then we are resolving a relative-path
- * reference. The relative path needs to be merged with the base
- * URI's path. Although there are many ways to do this, we will
- * describe a simple method using a separate string buffer.
- *
- * Allocate a buffer large enough for the result string.
- */
- len = 2; /* extra / and 0 */
- if (ref->path != NULL)
- len += strlen(ref->path);
- if (bas->path != NULL)
- len += strlen(bas->path);
- res->path = g_malloc(len);
- res->path[0] = 0;
-
- /*
- * a) All but the last segment of the base URI's path component is
- * copied to the buffer. In other words, any characters after the
- * last (right-most) slash character, if any, are excluded.
- */
- cur = 0;
- out = 0;
- if (bas->path != NULL) {
- while (bas->path[cur] != 0) {
- while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
- cur++;
- if (bas->path[cur] == 0)
- break;
-
- cur++;
- while (out < cur) {
- res->path[out] = bas->path[out];
- out++;
- }
- }
- }
- res->path[out] = 0;
-
- /*
- * b) The reference's path component is appended to the buffer
- * string.
- */
- if (ref->path != NULL && ref->path[0] != 0) {
- indx = 0;
- /*
- * Ensure the path includes a '/'
- */
- if ((out == 0) && (bas->server != NULL))
- res->path[out++] = '/';
- while (ref->path[indx] != 0) {
- res->path[out++] = ref->path[indx++];
- }
- }
- res->path[out] = 0;
-
- /*
- * Steps c) to h) are really path normalization steps
- */
- normalize_uri_path(res->path);
-
-step_7:
-
- /*
- * 7) The resulting URI components, including any inherited from the
- * base URI, are recombined to give the absolute form of the URI
- * reference.
- */
- val = uri_to_string(res);
-
-done:
- if (ref != NULL)
- uri_free(ref);
- if (bas != NULL)
- uri_free(bas);
- if (res != NULL)
- uri_free(res);
- return(val);
-}
-
-/**
- * uri_resolve_relative:
- * @URI: the URI reference under consideration
- * @base: the base value
- *
- * Expresses the URI of the reference in terms relative to the
- * base. Some examples of this operation include:
- * base = "http://site1.com/docs/book1.html"
- * URI input URI returned
- * docs/pic1.gif pic1.gif
- * docs/img/pic1.gif img/pic1.gif
- * img/pic1.gif ../img/pic1.gif
- * http://site1.com/docs/pic1.gif pic1.gif
- * http://site2.com/docs/pic1.gif http://site2.com/docs/pic1.gif
- *
- * base = "docs/book1.html"
- * URI input URI returned
- * docs/pic1.gif pic1.gif
- * docs/img/pic1.gif img/pic1.gif
- * img/pic1.gif ../img/pic1.gif
- * http://site1.com/docs/pic1.gif http://site1.com/docs/pic1.gif
- *
- *
- * Note: if the URI reference is really weird or complicated, it may be
- * worthwhile to first convert it into a "nice" one by calling
- * uri_resolve (using 'base') before calling this routine,
- * since this routine (for reasonable efficiency) assumes URI has
- * already been through some validation.
- *
- * Returns a new URI string (to be freed by the caller) or NULL in case
- * error.
- */
-char *
-uri_resolve_relative (const char *uri, const char * base)
-{
- char *val = NULL;
- int ret;
- int ix;
- int pos = 0;
- int nbslash = 0;
- int len;
- URI *ref = NULL;
- URI *bas = NULL;
- char *bptr, *uptr, *vptr;
- int remove_path = 0;
-
- if ((uri == NULL) || (*uri == 0))
- return NULL;
-
- /*
- * First parse URI into a standard form
- */
- ref = uri_new ();
- /* If URI not already in "relative" form */
- if (uri[0] != '.') {
- ret = uri_parse_into (ref, uri);
- if (ret != 0)
- goto done; /* Error in URI, return NULL */
- } else
- ref->path = g_strdup(uri);
-
- /*
- * Next parse base into the same standard form
- */
- if ((base == NULL) || (*base == 0)) {
- val = g_strdup (uri);
- goto done;
- }
- bas = uri_new ();
- if (base[0] != '.') {
- ret = uri_parse_into (bas, base);
- if (ret != 0)
- goto done; /* Error in base, return NULL */
- } else
- bas->path = g_strdup(base);
-
- /*
- * If the scheme / server on the URI differs from the base,
- * just return the URI
- */
- if ((ref->scheme != NULL) &&
- ((bas->scheme == NULL) ||
- (strcmp (bas->scheme, ref->scheme)) ||
- (strcmp (bas->server, ref->server)))) {
- val = g_strdup (uri);
- goto done;
- }
- if (bas->path == ref->path ||
- (bas->path && ref->path && !strcmp(bas->path, ref->path))) {
- val = g_strdup("");
- goto done;
- }
- if (bas->path == NULL) {
- val = g_strdup(ref->path);
- goto done;
- }
- if (ref->path == NULL) {
- ref->path = (char *) "/";
- remove_path = 1;
- }
-
- /*
- * At this point (at last!) we can compare the two paths
- *
- * First we take care of the special case where either of the
- * two path components may be missing (bug 316224)
- */
- if (bas->path == NULL) {
- if (ref->path != NULL) {
- uptr = ref->path;
- if (*uptr == '/')
- uptr++;
- /* exception characters from uri_to_string */
- val = uri_string_escape(uptr, "/;&=+$,");
- }
- goto done;
- }
- bptr = bas->path;
- if (ref->path == NULL) {
- for (ix = 0; bptr[ix] != 0; ix++) {
- if (bptr[ix] == '/')
- nbslash++;
- }
- uptr = NULL;
- len = 1; /* this is for a string terminator only */
- } else {
- /*
- * Next we compare the two strings and find where they first differ
- */
- if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
- pos += 2;
- if ((*bptr == '.') && (bptr[1] == '/'))
- bptr += 2;
- else if ((*bptr == '/') && (ref->path[pos] != '/'))
- bptr++;
- while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
- pos++;
-
- if (bptr[pos] == ref->path[pos]) {
- val = g_strdup("");
- goto done; /* (I can't imagine why anyone would do this) */
- }
-
- /*
- * In URI, "back up" to the last '/' encountered. This will be the
- * beginning of the "unique" suffix of URI
- */
- ix = pos;
- if ((ref->path[ix] == '/') && (ix > 0))
- ix--;
- else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
- ix -= 2;
- for (; ix > 0; ix--) {
- if (ref->path[ix] == '/')
- break;
- }
- if (ix == 0) {
- uptr = ref->path;
- } else {
- ix++;
- uptr = &ref->path[ix];
- }
-
- /*
- * In base, count the number of '/' from the differing point
- */
- if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */
- for (; bptr[ix] != 0; ix++) {
- if (bptr[ix] == '/')
- nbslash++;
- }
- }
- len = strlen (uptr) + 1;
- }
-
- if (nbslash == 0) {
- if (uptr != NULL)
- /* exception characters from uri_to_string */
- val = uri_string_escape(uptr, "/;&=+$,");
- goto done;
- }
-
- /*
- * Allocate just enough space for the returned string -
- * length of the remainder of the URI, plus enough space
- * for the "../" groups, plus one for the terminator
- */
- val = g_malloc (len + 3 * nbslash);
- vptr = val;
- /*
- * Put in as many "../" as needed
- */
- for (; nbslash>0; nbslash--) {
- *vptr++ = '.';
- *vptr++ = '.';
- *vptr++ = '/';
- }
- /*
- * Finish up with the end of the URI
- */
- if (uptr != NULL) {
- if ((vptr > val) && (len > 0) &&
- (uptr[0] == '/') && (vptr[-1] == '/')) {
- memcpy (vptr, uptr + 1, len - 1);
- vptr[len - 2] = 0;
- } else {
- memcpy (vptr, uptr, len);
- vptr[len - 1] = 0;
- }
- } else {
- vptr[len - 1] = 0;
- }
-
- /* escape the freshly-built path */
- vptr = val;
- /* exception characters from uri_to_string */
- val = uri_string_escape(vptr, "/;&=+$,");
- g_free(vptr);
-
-done:
- /*
- * Free the working variables
- */
- if (remove_path != 0)
- ref->path = NULL;
- if (ref != NULL)
- uri_free (ref);
- if (bas != NULL)
- uri_free (bas);
-
- return val;
-}
-
-/*
- * Utility functions to help parse and assemble query strings.
- */
-
-struct QueryParams *
-query_params_new (int init_alloc)
-{
- struct QueryParams *ps;
-
- if (init_alloc <= 0) init_alloc = 1;
-
- ps = g_new(QueryParams, 1);
- ps->n = 0;
- ps->alloc = init_alloc;
- ps->p = g_new(QueryParam, ps->alloc);
-
- return ps;
-}
-
-/* Ensure there is space to store at least one more parameter
- * at the end of the set.
- */
-static int
-query_params_append (struct QueryParams *ps,
- const char *name, const char *value)
-{
- if (ps->n >= ps->alloc) {
- ps->p = g_renew(QueryParam, ps->p, ps->alloc * 2);
- ps->alloc *= 2;
- }
-
- ps->p[ps->n].name = g_strdup(name);
- ps->p[ps->n].value = g_strdup(value);
- ps->p[ps->n].ignore = 0;
- ps->n++;
-
- return 0;
-}
-
-void
-query_params_free (struct QueryParams *ps)
-{
- int i;
-
- for (i = 0; i < ps->n; ++i) {
- g_free (ps->p[i].name);
- g_free (ps->p[i].value);
- }
- g_free (ps->p);
- g_free (ps);
-}
-
-struct QueryParams *
-query_params_parse (const char *query)
-{
- struct QueryParams *ps;
- const char *end, *eq;
-
- ps = query_params_new (0);
- if (!query || query[0] == '\0') return ps;
-
- while (*query) {
- char *name = NULL, *value = NULL;
-
- /* Find the next separator, or end of the string. */
- end = strchr (query, '&');
- if (!end)
- end = strchr (query, ';');
- if (!end)
- end = query + strlen (query);
-
- /* Find the first '=' character between here and end. */
- eq = strchr (query, '=');
- if (eq && eq >= end) eq = NULL;
-
- /* Empty section (eg. "&&"). */
- if (end == query)
- goto next;
-
- /* If there is no '=' character, then we have just "name"
- * and consistent with CGI.pm we assume value is "".
- */
- else if (!eq) {
- name = uri_string_unescape (query, end - query, NULL);
- value = NULL;
- }
- /* Or if we have "name=" here (works around annoying
- * problem when calling uri_string_unescape with len = 0).
- */
- else if (eq+1 == end) {
- name = uri_string_unescape (query, eq - query, NULL);
- value = g_new0(char, 1);
- }
- /* If the '=' character is at the beginning then we have
- * "=value" and consistent with CGI.pm we _ignore_ this.
- */
- else if (query == eq)
- goto next;
-
- /* Otherwise it's "name=value". */
- else {
- name = uri_string_unescape (query, eq - query, NULL);
- value = uri_string_unescape (eq+1, end - (eq+1), NULL);
- }
-
- /* Append to the parameter set. */
- query_params_append (ps, name, value);
- g_free(name);
- g_free(value);
-
- next:
- query = end;
- if (*query) query ++; /* skip '&' separator */
- }
-
- return ps;
-}