diff options
Diffstat (limited to 'contrib')
175 files changed, 5143 insertions, 51950 deletions
diff --git a/contrib/argp-standalone/Makefile.am b/contrib/argp-standalone/Makefile.am deleted file mode 100644 index 4775d4876aa..00000000000 --- a/contrib/argp-standalone/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -# From glibc - -# Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. - -# The GNU C 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 -# Library General Public License for more details. - -# You should have received a copy of the GNU Library General Public -# License along with the GNU C Library; see the file COPYING.LIB. If -# not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -AUTOMAKE_OPTIONS = foreign -SUBDIRS = . - -LIBOBJS = @LIBOBJS@ - -noinst_LIBRARIES = libargp.a - -noinst_HEADERS = argp.h argp-fmtstream.h argp-namefrob.h - -EXTRA_DIST = mempcpy.c strchrnul.c strndup.c strcasecmp.c vsnprintf.c autogen.sh - -# Leaves out argp-fs-xinl.c and argp-xinl.c -libargp_a_SOURCES = argp-ba.c argp-eexst.c argp-fmtstream.c \ - argp-help.c argp-parse.c argp-pv.c \ - argp-pvh.c - -libargp_a_LIBADD = $(LIBOBJS) - - diff --git a/contrib/argp-standalone/acinclude.m4 b/contrib/argp-standalone/acinclude.m4 deleted file mode 100644 index fb61e957dfa..00000000000 --- a/contrib/argp-standalone/acinclude.m4 +++ /dev/null @@ -1,1084 +0,0 @@ -dnl Try to detect the type of the third arg to getsockname() et al -AC_DEFUN([LSH_TYPE_SOCKLEN_T], -[AH_TEMPLATE([socklen_t], [Length type used by getsockopt]) -AC_CACHE_CHECK([for socklen_t in sys/socket.h], ac_cv_type_socklen_t, -[AC_EGREP_HEADER(socklen_t, sys/socket.h, - [ac_cv_type_socklen_t=yes], [ac_cv_type_socklen_t=no])]) -if test $ac_cv_type_socklen_t = no; then - AC_MSG_CHECKING(for AIX) - AC_EGREP_CPP(yes, [ -#ifdef _AIX - yes -#endif -],[ -AC_MSG_RESULT(yes) -AC_DEFINE(socklen_t, size_t) -],[ -AC_MSG_RESULT(no) -AC_DEFINE(socklen_t, int) -]) -fi -]) - -dnl Choose cc flags for compiling position independent code -AC_DEFUN([LSH_CCPIC], -[AC_MSG_CHECKING(CCPIC) -AC_CACHE_VAL(lsh_cv_sys_ccpic,[ - if test -z "$CCPIC" ; then - if test "$GCC" = yes ; then - case `uname -sr` in - BSD/OS*) - case `uname -r` in - 4.*) CCPIC="-fPIC";; - *) CCPIC="";; - esac - ;; - Darwin*) - CCPIC="-fPIC" - ;; - SunOS\ 5.*) - # Could also use -fPIC, if there are a large number of symbol reference - CCPIC="-fPIC" - ;; - CYGWIN*) - CCPIC="" - ;; - *) - CCPIC="-fpic" - ;; - esac - else - case `uname -sr` in - Darwin*) - CCPIC="-fPIC" - ;; - IRIX*) - CCPIC="-share" - ;; - hp*|HP*) CCPIC="+z"; ;; - FreeBSD*) CCPIC="-fpic";; - SCO_SV*) CCPIC="-KPIC -dy -Bdynamic";; - UnixWare*|OpenUNIX*) CCPIC="-KPIC -dy -Bdynamic";; - Solaris*) CCPIC="-KPIC -Bdynamic";; - Windows_NT*) CCPIC="-shared" ;; - esac - fi - fi - OLD_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $CCPIC" - AC_TRY_COMPILE([], [exit(0);], - lsh_cv_sys_ccpic="$CCPIC", lsh_cv_sys_ccpic='') - CFLAGS="$OLD_CFLAGS" -]) -CCPIC="$lsh_cv_sys_ccpic" -AC_MSG_RESULT($CCPIC) -AC_SUBST([CCPIC])]) - -dnl LSH_PATH_ADD(path-id, directory) -AC_DEFUN([LSH_PATH_ADD], -[AC_MSG_CHECKING($2) -ac_exists=no -if test -d "$2/." ; then - ac_real_dir=`cd $2 && pwd` - if test -n "$ac_real_dir" ; then - ac_exists=yes - for old in $1_REAL_DIRS ; do - ac_found=no - if test x$ac_real_dir = x$old ; then - ac_found=yes; - break; - fi - done - if test $ac_found = yes ; then - AC_MSG_RESULT(already added) - else - AC_MSG_RESULT(added) - # LDFLAGS="$LDFLAGS -L $2" - $1_REAL_DIRS="$ac_real_dir [$]$1_REAL_DIRS" - $1_DIRS="$2 [$]$1_DIRS" - fi - fi -fi -if test $ac_exists = no ; then - AC_MSG_RESULT(not found) -fi -]) - -dnl LSH_RPATH_ADD(dir) -AC_DEFUN([LSH_RPATH_ADD], [LSH_PATH_ADD(RPATH_CANDIDATE, $1)]) - -dnl LSH_RPATH_INIT(candidates) -AC_DEFUN([LSH_RPATH_INIT], -[AC_MSG_CHECKING([for -R flag]) -RPATHFLAG='' -case `uname -sr` in - OSF1\ V4.*) - RPATHFLAG="-rpath " - ;; - IRIX\ 6.*) - RPATHFLAG="-rpath " - ;; - IRIX\ 5.*) - RPATHFLAG="-rpath " - ;; - SunOS\ 5.*) - if test "$TCC" = "yes"; then - # tcc doesn't know about -R - RPATHFLAG="-Wl,-R," - else - RPATHFLAG=-R - fi - ;; - Linux\ 2.*) - RPATHFLAG="-Wl,-rpath," - ;; - *) - : - ;; -esac - -if test x$RPATHFLAG = x ; then - AC_MSG_RESULT(none) -else - AC_MSG_RESULT([using $RPATHFLAG]) -fi - -RPATH_CANDIDATE_REAL_DIRS='' -RPATH_CANDIDATE_DIRS='' - -AC_MSG_RESULT([Searching for libraries]) - -for d in $1 ; do - LSH_RPATH_ADD($d) -done -]) - -dnl Try to execute a main program, and if it fails, try adding some -dnl -R flag. -dnl LSH_RPATH_FIX -AC_DEFUN([LSH_RPATH_FIX], -[if test $cross_compiling = no -a "x$RPATHFLAG" != x ; then - ac_success=no - AC_TRY_RUN([int main(int argc, char **argv) { return 0; }], - ac_success=yes, ac_success=no, :) - - if test $ac_success = no ; then - AC_MSG_CHECKING([Running simple test program failed. Trying -R flags]) -dnl echo RPATH_CANDIDATE_DIRS = $RPATH_CANDIDATE_DIRS - ac_remaining_dirs='' - ac_rpath_save_LDFLAGS="$LDFLAGS" - for d in $RPATH_CANDIDATE_DIRS ; do - if test $ac_success = yes ; then - ac_remaining_dirs="$ac_remaining_dirs $d" - else - LDFLAGS="$RPATHFLAG$d $LDFLAGS" -dnl echo LDFLAGS = $LDFLAGS - AC_TRY_RUN([int main(int argc, char **argv) { return 0; }], - [ac_success=yes - ac_rpath_save_LDFLAGS="$LDFLAGS" - AC_MSG_RESULT([adding $RPATHFLAG$d]) - ], - [ac_remaining_dirs="$ac_remaining_dirs $d"], :) - LDFLAGS="$ac_rpath_save_LDFLAGS" - fi - done - RPATH_CANDIDATE_DIRS=$ac_remaining_dirs - fi - if test $ac_success = no ; then - AC_MSG_RESULT(failed) - fi -fi -]) - -dnl Like AC_CHECK_LIB, but uses $KRB_LIBS rather than $LIBS. -dnl LSH_CHECK_KRB_LIB(LIBRARY, FUNCTION, [, ACTION-IF-FOUND [, -dnl ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) - -AC_DEFUN([LSH_CHECK_KRB_LIB], -[AC_CHECK_LIB([$1], [$2], - ifelse([$3], , - [[ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - AC_DEFINE_UNQUOTED($ac_tr_lib) - KRB_LIBS="-l$1 $KRB_LIBS" - ]], [$3]), - ifelse([$4], , , [$4 -])dnl -, [$5 $KRB_LIBS]) -]) - -dnl LSH_LIB_ARGP(ACTION-IF-OK, ACTION-IF-BAD) -AC_DEFUN([LSH_LIB_ARGP], -[ ac_argp_save_LIBS="$LIBS" - ac_argp_save_LDFLAGS="$LDFLAGS" - ac_argp_ok=no - # First check if we can link with argp. - AC_SEARCH_LIBS(argp_parse, argp, - [ LSH_RPATH_FIX - AC_CACHE_CHECK([for working argp], - lsh_cv_lib_argp_works, - [ AC_TRY_RUN( -[#include <argp.h> -#include <stdlib.h> - -static const struct argp_option -options[] = -{ - { NULL, 0, NULL, 0, NULL, 0 } -}; - -struct child_state -{ - int n; -}; - -static error_t -child_parser(int key, char *arg, struct argp_state *state) -{ - struct child_state *input = (struct child_state *) state->input; - - switch(key) - { - default: - return ARGP_ERR_UNKNOWN; - case ARGP_KEY_END: - if (!input->n) - input->n = 1; - break; - } - return 0; -} - -const struct argp child_argp = -{ - options, - child_parser, - NULL, NULL, NULL, NULL, NULL -}; - -struct main_state -{ - struct child_state child; - int m; -}; - -static error_t -main_parser(int key, char *arg, struct argp_state *state) -{ - struct main_state *input = (struct main_state *) state->input; - - switch(key) - { - default: - return ARGP_ERR_UNKNOWN; - case ARGP_KEY_INIT: - state->child_inputs[0] = &input->child; - break; - case ARGP_KEY_END: - if (!input->m) - input->m = input->child.n; - - break; - } - return 0; -} - -static const struct argp_child -main_children[] = -{ - { &child_argp, 0, "", 0 }, - { NULL, 0, NULL, 0} -}; - -static const struct argp -main_argp = -{ options, main_parser, - NULL, - NULL, - main_children, - NULL, NULL -}; - -int main(int argc, char **argv) -{ - struct main_state input = { { 0 }, 0 }; - char *v[2] = { "foo", NULL }; - - argp_parse(&main_argp, 1, v, 0, NULL, &input); - - if ( (input.m == 1) && (input.child.n == 1) ) - return 0; - else - return 1; -} -], lsh_cv_lib_argp_works=yes, - lsh_cv_lib_argp_works=no, - lsh_cv_lib_argp_works=no)]) - - if test x$lsh_cv_lib_argp_works = xyes ; then - ac_argp_ok=yes - else - # Reset link flags - LIBS="$ac_argp_save_LIBS" - LDFLAGS="$ac_argp_save_LDFLAGS" - fi]) - - if test x$ac_argp_ok = xyes ; then - ifelse([$1],, true, [$1]) - else - ifelse([$2],, true, [$2]) - fi -]) - -dnl LSH_GCC_ATTRIBUTES -dnl Check for gcc's __attribute__ construction - -AC_DEFUN([LSH_GCC_ATTRIBUTES], -[AC_CACHE_CHECK(for __attribute__, - lsh_cv_c_attribute, -[ AC_TRY_COMPILE([ -#include <stdlib.h> -], -[ -static void foo(void) __attribute__ ((noreturn)); - -static void __attribute__ ((noreturn)) -foo(void) -{ - exit(1); -} -], -lsh_cv_c_attribute=yes, -lsh_cv_c_attribute=no)]) - -AH_TEMPLATE([HAVE_GCC_ATTRIBUTE], [Define if the compiler understands __attribute__]) -if test "x$lsh_cv_c_attribute" = "xyes"; then - AC_DEFINE(HAVE_GCC_ATTRIBUTE) -fi - -AH_BOTTOM( -[#if __GNUC__ || HAVE_GCC_ATTRIBUTE -# define NORETURN __attribute__ ((__noreturn__)) -# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a))) -# define UNUSED __attribute__ ((__unused__)) -#else -# define NORETURN -# define PRINTF_STYLE(f, a) -# define UNUSED -#endif -])]) - -AC_DEFUN([LSH_GCC_FUNCTION_NAME], -[# Check for gcc's __FUNCTION__ variable -AH_TEMPLATE([HAVE_GCC_FUNCTION], - [Define if the compiler understands __FUNCTION__]) -AH_BOTTOM( -[#if HAVE_GCC_FUNCTION -# define FUNCTION_NAME __FUNCTION__ -#else -# define FUNCTION_NAME "Unknown" -#endif -]) - -AC_CACHE_CHECK(for __FUNCTION__, - lsh_cv_c_FUNCTION, - [ AC_TRY_COMPILE(, - [ #if __GNUC__ == 3 - # error __FUNCTION__ is broken in gcc-3 - #endif - void foo(void) { char c = __FUNCTION__[0]; } ], - lsh_cv_c_FUNCTION=yes, - lsh_cv_c_FUNCTION=no)]) - -if test "x$lsh_cv_c_FUNCTION" = "xyes"; then - AC_DEFINE(HAVE_GCC_FUNCTION) -fi -]) - -# Check for alloca, and include the standard blurb in config.h -AC_DEFUN([LSH_FUNC_ALLOCA], -[AC_FUNC_ALLOCA -AC_CHECK_HEADERS([malloc.h]) -AH_BOTTOM( -[/* AIX requires this to be the first thing in the file. */ -#ifndef __GNUC__ -# if HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -# endif -# endif -# endif -#else /* defined __GNUC__ */ -# if HAVE_ALLOCA_H -# include <alloca.h> -# endif -#endif -/* Needed for alloca on windows */ -#if HAVE_MALLOC_H -# include <malloc.h> -#endif -])]) - -AC_DEFUN([LSH_FUNC_STRERROR], -[AC_CHECK_FUNCS(strerror) -AH_BOTTOM( -[#if HAVE_STRERROR -#define STRERROR strerror -#else -#define STRERROR(x) (sys_errlist[x]) -#endif -])]) - -AC_DEFUN([LSH_FUNC_STRSIGNAL], -[AC_CHECK_FUNCS(strsignal) -AC_CHECK_DECLS([sys_siglist, _sys_siglist]) -AH_BOTTOM( -[#if HAVE_STRSIGNAL -# define STRSIGNAL strsignal -#else /* !HAVE_STRSIGNAL */ -# if HAVE_DECL_SYS_SIGLIST -# define STRSIGNAL(x) (sys_siglist[x]) -# else -# if HAVE_DECL__SYS_SIGLIST -# define STRSIGNAL(x) (_sys_siglist[x]) -# else -# define STRSIGNAL(x) "Unknown signal" -# if __GNUC__ -# warning Using dummy STRSIGNAL -# endif -# endif -# endif -#endif /* !HAVE_STRSIGNAL */ -])]) - -dnl LSH_MAKE_CONDITIONAL(symbol, test) -AC_DEFUN([LSH_MAKE_CONDITIONAL], -[if $2 ; then - IF_$1='' - UNLESS_$1='# ' -else - IF_$1='# ' - UNLESS_$1='' -fi -AC_SUBST(IF_$1) -AC_SUBST(UNLESS_$1)]) - -dnl LSH_DEPENDENCY_TRACKING - -dnl Defines compiler flags DEP_FLAGS to generate dependency -dnl information, and DEP_PROCESS that is any shell commands needed for -dnl massaging the dependency information further. Dependencies are -dnl generated as a side effect of compilation. Dependency files -dnl themselves are not treated as targets. - -AC_DEFUN([LSH_DEPENDENCY_TRACKING], -[AC_ARG_ENABLE(dependency_tracking, - AC_HELP_STRING([--disable-dependency-tracking], - [Disable dependency tracking. Dependency tracking doesn't work with BSD make]),, - [enable_dependency_tracking=yes]) - -DEP_FLAGS='' -DEP_PROCESS='true' -if test x$enable_dependency_tracking = xyes ; then - if test x$GCC = xyes ; then - gcc_version=`gcc --version | head -1` - case "$gcc_version" in - 2.*|*[[!0-9.]]2.*) - enable_dependency_tracking=no - AC_MSG_WARN([Dependency tracking disabled, gcc-3.x is needed]) - ;; - *) - DEP_FLAGS='-MT $[]@ -MD -MP -MF $[]@.d' - DEP_PROCESS='true' - ;; - esac - else - enable_dependency_tracking=no - AC_MSG_WARN([Dependency tracking disabled]) - fi -fi - -if test x$enable_dependency_tracking = xyes ; then - DEP_INCLUDE='include ' -else - DEP_INCLUDE='# ' -fi - -AC_SUBST([DEP_INCLUDE]) -AC_SUBST([DEP_FLAGS]) -AC_SUBST([DEP_PROCESS])]) - -dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEADERS-TO-CHECK])] -dnl -dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the -dnl existence of an include file <stdint.h> that defines a set of -dnl typedefs, especially uint8_t,int32_t,uintptr_t. -dnl Many older installations will not provide this file, but some will -dnl have the very same definitions in <inttypes.h>. In other enviroments -dnl we can use the inet-types in <sys/types.h> which would define the -dnl typedefs int8_t and u_int8_t respectivly. -dnl -dnl This macros will create a local "_stdint.h" or the headerfile given as -dnl an argument. In many cases that file will just "#include <stdint.h>" -dnl or "#include <inttypes.h>", while in other environments it will provide -dnl the set of basic 'stdint's definitions/typedefs: -dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t -dnl int_least32_t.. int_fast32_t.. intmax_t -dnl which may or may not rely on the definitions of other files, -dnl or using the AC_CHECK_SIZEOF macro to determine the actual -dnl sizeof each type. -dnl -dnl if your header files require the stdint-types you will want to create an -dnl installable file mylib-int.h that all your other installable header -dnl may include. So if you have a library package named "mylib", just use -dnl AX_CREATE_STDINT_H(mylib-int.h) -dnl in configure.ac and go to install that very header file in Makefile.am -dnl along with the other headers (mylib.h) - and the mylib-specific headers -dnl can simply use "#include <mylib-int.h>" to obtain the stdint-types. -dnl -dnl Remember, if the system already had a valid <stdint.h>, the generated -dnl file will include it directly. No need for fuzzy HAVE_STDINT_H things... -dnl -dnl @, (status: used on new platforms) (see http://ac-archive.sf.net/gstdint/) -dnl @version $Id: acinclude.m4,v 1.27 2004/11/23 21:27:35 nisse Exp $ -dnl @author Guido Draheim <guidod@gmx.de> - -AC_DEFUN([AX_CREATE_STDINT_H], -[# ------ AX CREATE STDINT H ------------------------------------- -AC_MSG_CHECKING([for stdint types]) -ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` -# try to shortcircuit - if the default include path of the compiler -# can find a "stdint.h" header then we assume that all compilers can. -AC_CACHE_VAL([ac_cv_header_stdint_t],[ -old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" -old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" -old_CFLAGS="$CFLAGS" ; CFLAGS="" -AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;], -[ac_cv_stdint_result="(assuming C99 compatible system)" - ac_cv_header_stdint_t="stdint.h"; ], -[ac_cv_header_stdint_t=""]) -CXXFLAGS="$old_CXXFLAGS" -CPPFLAGS="$old_CPPFLAGS" -CFLAGS="$old_CFLAGS" ]) - -v="... $ac_cv_header_stdint_h" -if test "$ac_stdint_h" = "stdint.h" ; then - AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) -elif test "$ac_stdint_h" = "inttypes.h" ; then - AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) -elif test "_$ac_cv_header_stdint_t" = "_" ; then - AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) -else - ac_cv_header_stdint="$ac_cv_header_stdint_t" - AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) -fi - -if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. - -dnl .....intro message done, now do a few system checks..... -dnl btw, all CHECK_TYPE macros do automatically "DEFINE" a type, therefore -dnl we use the autoconf implementation detail _AC CHECK_TYPE_NEW instead - -inttype_headers=`echo $2 | sed -e 's/,/ /g'` - -ac_cv_stdint_result="(no helpful system typedefs seen)" -AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ - ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) - AC_MSG_RESULT([(..)]) - for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers ; do - unset ac_cv_type_uintptr_t - unset ac_cv_type_uint64_t - _AC_CHECK_TYPE_NEW(uintptr_t,[ac_cv_header_stdint_x=$i],dnl - continue,[#include <$i>]) - AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) - ac_cv_stdint_result="(seen uintptr_t$and64 in $i)" - break; - done - AC_MSG_CHECKING([for stdint uintptr_t]) - ]) - -if test "_$ac_cv_header_stdint_x" = "_" ; then -AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ - ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) - AC_MSG_RESULT([(..)]) - for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers ; do - unset ac_cv_type_uint32_t - unset ac_cv_type_uint64_t - AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],dnl - continue,[#include <$i>]) - AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) - ac_cv_stdint_result="(seen uint32_t$and64 in $i)" - break; - done - AC_MSG_CHECKING([for stdint uint32_t]) - ]) -fi - -if test "_$ac_cv_header_stdint_x" = "_" ; then -if test "_$ac_cv_header_stdint_o" = "_" ; then -AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ - ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) - AC_MSG_RESULT([(..)]) - for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do - unset ac_cv_type_u_int32_t - unset ac_cv_type_u_int64_t - AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],dnl - continue,[#include <$i>]) - AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) - ac_cv_stdint_result="(seen u_int32_t$and64 in $i)" - break; - done - AC_MSG_CHECKING([for stdint u_int32_t]) - ]) -fi fi - -dnl if there was no good C99 header file, do some typedef checks... -if test "_$ac_cv_header_stdint_x" = "_" ; then - AC_MSG_CHECKING([for stdint datatype model]) - AC_MSG_RESULT([(..)]) - AC_CHECK_SIZEOF(char) - AC_CHECK_SIZEOF(short) - AC_CHECK_SIZEOF(int) - AC_CHECK_SIZEOF(long) - AC_CHECK_SIZEOF(void*) - ac_cv_stdint_char_model="" - ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_char" - ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_short" - ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_int" - ac_cv_stdint_long_model="" - ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_int" - ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_long" - ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_voidp" - name="$ac_cv_stdint_long_model" - case "$ac_cv_stdint_char_model/$ac_cv_stdint_long_model" in - 122/242) name="$name, IP16 (standard 16bit machine)" ;; - 122/244) name="$name, LP32 (standard 32bit mac/win)" ;; - 122/*) name="$name (unusual int16 model)" ;; - 124/444) name="$name, ILP32 (standard 32bit unixish)" ;; - 124/488) name="$name, LP64 (standard 64bit unixish)" ;; - 124/448) name="$name, LLP64 (unusual 64bit unixish)" ;; - 124/*) name="$name (unusual int32 model)" ;; - 128/888) name="$name, ILP64 (unusual 64bit numeric)" ;; - 128/*) name="$name (unusual int64 model)" ;; - 222/*|444/*) name="$name (unusual dsptype)" ;; - *) name="$name (very unusal model)" ;; - esac - AC_MSG_RESULT([combined for stdint datatype model... $name]) -fi - -if test "_$ac_cv_header_stdint_x" != "_" ; then - ac_cv_header_stdint="$ac_cv_header_stdint_x" -elif test "_$ac_cv_header_stdint_o" != "_" ; then - ac_cv_header_stdint="$ac_cv_header_stdint_o" -elif test "_$ac_cv_header_stdint_u" != "_" ; then - ac_cv_header_stdint="$ac_cv_header_stdint_u" -else - ac_cv_header_stdint="stddef.h" -fi - -AC_MSG_CHECKING([for extra inttypes in chosen header]) -AC_MSG_RESULT([($ac_cv_header_stdint)]) -dnl see if int_least and int_fast types are present in _this_ header. -unset ac_cv_type_int_least32_t -unset ac_cv_type_int_fast32_t -AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) -AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) -AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) - -fi # shortcircut to system "stdint.h" -# ------------------ PREPARE VARIABLES ------------------------------ -if test "$GCC" = "yes" ; then -ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` -else -ac_cv_stdint_message="using $CC" -fi - -AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl -$ac_cv_stdint_result]) - -# ----------------- DONE inttypes.h checks START header ------------- -AC_CONFIG_COMMANDS([$ac_stdint_h],[ -AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) -ac_stdint=$tmp/_stdint.h - -echo "#ifndef" $_ac_stdint_h >$ac_stdint -echo "#define" $_ac_stdint_h "1" >>$ac_stdint -echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint -echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint -echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint -if test "_$ac_cv_header_stdint_t" != "_" ; then -echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint -fi - -cat >>$ac_stdint <<STDINT_EOF - -/* ................... shortcircuit part ........................... */ - -#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H -#include <stdint.h> -#else -#include <stddef.h> - -/* .................... configured part ............................ */ - -STDINT_EOF - -echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint -if test "_$ac_cv_header_stdint_x" != "_" ; then - ac_header="$ac_cv_header_stdint_x" - echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint -else - echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint -fi - -echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint -if test "_$ac_cv_header_stdint_o" != "_" ; then - ac_header="$ac_cv_header_stdint_o" - echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint -else - echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint -fi - -echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint -if test "_$ac_cv_header_stdint_u" != "_" ; then - ac_header="$ac_cv_header_stdint_u" - echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint -else - echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint -fi - -echo "" >>$ac_stdint - -if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then - echo "#include <$ac_header>" >>$ac_stdint - echo "" >>$ac_stdint -fi fi - -echo "/* which 64bit typedef has been found */" >>$ac_stdint -if test "$ac_cv_type_uint64_t" = "yes" ; then -echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint -else -echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint -fi -if test "$ac_cv_type_u_int64_t" = "yes" ; then -echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint -else -echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint -fi -echo "" >>$ac_stdint - -echo "/* which type model has been detected */" >>$ac_stdint -if test "_$ac_cv_stdint_char_model" != "_" ; then -echo "#define _STDINT_CHAR_MODEL" "$ac_cv_stdint_char_model" >>$ac_stdint -echo "#define _STDINT_LONG_MODEL" "$ac_cv_stdint_long_model" >>$ac_stdint -else -echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint -echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint -fi -echo "" >>$ac_stdint - -echo "/* whether int_least types were detected */" >>$ac_stdint -if test "$ac_cv_type_int_least32_t" = "yes"; then -echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint -else -echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint -fi -echo "/* whether int_fast types were detected */" >>$ac_stdint -if test "$ac_cv_type_int_fast32_t" = "yes"; then -echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint -else -echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint -fi -echo "/* whether intmax_t type was detected */" >>$ac_stdint -if test "$ac_cv_type_intmax_t" = "yes"; then -echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint -else -echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint -fi -echo "" >>$ac_stdint - - cat >>$ac_stdint <<STDINT_EOF -/* .................... detections part ............................ */ - -/* whether we need to define bitspecific types from compiler base types */ -#ifndef _STDINT_HEADER_INTPTR -#ifndef _STDINT_HEADER_UINT32 -#ifndef _STDINT_HEADER_U_INT32 -#define _STDINT_NEED_INT_MODEL_T -#else -#define _STDINT_HAVE_U_INT_TYPES -#endif -#endif -#endif - -#ifdef _STDINT_HAVE_U_INT_TYPES -#undef _STDINT_NEED_INT_MODEL_T -#endif - -#ifdef _STDINT_CHAR_MODEL -#if _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124 -#ifndef _STDINT_BYTE_MODEL -#define _STDINT_BYTE_MODEL 12 -#endif -#endif -#endif - -#ifndef _STDINT_HAVE_INT_LEAST32_T -#define _STDINT_NEED_INT_LEAST_T -#endif - -#ifndef _STDINT_HAVE_INT_FAST32_T -#define _STDINT_NEED_INT_FAST_T -#endif - -#ifndef _STDINT_HEADER_INTPTR -#define _STDINT_NEED_INTPTR_T -#ifndef _STDINT_HAVE_INTMAX_T -#define _STDINT_NEED_INTMAX_T -#endif -#endif - - -/* .................... definition part ............................ */ - -/* some system headers have good uint64_t */ -#ifndef _HAVE_UINT64_T -#if defined _STDINT_HAVE_UINT64_T || defined HAVE_UINT64_T -#define _HAVE_UINT64_T -#elif defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T -#define _HAVE_UINT64_T -typedef u_int64_t uint64_t; -#endif -#endif - -#ifndef _HAVE_UINT64_T -/* .. here are some common heuristics using compiler runtime specifics */ -#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L -#define _HAVE_UINT64_T -typedef long long int64_t; -typedef unsigned long long uint64_t; - -#elif !defined __STRICT_ANSI__ -#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ -#define _HAVE_UINT64_T -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ -/* note: all ELF-systems seem to have loff-support which needs 64-bit */ -#if !defined _NO_LONGLONG -#define _HAVE_UINT64_T -typedef long long int64_t; -typedef unsigned long long uint64_t; -#endif - -#elif defined __alpha || (defined __mips && defined _ABIN32) -#if !defined _NO_LONGLONG -typedef long int64_t; -typedef unsigned long uint64_t; -#endif - /* compiler/cpu type to define int64_t */ -#endif -#endif -#endif - -#if defined _STDINT_HAVE_U_INT_TYPES -/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ -typedef u_int8_t uint8_t; -typedef u_int16_t uint16_t; -typedef u_int32_t uint32_t; - -/* glibc compatibility */ -#ifndef __int8_t_defined -#define __int8_t_defined -#endif -#endif - -#ifdef _STDINT_NEED_INT_MODEL_T -/* we must guess all the basic types. Apart from byte-adressable system, */ -/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ -/* (btw, those nibble-addressable systems are way off, or so we assume) */ - -dnl /* have a look at "64bit and data size neutrality" at */ -dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ -dnl /* (the shorthand "ILP" types always have a "P" part) */ - -#if defined _STDINT_BYTE_MODEL -#if _STDINT_LONG_MODEL+0 == 242 -/* 2:4:2 = IP16 = a normal 16-bit system */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; -#ifndef __int8_t_defined -#define __int8_t_defined -typedef char int8_t; -typedef short int16_t; -typedef long int32_t; -#endif -#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 -/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ -/* 4:4:4 = ILP32 = a normal 32-bit system */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -#ifndef __int8_t_defined -#define __int8_t_defined -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -#endif -#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 -/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ -/* 4:8:8 = LP64 = a normal 64-bit system */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -#ifndef __int8_t_defined -#define __int8_t_defined -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -#endif -/* this system has a "long" of 64bit */ -#ifndef _HAVE_UINT64_T -#define _HAVE_UINT64_T -typedef unsigned long uint64_t; -typedef long int64_t; -#endif -#elif _STDINT_LONG_MODEL+0 == 448 -/* LLP64 a 64-bit system derived from a 32-bit system */ -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -#ifndef __int8_t_defined -#define __int8_t_defined -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -#endif -/* assuming the system has a "long long" */ -#ifndef _HAVE_UINT64_T -#define _HAVE_UINT64_T -typedef unsigned long long uint64_t; -typedef long long int64_t; -#endif -#else -#define _STDINT_NO_INT32_T -#endif -#else -#define _STDINT_NO_INT8_T -#define _STDINT_NO_INT32_T -#endif -#endif - -/* - * quote from SunOS-5.8 sys/inttypes.h: - * Use at your own risk. As of February 1996, the committee is squarely - * behind the fixed sized types; the "least" and "fast" types are still being - * discussed. The probability that the "fast" types may be removed before - * the standard is finalized is high enough that they are not currently - * implemented. - */ - -#if defined _STDINT_NEED_INT_LEAST_T -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -#ifdef _HAVE_UINT64_T -typedef int64_t int_least64_t; -#endif - -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -#ifdef _HAVE_UINT64_T -typedef uint64_t uint_least64_t; -#endif - /* least types */ -#endif - -#if defined _STDINT_NEED_INT_FAST_T -typedef int8_t int_fast8_t; -typedef int int_fast16_t; -typedef int32_t int_fast32_t; -#ifdef _HAVE_UINT64_T -typedef int64_t int_fast64_t; -#endif - -typedef uint8_t uint_fast8_t; -typedef unsigned uint_fast16_t; -typedef uint32_t uint_fast32_t; -#ifdef _HAVE_UINT64_T -typedef uint64_t uint_fast64_t; -#endif - /* fast types */ -#endif - -#ifdef _STDINT_NEED_INTMAX_T -#ifdef _HAVE_UINT64_T -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; -#else -typedef long intmax_t; -typedef unsigned long uintmax_t; -#endif -#endif - -#ifdef _STDINT_NEED_INTPTR_T -#ifndef __intptr_t_defined -#define __intptr_t_defined -/* we encourage using "long" to store pointer values, never use "int" ! */ -#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 -typedef unsinged int uintptr_t; -typedef int intptr_t; -#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 -typedef unsigned long uintptr_t; -typedef long intptr_t; -#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T -typedef uint64_t uintptr_t; -typedef int64_t intptr_t; -#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ -typedef unsigned long uintptr_t; -typedef long intptr_t; -#endif -#endif -#endif - - /* shortcircuit*/ -#endif - /* once */ -#endif -#endif -STDINT_EOF - if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then - AC_MSG_NOTICE([$ac_stdint_h is unchanged]) - else - ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` - AS_MKDIR_P(["$ac_dir"]) - rm -f $ac_stdint_h - mv $ac_stdint $ac_stdint_h - fi -],[# variables for create stdint.h replacement -PACKAGE="$PACKAGE" -VERSION="$VERSION" -ac_stdint_h="$ac_stdint_h" -_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) -ac_cv_stdint_message="$ac_cv_stdint_message" -ac_cv_header_stdint_t="$ac_cv_header_stdint_t" -ac_cv_header_stdint_x="$ac_cv_header_stdint_x" -ac_cv_header_stdint_o="$ac_cv_header_stdint_o" -ac_cv_header_stdint_u="$ac_cv_header_stdint_u" -ac_cv_type_uint64_t="$ac_cv_type_uint64_t" -ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" -ac_cv_stdint_char_model="$ac_cv_stdint_char_model" -ac_cv_stdint_long_model="$ac_cv_stdint_long_model" -ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" -ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" -ac_cv_type_intmax_t="$ac_cv_type_intmax_t" -]) -]) diff --git a/contrib/argp-standalone/argp-ba.c b/contrib/argp-standalone/argp-ba.c deleted file mode 100644 index 0d3958c1151..00000000000 --- a/contrib/argp-standalone/argp-ba.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Default definition for ARGP_PROGRAM_BUG_ADDRESS. - Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* If set by the user program, it should point to string that is the - bug-reporting address for the program. It will be printed by argp_help if - the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help - messages), embedded in a sentence that says something like `Report bugs to - ADDR.'. */ -const char *argp_program_bug_address = 0; diff --git a/contrib/argp-standalone/argp-eexst.c b/contrib/argp-standalone/argp-eexst.c deleted file mode 100644 index 46b27847ad4..00000000000 --- a/contrib/argp-standalone/argp-eexst.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Default definition for ARGP_ERR_EXIT_STATUS - Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if HAVE_SYSEXITS_H -# include <sysexits.h> -#else -# define EX_USAGE 64 -#endif - -#include "argp.h" - -/* The exit status that argp will use when exiting due to a parsing error. - If not defined or set by the user program, this defaults to EX_USAGE from - <sysexits.h>. */ -error_t argp_err_exit_status = EX_USAGE; diff --git a/contrib/argp-standalone/argp-fmtstream.c b/contrib/argp-standalone/argp-fmtstream.c deleted file mode 100644 index 494b6b31d12..00000000000 --- a/contrib/argp-standalone/argp-fmtstream.c +++ /dev/null @@ -1,477 +0,0 @@ -/* Word-wrapping and line-truncating streams - Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This package emulates glibc `line_wrap_stream' semantics for systems that - don't have that. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <stdarg.h> -#include <ctype.h> - -#include "argp-fmtstream.h" -#include "argp-namefrob.h" - -#ifndef ARGP_FMTSTREAM_USE_LINEWRAP - -#ifndef isblank -#define isblank(ch) ((ch)==' ' || (ch)=='\t') -#endif - -#if defined _LIBC && defined USE_IN_LIBIO -# include <libio/libioP.h> -# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) -#endif - -#define INIT_BUF_SIZE 200 -#define PRINTF_SIZE_GUESS 150 - -/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines - written on it with LMARGIN spaces and limits them to RMARGIN columns - total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by - replacing the whitespace before them with a newline and WMARGIN spaces. - Otherwise, chars beyond RMARGIN are simply dropped until a newline. - Returns NULL if there was an error. */ -argp_fmtstream_t -__argp_make_fmtstream (FILE *stream, - size_t lmargin, size_t rmargin, ssize_t wmargin) -{ - argp_fmtstream_t fs = malloc (sizeof (struct argp_fmtstream)); - if (fs) - { - fs->stream = stream; - - fs->lmargin = lmargin; - fs->rmargin = rmargin; - fs->wmargin = wmargin; - fs->point_col = 0; - fs->point_offs = 0; - - fs->buf = malloc (INIT_BUF_SIZE); - if (! fs->buf) - { - free (fs); - fs = 0; - } - else - { - fs->p = fs->buf; - fs->end = fs->buf + INIT_BUF_SIZE; - } - } - - return fs; -} -#ifdef weak_alias -weak_alias (__argp_make_fmtstream, argp_make_fmtstream) -#endif - -/* Flush FS to its stream, and free it (but don't close the stream). */ -void -__argp_fmtstream_free (argp_fmtstream_t fs) -{ - __argp_fmtstream_update (fs); - if (fs->p > fs->buf) - FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream); - free (fs->buf); - free (fs); -} -#ifdef weak_alias -weak_alias (__argp_fmtstream_free, argp_fmtstream_free) -#endif - -/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the - end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ -void -__argp_fmtstream_update (argp_fmtstream_t fs) -{ - char *buf, *nl; - size_t len; - - /* Scan the buffer for newlines. */ - buf = fs->buf + fs->point_offs; - while (buf < fs->p) - { - size_t r; - - if (fs->point_col == 0 && fs->lmargin != 0) - { - /* We are starting a new line. Print spaces to the left margin. */ - const size_t pad = fs->lmargin; - if (fs->p + pad < fs->end) - { - /* We can fit in them in the buffer by moving the - buffer text up and filling in the beginning. */ - memmove (buf + pad, buf, fs->p - buf); - fs->p += pad; /* Compensate for bigger buffer. */ - memset (buf, ' ', pad); /* Fill in the spaces. */ - buf += pad; /* Don't bother searching them. */ - } - else - { - /* No buffer space for spaces. Must flush. */ - size_t i; - for (i = 0; i < pad; i++) - PUTC_UNLOCKED (' ', fs->stream); - } - fs->point_col = pad; - } - - len = fs->p - buf; - nl = memchr (buf, '\n', len); - - if (fs->point_col < 0) - fs->point_col = 0; - - if (!nl) - { - /* The buffer ends in a partial line. */ - - if (fs->point_col + len < fs->rmargin) - { - /* The remaining buffer text is a partial line and fits - within the maximum line width. Advance point for the - characters to be written and stop scanning. */ - fs->point_col += len; - break; - } - else - /* Set the end-of-line pointer for the code below to - the end of the buffer. */ - nl = fs->p; - } - else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) - { - /* The buffer contains a full line that fits within the maximum - line width. Reset point and scan the next line. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } - - /* This line is too long. */ - r = fs->rmargin - 1; - - if (fs->wmargin < 0) - { - /* Truncate the line by overwriting the excess with the - newline and anything after it in the buffer. */ - if (nl < fs->p) - { - memmove (buf + (r - fs->point_col), nl, fs->p - nl); - fs->p -= buf + (r - fs->point_col) - nl; - /* Reset point for the next line and start scanning it. */ - fs->point_col = 0; - buf += r + 1; /* Skip full line plus \n. */ - } - else - { - /* The buffer ends with a partial line that is beyond the - maximum line width. Advance point for the characters - written, and discard those past the max from the buffer. */ - fs->point_col += len; - fs->p -= fs->point_col - r; - break; - } - } - else - { - /* Do word wrap. Go to the column just past the maximum line - width and scan back for the beginning of the word there. - Then insert a line break. */ - - char *p, *nextline; - int i; - - p = buf + (r + 1 - fs->point_col); - while (p >= buf && !isblank (*p)) - --p; - nextline = p + 1; /* This will begin the next line. */ - - if (nextline > buf) - { - /* Swallow separating blanks. */ - if (p >= buf) - do - --p; - while (p >= buf && isblank (*p)); - nl = p + 1; /* The newline will replace the first blank. */ - } - else - { - /* A single word that is greater than the maximum line width. - Oh well. Put it on an overlong line by itself. */ - p = buf + (r + 1 - fs->point_col); - /* Find the end of the long word. */ - do - ++p; - while (p < nl && !isblank (*p)); - if (p == nl) - { - /* It already ends a line. No fussing required. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } - /* We will move the newline to replace the first blank. */ - nl = p; - /* Swallow separating blanks. */ - do - ++p; - while (isblank (*p)); - /* The next line will start here. */ - nextline = p; - } - - /* Note: There are a bunch of tests below for - NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall - at the end of the buffer, and NEXTLINE is in fact empty (and so - we need not be careful to maintain its contents). */ - - if (nextline == buf + len + 1 - ? fs->end - nl < fs->wmargin + 1 - : nextline - (nl + 1) < fs->wmargin) - { - /* The margin needs more blanks than we removed. */ - if (fs->end - fs->p > fs->wmargin + 1) - /* Make some space for them. */ - { - size_t mv = fs->p - nextline; - memmove (nl + 1 + fs->wmargin, nextline, mv); - nextline = nl + 1 + fs->wmargin; - len = nextline + mv - buf; - *nl++ = '\n'; - } - else - /* Output the first line so we can use the space. */ - { - if (nl > fs->buf) - FWRITE_UNLOCKED (fs->buf, 1, nl - fs->buf, fs->stream); - PUTC_UNLOCKED ('\n', fs->stream); - len += buf - fs->buf; - nl = buf = fs->buf; - } - } - else - /* We can fit the newline and blanks in before - the next word. */ - *nl++ = '\n'; - - if (nextline - nl >= fs->wmargin - || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) - /* Add blanks up to the wrap margin column. */ - for (i = 0; i < fs->wmargin; ++i) - *nl++ = ' '; - else - for (i = 0; i < fs->wmargin; ++i) - PUTC_UNLOCKED (' ', fs->stream); - - /* Copy the tail of the original buffer into the current buffer - position. */ - if (nl < nextline) - memmove (nl, nextline, buf + len - nextline); - len -= nextline - buf; - - /* Continue the scan on the remaining lines in the buffer. */ - buf = nl; - - /* Restore bufp to include all the remaining text. */ - fs->p = nl + len; - - /* Reset the counter of what has been output this line. If wmargin - is 0, we want to avoid the lmargin getting added, so we set - point_col to a magic value of -1 in that case. */ - fs->point_col = fs->wmargin ? fs->wmargin : -1; - } - } - - /* Remember that we've scanned as far as the end of the buffer. */ - fs->point_offs = fs->p - fs->buf; -} - -/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by - growing the buffer, or by flushing it. True is returned iff we succeed. */ -int -__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) -{ - if ((size_t) (fs->end - fs->p) < amount) - { - ssize_t wrote; - - /* Flush FS's buffer. */ - __argp_fmtstream_update (fs); - - wrote = FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream); - if (wrote == fs->p - fs->buf) - { - fs->p = fs->buf; - fs->point_offs = 0; - } - else - { - fs->p -= wrote; - fs->point_offs -= wrote; - memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); - return 0; - } - - if ((size_t) (fs->end - fs->buf) < amount) - /* Gotta grow the buffer. */ - { - size_t new_size = fs->end - fs->buf + amount; - char *new_buf = realloc (fs->buf, new_size); - - if (! new_buf) - { - __set_errno (ENOMEM); - return 0; - } - - fs->buf = new_buf; - fs->end = new_buf + new_size; - fs->p = fs->buf; - } - } - - return 1; -} - -ssize_t -__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) -{ - size_t out; - size_t avail; - size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */ - - do - { - va_list args; - - if (! __argp_fmtstream_ensure (fs, size_guess)) - return -1; - - va_start (args, fmt); - avail = fs->end - fs->p; - out = __vsnprintf (fs->p, avail, fmt, args); - va_end (args); - if (out >= avail) - size_guess = out + 1; - } - while (out >= avail); - - fs->p += out; - - return out; -} -#ifdef weak_alias -weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) -#endif - -#if __STDC_VERSION__ - 199900L < 1 -/* Duplicate the inline definitions in argp-fmtstream.h, for compilers - * that don't do inlining. */ -size_t -__argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len) -{ - if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) - { - memcpy (__fs->p, __str, __len); - __fs->p += __len; - return __len; - } - else - return 0; -} - -int -__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) -{ - size_t __len = strlen (__str); - if (__len) - { - size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); - return __wrote == __len ? 0 : -1; - } - else - return 0; -} - -int -__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) -{ - if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) - return *__fs->p++ = __ch; - else - return EOF; -} - -/* Set __FS's left margin to __LMARGIN and return the old value. */ -size_t -__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->lmargin; - __fs->lmargin = __lmargin; - return __old; -} - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -size_t -__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->rmargin; - __fs->rmargin = __rmargin; - return __old; -} - -/* Set FS's wrap margin to __WMARGIN and return the old value. */ -size_t -__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->wmargin; - __fs->wmargin = __wmargin; - return __old; -} - -/* Return the column number of the current output point in __FS. */ -size_t -__argp_fmtstream_point (argp_fmtstream_t __fs) -{ - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - return __fs->point_col >= 0 ? __fs->point_col : 0; -} -#endif /* __STDC_VERSION__ - 199900L < 1 */ - -#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/contrib/argp-standalone/argp-fmtstream.h b/contrib/argp-standalone/argp-fmtstream.h deleted file mode 100644 index 828f4357d56..00000000000 --- a/contrib/argp-standalone/argp-fmtstream.h +++ /dev/null @@ -1,327 +0,0 @@ -/* Word-wrapping and line-truncating streams. - Copyright (C) 1997, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This package emulates glibc `line_wrap_stream' semantics for systems that - don't have that. If the system does have it, it is just a wrapper for - that. This header file is only used internally while compiling argp, and - shouldn't be installed. */ - -#ifndef _ARGP_FMTSTREAM_H -#define _ARGP_FMTSTREAM_H - -#include <stdio.h> -#include <string.h> - -#if HAVE_UNISTD_H -# include <unistd.h> -#else -/* This is a kludge to make the code compile on windows. Perhaps it - would be better to just replace ssize_t with int through out the - code. */ -# define ssize_t int -#endif - -#if _LIBC || (defined (HAVE_FLOCKFILE) && defined(HAVE_PUTC_UNLOCKED) \ - && defined (HAVE_FPUTS_UNLOCKED) && defined (HAVE_FWRITE_UNLOCKED) ) -/* Use locking funxtions */ -# define FLOCKFILE(f) flockfile(f) -# define FUNLOCKFILE(f) funlockfile(f) -# define PUTC_UNLOCKED(c, f) putc_unlocked((c), (f)) -# define FPUTS_UNLOCKED(s, f) fputs_unlocked((s), (f)) -# define FWRITE_UNLOCKED(b, s, n, f) fwrite_unlocked((b), (s), (n), (f)) -#else -/* Disable stdio locking */ -# define FLOCKFILE(f) -# define FUNLOCKFILE(f) -# define PUTC_UNLOCKED(c, f) putc((c), (f)) -# define FPUTS_UNLOCKED(s, f) fputs((s), (f)) -# define FWRITE_UNLOCKED(b, s, n, f) fwrite((b), (s), (n), (f)) -#endif /* No thread safe i/o */ - -#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ - || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) -/* line_wrap_stream is available, so use that. */ -#define ARGP_FMTSTREAM_USE_LINEWRAP -#endif - -#ifdef ARGP_FMTSTREAM_USE_LINEWRAP -/* Just be a simple wrapper for line_wrap_stream; the semantics are - *slightly* different, as line_wrap_stream doesn't actually make a new - object, it just modifies the given stream (reversibly) to do - line-wrapping. Since we control who uses this code, it doesn't matter. */ - -#include <linewrap.h> - -typedef FILE *argp_fmtstream_t; - -#define argp_make_fmtstream line_wrap_stream -#define __argp_make_fmtstream line_wrap_stream -#define argp_fmtstream_free line_unwrap_stream -#define __argp_fmtstream_free line_unwrap_stream - -#define __argp_fmtstream_putc(fs,ch) putc(ch,fs) -#define argp_fmtstream_putc(fs,ch) putc(ch,fs) -#define __argp_fmtstream_puts(fs,str) fputs(str,fs) -#define argp_fmtstream_puts(fs,str) fputs(str,fs) -#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) -#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) -#define __argp_fmtstream_printf fprintf -#define argp_fmtstream_printf fprintf - -#define __argp_fmtstream_lmargin line_wrap_lmargin -#define argp_fmtstream_lmargin line_wrap_lmargin -#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin -#define argp_fmtstream_set_lmargin line_wrap_set_lmargin -#define __argp_fmtstream_rmargin line_wrap_rmargin -#define argp_fmtstream_rmargin line_wrap_rmargin -#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin -#define argp_fmtstream_set_rmargin line_wrap_set_rmargin -#define __argp_fmtstream_wmargin line_wrap_wmargin -#define argp_fmtstream_wmargin line_wrap_wmargin -#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin -#define argp_fmtstream_set_wmargin line_wrap_set_wmargin -#define __argp_fmtstream_point line_wrap_point -#define argp_fmtstream_point line_wrap_point - -#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ -/* Guess we have to define our own version. */ - -#ifndef __const -#define __const const -#endif - - -struct argp_fmtstream -{ - FILE *stream; /* The stream we're outputting to. */ - - size_t lmargin, rmargin; /* Left and right margins. */ - ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ - - /* Point in buffer to which we've processed for wrapping, but not output. */ - size_t point_offs; - /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ - ssize_t point_col; - - char *buf; /* Output buffer. */ - char *p; /* Current end of text in BUF. */ - char *end; /* Absolute end of BUF. */ -}; - -typedef struct argp_fmtstream *argp_fmtstream_t; - -/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines - written on it with LMARGIN spaces and limits them to RMARGIN columns - total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by - replacing the whitespace before them with a newline and WMARGIN spaces. - Otherwise, chars beyond RMARGIN are simply dropped until a newline. - Returns NULL if there was an error. */ -extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, - size_t __lmargin, - size_t __rmargin, - ssize_t __wmargin); -extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, - size_t __lmargin, - size_t __rmargin, - ssize_t __wmargin); - -/* Flush __FS to its stream, and free it (but don't close the stream). */ -extern void __argp_fmtstream_free (argp_fmtstream_t __fs); -extern void argp_fmtstream_free (argp_fmtstream_t __fs); - -extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, - __const char *__fmt, ...) - PRINTF_STYLE(2,3); -extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, - __const char *__fmt, ...) - PRINTF_STYLE(2,3); - -#if __STDC_VERSION__ - 199900L < 1 -extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); -extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); - -extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); -extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); - -extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len); -extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len); -#endif /* __STDC_VERSION__ - 199900L < 1 */ - -/* Access macros for various bits of state. */ -#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) -#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) -#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) -#define __argp_fmtstream_lmargin argp_fmtstream_lmargin -#define __argp_fmtstream_rmargin argp_fmtstream_rmargin -#define __argp_fmtstream_wmargin argp_fmtstream_wmargin - -#if __STDC_VERSION__ - 199900L < 1 -/* Set __FS's left margin to LMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); -extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); -extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); - -/* Set __FS's wrap margin to __WMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); -extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); - -/* Return the column number of the current output point in __FS. */ -extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); -extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); -#endif /* __STDC_VERSION__ - 199900L < 1 */ - -/* Internal routines. */ -extern void _argp_fmtstream_update (argp_fmtstream_t __fs); -extern void __argp_fmtstream_update (argp_fmtstream_t __fs); -extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); -extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); - -#ifdef __OPTIMIZE__ -/* Inline versions of above routines. */ - -#if !_LIBC -#define __argp_fmtstream_putc argp_fmtstream_putc -#define __argp_fmtstream_puts argp_fmtstream_puts -#define __argp_fmtstream_write argp_fmtstream_write -#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin -#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin -#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin -#define __argp_fmtstream_point argp_fmtstream_point -#define __argp_fmtstream_update _argp_fmtstream_update -#define __argp_fmtstream_ensure _argp_fmtstream_ensure -#endif - -#ifndef ARGP_FS_EI -#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__) -#define ARGP_FS_EI extern inline -#else -#define ARGP_FS_EI inline -#endif -#endif - -ARGP_FS_EI size_t -__argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len) -{ - if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) - { - memcpy (__fs->p, __str, __len); - __fs->p += __len; - return __len; - } - else - return 0; -} - -ARGP_FS_EI int -__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) -{ - size_t __len = strlen (__str); - if (__len) - { - size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); - return __wrote == __len ? 0 : -1; - } - else - return 0; -} - -ARGP_FS_EI int -__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) -{ - if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) - return *__fs->p++ = __ch; - else - return EOF; -} - -/* Set __FS's left margin to __LMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->lmargin; - __fs->lmargin = __lmargin; - return __old; -} - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->rmargin; - __fs->rmargin = __rmargin; - return __old; -} - -/* Set FS's wrap margin to __WMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->wmargin; - __fs->wmargin = __wmargin; - return __old; -} - -/* Return the column number of the current output point in __FS. */ -ARGP_FS_EI size_t -__argp_fmtstream_point (argp_fmtstream_t __fs) -{ - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - return __fs->point_col >= 0 ? __fs->point_col : 0; -} - -#if !_LIBC -#undef __argp_fmtstream_putc -#undef __argp_fmtstream_puts -#undef __argp_fmtstream_write -#undef __argp_fmtstream_set_lmargin -#undef __argp_fmtstream_set_rmargin -#undef __argp_fmtstream_set_wmargin -#undef __argp_fmtstream_point -#undef __argp_fmtstream_update -#undef __argp_fmtstream_ensure -#endif - -#endif /* __OPTIMIZE__ */ - -#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ - -#endif /* argp-fmtstream.h */ diff --git a/contrib/argp-standalone/argp-help.c b/contrib/argp-standalone/argp-help.c deleted file mode 100644 index ced78c4cb26..00000000000 --- a/contrib/argp-standalone/argp-help.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* Hierarchial argument parsing help output - Copyright (C) 1995,96,97,98,99,2000, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <stdarg.h> -#include <ctype.h> -#if HAVE_MALLOC_H -/* Needed, for alloca on windows */ -# include <malloc.h> -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -# ifdef _LIBC -# undef dgettext -# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) -# endif -# else -# define dgettext(domain, msgid) (msgid) -# endif -#endif - -#include "argp.h" -#include "argp-fmtstream.h" -#include "argp-namefrob.h" - - -#ifndef _LIBC -# ifndef __strchrnul -# define __strchrnul strchrnul -# endif -# ifndef __mempcpy -# define __mempcpy mempcpy -# endif -/* We need to use a different name, as __strndup is likely a macro. */ -# define STRNDUP strndup -# if HAVE_STRERROR -# define STRERROR strerror -# else -# define STRERROR(x) (sys_errlist[x]) -# endif -#else /* _LIBC */ -# define FLOCKFILE __flockfile -# define FUNLOCKFILE __funlockfile -# define STRNDUP __strndup -# define STRERROR strerror -#endif - -#if !_LIBC -# if !HAVE_STRNDUP -char *strndup (const char *s, size_t size); -# endif /* !HAVE_STRNDUP */ - -# if !HAVE_MEMPCPY -void *mempcpy (void *to, const void *from, size_t size); -# endif /* !HAVE_MEMPCPY */ - -# if !HAVE_STRCHRNUL -char *strchrnul(const char *s, int c); -# endif /* !HAVE_STRCHRNUL */ - -# if !HAVE_STRCASECMP -int strcasecmp(const char *s1, const char *s2); -#endif - -#endif /* !_LIBC */ - - -/* User-selectable (using an environment variable) formatting parameters. - - These may be specified in an environment variable called `ARGP_HELP_FMT', - with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 - Where VALn must be a positive integer. The list of variables is in the - UPARAM_NAMES vector, below. */ - -/* Default parameters. */ -#define DUP_ARGS 0 /* True if option argument can be duplicated. */ -#define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ -#define SHORT_OPT_COL 2 /* column in which short options start */ -#define LONG_OPT_COL 6 /* column in which long options start */ -#define DOC_OPT_COL 2 /* column in which doc options start */ -#define OPT_DOC_COL 29 /* column in which option text starts */ -#define HEADER_COL 1 /* column in which group headers are printed */ -#define USAGE_INDENT 12 /* indentation of wrapped usage lines */ -#define RMARGIN 79 /* right margin used for wrapping */ - -/* User-selectable (using an environment variable) formatting parameters. - They must all be of type `int' for the parsing code to work. */ -struct uparams -{ - /* If true, arguments for an option are shown with both short and long - options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. - If false, then if an option has both, the argument is only shown with - the long one, e.g., `-x, --longx=ARG', and a message indicating that - this really means both is printed below the options. */ - int dup_args; - - /* This is true if when DUP_ARGS is false, and some duplicate arguments have - been suppressed, an explanatory message should be printed. */ - int dup_args_note; - - /* Various output columns. */ - int short_opt_col; - int long_opt_col; - int doc_opt_col; - int opt_doc_col; - int header_col; - int usage_indent; - int rmargin; - - int valid; /* True when the values in here are valid. */ -}; - -/* This is a global variable, as user options are only ever read once. */ -static struct uparams uparams = { - DUP_ARGS, DUP_ARGS_NOTE, - SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, - USAGE_INDENT, RMARGIN, - 0 -}; - -/* A particular uparam, and what the user name is. */ -struct uparam_name -{ - const char *name; /* User name. */ - int is_bool; /* Whether it's `boolean'. */ - size_t uparams_offs; /* Location of the (int) field in UPARAMS. */ -}; - -/* The name-field mappings we know about. */ -static const struct uparam_name uparam_names[] = -{ - { "dup-args", 1, offsetof (struct uparams, dup_args) }, - { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) }, - { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) }, - { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) }, - { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) }, - { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) }, - { "header-col", 0, offsetof (struct uparams, header_col) }, - { "usage-indent", 0, offsetof (struct uparams, usage_indent) }, - { "rmargin", 0, offsetof (struct uparams, rmargin) }, - { 0, 0, 0 } -}; - -/* Read user options from the environment, and fill in UPARAMS appropiately. */ -static void -fill_in_uparams (const struct argp_state *state) -{ - - const char *var = getenv ("ARGP_HELP_FMT"); - -#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0); - - if (var) - /* Parse var. */ - while (*var) - { - SKIPWS (var); - - if (isalpha (*var)) - { - size_t var_len; - const struct uparam_name *un; - int unspec = 0, val = 0; - const char *arg = var; - - while (isalnum (*arg) || *arg == '-' || *arg == '_') - arg++; - var_len = arg - var; - - SKIPWS (arg); - - if (*arg == '\0' || *arg == ',') - unspec = 1; - else if (*arg == '=') - { - arg++; - SKIPWS (arg); - } - - if (unspec) - { - if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') - { - val = 0; - var += 3; - var_len -= 3; - } - else - val = 1; - } - else if (isdigit (*arg)) - { - val = atoi (arg); - while (isdigit (*arg)) - arg++; - SKIPWS (arg); - } - - for (un = uparam_names; un->name; un++) - if (strlen (un->name) == var_len - && strncmp (var, un->name, var_len) == 0) - { - if (unspec && !un->is_bool) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ -%.*s: ARGP_HELP_FMT parameter requires a value"), - (int) var_len, var); - else - *(int *)((char *)&uparams + un->uparams_offs) = val; - break; - } - if (! un->name) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ -%.*s: Unknown ARGP_HELP_FMT parameter"), - (int) var_len, var); - - var = arg; - if (*var == ',') - var++; - } - else if (*var) - { - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "Garbage in ARGP_HELP_FMT: %s"), var); - break; - } - } -} - -/* Returns true if OPT hasn't been marked invisible. Visibility only affects - whether OPT is displayed or used in sorting, not option shadowing. */ -#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) - -/* Returns true if OPT is an alias for an earlier option. */ -#define oalias(opt) ((opt)->flags & OPTION_ALIAS) - -/* Returns true if OPT is an documentation-only entry. */ -#define odoc(opt) ((opt)->flags & OPTION_DOC) - -/* Returns true if OPT is the end-of-list marker for a list of options. */ -#define oend(opt) __option_is_end (opt) - -/* Returns true if OPT has a short option. */ -#define oshort(opt) __option_is_short (opt) - -/* - The help format for a particular option is like: - - -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... - - Where ARG will be omitted if there's no argument, for this option, or - will be surrounded by "[" and "]" appropiately if the argument is - optional. The documentation string is word-wrapped appropiately, and if - the list of options is long enough, it will be started on a separate line. - If there are no short options for a given option, the first long option is - indented slighly in a way that's supposed to make most long options appear - to be in a separate column. - - For example, the following output (from ps): - - -p PID, --pid=PID List the process PID - --pgrp=PGRP List processes in the process group PGRP - -P, -x, --no-parent Include processes without parents - -Q, --all-fields Don't elide unusable fields (normally if there's - some reason ps can't print a field for any - process, it's removed from the output entirely) - -r, --reverse, --gratuitously-long-reverse-option - Reverse the order of any sort - --session[=SID] Add the processes from the session SID (which - defaults to the sid of the current process) - - Here are some more options: - -f ZOT, --foonly=ZOT Glork a foonly - -z, --zaza Snit a zar - - -?, --help Give this help list - --usage Give a short usage message - -V, --version Print program version - - The struct argp_option array for the above could look like: - - { - {"pid", 'p', "PID", 0, "List the process PID"}, - {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, - {"no-parent", 'P', 0, 0, "Include processes without parents"}, - {0, 'x', 0, OPTION_ALIAS}, - {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" - " if there's some reason ps can't" - " print a field for any process, it's" - " removed from the output entirely)" }, - {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, - {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, - {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, - "Add the processes from the session" - " SID (which defaults to the sid of" - " the current process)" }, - - {0,0,0,0, "Here are some more options:"}, - {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, - {"zaza", 'z', 0, 0, "Snit a zar"}, - - {0} - } - - Note that the last three options are automatically supplied by argp_parse, - unless you tell it not to with ARGP_NO_HELP. - -*/ - -/* Returns true if CH occurs between BEG and END. */ -static int -find_char (char ch, char *beg, char *end) -{ - while (beg < end) - if (*beg == ch) - return 1; - else - beg++; - return 0; -} - -struct hol_cluster; /* fwd decl */ - -struct hol_entry -{ - /* First option. */ - const struct argp_option *opt; - /* Number of options (including aliases). */ - unsigned num; - - /* A pointers into the HOL's short_options field, to the first short option - letter for this entry. The order of the characters following this point - corresponds to the order of options pointed to by OPT, and there are at - most NUM. A short option recorded in a option following OPT is only - valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's - probably been shadowed by some other entry). */ - char *short_options; - - /* Entries are sorted by their group first, in the order: - 1, 2, ..., n, 0, -m, ..., -2, -1 - and then alphabetically within each group. The default is 0. */ - int group; - - /* The cluster of options this entry belongs to, or 0 if none. */ - struct hol_cluster *cluster; - - /* The argp from which this option came. */ - const struct argp *argp; -}; - -/* A cluster of entries to reflect the argp tree structure. */ -struct hol_cluster -{ - /* A descriptive header printed before options in this cluster. */ - const char *header; - - /* Used to order clusters within the same group with the same parent, - according to the order in which they occurred in the parent argp's child - list. */ - int index; - - /* How to sort this cluster with respect to options and other clusters at the - same depth (clusters always follow options in the same group). */ - int group; - - /* The cluster to which this cluster belongs, or 0 if it's at the base - level. */ - struct hol_cluster *parent; - - /* The argp from which this cluster is (eventually) derived. */ - const struct argp *argp; - - /* The distance this cluster is from the root. */ - int depth; - - /* Clusters in a given hol are kept in a linked list, to make freeing them - possible. */ - struct hol_cluster *next; -}; - -/* A list of options for help. */ -struct hol -{ - /* An array of hol_entry's. */ - struct hol_entry *entries; - /* The number of entries in this hol. If this field is zero, the others - are undefined. */ - unsigned num_entries; - - /* A string containing all short options in this HOL. Each entry contains - pointers into this string, so the order can't be messed with blindly. */ - char *short_options; - - /* Clusters of entries in this hol. */ - struct hol_cluster *clusters; -}; - -/* Create a struct hol from the options in ARGP. CLUSTER is the - hol_cluster in which these entries occur, or 0, if at the root. */ -static struct hol * -make_hol (const struct argp *argp, struct hol_cluster *cluster) -{ - char *so; - const struct argp_option *o; - const struct argp_option *opts = argp->options; - struct hol_entry *entry; - unsigned num_short_options = 0; - struct hol *hol = malloc (sizeof (struct hol)); - - assert (hol); - - hol->num_entries = 0; - hol->clusters = 0; - - if (opts) - { - int cur_group = 0; - - /* The first option must not be an alias. */ - assert (! oalias (opts)); - - /* Calculate the space needed. */ - for (o = opts; ! oend (o); o++) - { - if (! oalias (o)) - hol->num_entries++; - if (oshort (o)) - num_short_options++; /* This is an upper bound. */ - } - - hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); - hol->short_options = malloc (num_short_options + 1); - - assert (hol->entries && hol->short_options); - - /* Fill in the entries. */ - so = hol->short_options; - for (o = opts, entry = hol->entries; ! oend (o); entry++) - { - entry->opt = o; - entry->num = 0; - entry->short_options = so; - entry->group = cur_group = - o->group - ? o->group - : ((!o->name && !o->key) - ? cur_group + 1 - : cur_group); - entry->cluster = cluster; - entry->argp = argp; - - do - { - entry->num++; - if (oshort (o) && ! find_char (o->key, hol->short_options, so)) - /* O has a valid short option which hasn't already been used.*/ - *so++ = o->key; - o++; - } - while (! oend (o) && oalias (o)); - } - *so = '\0'; /* null terminated so we can find the length */ - } - - return hol; -} - -/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the - associated argp child list entry), INDEX, and PARENT, and return a pointer - to it. ARGP is the argp that this cluster results from. */ -static struct hol_cluster * -hol_add_cluster (struct hol *hol, int group, const char *header, int index, - struct hol_cluster *parent, const struct argp *argp) -{ - struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); - if (cl) - { - cl->group = group; - cl->header = header; - - cl->index = index; - cl->parent = parent; - cl->argp = argp; - cl->depth = parent ? parent->depth + 1 : 0; - - cl->next = hol->clusters; - hol->clusters = cl; - } - return cl; -} - -/* Free HOL and any resources it uses. */ -static void -hol_free (struct hol *hol) -{ - struct hol_cluster *cl = hol->clusters; - - while (cl) - { - struct hol_cluster *next = cl->next; - free (cl); - cl = next; - } - - if (hol->num_entries > 0) - { - free (hol->entries); - free (hol->short_options); - } - - free (hol); -} - -static inline int -hol_entry_short_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) -{ - unsigned nopts; - int val = 0; - const struct argp_option *opt, *real = entry->opt; - char *so = entry->short_options; - - for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) - if (oshort (opt) && *so == opt->key) - { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); - so++; - } - - return val; -} - -static inline int -hol_entry_long_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) -{ - unsigned nopts; - int val = 0; - const struct argp_option *opt, *real = entry->opt; - - for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) - if (opt->name) - { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); - } - - return val; -} - -/* Iterator that returns true for the first short option. */ -static inline int -until_short (const struct argp_option *opt, const struct argp_option *real UNUSED, - const char *domain UNUSED, void *cookie UNUSED) -{ - return oshort (opt) ? opt->key : 0; -} - -/* Returns the first valid short option in ENTRY, or 0 if there is none. */ -static char -hol_entry_first_short (const struct hol_entry *entry) -{ - return hol_entry_short_iterate (entry, until_short, - entry->argp->argp_domain, 0); -} - -/* Returns the first valid long option in ENTRY, or 0 if there is none. */ -static const char * -hol_entry_first_long (const struct hol_entry *entry) -{ - const struct argp_option *opt; - unsigned num; - for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - return opt->name; - return 0; -} - -/* Returns the entry in HOL with the long option name NAME, or 0 if there is - none. */ -static struct hol_entry * -hol_find_entry (struct hol *hol, const char *name) -{ - struct hol_entry *entry = hol->entries; - unsigned num_entries = hol->num_entries; - - while (num_entries-- > 0) - { - const struct argp_option *opt = entry->opt; - unsigned num_opts = entry->num; - - while (num_opts-- > 0) - if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) - return entry; - else - opt++; - - entry++; - } - - return 0; -} - -/* If an entry with the long option NAME occurs in HOL, set it's special - sort position to GROUP. */ -static void -hol_set_group (struct hol *hol, const char *name, int group) -{ - struct hol_entry *entry = hol_find_entry (hol, name); - if (entry) - entry->group = group; -} - -/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. - EQ is what to return if GROUP1 and GROUP2 are the same. */ -static int -group_cmp (int group1, int group2, int eq) -{ - if (group1 == group2) - return eq; - else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) - return group1 - group2; - else - return group2 - group1; -} - -/* Compare clusters CL1 & CL2 by the order that they should appear in - output. */ -static int -hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) -{ - /* If one cluster is deeper than the other, use its ancestor at the same - level, so that finding the common ancestor is straightforward. */ - while (cl1->depth < cl2->depth) - cl1 = cl1->parent; - while (cl2->depth < cl1->depth) - cl2 = cl2->parent; - - /* Now reduce both clusters to their ancestors at the point where both have - a common parent; these can be directly compared. */ - while (cl1->parent != cl2->parent) - cl1 = cl1->parent, cl2 = cl2->parent; - - return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); -} - -/* Return the ancestor of CL that's just below the root (i.e., has a parent - of 0). */ -static struct hol_cluster * -hol_cluster_base (struct hol_cluster *cl) -{ - while (cl->parent) - cl = cl->parent; - return cl; -} - -/* Return true if CL1 is a child of CL2. */ -static int -hol_cluster_is_child (const struct hol_cluster *cl1, - const struct hol_cluster *cl2) -{ - while (cl1 && cl1 != cl2) - cl1 = cl1->parent; - return cl1 == cl2; -} - -/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail - that should be used for comparisons, and returns true iff it should be - treated as a non-option. */ - -/* FIXME: Can we use unsigned char * for the argument? */ -static int -canon_doc_option (const char **name) -{ - int non_opt; - /* Skip initial whitespace. */ - while (isspace ( (unsigned char) **name)) - (*name)++; - /* Decide whether this looks like an option (leading `-') or not. */ - non_opt = (**name != '-'); - /* Skip until part of name used for sorting. */ - while (**name && !isalnum ( (unsigned char) **name)) - (*name)++; - return non_opt; -} - -/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help - listing. */ -static int -hol_entry_cmp (const struct hol_entry *entry1, - const struct hol_entry *entry2) -{ - /* The group numbers by which the entries should be ordered; if either is - in a cluster, then this is just the group within the cluster. */ - int group1 = entry1->group, group2 = entry2->group; - - if (entry1->cluster != entry2->cluster) - { - /* The entries are not within the same cluster, so we can't compare them - directly, we have to use the appropiate clustering level too. */ - if (! entry1->cluster) - /* ENTRY1 is at the `base level', not in a cluster, so we have to - compare it's group number with that of the base cluster in which - ENTRY2 resides. Note that if they're in the same group, the - clustered option always comes laster. */ - return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); - else if (! entry2->cluster) - /* Likewise, but ENTRY2's not in a cluster. */ - return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); - else - /* Both entries are in clusters, we can just compare the clusters. */ - return hol_cluster_cmp (entry1->cluster, entry2->cluster); - } - else if (group1 == group2) - /* The entries are both in the same cluster and group, so compare them - alphabetically. */ - { - int short1 = hol_entry_first_short (entry1); - int short2 = hol_entry_first_short (entry2); - int doc1 = odoc (entry1->opt); - int doc2 = odoc (entry2->opt); - /* FIXME: Can we use unsigned char * instead? */ - const char *long1 = hol_entry_first_long (entry1); - const char *long2 = hol_entry_first_long (entry2); - - if (doc1) - doc1 = canon_doc_option (&long1); - if (doc2) - doc2 = canon_doc_option (&long2); - - if (doc1 != doc2) - /* `documentation' options always follow normal options (or - documentation options that *look* like normal options). */ - return doc1 - doc2; - else if (!short1 && !short2 && long1 && long2) - /* Only long options. */ - return __strcasecmp (long1, long2); - else - /* Compare short/short, long/short, short/long, using the first - character of long options. Entries without *any* valid - options (such as options with OPTION_HIDDEN set) will be put - first, but as they're not displayed, it doesn't matter where - they are. */ - { - unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0; - unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0; -#ifdef _tolower - int lower_cmp = _tolower (first1) - _tolower (first2); -#else - int lower_cmp = tolower (first1) - tolower (first2); -#endif - /* Compare ignoring case, except when the options are both the - same letter, in which case lower-case always comes first. */ - /* NOTE: The subtraction below does the right thing - even with eight-bit chars: first1 and first2 are - converted to int *before* the subtraction. */ - return lower_cmp ? lower_cmp : first2 - first1; - } - } - else - /* Within the same cluster, but not the same group, so just compare - groups. */ - return group_cmp (group1, group2, 0); -} - -/* Version of hol_entry_cmp with correct signature for qsort. */ -static int -hol_entry_qcmp (const void *entry1_v, const void *entry2_v) -{ - return hol_entry_cmp (entry1_v, entry2_v); -} - -/* Sort HOL by group and alphabetically by option name (with short options - taking precedence over long). Since the sorting is for display purposes - only, the shadowing of options isn't effected. */ -static void -hol_sort (struct hol *hol) -{ - if (hol->num_entries > 0) - qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), - hol_entry_qcmp); -} - -/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow - any in MORE with the same name. */ -static void -hol_append (struct hol *hol, struct hol *more) -{ - struct hol_cluster **cl_end = &hol->clusters; - - /* Steal MORE's cluster list, and add it to the end of HOL's. */ - while (*cl_end) - cl_end = &(*cl_end)->next; - *cl_end = more->clusters; - more->clusters = 0; - - /* Merge entries. */ - if (more->num_entries > 0) - { - if (hol->num_entries == 0) - { - hol->num_entries = more->num_entries; - hol->entries = more->entries; - hol->short_options = more->short_options; - more->num_entries = 0; /* Mark MORE's fields as invalid. */ - } - else - /* Append the entries in MORE to those in HOL, taking care to only add - non-shadowed SHORT_OPTIONS values. */ - { - unsigned left; - char *so, *more_so; - struct hol_entry *e; - unsigned num_entries = hol->num_entries + more->num_entries; - struct hol_entry *entries = - malloc (num_entries * sizeof (struct hol_entry)); - unsigned hol_so_len = strlen (hol->short_options); - char *short_options = - malloc (hol_so_len + strlen (more->short_options) + 1); - - __mempcpy (__mempcpy (entries, hol->entries, - hol->num_entries * sizeof (struct hol_entry)), - more->entries, - more->num_entries * sizeof (struct hol_entry)); - - __mempcpy (short_options, hol->short_options, hol_so_len); - - /* Fix up the short options pointers from HOL. */ - for (e = entries, left = hol->num_entries; left > 0; e++, left--) - e->short_options += (short_options - hol->short_options); - - /* Now add the short options from MORE, fixing up its entries - too. */ - so = short_options + hol_so_len; - more_so = more->short_options; - for (left = more->num_entries; left > 0; e++, left--) - { - int opts_left; - const struct argp_option *opt; - - e->short_options = so; - - for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) - { - int ch = *more_so; - if (oshort (opt) && ch == opt->key) - /* The next short option in MORE_SO, CH, is from OPT. */ - { - if (! find_char (ch, short_options, - short_options + hol_so_len)) - /* The short option CH isn't shadowed by HOL's options, - so add it to the sum. */ - *so++ = ch; - more_so++; - } - } - } - - *so = '\0'; - - free (hol->entries); - free (hol->short_options); - - hol->entries = entries; - hol->num_entries = num_entries; - hol->short_options = short_options; - } - } - - hol_free (more); -} - -/* Inserts enough spaces to make sure STREAM is at column COL. */ -static void -indent_to (argp_fmtstream_t stream, unsigned col) -{ - int needed = col - __argp_fmtstream_point (stream); - while (needed-- > 0) - __argp_fmtstream_putc (stream, ' '); -} - -/* Output to STREAM either a space, or a newline if there isn't room for at - least ENSURE characters before the right margin. */ -static void -space (argp_fmtstream_t stream, size_t ensure) -{ - if (__argp_fmtstream_point (stream) + ensure - >= __argp_fmtstream_rmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - else - __argp_fmtstream_putc (stream, ' '); -} - -/* If the option REAL has an argument, we print it in using the printf - format REQ_FMT or OPT_FMT depending on whether it's a required or - optional argument. */ -static void -arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, - const char *domain UNUSED, argp_fmtstream_t stream) -{ - if (real->arg) - { - if (real->flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, opt_fmt, - dgettext (domain, real->arg)); - else - __argp_fmtstream_printf (stream, req_fmt, - dgettext (domain, real->arg)); - } -} - -/* Helper functions for hol_entry_help. */ - -/* State used during the execution of hol_help. */ -struct hol_help_state -{ - /* PREV_ENTRY should contain the previous entry printed, or 0. */ - struct hol_entry *prev_entry; - - /* If an entry is in a different group from the previous one, and SEP_GROUPS - is true, then a blank line will be printed before any output. */ - int sep_groups; - - /* True if a duplicate option argument was suppressed (only ever set if - UPARAMS.dup_args is false). */ - int suppressed_dup_arg; -}; - -/* Some state used while printing a help entry (used to communicate with - helper functions). See the doc for hol_entry_help for more info, as most - of the fields are copied from its arguments. */ -struct pentry_state -{ - const struct hol_entry *entry; - argp_fmtstream_t stream; - struct hol_help_state *hhstate; - - /* True if nothing's been printed so far. */ - int first; - - /* If non-zero, the state that was used to print this help. */ - const struct argp_state *state; -}; - -/* If a user doc filter should be applied to DOC, do so. */ -static const char * -filter_doc (const char *doc, int key, const struct argp *argp, - const struct argp_state *state) -{ - if (argp->help_filter) - /* We must apply a user filter to this output. */ - { - void *input = __argp_input (argp, state); - return (*argp->help_filter) (key, doc, input); - } - else - /* No filter. */ - return doc; -} - -/* Prints STR as a header line, with the margin lines set appropiately, and - notes the fact that groups should be separated with a blank line. ARGP is - the argp that should dictate any user doc filtering to take place. Note - that the previous wrap margin isn't restored, but the left margin is reset - to 0. */ -static void -print_header (const char *str, const struct argp *argp, - struct pentry_state *pest) -{ - const char *tstr = dgettext (argp->argp_domain, str); - const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); - - if (fstr) - { - if (*fstr) - { - if (pest->hhstate->prev_entry) - /* Precede with a blank line. */ - __argp_fmtstream_putc (pest->stream, '\n'); - indent_to (pest->stream, uparams.header_col); - __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); - __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); - __argp_fmtstream_puts (pest->stream, fstr); - __argp_fmtstream_set_lmargin (pest->stream, 0); - __argp_fmtstream_putc (pest->stream, '\n'); - } - - pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ - } - - if (fstr != tstr) - free ((char *) fstr); -} - -/* Inserts a comma if this isn't the first item on the line, and then makes - sure we're at least to column COL. If this *is* the first item on a line, - prints any pending whitespace/headers that should precede this line. Also - clears FIRST. */ -static void -comma (unsigned col, struct pentry_state *pest) -{ - if (pest->first) - { - const struct hol_entry *pe = pest->hhstate->prev_entry; - const struct hol_cluster *cl = pest->entry->cluster; - - if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) - __argp_fmtstream_putc (pest->stream, '\n'); - - if (cl && cl->header && *cl->header - && (!pe - || (pe->cluster != cl - && !hol_cluster_is_child (pe->cluster, cl)))) - /* If we're changing clusters, then this must be the start of the - ENTRY's cluster unless that is an ancestor of the previous one - (in which case we had just popped into a sub-cluster for a bit). - If so, then print the cluster's header line. */ - { - int old_wm = __argp_fmtstream_wmargin (pest->stream); - print_header (cl->header, cl->argp, pest); - __argp_fmtstream_set_wmargin (pest->stream, old_wm); - } - - pest->first = 0; - } - else - __argp_fmtstream_puts (pest->stream, ", "); - - indent_to (pest->stream, col); -} - -/* Print help for ENTRY to STREAM. */ -static void -hol_entry_help (struct hol_entry *entry, const struct argp_state *state, - argp_fmtstream_t stream, struct hol_help_state *hhstate) -{ - unsigned num; - const struct argp_option *real = entry->opt, *opt; - char *so = entry->short_options; - int have_long_opt = 0; /* We have any long options. */ - /* Saved margins. */ - int old_lm = __argp_fmtstream_set_lmargin (stream, 0); - int old_wm = __argp_fmtstream_wmargin (stream); - /* PEST is a state block holding some of our variables that we'd like to - share with helper functions. */ - - /* Decent initializers are a GNU extension, so don't use it here. */ - struct pentry_state pest; - pest.entry = entry; - pest.stream = stream; - pest.hhstate = hhstate; - pest.first = 1; - pest.state = state; - - if (! odoc (real)) - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - have_long_opt = 1; - break; - } - - /* First emit short options. */ - __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (oshort (opt) && opt->key == *so) - /* OPT has a valid (non shadowed) short option. */ - { - if (ovisible (opt)) - { - comma (uparams.short_opt_col, &pest); - __argp_fmtstream_putc (stream, '-'); - __argp_fmtstream_putc (stream, *so); - if (!have_long_opt || uparams.dup_args) - arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } - so++; - } - - /* Now, long options. */ - if (odoc (real)) - /* A `documentation' option. */ - { - __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - comma (uparams.doc_opt_col, &pest); - /* Calling gettext here isn't quite right, since sorting will - have been done on the original; but documentation options - should be pretty rare anyway... */ - __argp_fmtstream_puts (stream, - dgettext (state->root_argp->argp_domain, - opt->name)); - } - } - else - /* A real long option. */ - { - int first_long_opt = 1; - - __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - comma (uparams.long_opt_col, &pest); - __argp_fmtstream_printf (stream, "--%s", opt->name); - if (first_long_opt || uparams.dup_args) - arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, - stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } - } - - /* Next, documentation strings. */ - __argp_fmtstream_set_lmargin (stream, 0); - - if (pest.first) - { - /* Didn't print any switches, what's up? */ - if (!oshort (real) && !real->name) - /* This is a group header, print it nicely. */ - print_header (real->doc, entry->argp, &pest); - else - /* Just a totally shadowed option or null header; print nothing. */ - goto cleanup; /* Just return, after cleaning up. */ - } - else - { - const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, - real->doc) : 0; - const char *fstr = filter_doc (tstr, real->key, entry->argp, state); - if (fstr && *fstr) - { - unsigned int col = __argp_fmtstream_point (stream); - - __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); - __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); - - if (col > (unsigned int) (uparams.opt_doc_col + 3)) - __argp_fmtstream_putc (stream, '\n'); - else if (col >= (unsigned int) uparams.opt_doc_col) - __argp_fmtstream_puts (stream, " "); - else - indent_to (stream, uparams.opt_doc_col); - - __argp_fmtstream_puts (stream, fstr); - } - if (fstr && fstr != tstr) - free ((char *) fstr); - - /* Reset the left margin. */ - __argp_fmtstream_set_lmargin (stream, 0); - __argp_fmtstream_putc (stream, '\n'); - } - - hhstate->prev_entry = entry; - -cleanup: - __argp_fmtstream_set_lmargin (stream, old_lm); - __argp_fmtstream_set_wmargin (stream, old_wm); -} - -/* Output a long help message about the options in HOL to STREAM. */ -static void -hol_help (struct hol *hol, const struct argp_state *state, - argp_fmtstream_t stream) -{ - unsigned num; - struct hol_entry *entry; - struct hol_help_state hhstate = { 0, 0, 0 }; - - for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) - hol_entry_help (entry, state, stream, &hhstate); - - if (hhstate.suppressed_dup_arg && uparams.dup_args_note) - { - const char *tstr = dgettext (state->root_argp->argp_domain, "\ -Mandatory or optional arguments to long options are also mandatory or \ -optional for any corresponding short options."); - const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, - state ? state->root_argp : 0, state); - if (fstr && *fstr) - { - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, fstr); - __argp_fmtstream_putc (stream, '\n'); - } - if (fstr && fstr != tstr) - free ((char *) fstr); - } -} - -/* Helper functions for hol_usage. */ - -/* If OPT is a short option without an arg, append its key to the string - pointer pointer to by COOKIE, and advance the pointer. */ -static int -add_argless_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain UNUSED, void *cookie) -{ - char **snao_end = cookie; - if (!(opt->arg || real->arg) - && !((opt->flags | real->flags) & OPTION_NO_USAGE)) - *(*snao_end)++ = opt->key; - return 0; -} - -/* If OPT is a short option with an arg, output a usage entry for it to the - stream pointed at by COOKIE. */ -static int -usage_argful_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain UNUSED, void *cookie) -{ - argp_fmtstream_t stream = cookie; - const char *arg = opt->arg; - int flags = opt->flags | real->flags; - - if (! arg) - arg = real->arg; - - if (arg && !(flags & OPTION_NO_USAGE)) - { - arg = dgettext (domain, arg); - - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); - else - { - /* Manually do line wrapping so that it (probably) won't - get wrapped at the embedded space. */ - space (stream, 6 + strlen (arg)); - __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); - } - } - - return 0; -} - -/* Output a usage entry for the long option opt to the stream pointed at by - COOKIE. */ -static int -usage_long_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain UNUSED, void *cookie) -{ - argp_fmtstream_t stream = cookie; - const char *arg = opt->arg; - int flags = opt->flags | real->flags; - - if (! arg) - arg = real->arg; - - if (! (flags & OPTION_NO_USAGE)) - { - if (arg) - { - arg = dgettext (domain, arg); - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); - else - __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); - } - else - __argp_fmtstream_printf (stream, " [--%s]", opt->name); - } - - return 0; -} - -/* Print a short usage description for the arguments in HOL to STREAM. */ -static void -hol_usage (struct hol *hol, argp_fmtstream_t stream) -{ - if (hol->num_entries > 0) - { - unsigned nentries; - struct hol_entry *entry; - char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); - char *snao_end = short_no_arg_opts; - - /* First we put a list of short options without arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, add_argless_short_opt, - entry->argp->argp_domain, &snao_end); - if (snao_end > short_no_arg_opts) - { - *snao_end++ = 0; - __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); - } - - /* Now a list of short options *with* arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, usage_argful_short_opt, - entry->argp->argp_domain, stream); - - /* Finally, a list of long options (whew!). */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_long_iterate (entry, usage_long_opt, - entry->argp->argp_domain, stream); - } -} - -/* Make a HOL containing all levels of options in ARGP. CLUSTER is the - cluster in which ARGP's entries should be clustered, or 0. */ -static struct hol * -argp_hol (const struct argp *argp, struct hol_cluster *cluster) -{ - const struct argp_child *child = argp->children; - struct hol *hol = make_hol (argp, cluster); - if (child) - while (child->argp) - { - struct hol_cluster *child_cluster = - ((child->group || child->header) - /* Put CHILD->argp within its own cluster. */ - ? hol_add_cluster (hol, child->group, child->header, - child - argp->children, cluster, argp) - /* Just merge it into the parent's cluster. */ - : cluster); - hol_append (hol, argp_hol (child->argp, child_cluster)) ; - child++; - } - return hol; -} - -/* Calculate how many different levels with alternative args strings exist in - ARGP. */ -static size_t -argp_args_levels (const struct argp *argp) -{ - size_t levels = 0; - const struct argp_child *child = argp->children; - - if (argp->args_doc && strchr (argp->args_doc, '\n')) - levels++; - - if (child) - while (child->argp) - levels += argp_args_levels ((child++)->argp); - - return levels; -} - -/* Print all the non-option args documented in ARGP to STREAM. Any output is - preceded by a space. LEVELS is a pointer to a byte vector the length - returned by argp_args_levels; it should be initialized to zero, and - updated by this routine for the next call if ADVANCE is true. True is - returned as long as there are more patterns to output. */ -static int -argp_args_usage (const struct argp *argp, const struct argp_state *state, - char **levels, int advance, argp_fmtstream_t stream) -{ - char *our_level = *levels; - int multiple = 0; - const struct argp_child *child = argp->children; - const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; - const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); - - if (fdoc) - { - const char *cp = fdoc; - nl = __strchrnul (cp, '\n'); - if (*nl != '\0') - /* This is a `multi-level' args doc; advance to the correct position - as determined by our state in LEVELS, and update LEVELS. */ - { - int i; - multiple = 1; - for (i = 0; i < *our_level; i++) - cp = nl + 1, nl = __strchrnul (cp, '\n'); - (*levels)++; - } - - /* Manually do line wrapping so that it (probably) won't get wrapped at - any embedded spaces. */ - space (stream, 1 + nl - cp); - - __argp_fmtstream_write (stream, cp, nl - cp); - } - if (fdoc && fdoc != tdoc) - free ((char *)fdoc); /* Free user's modified doc string. */ - - if (child) - while (child->argp) - advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); - - if (advance && multiple) - { - /* Need to increment our level. */ - if (*nl) - /* There's more we can do here. */ - { - (*our_level)++; - advance = 0; /* Our parent shouldn't advance also. */ - } - else if (*our_level > 0) - /* We had multiple levels, but used them up; reset to zero. */ - *our_level = 0; - } - - return !advance; -} - -/* Print the documentation for ARGP to STREAM; if POST is false, then - everything preceeding a `\v' character in the documentation strings (or - the whole string, for those with none) is printed, otherwise, everything - following the `\v' character (nothing for strings without). Each separate - bit of documentation is separated a blank line, and if PRE_BLANK is true, - then the first is as well. If FIRST_ONLY is true, only the first - occurrence is output. Returns true if anything was output. */ -static int -argp_doc (const struct argp *argp, const struct argp_state *state, - int post, int pre_blank, int first_only, - argp_fmtstream_t stream) -{ - const char *text; - const char *inp_text; - void *input = 0; - int anything = 0; - size_t inp_text_limit = 0; - const char *doc = dgettext (argp->argp_domain, argp->doc); - const struct argp_child *child = argp->children; - - if (doc) - { - char *vt = strchr (doc, '\v'); - inp_text = post ? (vt ? vt + 1 : 0) : doc; - inp_text_limit = (!post && vt) ? (vt - doc) : 0; - } - else - inp_text = 0; - - if (argp->help_filter) - /* We have to filter the doc strings. */ - { - if (inp_text_limit) - /* Copy INP_TEXT so that it's nul-terminated. */ - inp_text = STRNDUP (inp_text, inp_text_limit); - input = __argp_input (argp, state); - text = - (*argp->help_filter) (post - ? ARGP_KEY_HELP_POST_DOC - : ARGP_KEY_HELP_PRE_DOC, - inp_text, input); - } - else - text = (const char *) inp_text; - - if (text) - { - if (pre_blank) - __argp_fmtstream_putc (stream, '\n'); - - if (text == inp_text && inp_text_limit) - __argp_fmtstream_write (stream, inp_text, inp_text_limit); - else - __argp_fmtstream_puts (stream, text); - - if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - - anything = 1; - } - - if (text && text != inp_text) - free ((char *) text); /* Free TEXT returned from the help filter. */ - if (inp_text && inp_text_limit && argp->help_filter) - free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ - - if (post && argp->help_filter) - /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ - { - text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); - if (text) - { - if (anything || pre_blank) - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, text); - free ((char *) text); - if (__argp_fmtstream_point (stream) - > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - anything = 1; - } - } - - if (child) - while (child->argp && !(first_only && anything)) - anything |= - argp_doc ((child++)->argp, state, - post, anything || pre_blank, first_only, - stream); - - return anything; -} - -/* Output a usage message for ARGP to STREAM. If called from - argp_state_help, STATE is the relevent parsing state. FLAGS are from the - set ARGP_HELP_*. NAME is what to use wherever a `program name' is - needed. */ - -static void -_help (const struct argp *argp, const struct argp_state *state, FILE *stream, - unsigned flags, const char *name) -{ - int anything = 0; /* Whether we've output anything. */ - struct hol *hol = 0; - argp_fmtstream_t fs; - - if (! stream) - return; - - FLOCKFILE (stream); - - if (! uparams.valid) - fill_in_uparams (state); - - fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); - if (! fs) - { - FUNLOCKFILE (stream); - return; - } - - if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) - { - hol = argp_hol (argp, 0); - - /* If present, these options always come last. */ - hol_set_group (hol, "help", -1); - hol_set_group (hol, "version", -1); - - hol_sort (hol); - } - - if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) - /* Print a short `Usage:' message. */ - { - int first_pattern = 1, more_patterns; - size_t num_pattern_levels = argp_args_levels (argp); - char *pattern_levels = alloca (num_pattern_levels); - - memset (pattern_levels, 0, num_pattern_levels); - - do - { - int old_lm; - int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); - char *levels = pattern_levels; - - if (first_pattern) - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, "Usage:"), - name); - else - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, " or: "), - name); - - /* We set the lmargin as well as the wmargin, because hol_usage - manually wraps options with newline to avoid annoying breaks. */ - old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); - - if (flags & ARGP_HELP_SHORT_USAGE) - /* Just show where the options go. */ - { - if (hol->num_entries > 0) - __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, - " [OPTION...]")); - } - else - /* Actually print the options. */ - { - hol_usage (hol, fs); - flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ - } - - more_patterns = argp_args_usage (argp, state, &levels, 1, fs); - - __argp_fmtstream_set_wmargin (fs, old_wm); - __argp_fmtstream_set_lmargin (fs, old_lm); - - __argp_fmtstream_putc (fs, '\n'); - anything = 1; - - first_pattern = 0; - } - while (more_patterns); - } - - if (flags & ARGP_HELP_PRE_DOC) - anything |= argp_doc (argp, state, 0, 0, 1, fs); - - if (flags & ARGP_HELP_SEE) - { - __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ -Try `%s --help' or `%s --usage' for more information.\n"), - name, name); - anything = 1; - } - - if (flags & ARGP_HELP_LONG) - /* Print a long, detailed help message. */ - { - /* Print info about all the options. */ - if (hol->num_entries > 0) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - hol_help (hol, state, fs); - anything = 1; - } - } - - if (flags & ARGP_HELP_POST_DOC) - /* Print any documentation strings at the end. */ - anything |= argp_doc (argp, state, 1, anything, 0, fs); - - if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, - "Report bugs to %s.\n"), - argp_program_bug_address); - anything = 1; - } - - FUNLOCKFILE (stream); - - if (hol) - hol_free (hol); - - __argp_fmtstream_free (fs); -} - -/* Output a usage message for ARGP to STREAM. FLAGS are from the set - ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ -void __argp_help (const struct argp *argp, FILE *stream, - unsigned flags, char *name) -{ - _help (argp, 0, stream, flags, name); -} -#ifdef weak_alias -weak_alias (__argp_help, argp_help) -#endif - -char *__argp_basename(char *name) -{ - char *short_name = strrchr(name, '/'); - return short_name ? short_name + 1 : name; -} - -char * -__argp_short_program_name(const struct argp_state *state) -{ - if (state) - return state->name; -#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - return program_invocation_short_name; -#elif HAVE_DECL_PROGRAM_INVOCATION_NAME - return __argp_basename(program_invocation_name); -#else /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */ - /* FIXME: What now? Miles suggests that it is better to use NULL, - but currently the value is passed on directly to fputs_unlocked, - so that requires more changes. */ -# if __GNUC__ - return ""; -# endif /* __GNUC__ */ -#endif /* !HAVE_DECL_PROGRAM_INVOCATION_NAME */ -} - -/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are - from the set ARGP_HELP_*. */ -void -__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) -{ - if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) - { - if (state && (state->flags & ARGP_LONG_ONLY)) - flags |= ARGP_HELP_LONG_ONLY; - - _help (state ? state->root_argp : 0, state, stream, flags, - __argp_short_program_name(state)); - - if (!state || ! (state->flags & ARGP_NO_EXIT)) - { - if (flags & ARGP_HELP_EXIT_ERR) - exit (argp_err_exit_status); - if (flags & ARGP_HELP_EXIT_OK) - exit (0); - } - } -} -#ifdef weak_alias -weak_alias (__argp_state_help, argp_state_help) -#endif - -/* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' - message, then exit (1). */ -void -__argp_error (const struct argp_state *state, const char *fmt, ...) -{ - if (!state || !(state->flags & ARGP_NO_ERRS)) - { - FILE *stream = state ? state->err_stream : stderr; - - if (stream) - { - va_list ap; - - FLOCKFILE (stream); - - FPUTS_UNLOCKED (__argp_short_program_name(state), - stream); - PUTC_UNLOCKED (':', stream); - PUTC_UNLOCKED (' ', stream); - - va_start (ap, fmt); - vfprintf (stream, fmt, ap); - va_end (ap); - - PUTC_UNLOCKED ('\n', stream); - - __argp_state_help (state, stream, ARGP_HELP_STD_ERR); - - FUNLOCKFILE (stream); - } - } -} -#ifdef weak_alias -weak_alias (__argp_error, argp_error) -#endif - -/* Similar to the standard gnu error-reporting function error(), but will - respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print - to STATE->err_stream. This is useful for argument parsing code that is - shared between program startup (when exiting is desired) and runtime - option parsing (when typically an error code is returned instead). The - difference between this function and argp_error is that the latter is for - *parsing errors*, and the former is for other problems that occur during - parsing but don't reflect a (syntactic) problem with the input. */ -void -__argp_failure (const struct argp_state *state, int status, int errnum, - const char *fmt, ...) -{ - if (!state || !(state->flags & ARGP_NO_ERRS)) - { - FILE *stream = state ? state->err_stream : stderr; - - if (stream) - { - FLOCKFILE (stream); - - FPUTS_UNLOCKED (__argp_short_program_name(state), - stream); - - if (fmt) - { - va_list ap; - - PUTC_UNLOCKED (':', stream); - PUTC_UNLOCKED (' ', stream); - - va_start (ap, fmt); - vfprintf (stream, fmt, ap); - va_end (ap); - } - - if (errnum) - { - PUTC_UNLOCKED (':', stream); - PUTC_UNLOCKED (' ', stream); - fputs (STRERROR (errnum), stream); - } - - PUTC_UNLOCKED ('\n', stream); - - FUNLOCKFILE (stream); - - if (status && (!state || !(state->flags & ARGP_NO_EXIT))) - exit (status); - } - } -} -#ifdef weak_alias -weak_alias (__argp_failure, argp_failure) -#endif diff --git a/contrib/argp-standalone/argp-namefrob.h b/contrib/argp-standalone/argp-namefrob.h deleted file mode 100644 index 0ce11481a7b..00000000000 --- a/contrib/argp-standalone/argp-namefrob.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Name frobnication for compiling argp outside of glibc - Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#if !_LIBC -/* This code is written for inclusion in gnu-libc, and uses names in the - namespace reserved for libc. If we're not compiling in libc, define those - names to be the normal ones instead. */ - -/* argp-parse functions */ -#undef __argp_parse -#define __argp_parse argp_parse -#undef __option_is_end -#define __option_is_end _option_is_end -#undef __option_is_short -#define __option_is_short _option_is_short -#undef __argp_input -#define __argp_input _argp_input - -/* argp-help functions */ -#undef __argp_help -#define __argp_help argp_help -#undef __argp_error -#define __argp_error argp_error -#undef __argp_failure -#define __argp_failure argp_failure -#undef __argp_state_help -#define __argp_state_help argp_state_help -#undef __argp_usage -#define __argp_usage argp_usage -#undef __argp_basename -#define __argp_basename _argp_basename -#undef __argp_short_program_name -#define __argp_short_program_name _argp_short_program_name - -/* argp-fmtstream functions */ -#undef __argp_make_fmtstream -#define __argp_make_fmtstream argp_make_fmtstream -#undef __argp_fmtstream_free -#define __argp_fmtstream_free argp_fmtstream_free -#undef __argp_fmtstream_putc -#define __argp_fmtstream_putc argp_fmtstream_putc -#undef __argp_fmtstream_puts -#define __argp_fmtstream_puts argp_fmtstream_puts -#undef __argp_fmtstream_write -#define __argp_fmtstream_write argp_fmtstream_write -#undef __argp_fmtstream_printf -#define __argp_fmtstream_printf argp_fmtstream_printf -#undef __argp_fmtstream_set_lmargin -#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin -#undef __argp_fmtstream_set_rmargin -#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin -#undef __argp_fmtstream_set_wmargin -#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin -#undef __argp_fmtstream_point -#define __argp_fmtstream_point argp_fmtstream_point -#undef __argp_fmtstream_update -#define __argp_fmtstream_update _argp_fmtstream_update -#undef __argp_fmtstream_ensure -#define __argp_fmtstream_ensure _argp_fmtstream_ensure -#undef __argp_fmtstream_lmargin -#define __argp_fmtstream_lmargin argp_fmtstream_lmargin -#undef __argp_fmtstream_rmargin -#define __argp_fmtstream_rmargin argp_fmtstream_rmargin -#undef __argp_fmtstream_wmargin -#define __argp_fmtstream_wmargin argp_fmtstream_wmargin - -/* normal libc functions we call */ -#undef __sleep -#define __sleep sleep -#undef __strcasecmp -#define __strcasecmp strcasecmp -#undef __vsnprintf -#define __vsnprintf vsnprintf - -#endif /* !_LIBC */ - -#ifndef __set_errno -#define __set_errno(e) (errno = (e)) -#endif diff --git a/contrib/argp-standalone/argp-parse.c b/contrib/argp-standalone/argp-parse.c deleted file mode 100644 index 78f7bf139b6..00000000000 --- a/contrib/argp-standalone/argp-parse.c +++ /dev/null @@ -1,1305 +0,0 @@ -/* Hierarchial argument parsing - Copyright (C) 1995, 96, 97, 98, 99, 2000,2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <stdlib.h> -#include <string.h> -#if HAVE_UNISTD_H -# include <unistd.h> -#endif -#include <limits.h> -#include <assert.h> - -#if HAVE_MALLOC_H -/* Needed, for alloca on windows */ -# include <malloc.h> -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -# ifdef _LIBC -# undef dgettext -# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) -# endif -# else -# define dgettext(domain, msgid) (msgid) -# define gettext(msgid) (msgid) -# endif -#endif -#ifndef N_ -# define N_(msgid) (msgid) -#endif - -#if _LIBC - 0 -#include <bits/libc-lock.h> -#else -#ifdef HAVE_CTHREADS_H -#include <cthreads.h> -#endif -#endif /* _LIBC */ - -#include "argp.h" -#include "argp-namefrob.h" - - -/* The meta-argument used to prevent any further arguments being interpreted - as options. */ -#define QUOTE "--" - -/* EZ alias for ARGP_ERR_UNKNOWN. */ -#define EBADKEY ARGP_ERR_UNKNOWN - - -/* Default options. */ - -/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep - for one second intervals, decrementing _ARGP_HANG until it's zero. Thus - you can force the program to continue by attaching a debugger and setting - it to 0 yourself. */ -volatile int _argp_hang; - -#define OPT_PROGNAME -2 -#define OPT_USAGE -3 -#if HAVE_SLEEP && HAVE_GETPID -#define OPT_HANG -4 -#endif - -static const struct argp_option argp_default_options[] = -{ - {"help", '?', 0, 0, N_("Give this help list"), -1}, - {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0 }, - {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, - N_("Set the program name"), 0}, -#if OPT_HANG - {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, - N_("Hang for SECS seconds (default 3600)"), 0 }, -#endif - {0, 0, 0, 0, 0, 0} -}; - -static error_t -argp_default_parser (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case '?': - __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); - break; - case OPT_USAGE: - __argp_state_help (state, state->out_stream, - ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); - break; - - case OPT_PROGNAME: /* Set the program name. */ -#if HAVE_DECL_PROGRAM_INVOCATION_NAME - program_invocation_name = arg; -#endif - /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka - __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined - to be that, so we have to be a bit careful here.] */ - - /* Update what we use for messages. */ - - state->name = __argp_basename(arg); - -#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - program_invocation_short_name = state->name; -#endif - - if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) - == ARGP_PARSE_ARGV0) - /* Update what getopt uses too. */ - state->argv[0] = arg; - - break; - -#if OPT_HANG - case OPT_HANG: - _argp_hang = atoi (arg ? arg : "3600"); - fprintf(state->err_stream, "%s: pid = %ld\n", - state->name, (long) getpid()); - while (_argp_hang-- > 0) - __sleep (1); - break; -#endif - - default: - return EBADKEY; - } - return 0; -} - -static const struct argp argp_default_argp = - {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; - - -static const struct argp_option argp_version_options[] = -{ - {"version", 'V', 0, 0, N_("Print program version"), -1}, - {0, 0, 0, 0, 0, 0 } -}; - -static error_t -argp_version_parser (int key, char *arg UNUSED, struct argp_state *state) -{ - switch (key) - { - case 'V': - if (argp_program_version_hook) - (*argp_program_version_hook) (state->out_stream, state); - else if (argp_program_version) - fprintf (state->out_stream, "%s\n", argp_program_version); - else - __argp_error (state, dgettext (state->root_argp->argp_domain, - "(PROGRAM ERROR) No version known!?")); - if (! (state->flags & ARGP_NO_EXIT)) - exit (0); - break; - default: - return EBADKEY; - } - return 0; -} - -static const struct argp argp_version_argp = - {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; - - - -/* The state of a `group' during parsing. Each group corresponds to a - particular argp structure from the tree of such descending from the top - level argp passed to argp_parse. */ -struct group -{ - /* This group's parsing function. */ - argp_parser_t parser; - - /* Which argp this group is from. */ - const struct argp *argp; - - /* The number of non-option args sucessfully handled by this parser. */ - unsigned args_processed; - - /* This group's parser's parent's group. */ - struct group *parent; - unsigned parent_index; /* And the our position in the parent. */ - - /* These fields are swapped into and out of the state structure when - calling this group's parser. */ - void *input, **child_inputs; - void *hook; -}; - -/* Call GROUP's parser with KEY and ARG, swapping any group-specific info - from STATE before calling, and back into state afterwards. If GROUP has - no parser, EBADKEY is returned. */ -static error_t -group_parse (struct group *group, struct argp_state *state, int key, char *arg) -{ - if (group->parser) - { - error_t err; - state->hook = group->hook; - state->input = group->input; - state->child_inputs = group->child_inputs; - state->arg_num = group->args_processed; - err = (*group->parser)(key, arg, state); - group->hook = state->hook; - return err; - } - else - return EBADKEY; -} - -struct parser -{ - const struct argp *argp; - - const char *posixly_correct; - - /* True if there are only no-option arguments left, which are just - passed verbatim with ARGP_KEY_ARG. This is set if we encounter a - quote, or the end of the proper options, but may be cleared again - if the user moves the next argument pointer backwards. */ - int args_only; - - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, the default is - REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is - defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; stop option - processing when the first non-option is seen. This is what Unix - does. This mode of operation is selected by either setting the - environment variable POSIXLY_CORRECT, or using `+' as the first - character of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. This - allows options to be given in any order, even with programs that - were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - */ - enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; - - /* A segment of non-option arguments that have been skipped for - later processing, after all options. `first_nonopt' is the index - in ARGV of the first of them; `last_nonopt' is the index after - the last of them. - - If quoted or args_only is non-zero, this segment should be empty. */ - - /* FIXME: I'd prefer to use unsigned, but it's more consistent to - use the same type as for state.next. */ - int first_nonopt; - int last_nonopt; - - /* String of all recognized short options. Needed for ARGP_LONG_ONLY. */ - /* FIXME: Perhaps change to a pointer to a suitable bitmap instead? */ - char *short_opts; - - /* For parsing combined short options. */ - char *nextchar; - - /* States of the various parsing groups. */ - struct group *groups; - /* The end of the GROUPS array. */ - struct group *egroup; - /* An vector containing storage for the CHILD_INPUTS field in all groups. */ - void **child_inputs; - - /* State block supplied to parsing routines. */ - struct argp_state state; - - /* Memory used by this parser. */ - void *storage; -}; - -/* Search for a group defining a short option. */ -static const struct argp_option * -find_short_option(struct parser *parser, int key, struct group **p) -{ - struct group *group; - - assert(key >= 0); - assert(isascii(key)); - - for (group = parser->groups; group < parser->egroup; group++) - { - const struct argp_option *opts; - - for (opts = group->argp->options; !__option_is_end(opts); opts++) - if (opts->key == key) - { - *p = group; - return opts; - } - } - return NULL; -} - -enum match_result { MATCH_EXACT, MATCH_PARTIAL, MATCH_NO }; - -/* If defined, allow complete.el-like abbreviations of long options. */ -#ifndef ARGP_COMPLETE -#define ARGP_COMPLETE 0 -#endif - -/* Matches an encountern long-option argument ARG against an option NAME. - * ARG is terminated by NUL or '='. */ -static enum match_result -match_option(const char *arg, const char *name) -{ - unsigned i, j; - for (i = j = 0;; i++, j++) - { - switch(arg[i]) - { - case '\0': - case '=': - return name[j] ? MATCH_PARTIAL : MATCH_EXACT; -#if ARGP_COMPLETE - case '-': - while (name[j] != '-') - if (!name[j++]) - return MATCH_NO; - break; -#endif - default: - if (arg[i] != name[j]) - return MATCH_NO; - } - } -} - -static const struct argp_option * -find_long_option(struct parser *parser, - const char *arg, - struct group **p) -{ - struct group *group; - - /* Partial match found so far. */ - struct group *matched_group = NULL; - const struct argp_option *matched_option = NULL; - - /* Number of partial matches. */ - int num_partial = 0; - - for (group = parser->groups; group < parser->egroup; group++) - { - const struct argp_option *opts; - - for (opts = group->argp->options; !__option_is_end(opts); opts++) - { - if (!opts->name) - continue; - switch (match_option(arg, opts->name)) - { - case MATCH_NO: - break; - case MATCH_PARTIAL: - num_partial++; - - matched_group = group; - matched_option = opts; - - break; - case MATCH_EXACT: - /* Exact match. */ - *p = group; - return opts; - } - } - } - if (num_partial == 1) - { - *p = matched_group; - return matched_option; - } - - return NULL; -} - - -/* The next usable entries in the various parser tables being filled in by - convert_options. */ -struct parser_convert_state -{ - struct parser *parser; - char *short_end; - void **child_inputs_end; -}; - -/* Initialize GROUP from ARGP. If CVT->SHORT_END is non-NULL, short - options are recorded in the short options string. Returns the next - unused group entry. CVT holds state used during the conversion. */ -static struct group * -convert_options (const struct argp *argp, - struct group *parent, unsigned parent_index, - struct group *group, struct parser_convert_state *cvt) -{ - const struct argp_option *opt = argp->options; - const struct argp_child *children = argp->children; - - if (opt || argp->parser) - { - /* This parser needs a group. */ - if (cvt->short_end) - { - /* Record any short options. */ - for ( ; !__option_is_end (opt); opt++) - if (__option_is_short(opt)) - *cvt->short_end++ = opt->key; - } - - group->parser = argp->parser; - group->argp = argp; - group->args_processed = 0; - group->parent = parent; - group->parent_index = parent_index; - group->input = 0; - group->hook = 0; - group->child_inputs = 0; - - if (children) - /* Assign GROUP's CHILD_INPUTS field some space from - CVT->child_inputs_end.*/ - { - unsigned num_children = 0; - while (children[num_children].argp) - num_children++; - group->child_inputs = cvt->child_inputs_end; - cvt->child_inputs_end += num_children; - } - parent = group++; - } - else - parent = 0; - - if (children) - { - unsigned index = 0; - while (children->argp) - group = - convert_options (children++->argp, parent, index++, group, cvt); - } - - return group; -} -/* Allocate and initialize the group structures, so that they are - ordered as if by traversing the corresponding argp parser tree in - pre-order. Also build the list of short options, if that is needed. */ -static void -parser_convert (struct parser *parser, const struct argp *argp) -{ - struct parser_convert_state cvt; - - cvt.parser = parser; - cvt.short_end = parser->short_opts; - cvt.child_inputs_end = parser->child_inputs; - - parser->argp = argp; - - if (argp) - parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt); - else - parser->egroup = parser->groups; /* No parsers at all! */ - - if (parser->short_opts) - *cvt.short_end ='\0'; -} - -/* Lengths of various parser fields which we will allocated. */ -struct parser_sizes -{ - /* Needed only ARGP_LONG_ONLY */ - size_t short_len; /* Number of short options. */ - - size_t num_groups; /* Group structures we allocate. */ - size_t num_child_inputs; /* Child input slots. */ -}; - -/* For ARGP, increments the NUM_GROUPS field in SZS by the total - number of argp structures descended from it, and the SHORT_LEN by - the total number of short options. */ -static void -calc_sizes (const struct argp *argp, struct parser_sizes *szs) -{ - const struct argp_child *child = argp->children; - const struct argp_option *opt = argp->options; - - if (opt || argp->parser) - { - /* This parser needs a group. */ - szs->num_groups++; - if (opt) - { - while (__option_is_short (opt++)) - szs->short_len++; - } - } - - if (child) - while (child->argp) - { - calc_sizes ((child++)->argp, szs); - szs->num_child_inputs++; - } -} - -/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ -static error_t -parser_init (struct parser *parser, const struct argp *argp, - int argc, char **argv, int flags, void *input) -{ - error_t err = 0; - struct group *group; - struct parser_sizes szs; - - parser->posixly_correct = getenv ("POSIXLY_CORRECT"); - - if (flags & ARGP_IN_ORDER) - parser->ordering = RETURN_IN_ORDER; - else if (flags & ARGP_NO_ARGS) - parser->ordering = REQUIRE_ORDER; - else if (parser->posixly_correct) - parser->ordering = REQUIRE_ORDER; - else - parser->ordering = PERMUTE; - - szs.short_len = 0; - szs.num_groups = 0; - szs.num_child_inputs = 0; - - if (argp) - calc_sizes (argp, &szs); - - if (!(flags & ARGP_LONG_ONLY)) - /* We have no use for the short option array. */ - szs.short_len = 0; - - /* Lengths of the various bits of storage used by PARSER. */ -#define GLEN (szs.num_groups + 1) * sizeof (struct group) -#define CLEN (szs.num_child_inputs * sizeof (void *)) -#define SLEN (szs.short_len + 1) -#define STORAGE(offset) ((void *) (((char *) parser->storage) + (offset))) - - parser->storage = malloc (GLEN + CLEN + SLEN); - if (! parser->storage) - return ENOMEM; - - parser->groups = parser->storage; - - parser->child_inputs = STORAGE(GLEN); - memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); - - if (flags & ARGP_LONG_ONLY) - parser->short_opts = STORAGE(GLEN + CLEN); - else - parser->short_opts = NULL; - - parser_convert (parser, argp); - - memset (&parser->state, 0, sizeof (struct argp_state)); - - parser->state.root_argp = parser->argp; - parser->state.argc = argc; - parser->state.argv = argv; - parser->state.flags = flags; - parser->state.err_stream = stderr; - parser->state.out_stream = stdout; - parser->state.pstate = parser; - - parser->args_only = 0; - parser->nextchar = NULL; - parser->first_nonopt = parser->last_nonopt = 0; - - /* Call each parser for the first time, giving it a chance to propagate - values to child parsers. */ - if (parser->groups < parser->egroup) - parser->groups->input = input; - for (group = parser->groups; - group < parser->egroup && (!err || err == EBADKEY); - group++) - { - if (group->parent) - /* If a child parser, get the initial input value from the parent. */ - group->input = group->parent->child_inputs[group->parent_index]; - - if (!group->parser - && group->argp->children && group->argp->children->argp) - /* For the special case where no parsing function is supplied for an - argp, propagate its input to its first child, if any (this just - makes very simple wrapper argps more convenient). */ - group->child_inputs[0] = group->input; - - err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); - } - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - if (err) - return err; - - if (argv[0] && !(parser->state.flags & ARGP_PARSE_ARGV0)) - /* There's an argv[0]; use it for messages. */ - { - parser->state.name = __argp_basename(argv[0]); - - /* Don't parse it as an argument. */ - parser->state.next = 1; - } - else - parser->state.name = __argp_short_program_name(NULL); - - return 0; -} - -/* Free any storage consumed by PARSER (but not PARSER itself). */ -static error_t -parser_finalize (struct parser *parser, - error_t err, int arg_ebadkey, int *end_index) -{ - struct group *group; - - if (err == EBADKEY && arg_ebadkey) - /* Suppress errors generated by unparsed arguments. */ - err = 0; - - if (! err) - { - if (parser->state.next == parser->state.argc) - /* We successfully parsed all arguments! Call all the parsers again, - just a few more times... */ - { - for (group = parser->groups; - group < parser->egroup && (!err || err==EBADKEY); - group++) - if (group->args_processed == 0) - err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); - for (group = parser->egroup - 1; - group >= parser->groups && (!err || err==EBADKEY); - group--) - err = group_parse (group, &parser->state, ARGP_KEY_END, 0); - - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - /* Tell the user that all arguments are parsed. */ - if (end_index) - *end_index = parser->state.next; - } - else if (end_index) - /* Return any remaining arguments to the user. */ - *end_index = parser->state.next; - else - /* No way to return the remaining arguments, they must be bogus. */ - { - if (!(parser->state.flags & ARGP_NO_ERRS) - && parser->state.err_stream) - fprintf (parser->state.err_stream, - dgettext (parser->argp->argp_domain, - "%s: Too many arguments\n"), - parser->state.name); - err = EBADKEY; - } - } - - /* Okay, we're all done, with either an error or success; call the parsers - to indicate which one. */ - - if (err) - { - /* Maybe print an error message. */ - if (err == EBADKEY) - /* An appropriate message describing what the error was should have - been printed earlier. */ - __argp_state_help (&parser->state, parser->state.err_stream, - ARGP_HELP_STD_ERR); - - /* Since we didn't exit, give each parser an error indication. */ - for (group = parser->groups; group < parser->egroup; group++) - group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); - } - else - /* Notify parsers of success, and propagate back values from parsers. */ - { - /* We pass over the groups in reverse order so that child groups are - given a chance to do there processing before passing back a value to - the parent. */ - for (group = parser->egroup - 1 - ; group >= parser->groups && (!err || err == EBADKEY) - ; group--) - err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - } - - /* Call parsers once more, to do any final cleanup. Errors are ignored. */ - for (group = parser->egroup - 1; group >= parser->groups; group--) - group_parse (group, &parser->state, ARGP_KEY_FINI, 0); - - if (err == EBADKEY) - err = EINVAL; - - free (parser->storage); - - return err; -} - -/* Call the user parsers to parse the non-option argument VAL, at the - current position, returning any error. The state NEXT pointer - should point to the argument; this function will adjust it - correctly to reflect however many args actually end up being - consumed. */ -static error_t -parser_parse_arg (struct parser *parser, char *val) -{ - /* Save the starting value of NEXT */ - int index = parser->state.next; - error_t err = EBADKEY; - struct group *group; - int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ - - /* Try to parse the argument in each parser. */ - for (group = parser->groups - ; group < parser->egroup && err == EBADKEY - ; group++) - { - parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ - key = ARGP_KEY_ARG; - err = group_parse (group, &parser->state, key, val); - - if (err == EBADKEY) - /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ - { - parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ - key = ARGP_KEY_ARGS; - err = group_parse (group, &parser->state, key, 0); - } - } - - if (! err) - { - if (key == ARGP_KEY_ARGS) - /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't - changed by the user, *all* arguments should be considered - consumed. */ - parser->state.next = parser->state.argc; - - if (parser->state.next > index) - /* Remember that we successfully processed a non-option - argument -- but only if the user hasn't gotten tricky and set - the clock back. */ - (--group)->args_processed += (parser->state.next - index); - else - /* The user wants to reparse some args, so try looking for options again. */ - parser->args_only = 0; - } - - return err; -} - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,next), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (struct parser *parser) -{ - int bottom = parser->first_nonopt; - int middle = parser->last_nonopt; - int top = parser->state.next; - char **argv = parser->state.argv; - - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - parser->first_nonopt += (parser->state.next - parser->last_nonopt); - parser->last_nonopt = parser->state.next; -} - - - -enum arg_type { ARG_ARG, ARG_SHORT_OPTION, - ARG_LONG_OPTION, ARG_LONG_ONLY_OPTION, - ARG_QUOTE }; - -static enum arg_type -classify_arg(struct parser *parser, char *arg, char **opt) -{ - if (arg[0] == '-') - /* Looks like an option... */ - switch (arg[1]) - { - case '\0': - /* "-" is not an option. */ - return ARG_ARG; - case '-': - /* Long option, or quote. */ - if (!arg[2]) - return ARG_QUOTE; - - /* A long option. */ - if (opt) - *opt = arg + 2; - return ARG_LONG_OPTION; - - default: - /* Short option. But if ARGP_LONG_ONLY, it can also be a long option. */ - - if (opt) - *opt = arg + 1; - - if (parser->state.flags & ARGP_LONG_ONLY) - { - /* Rules from getopt.c: - - If long_only and the ARGV-element has the form "-f", - where f is a valid short option, don't consider it an - abbreviated form of a long option that starts with f. - Otherwise there would be no way to give the -f short - option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an - abbreviation of the long option, just like "--fu", and - not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - assert(parser->short_opts); - - if (arg[2] || !strchr(parser->short_opts, arg[1])) - return ARG_LONG_ONLY_OPTION; - } - - return ARG_SHORT_OPTION; - } - - else - return ARG_ARG; -} - -/* Parse the next argument in PARSER (as indicated by PARSER->state.next). - Any error from the parsers is returned, and *ARGP_EBADKEY indicates - whether a value of EBADKEY is due to an unrecognized argument (which is - generally not fatal). */ -static error_t -parser_parse_next (struct parser *parser, int *arg_ebadkey) -{ - if (parser->state.quoted && parser->state.next < parser->state.quoted) - /* The next argument pointer has been moved to before the quoted - region, so pretend we never saw the quoting `--', and start - looking for options again. If the `--' is still there we'll just - process it one more time. */ - parser->state.quoted = parser->args_only = 0; - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if NEXT has been - moved back by the user (who may also have changed the arguments). */ - if (parser->last_nonopt > parser->state.next) - parser->last_nonopt = parser->state.next; - if (parser->first_nonopt > parser->state.next) - parser->first_nonopt = parser->state.next; - - if (parser->nextchar) - /* Deal with short options. */ - { - struct group *group; - char c; - const struct argp_option *option; - char *value = NULL;; - - assert(!parser->args_only); - - c = *parser->nextchar++; - - option = find_short_option(parser, c, &group); - if (!option) - { - if (parser->posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: illegal option -- %c\n"), - parser->state.name, c); - else - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: invalid option -- %c\n"), - parser->state.name, c); - - *arg_ebadkey = 0; - return EBADKEY; - } - - if (!*parser->nextchar) - parser->nextchar = NULL; - - if (option->arg) - { - value = parser->nextchar; - parser->nextchar = NULL; - - if (!value - && !(option->flags & OPTION_ARG_OPTIONAL)) - /* We need an mandatory argument. */ - { - if (parser->state.next == parser->state.argc) - /* Missing argument */ - { - /* 1003.2 specifies the format of this message. */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: option requires an argument -- %c\n"), - parser->state.name, c); - - *arg_ebadkey = 0; - return EBADKEY; - } - value = parser->state.argv[parser->state.next++]; - } - } - return group_parse(group, &parser->state, - option->key, value); - } - else - /* Advance to the next ARGV-element. */ - { - if (parser->args_only) - { - *arg_ebadkey = 1; - if (parser->state.next >= parser->state.argc) - /* We're done. */ - return EBADKEY; - else - return parser_parse_arg(parser, - parser->state.argv[parser->state.next]); - } - - if (parser->state.next >= parser->state.argc) - /* Almost done. If there are non-options that we skipped - previously, we should process them now. */ - { - *arg_ebadkey = 1; - if (parser->first_nonopt != parser->last_nonopt) - { - exchange(parser); - - /* Start processing the arguments we skipped previously. */ - parser->state.next = parser->first_nonopt; - - parser->first_nonopt = parser->last_nonopt = 0; - - parser->args_only = 1; - return 0; - } - else - /* Indicate that we're really done. */ - return EBADKEY; - } - else - /* Look for options. */ - { - char *arg = parser->state.argv[parser->state.next]; - - char *optstart; - enum arg_type token = classify_arg(parser, arg, &optstart); - - switch (token) - { - case ARG_ARG: - switch (parser->ordering) - { - case PERMUTE: - if (parser->first_nonopt == parser->last_nonopt) - /* Skipped sequence is empty; start a new one. */ - parser->first_nonopt = parser->last_nonopt = parser->state.next; - - else if (parser->last_nonopt != parser->state.next) - /* We have a non-empty skipped sequence, and - we're not at the end-point, so move it. */ - exchange(parser); - - assert(parser->last_nonopt == parser->state.next); - - /* Skip this argument for now. */ - parser->state.next++; - parser->last_nonopt = parser->state.next; - - return 0; - - case REQUIRE_ORDER: - /* Implicit quote before the first argument. */ - parser->args_only = 1; - return 0; - - case RETURN_IN_ORDER: - *arg_ebadkey = 1; - return parser_parse_arg(parser, arg); - - default: - abort(); - } - case ARG_QUOTE: - /* Skip it, then exchange with any previous non-options. */ - parser->state.next++; - assert (parser->last_nonopt != parser->state.next); - - if (parser->first_nonopt != parser->last_nonopt) - { - exchange(parser); - - /* Start processing the skipped and the quoted - arguments. */ - - parser->state.quoted = parser->state.next = parser->first_nonopt; - - /* Also empty the skipped-list, to avoid confusion - if the user resets the next pointer. */ - parser->first_nonopt = parser->last_nonopt = 0; - } - else - parser->state.quoted = parser->state.next; - - parser->args_only = 1; - return 0; - - case ARG_LONG_ONLY_OPTION: - case ARG_LONG_OPTION: - { - struct group *group; - const struct argp_option *option; - char *value; - - parser->state.next++; - option = find_long_option(parser, optstart, &group); - - if (!option) - { - /* NOTE: This includes any "=something" in the output. */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: unrecognized option `%s'\n"), - parser->state.name, arg); - *arg_ebadkey = 0; - return EBADKEY; - } - - value = strchr(optstart, '='); - if (value) - value++; - - if (value && !option->arg) - /* Unexpected argument. */ - { - if (token == ARG_LONG_OPTION) - /* --option */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: option `--%s' doesn't allow an argument\n"), - parser->state.name, option->name); - else - /* +option or -option */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: option `%c%s' doesn't allow an argument\n"), - parser->state.name, arg[0], option->name); - - *arg_ebadkey = 0; - return EBADKEY; - } - - if (option->arg && !value - && !(option->flags & OPTION_ARG_OPTIONAL)) - /* We need an mandatory argument. */ - { - if (parser->state.next == parser->state.argc) - /* Missing argument */ - { - if (token == ARG_LONG_OPTION) - /* --option */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: option `--%s' requires an argument\n"), - parser->state.name, option->name); - else - /* +option or -option */ - fprintf (parser->state.err_stream, - dgettext(parser->state.root_argp->argp_domain, - "%s: option `%c%s' requires an argument\n"), - parser->state.name, arg[0], option->name); - - *arg_ebadkey = 0; - return EBADKEY; - } - - value = parser->state.argv[parser->state.next++]; - } - *arg_ebadkey = 0; - return group_parse(group, &parser->state, - option->key, value); - } - case ARG_SHORT_OPTION: - parser->state.next++; - parser->nextchar = optstart; - return 0; - - default: - abort(); - } - } - } -} - -/* Parse the options strings in ARGC & ARGV according to the argp in ARGP. - FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the - index in ARGV of the first unparsed option is returned in it. If an - unknown option is present, EINVAL is returned; if some parser routine - returned a non-zero value, it is returned; otherwise 0 is returned. */ -error_t -__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, - int *end_index, void *input) -{ - error_t err; - struct parser parser; - - /* If true, then err == EBADKEY is a result of a non-option argument failing - to be parsed (which in some cases isn't actually an error). */ - int arg_ebadkey = 0; - - if (! (flags & ARGP_NO_HELP)) - /* Add our own options. */ - { - struct argp_child *child = alloca (4 * sizeof (struct argp_child)); - struct argp *top_argp = alloca (sizeof (struct argp)); - - /* TOP_ARGP has no options, it just serves to group the user & default - argps. */ - memset (top_argp, 0, sizeof (*top_argp)); - top_argp->children = child; - - memset (child, 0, 4 * sizeof (struct argp_child)); - - if (argp) - (child++)->argp = argp; - (child++)->argp = &argp_default_argp; - if (argp_program_version || argp_program_version_hook) - (child++)->argp = &argp_version_argp; - child->argp = 0; - - argp = top_argp; - } - - /* Construct a parser for these arguments. */ - err = parser_init (&parser, argp, argc, argv, flags, input); - - if (! err) - /* Parse! */ - { - while (! err) - err = parser_parse_next (&parser, &arg_ebadkey); - err = parser_finalize (&parser, err, arg_ebadkey, end_index); - } - - return err; -} -#ifdef weak_alias -weak_alias (__argp_parse, argp_parse) -#endif - -/* Return the input field for ARGP in the parser corresponding to STATE; used - by the help routines. */ -void * -__argp_input (const struct argp *argp, const struct argp_state *state) -{ - if (state) - { - struct group *group; - struct parser *parser = state->pstate; - - for (group = parser->groups; group < parser->egroup; group++) - if (group->argp == argp) - return group->input; - } - - return 0; -} -#ifdef weak_alias -weak_alias (__argp_input, _argp_input) -#endif - -/* Defined here, in case a user is not inlining the definitions in - * argp.h */ -void -__argp_usage (__const struct argp_state *__state) -{ - __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); -} - -int -__option_is_short (__const struct argp_option *__opt) -{ - if (__opt->flags & OPTION_DOC) - return 0; - else - { - int __key = __opt->key; - /* FIXME: whether or not a particular key implies a short option - * ought not to be locale dependent. */ - return __key > 0 && isprint (__key); - } -} - -int -__option_is_end (__const struct argp_option *__opt) -{ - return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; -} diff --git a/contrib/argp-standalone/argp-pv.c b/contrib/argp-standalone/argp-pv.c deleted file mode 100644 index d7d374a66bd..00000000000 --- a/contrib/argp-standalone/argp-pv.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Default definition for ARGP_PROGRAM_VERSION. - Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* If set by the user program to a non-zero value, then a default option - --version is added (unless the ARGP_NO_HELP flag is used), which will - print this this string followed by a newline and exit (unless the - ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ -const char *argp_program_version = 0; diff --git a/contrib/argp-standalone/argp-pvh.c b/contrib/argp-standalone/argp-pvh.c deleted file mode 100644 index 829a1cda80d..00000000000 --- a/contrib/argp-standalone/argp-pvh.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Default definition for ARGP_PROGRAM_VERSION_HOOK. - Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "argp.h" - -/* If set by the user program to a non-zero value, then a default option - --version is added (unless the ARGP_NO_HELP flag is used), which calls - this function with a stream to print the version to and a pointer to the - current parsing state, and then exits (unless the ARGP_NO_EXIT flag is - used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ -void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = 0; diff --git a/contrib/argp-standalone/argp.h b/contrib/argp-standalone/argp.h deleted file mode 100644 index 29d3dfe9720..00000000000 --- a/contrib/argp-standalone/argp.h +++ /dev/null @@ -1,602 +0,0 @@ -/* Hierarchial argument parsing. - Copyright (C) 1995, 96, 97, 98, 99, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader <miles@gnu.ai.mit.edu>. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _ARGP_H -#define _ARGP_H - -#include <stdio.h> -#include <ctype.h> - -#define __need_error_t -#include <errno.h> - -#ifndef __THROW -# define __THROW -#endif - -#ifndef __const -# define __const const -#endif - -#ifndef __error_t_defined -typedef int error_t; -# define __error_t_defined -#endif - -/* FIXME: What's the right way to check for __restrict? Sun's cc seems - not to have it. Perhaps it's easiest to just delete the use of - __restrict from the prototypes. */ -#ifndef __restrict -# ifndef __GNUC___ -# define __restrict -# endif -#endif - -/* NOTE: We can't use the autoconf tests, since this is supposed to be - an installed header file and argp's config.h is of course not - installed. */ -#ifndef PRINTF_STYLE -# if __GNUC__ >= 2 -# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a))) -# else -# define PRINTF_STYLE(f, a) -# endif -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* A description of a particular option. A pointer to an array of - these is passed in the OPTIONS field of an argp structure. Each option - entry can correspond to one long option and/or one short option; more - names for the same option can be added by following an entry in an option - array with options having the OPTION_ALIAS flag set. */ -struct argp_option -{ - /* The long option name. For more than one name for the same option, you - can use following options with the OPTION_ALIAS flag set. */ - __const char *name; - - /* What key is returned for this option. If > 0 and printable, then it's - also accepted as a short option. */ - int key; - - /* If non-NULL, this is the name of the argument associated with this - option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */ - __const char *arg; - - /* OPTION_ flags. */ - int flags; - - /* The doc string for this option. If both NAME and KEY are 0, This string - will be printed outdented from the normal option column, making it - useful as a group header (it will be the first thing printed in its - group); in this usage, it's conventional to end the string with a `:'. */ - __const char *doc; - - /* The group this option is in. In a long help message, options are sorted - alphabetically within each group, and the groups presented in the order - 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with - if this field 0 will inherit the group number of the previous entry, or - zero if it's the first one, unless its a group header (NAME and KEY both - 0), in which case, the previous entry + 1 is the default. Automagic - options such as --help are put into group -1. */ - int group; -}; - -/* The argument associated with this option is optional. */ -#define OPTION_ARG_OPTIONAL 0x1 - -/* This option isn't displayed in any help messages. */ -#define OPTION_HIDDEN 0x2 - -/* This option is an alias for the closest previous non-alias option. This - means that it will be displayed in the same help entry, and will inherit - fields other than NAME and KEY from the aliased option. */ -#define OPTION_ALIAS 0x4 - -/* This option isn't actually an option (and so should be ignored by the - actual option parser), but rather an arbitrary piece of documentation that - should be displayed in much the same manner as the options. If this flag - is set, then the option NAME field is displayed unmodified (e.g., no `--' - prefix is added) at the left-margin (where a *short* option would normally - be displayed), and the documentation string in the normal place. For - purposes of sorting, any leading whitespace and puncuation is ignored, - except that if the first non-whitespace character is not `-', this entry - is displayed after all options (and OPTION_DOC entries with a leading `-') - in the same group. */ -#define OPTION_DOC 0x8 - -/* This option shouldn't be included in `long' usage messages (but is still - included in help messages). This is mainly intended for options that are - completely documented in an argp's ARGS_DOC field, in which case including - the option in the generic usage list would be redundant. For instance, - if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to - distinguish these two cases, -x should probably be marked - OPTION_NO_USAGE. */ -#define OPTION_NO_USAGE 0x10 - -struct argp; /* fwd declare this type */ -struct argp_state; /* " */ -struct argp_child; /* " */ - -/* The type of a pointer to an argp parsing function. */ -typedef error_t (*argp_parser_t) (int key, char *arg, - struct argp_state *state); - -/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such - returns will simply be ignored. For user keys, this error will be turned - into EINVAL (if the call to argp_parse is such that errors are propagated - back to the user instead of exiting); returning EINVAL itself would result - in an immediate stop to parsing in *all* cases. */ -#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */ - -/* Special values for the KEY argument to an argument parsing function. - ARGP_ERR_UNKNOWN should be returned if they aren't understood. - - The sequence of keys to a parsing function is either (where each - uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key): - - INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all - or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed - or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized - - The third case is where every parser returned ARGP_KEY_UNKNOWN for an - argument, in which case parsing stops at that argument (returning the - unparsed arguments to the caller of argp_parse if requested, or stopping - with an error message if not). - - If an error occurs (either detected by argp, or because the parsing - function returned an error value), then the parser is called with - ARGP_KEY_ERROR, and no further calls are made. */ - -/* This is not an option at all, but rather a command line argument. If a - parser receiving this key returns success, the fact is recorded, and the - ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the - argument, a parser function decrements the NEXT field of the state it's - passed, the option won't be considered processed; this is to allow you to - actually modify the argument (perhaps into an option), and have it - processed again. */ -#define ARGP_KEY_ARG 0 -/* There are remaining arguments not parsed by any parser, which may be found - starting at (STATE->argv + STATE->next). If success is returned, but - STATE->next left untouched, it's assumed that all arguments were consume, - otherwise, the parser should adjust STATE->next to reflect any arguments - consumed. */ -#define ARGP_KEY_ARGS 0x1000006 -/* There are no more command line arguments at all. */ -#define ARGP_KEY_END 0x1000001 -/* Because it's common to want to do some special processing if there aren't - any non-option args, user parsers are called with this key if they didn't - successfully process any non-option arguments. Called just before - ARGP_KEY_END (where more general validity checks on previously parsed - arguments can take place). */ -#define ARGP_KEY_NO_ARGS 0x1000002 -/* Passed in before any parsing is done. Afterwards, the values of each - element of the CHILD_INPUT field, if any, in the state structure is - copied to each child's state to be the initial value of the INPUT field. */ -#define ARGP_KEY_INIT 0x1000003 -/* Use after all other keys, including SUCCESS & END. */ -#define ARGP_KEY_FINI 0x1000007 -/* Passed in when parsing has successfully been completed (even if there are - still arguments remaining). */ -#define ARGP_KEY_SUCCESS 0x1000004 -/* Passed in if an error occurs. */ -#define ARGP_KEY_ERROR 0x1000005 - -/* An argp structure contains a set of options declarations, a function to - deal with parsing one, documentation string, a possible vector of child - argp's, and perhaps a function to filter help output. When actually - parsing options, getopt is called with the union of all the argp - structures chained together through their CHILD pointers, with conflicts - being resolved in favor of the first occurrence in the chain. */ -struct argp -{ - /* An array of argp_option structures, terminated by an entry with both - NAME and KEY having a value of 0. */ - __const struct argp_option *options; - - /* What to do with an option from this structure. KEY is the key - associated with the option, and ARG is any associated argument (NULL if - none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be - returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then - parsing is stopped immediately, and that value is returned from - argp_parse(). For special (non-user-supplied) values of KEY, see the - ARGP_KEY_ definitions below. */ - argp_parser_t parser; - - /* A string describing what other arguments are wanted by this program. It - is only used by argp_usage to print the `Usage:' message. If it - contains newlines, the strings separated by them are considered - alternative usage patterns, and printed on separate lines (lines after - the first are prefix by ` or: ' instead of `Usage:'). */ - __const char *args_doc; - - /* If non-NULL, a string containing extra text to be printed before and - after the options in a long help message (separated by a vertical tab - `\v' character). */ - __const char *doc; - - /* A vector of argp_children structures, terminated by a member with a 0 - argp field, pointing to child argps should be parsed with this one. Any - conflicts are resolved in favor of this argp, or early argps in the - CHILDREN list. This field is useful if you use libraries that supply - their own argp structure, which you want to use in conjunction with your - own. */ - __const struct argp_child *children; - - /* If non-zero, this should be a function to filter the output of help - messages. KEY is either a key from an option, in which case TEXT is - that option's help text, or a special key from the ARGP_KEY_HELP_ - defines, below, describing which other help text TEXT is. The function - should return either TEXT, if it should be used as-is, a replacement - string, which should be malloced, and will be freed by argp, or NULL, - meaning `print nothing'. The value for TEXT is *after* any translation - has been done, so if any of the replacement text also needs translation, - that should be done by the filter function. INPUT is either the input - supplied to argp_parse, or NULL, if argp_help was called directly. */ - char *(*help_filter) (int __key, __const char *__text, void *__input); - - /* If non-zero the strings used in the argp library are translated using - the domain described by this string. Otherwise the currently installed - default domain is used. */ - const char *argp_domain; -}; - -/* Possible KEY arguments to a help filter function. */ -#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */ -#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ -#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ -#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; - TEXT is NULL for this key. */ -/* Explanatory note emitted when duplicate option arguments have been - suppressed. */ -#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 -#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */ - -/* When an argp has a non-zero CHILDREN field, it should point to a vector of - argp_child structures, each of which describes a subsidiary argp. */ -struct argp_child -{ - /* The child parser. */ - __const struct argp *argp; - - /* Flags for this child. */ - int flags; - - /* If non-zero, an optional header to be printed in help output before the - child options. As a side-effect, a non-zero value forces the child - options to be grouped together; to achieve this effect without actually - printing a header string, use a value of "". */ - __const char *header; - - /* Where to group the child options relative to the other (`consolidated') - options in the parent argp; the values are the same as the GROUP field - in argp_option structs, but all child-groupings follow parent options at - a particular group level. If both this field and HEADER are zero, then - they aren't grouped at all, but rather merged with the parent options - (merging the child's grouping levels with the parents). */ - int group; -}; - -/* Parsing state. This is provided to parsing functions called by argp, - which may examine and, as noted, modify fields. */ -struct argp_state -{ - /* The top level ARGP being parsed. */ - __const struct argp *root_argp; - - /* The argument vector being parsed. May be modified. */ - int argc; - char **argv; - - /* The index in ARGV of the next arg that to be parsed. May be modified. */ - int next; - - /* The flags supplied to argp_parse. May be modified. */ - unsigned flags; - - /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the - number of the current arg, starting at zero, and incremented after each - such call returns. At all other times, this is the number of such - arguments that have been processed. */ - unsigned arg_num; - - /* If non-zero, the index in ARGV of the first argument following a special - `--' argument (which prevents anything following being interpreted as an - option). Only set once argument parsing has proceeded past this point. */ - int quoted; - - /* An arbitrary pointer passed in from the user. */ - void *input; - /* Values to pass to child parsers. This vector will be the same length as - the number of children for the current parser. */ - void **child_inputs; - - /* For the parser's use. Initialized to 0. */ - void *hook; - - /* The name used when printing messages. This is initialized to ARGV[0], - or PROGRAM_INVOCATION_NAME if that is unavailable. */ - char *name; - - /* Streams used when argp prints something. */ - FILE *err_stream; /* For errors; initialized to stderr. */ - FILE *out_stream; /* For information; initialized to stdout. */ - - void *pstate; /* Private, for use by argp. */ -}; - -/* Flags for argp_parse (note that the defaults are those that are - convenient for program command line parsing): */ - -/* Don't ignore the first element of ARGV. Normally (and always unless - ARGP_NO_ERRS is set) the first element of the argument vector is - skipped for option parsing purposes, as it corresponds to the program name - in a command line. */ -#define ARGP_PARSE_ARGV0 0x01 - -/* Don't print error messages for unknown options to stderr; unless this flag - is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program - name in the error messages. This flag implies ARGP_NO_EXIT (on the - assumption that silent exiting upon errors is bad behaviour). */ -#define ARGP_NO_ERRS 0x02 - -/* Don't parse any non-option args. Normally non-option args are parsed by - calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg - as the value. Since it's impossible to know which parse function wants to - handle it, each one is called in turn, until one returns 0 or an error - other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the - argp_parse returns prematurely (but with a return value of 0). If all - args have been parsed without error, all parsing functions are called one - last time with a key of ARGP_KEY_END. This flag needn't normally be set, - as the normal behavior is to stop parsing as soon as some argument can't - be handled. */ -#define ARGP_NO_ARGS 0x04 - -/* Parse options and arguments in the same order they occur on the command - line -- normally they're rearranged so that all options come first. */ -#define ARGP_IN_ORDER 0x08 - -/* Don't provide the standard long option --help, which causes usage and - option help information to be output to stdout, and exit (0) called. */ -#define ARGP_NO_HELP 0x10 - -/* Don't exit on errors (they may still result in error messages). */ -#define ARGP_NO_EXIT 0x20 - -/* Use the gnu getopt `long-only' rules for parsing arguments. */ -#define ARGP_LONG_ONLY 0x40 - -/* Turns off any message-printing/exiting options. */ -#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP) - -/* Parse the options strings in ARGC & ARGV according to the options in ARGP. - FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the - index in ARGV of the first unparsed option is returned in it. If an - unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser - routine returned a non-zero value, it is returned; otherwise 0 is - returned. This function may also call exit unless the ARGP_NO_HELP flag - is set. INPUT is a pointer to a value to be passed in to the parser. */ -extern error_t argp_parse (__const struct argp *__restrict argp, - int argc, char **__restrict argv, - unsigned flags, int *__restrict arg_index, - void *__restrict input) __THROW; -extern error_t __argp_parse (__const struct argp *__restrict argp, - int argc, char **__restrict argv, - unsigned flags, int *__restrict arg_index, - void *__restrict input) __THROW; - -/* Global variables. */ - -/* If defined or set by the user program to a non-zero value, then a default - option --version is added (unless the ARGP_NO_HELP flag is used), which - will print this string followed by a newline and exit (unless the - ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ -extern __const char *argp_program_version; - -/* If defined or set by the user program to a non-zero value, then a default - option --version is added (unless the ARGP_NO_HELP flag is used), which - calls this function with a stream to print the version to and a pointer to - the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is - used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ -extern void (*argp_program_version_hook) (FILE *__restrict __stream, - struct argp_state *__restrict - __state); - -/* If defined or set by the user program, it should point to string that is - the bug-reporting address for the program. It will be printed by - argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various - standard help messages), embedded in a sentence that says something like - `Report bugs to ADDR.'. */ -extern __const char *argp_program_bug_address; - -/* The exit status that argp will use when exiting due to a parsing error. - If not defined or set by the user program, this defaults to EX_USAGE from - <sysexits.h>. */ -extern error_t argp_err_exit_status; - -/* Flags for argp_help. */ -#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ -#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ -#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */ -#define ARGP_HELP_LONG 0x08 /* a long help message. */ -#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ -#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ -#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) -#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ -#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to - reflect ARGP_LONG_ONLY mode. */ - -/* These ARGP_HELP flags are only understood by argp_state_help. */ -#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ -#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ - -/* The standard thing to do after a program command line parsing error, if an - error message has already been printed. */ -#define ARGP_HELP_STD_ERR \ - (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) -/* The standard thing to do after a program command line parsing error, if no - more specific error message has been printed. */ -#define ARGP_HELP_STD_USAGE \ - (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) -/* The standard thing to do in response to a --help option. */ -#define ARGP_HELP_STD_HELP \ - (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \ - | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) - -/* Output a usage message for ARGP to STREAM. FLAGS are from the set - ARGP_HELP_*. */ -extern void argp_help (__const struct argp *__restrict __argp, - FILE *__restrict __stream, - unsigned __flags, char *__restrict __name) __THROW; -extern void __argp_help (__const struct argp *__restrict __argp, - FILE *__restrict __stream, unsigned __flags, - char *__name) __THROW; - -/* The following routines are intended to be called from within an argp - parsing routine (thus taking an argp_state structure as the first - argument). They may or may not print an error message and exit, depending - on the flags in STATE -- in any case, the caller should be prepared for - them *not* to exit, and should return an appropiate error after calling - them. [argp_usage & argp_error should probably be called argp_state_..., - but they're used often enough that they should be short] */ - -/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are - from the set ARGP_HELP_*. */ -extern void argp_state_help (__const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags) __THROW; -extern void __argp_state_help (__const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags) __THROW; - -/* Possibly output the standard usage message for ARGP to stderr and exit. */ -extern void argp_usage (__const struct argp_state *__state) __THROW; -extern void __argp_usage (__const struct argp_state *__state) __THROW; - -/* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' - message, then exit (1). */ -extern void argp_error (__const struct argp_state *__restrict __state, - __const char *__restrict __fmt, ...) __THROW - PRINTF_STYLE(2,3); -extern void __argp_error (__const struct argp_state *__restrict __state, - __const char *__restrict __fmt, ...) __THROW - PRINTF_STYLE(2,3); - -/* Similar to the standard gnu error-reporting function error(), but will - respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print - to STATE->err_stream. This is useful for argument parsing code that is - shared between program startup (when exiting is desired) and runtime - option parsing (when typically an error code is returned instead). The - difference between this function and argp_error is that the latter is for - *parsing errors*, and the former is for other problems that occur during - parsing but don't reflect a (syntactic) problem with the input. */ -extern void argp_failure (__const struct argp_state *__restrict __state, - int __status, int __errnum, - __const char *__restrict __fmt, ...) __THROW - PRINTF_STYLE(4,5); -extern void __argp_failure (__const struct argp_state *__restrict __state, - int __status, int __errnum, - __const char *__restrict __fmt, ...) __THROW - PRINTF_STYLE(4,5); - -/* Returns true if the option OPT is a valid short option. */ -extern int _option_is_short (__const struct argp_option *__opt) __THROW; -extern int __option_is_short (__const struct argp_option *__opt) __THROW; - -/* Returns true if the option OPT is in fact the last (unused) entry in an - options array. */ -extern int _option_is_end (__const struct argp_option *__opt) __THROW; -extern int __option_is_end (__const struct argp_option *__opt) __THROW; - -/* Return the input field for ARGP in the parser corresponding to STATE; used - by the help routines. */ -extern void *_argp_input (__const struct argp *__restrict __argp, - __const struct argp_state *__restrict __state) - __THROW; -extern void *__argp_input (__const struct argp *__restrict __argp, - __const struct argp_state *__restrict __state) - __THROW; - -/* Used for extracting the program name from argv[0] */ -extern char *_argp_basename(char *name) __THROW; -extern char *__argp_basename(char *name) __THROW; - -/* Getting the program name given an argp state */ -extern char * -_argp_short_program_name(const struct argp_state *state) __THROW; -extern char * -__argp_short_program_name(const struct argp_state *state) __THROW; - - -#ifdef __USE_EXTERN_INLINES - -# if !_LIBC -# define __argp_usage argp_usage -# define __argp_state_help argp_state_help -# define __option_is_short _option_is_short -# define __option_is_end _option_is_end -# endif - -# ifndef ARGP_EI -# define ARGP_EI extern __inline__ -# endif - -ARGP_EI void -__argp_usage (__const struct argp_state *__state) -{ - __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); -} - -ARGP_EI int -__option_is_short (__const struct argp_option *__opt) -{ - if (__opt->flags & OPTION_DOC) - return 0; - else - { - int __key = __opt->key; - return __key > 0 && isprint (__key); - } -} - -ARGP_EI int -__option_is_end (__const struct argp_option *__opt) -{ - return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; -} - -# if !_LIBC -# undef __argp_usage -# undef __argp_state_help -# undef __option_is_short -# undef __option_is_end -# endif -#endif /* Use extern inlines. */ - -#ifdef __cplusplus -} -#endif - -#endif /* argp.h */ diff --git a/contrib/argp-standalone/autogen.sh b/contrib/argp-standalone/autogen.sh deleted file mode 100755 index 8337353b5ae..00000000000 --- a/contrib/argp-standalone/autogen.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -aclocal -I . -autoheader -autoconf -automake --add-missing --copy --foreign diff --git a/contrib/argp-standalone/configure.ac b/contrib/argp-standalone/configure.ac deleted file mode 100644 index c0867eb5b35..00000000000 --- a/contrib/argp-standalone/configure.ac +++ /dev/null @@ -1,105 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. - -dnl This configure.ac is only for building a standalone argp library. -AC_INIT([argp], [standalone-1.3]) -AC_PREREQ(2.54) -AC_CONFIG_SRCDIR([argp-ba.c]) -# Needed to stop autoconf from looking for files in parent directories. -AC_CONFIG_AUX_DIR([.]) - -AM_INIT_AUTOMAKE -AC_CONFIG_HEADERS(config.h) - -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)]) - -# GNU libc defaults to supplying the ISO C library functions only. The -# _GNU_SOURCE define enables these extensions, in particular we want -# errno.h to declare program_invocation_name. Enable it on all -# systems; no problems have been reported with it so far. -AC_GNU_SOURCE - -# Checks for programs. -AC_PROG_CC -AC_PROG_MAKE_SET -AC_PROG_RANLIB -AC_PROG_CC - -if test "x$am_cv_prog_cc_stdc" = xno ; then - AC_ERROR([the C compiler doesn't handle ANSI-C]) -fi - -# Checks for libraries. - -# Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(libintl.h limits.h malloc.h unistd.h sysexits.h stdarg.h) - -# Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_INLINE -AC_TYPE_SIZE_T - -LSH_GCC_ATTRIBUTES - -# Checks for library functions. -AC_FUNC_ALLOCA -AC_FUNC_VPRINTF -AC_CHECK_FUNCS(strerror sleep getpid snprintf) - -AC_REPLACE_FUNCS(mempcpy strndup strchrnul strcasecmp vsnprintf) - -dnl ARGP_CHECK_FUNC(includes, function-call [, if-found [, if-not-found]]) -AC_DEFUN([ARGP_CHECK_FUNC], - [AS_VAR_PUSHDEF([ac_func], m4_substr([$2], 0, m4_index([$2], [(]))) - AS_VAR_PUSHDEF([ac_var], [ac_cv_func_call_]ac_func) - AH_TEMPLATE(AS_TR_CPP(HAVE_[]ac_func), - [Define to 1 if you have the `]ac_func[' function.]) - AC_CACHE_CHECK([for $2], ac_var, - [AC_TRY_LINK([$1], [$2], - [AS_VAR_SET(ac_var, yes)], - [AS_VAR_SET(ac_var, no)])]) - if test AS_VAR_GET(ac_var) = yes ; then - ifelse([$3],, - [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]ac_func))], - [$3 -]) - else - ifelse([$4],, true, [$4]) - fi - AS_VAR_POPDEF([ac_var]) - AS_VAR_POPDEF([ac_func]) - ]) - -# At least on freebsd, putc_unlocked is a macro, so the standard -# AC_CHECK_FUNCS doesn't work well. -ARGP_CHECK_FUNC([#include <stdio.h>], [putc_unlocked('x', stdout)]) - -AC_CHECK_FUNCS(flockfile) -AC_CHECK_FUNCS(fputs_unlocked fwrite_unlocked) - -# Used only by argp-test.c, so don't use AC_REPLACE_FUNCS. -AC_CHECK_FUNCS(strdup asprintf) - -AC_CHECK_DECLS([program_invocation_name, program_invocation_short_name], - [], [], [[#include <errno.h>]]) - -# Set these flags *last*, or else the test programs won't compile -if test x$GCC = xyes ; then - # Using -ggdb3 makes (some versions of) Redhat's gcc-2.96 dump core - if "$CC" --version | grep '^2\.96$' 1>/dev/null 2>&1; then - true - else - CFLAGS="$CFLAGS -ggdb3" - fi - CFLAGS="$CFLAGS -Wall -W \ - -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes \ - -Waggregate-return \ - -Wpointer-arith -Wbad-function-cast -Wnested-externs" -fi - -CPPFLAGS="$CPPFLAGS -I$srcdir" - -dnl Added for C99 standards -CFLAGS="$CFLAGS -std=gnu89 -static" - -AC_OUTPUT(Makefile) diff --git a/contrib/argp-standalone/mempcpy.c b/contrib/argp-standalone/mempcpy.c deleted file mode 100644 index 21d8bd2ed94..00000000000 --- a/contrib/argp-standalone/mempcpy.c +++ /dev/null @@ -1,21 +0,0 @@ -/* strndup.c - * - */ - -/* Written by Niels Möller <nisse@lysator.liu.se> - * - * This file is hereby placed in the public domain. - */ - -#include <string.h> - -void * -mempcpy (void *, const void *, size_t) ; - -void * -mempcpy (void *to, const void *from, size_t size) -{ - memcpy(to, from, size); - return (char *) to + size; -} - diff --git a/contrib/argp-standalone/strcasecmp.c b/contrib/argp-standalone/strcasecmp.c deleted file mode 100644 index 9c1637232fd..00000000000 --- a/contrib/argp-standalone/strcasecmp.c +++ /dev/null @@ -1,29 +0,0 @@ -/* strcasecmp.c - * - */ - -/* Written by Niels Möller <nisse@lysator.liu.se> - * - * This file is hereby placed in the public domain. - */ - -#include <ctype.h> -int strcasecmp(const char *, const char *); - -int strcasecmp(const char *s1, const char *s2) -{ - unsigned i; - - for (i = 0; s1[i] && s2[i]; i++) - { - unsigned char c1 = tolower( (unsigned char) s1[i]); - unsigned char c2 = tolower( (unsigned char) s2[i]); - - if (c1 < c2) - return -1; - else if (c1 > c2) - return 1; - } - - return !s2[i] - !s1[i]; -} diff --git a/contrib/argp-standalone/strchrnul.c b/contrib/argp-standalone/strchrnul.c deleted file mode 100644 index ee4145e4eda..00000000000 --- a/contrib/argp-standalone/strchrnul.c +++ /dev/null @@ -1,23 +0,0 @@ -/* strchrnul.c - * - */ - -/* Written by Niels Möller <nisse@lysator.liu.se> - * - * This file is hereby placed in the public domain. - */ - -/* FIXME: What is this function supposed to do? My guess is that it is - * like strchr, but returns a pointer to the NUL character, not a NULL - * pointer, if the character isn't found. */ - -char *strchrnul(const char *, int ); - -char *strchrnul(const char *s, int c) -{ - const char *p = s; - while (*p && (*p != c)) - p++; - - return (char *) p; -} diff --git a/contrib/argp-standalone/strndup.c b/contrib/argp-standalone/strndup.c deleted file mode 100644 index 4147b7a2051..00000000000 --- a/contrib/argp-standalone/strndup.c +++ /dev/null @@ -1,34 +0,0 @@ -/* strndup.c - * - */ - -/* Written by Niels Möller <nisse@lysator.liu.se> - * - * This file is hereby placed in the public domain. - */ - -#include <stdlib.h> -#include <string.h> - -char * -strndup (const char *, size_t); - -char * -strndup (const char *s, size_t size) -{ - char *r; - char *end = memchr(s, 0, size); - - if (end) - /* Length + 1 */ - size = end - s + 1; - - r = malloc(size); - - if (size) - { - memcpy(r, s, size-1); - r[size-1] = '\0'; - } - return r; -} diff --git a/contrib/argp-standalone/vsnprintf.c b/contrib/argp-standalone/vsnprintf.c deleted file mode 100644 index 33c9a5d0042..00000000000 --- a/contrib/argp-standalone/vsnprintf.c +++ /dev/null @@ -1,839 +0,0 @@ -/* Copied from http://www.fiction.net/blong/programs/snprintf.c */ - -/* - * Copyright Patrick Powell 1995 - * This code is based on code written by Patrick Powell (papowell@astart.com) - * It may be used for any purpose as long as this notice remains intact - * on all source code distributions - */ - -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - * - * More Recently: - * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 - * This was ugly. It is still ugly. I opted out of floating point - * numbers, but the formatter understands just about everything - * from the normal C string format, at least as far as I can tell from - * the Solaris 2.5 printf(3S) man page. - * - * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 - * Ok, added some minimal floating point support, which means this - * probably requires libm on most operating systems. Don't yet - * support the exponent (e,E) and sigfig (g,G). Also, fmtint() - * was pretty badly broken, it just wasn't being exercised in ways - * which showed it, so that's been fixed. Also, formated the code - * to mutt conventions, and removed dead code left over from the - * original. Also, there is now a builtin-test, just compile with: - * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm - * and run snprintf for results. - * - * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i - * The PGP code was using unsigned hexadecimal formats. - * Unfortunately, unsigned formats simply didn't work. - * - * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 - * The original code assumed that both snprintf() and vsnprintf() were - * missing. Some systems only have snprintf() but not vsnprintf(), so - * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. - * - * Andrew Tridgell (tridge@samba.org) Oct 1998 - * fixed handling of %.0f - * added test for HAVE_LONG_DOUBLE - * - * Russ Allbery <rra@stanford.edu> 2000-08-26 - * fixed return value to comply with C99 - * fixed handling of snprintf(NULL, ...) - * - * Niels Möller <nisse@lysator.liu.se> 2004-03-05 - * fixed calls to isdigit to use unsigned char. - * fixed calls to va_arg; short arguments are always passed as int. - * - **************************************************************/ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -#include <string.h> -#include <ctype.h> -#include <sys/types.h> - -/* Define this as a fall through, HAVE_STDARG_H is probably already set */ - -#define HAVE_VARARGS_H - - -/* varargs declarations: */ - -#if defined(HAVE_STDARG_H) -# include <stdarg.h> -# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap, f) -# define VA_SHIFT(v,t) ; /* no-op for ANSI */ -# define VA_END va_end(ap) -#else -# if defined(HAVE_VARARGS_H) -# include <varargs.h> -# undef HAVE_STDARGS -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap) /* f is ignored! */ -# define VA_SHIFT(v,t) v = va_arg(ap,t) -# define VA_END va_end(ap) -# else -/*XX ** NO VARARGS ** XX*/ -# endif -#endif - -#ifdef HAVE_LONG_DOUBLE -#define LDOUBLE long double -#else -#define LDOUBLE double -#endif - -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); - -static int dopr (char *buffer, size_t maxlen, const char *format, - va_list args); -static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max); -static int fmtint (char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags); -static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags); -static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); - -/* - * dopr(): poor man's version of doprintf - */ - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) - -/* Conversion Flags */ -#define DP_C_SHORT 1 -#define DP_C_LONG 2 -#define DP_C_LDOUBLE 3 - -#define char_to_int(p) (p - '0') -#define MAX(p,q) ((p >= q) ? p : q) -#define MIN(p,q) ((p <= q) ? p : q) - -static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) -{ - unsigned char ch; - long value; - LDOUBLE fvalue; - char *strvalue; - int min; - int max; - int state; - int flags; - int cflags; - int total; - size_t currlen; - - state = DP_S_DEFAULT; - currlen = flags = cflags = min = 0; - max = -1; - ch = *format++; - total = 0; - - while (state != DP_S_DONE) - { - if (ch == '\0') - state = DP_S_DONE; - - switch(state) - { - case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - total += dopr_outch (buffer, &currlen, maxlen, ch); - ch = *format++; - break; - case DP_S_FLAGS: - switch (ch) - { - case '-': - flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - flags |= DP_F_ZERO; - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (isdigit(ch)) - { - min = 10*min + char_to_int (ch); - ch = *format++; - } - else if (ch == '*') - { - min = va_arg (args, int); - ch = *format++; - state = DP_S_DOT; - } - else - state = DP_S_DOT; - break; - case DP_S_DOT: - if (ch == '.') - { - state = DP_S_MAX; - ch = *format++; - } - else - state = DP_S_MOD; - break; - case DP_S_MAX: - if (isdigit(ch)) - { - if (max < 0) - max = 0; - max = 10*max + char_to_int (ch); - ch = *format++; - } - else if (ch == '*') - { - max = va_arg (args, int); - ch = *format++; - state = DP_S_MOD; - } - else - state = DP_S_MOD; - break; - case DP_S_MOD: - /* Currently, we don't support Long Long, bummer */ - switch (ch) - { - case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; - case 'l': - cflags = DP_C_LONG; - ch = *format++; - break; - case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - switch (ch) - { - case 'd': - case 'i': - if (cflags == DP_C_SHORT) - value = (short) va_arg (args, int); - else if (cflags == DP_C_LONG) - value = va_arg (args, long int); - else - value = va_arg (args, int); - total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'o': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = (unsigned short) va_arg (args, unsigned); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); - break; - case 'u': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = (unsigned short) va_arg (args, unsigned); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'X': - flags |= DP_F_UP; - case 'x': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = (unsigned short) va_arg (args, unsigned); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); - break; - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - /* um, floating point? */ - total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'E': - flags |= DP_F_UP; - case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - break; - case 'G': - flags |= DP_F_UP; - case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - break; - case 'c': - total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); - break; - case 's': - strvalue = va_arg (args, char *); - total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); - break; - case 'p': - strvalue = va_arg (args, void *); - total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, - max, flags); - break; - case 'n': - if (cflags == DP_C_SHORT) - { - short int *num; - num = va_arg (args, short int *); - *num = currlen; - } - else if (cflags == DP_C_LONG) - { - long int *num; - num = va_arg (args, long int *); - *num = currlen; - } - else - { - int *num; - num = va_arg (args, int *); - *num = currlen; - } - break; - case '%': - total += dopr_outch (buffer, &currlen, maxlen, ch); - break; - case 'w': - /* not supported yet, treat as next char */ - ch = *format++; - break; - default: - /* Unknown, skip */ - break; - } - ch = *format++; - state = DP_S_DEFAULT; - flags = cflags = min = 0; - max = -1; - break; - case DP_S_DONE: - break; - default: - /* hmm? */ - break; /* some picky compilers need this */ - } - } - if (buffer != NULL) - { - if (currlen < maxlen - 1) - buffer[currlen] = '\0'; - else - buffer[maxlen - 1] = '\0'; - } - return total; -} - -static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) -{ - int padlen, strln; /* amount to pad */ - int cnt = 0; - int total = 0; - - if (value == 0) - { - value = "<NULL>"; - } - - for (strln = 0; value[strln]; ++strln); /* strlen */ - if (max >= 0 && max < strln) - strln = max; - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justify */ - - while (padlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - while (*value && ((max < 0) || (cnt < max))) - { - total += dopr_outch (buffer, currlen, maxlen, *value++); - ++cnt; - } - while (padlen < 0) - { - total += dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } - return total; -} - -/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ - -static int fmtint (char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags) -{ - int signvalue = 0; - unsigned long uvalue; - char convert[20]; - int place = 0; - int spadlen = 0; /* amount to space pad */ - int zpadlen = 0; /* amount to zero pad */ - int caps = 0; - int total = 0; - - if (max < 0) - max = 0; - - uvalue = value; - - if(!(flags & DP_F_UNSIGNED)) - { - if( value < 0 ) { - signvalue = '-'; - uvalue = -value; - } - else - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else - if (flags & DP_F_SPACE) - signvalue = ' '; - } - - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ - - do { - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); - } while(uvalue && (place < 20)); - if (place == 20) place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); - if (zpadlen < 0) zpadlen = 0; - if (spadlen < 0) spadlen = 0; - if (flags & DP_F_ZERO) - { - zpadlen = MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ - -#ifdef DEBUG_SNPRINTF - dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", - zpadlen, spadlen, min, max, place)); -#endif - - /* Spaces */ - while (spadlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* Sign */ - if (signvalue) - total += dopr_outch (buffer, currlen, maxlen, signvalue); - - /* Zeros */ - if (zpadlen > 0) - { - while (zpadlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - - /* Digits */ - while (place > 0) - total += dopr_outch (buffer, currlen, maxlen, convert[--place]); - - /* Left Justified spaces */ - while (spadlen < 0) { - total += dopr_outch (buffer, currlen, maxlen, ' '); - ++spadlen; - } - - return total; -} - -static LDOUBLE abs_val (LDOUBLE value) -{ - LDOUBLE result = value; - - if (value < 0) - result = -value; - - return result; -} - -static LDOUBLE pow10_argp (int exp) -{ - LDOUBLE result = 1; - - while (exp) - { - result *= 10; - exp--; - } - - return result; -} - -static long round_argp (LDOUBLE value) -{ - long intpart; - - intpart = value; - value = value - intpart; - if (value >= 0.5) - intpart++; - - return intpart; -} - -static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags) -{ - int signvalue = 0; - LDOUBLE ufvalue; - char iconvert[20]; - char fconvert[20]; - int iplace = 0; - int fplace = 0; - int padlen = 0; /* amount to pad */ - int zpadlen = 0; - int caps = 0; - int total = 0; - long intpart; - long fracpart; - - /* - * AIX manpage says the default is 0, but Solaris says the default - * is 6, and sprintf on AIX defaults to 6 - */ - if (max < 0) - max = 6; - - ufvalue = abs_val (fvalue); - - if (fvalue < 0) - signvalue = '-'; - else - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else - if (flags & DP_F_SPACE) - signvalue = ' '; - -#if 0 - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ -#endif - - intpart = ufvalue; - - /* - * Sorry, we only support 9 digits past the decimal because of our - * conversion method - */ - if (max > 9) - max = 9; - - /* We "cheat" by converting the fractional part to integer by - * multiplying by a factor of 10 - */ - fracpart = round_argp ((pow10_argp (max)) * (ufvalue - intpart)); - - if (fracpart >= pow10_argp (max)) - { - intpart++; - fracpart -= pow10_argp (max); - } - -#ifdef DEBUG_SNPRINTF - dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); -#endif - - /* Convert integer part */ - do { - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; - intpart = (intpart / 10); - } while(intpart && (iplace < 20)); - if (iplace == 20) iplace--; - iconvert[iplace] = 0; - - /* Convert fractional part */ - do { - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; - fracpart = (fracpart / 10); - } while(fracpart && (fplace < 20)); - if (fplace == 20) fplace--; - fconvert[fplace] = 0; - - /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; - if (zpadlen < 0) - zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ - - if ((flags & DP_F_ZERO) && (padlen > 0)) - { - if (signvalue) - { - total += dopr_outch (buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - total += dopr_outch (buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - if (max > 0) - { - total += dopr_outch (buffer, currlen, maxlen, '.'); - - while (fplace > 0) - total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); - } - - while (zpadlen > 0) - { - total += dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (padlen < 0) - { - total += dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } - - return total; -} - -static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) -{ - if (*currlen + 1 < maxlen) - buffer[(*currlen)++] = c; - return 1; -} - -#ifndef HAVE_VSNPRINTF -int vsnprintf (char *str, size_t count, const char *fmt, va_list args) -{ - if (str != NULL) - str[0] = 0; - return dopr(str, count, fmt, args); -} -#endif /* !HAVE_VSNPRINTF */ - -#ifndef HAVE_SNPRINTF -/* VARARGS3 */ -#ifdef HAVE_STDARGS -int snprintf (char *str,size_t count,const char *fmt,...) -#else -int snprintf (va_alist) va_dcl -#endif -{ -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - VA_LOCAL_DECL; - int total; - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - total = vsnprintf(str, count, fmt, ap); - VA_END; - return total; -} -#endif /* !HAVE_SNPRINTF */ - -#ifdef TEST_SNPRINTF -#ifndef LONG_STRING -#define LONG_STRING 1024 -#endif -int main (void) -{ - char buf1[LONG_STRING]; - char buf2[LONG_STRING]; - char *fp_fmt[] = { - "%-1.5f", - "%1.5f", - "%123.9f", - "%10.5f", - "% 10.5f", - "%+22.9f", - "%+4.9f", - "%01.3f", - "%4f", - "%3.1f", - "%3.2f", - "%.0f", - "%.1f", - NULL - }; - double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 0}; - char *int_fmt[] = { - "%-1.5d", - "%1.5d", - "%123.9d", - "%5.5d", - "%10.5d", - "% 10.5d", - "%+22.33d", - "%01.3d", - "%4d", - NULL - }; - long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; - int x, y; - int fail = 0; - int num = 0; - - printf ("Testing snprintf format codes against system sprintf...\n"); - - for (x = 0; fp_fmt[x] != NULL ; x++) - for (y = 0; fp_nums[y] != 0 ; y++) - { - snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); - if (strcmp (buf1, buf2)) - { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - fp_fmt[x], buf1, buf2); - fail++; - } - num++; - } - - for (x = 0; int_fmt[x] != NULL ; x++) - for (y = 0; int_nums[y] != 0 ; y++) - { - snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); - sprintf (buf2, int_fmt[x], int_nums[y]); - if (strcmp (buf1, buf2)) - { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - int_fmt[x], buf1, buf2); - fail++; - } - num++; - } - printf ("%d tests failed out of %d.\n", fail, num); -} -#endif /* SNPRINTF_TEST */ - -#endif /* !HAVE_SNPRINTF */ diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h index 9358ac810e1..7d28462de47 100644 --- a/contrib/fuse-include/fuse-mount.h +++ b/contrib/fuse-include/fuse-mount.h @@ -8,6 +8,6 @@ */ void gf_fuse_unmount (const char *mountpoint, int fd); -int gf_fuse_mount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, +int gf_fuse_unmount_daemon (const char *mountpoint, int fd); +int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mtab_pid, int status_fd); diff --git a/contrib/fuse-include/fuse_kernel.h b/contrib/fuse-include/fuse_kernel.h index 60bb2f9f7b7..1e41e237e6f 100644 --- a/contrib/fuse-include/fuse_kernel.h +++ b/contrib/fuse-include/fuse_kernel.h @@ -93,6 +93,18 @@ * * 7.22 * - add FUSE_ASYNC_DIO + * + * 7.23 + * - add FUSE_WRITEBACK_CACHE + * - add time_gran to fuse_init_out + * - add reserved space to fuse_init_out + * - add FATTR_CTIME + * - add ctime and ctimensec to fuse_setattr_in + * - add FUSE_RENAME2 request + * - add FUSE_NO_OPEN_SUPPORT flag + * + * 7.24 + * - add FUSE_LSEEK for SEEK_HOLE and SEEK_DATA support */ #ifndef _LINUX_FUSE_H @@ -128,7 +140,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 22 +#define FUSE_KERNEL_MINOR_VERSION 24 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -188,6 +200,7 @@ struct fuse_file_lock { #define FATTR_ATIME_NOW (1 << 7) #define FATTR_MTIME_NOW (1 << 8) #define FATTR_LOCKOWNER (1 << 9) +#define FATTR_CTIME (1 << 10) /** * Flags returned by the OPEN request @@ -219,6 +232,8 @@ struct fuse_file_lock { * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one) * FUSE_READDIRPLUS_AUTO: adaptive readdirplus * FUSE_ASYNC_DIO: asynchronous direct I/O submission + * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes + * FUSE_NO_OPEN_SUPPORT: kernel supports zero-message opens */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -236,6 +251,8 @@ struct fuse_file_lock { #define FUSE_DO_READDIRPLUS (1 << 13) #define FUSE_READDIRPLUS_AUTO (1 << 14) #define FUSE_ASYNC_DIO (1 << 15) +#define FUSE_WRITEBACK_CACHE (1 << 16) +#define FUSE_NO_OPEN_SUPPORT (1 << 17) /** * CUSE INIT request/reply flags @@ -343,6 +360,8 @@ enum fuse_opcode { FUSE_BATCH_FORGET = 42, FUSE_FALLOCATE = 43, FUSE_READDIRPLUS = 44, + FUSE_RENAME2 = 45, + FUSE_LSEEK = 46, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -421,6 +440,12 @@ struct fuse_rename_in { uint64_t newdir; }; +struct fuse_rename2_in { + uint64_t newdir; + uint32_t flags; + uint32_t padding; +}; + struct fuse_link_in { uint64_t oldnodeid; }; @@ -433,10 +458,10 @@ struct fuse_setattr_in { uint64_t lock_owner; uint64_t atime; uint64_t mtime; - uint64_t unused2; + uint64_t ctime; uint32_t atimensec; uint32_t mtimensec; - uint32_t unused3; + uint32_t ctimensec; uint32_t mode; uint32_t unused4; uint32_t uid; @@ -554,6 +579,9 @@ struct fuse_init_in { uint32_t flags; }; +#define FUSE_COMPAT_INIT_OUT_SIZE 8 +#define FUSE_COMPAT_22_INIT_OUT_SIZE 24 + struct fuse_init_out { uint32_t major; uint32_t minor; @@ -562,6 +590,8 @@ struct fuse_init_out { uint16_t max_background; uint16_t congestion_threshold; uint32_t max_write; + uint32_t time_gran; + uint32_t unused[9]; }; #define CUSE_INIT_INFO_MAX 4096 @@ -729,4 +759,15 @@ struct fuse_notify_retrieve_in { uint64_t dummy4; }; +struct fuse_lseek_in { + uint64_t fh; + uint64_t offset; + int32_t whence; + uint32_t padding; +}; + +struct fuse_lseek_out { + uint64_t offset; +}; + #endif /* _LINUX_FUSE_H */ diff --git a/contrib/fuse-lib/misc.c b/contrib/fuse-lib/misc.c index 0c41b1a1917..1a9b418e511 100644 --- a/contrib/fuse-lib/misc.c +++ b/contrib/fuse-lib/misc.c @@ -10,7 +10,7 @@ #include <string.h> #include <limits.h> #include <fcntl.h> -#include "glusterfs.h" +#include "glusterfs/glusterfs.h" #include "fuse_kernel.h" #include "fuse-misc.h" @@ -41,7 +41,6 @@ void convert_fuse_file_lock (struct fuse_file_lock *fl, struct gf_flock *flock, uint64_t lk_owner) { - memset (flock, 0, sizeof (struct flock)); flock->l_type = fl->type; flock->l_whence = SEEK_SET; flock->l_start = fl->start; diff --git a/contrib/fuse-lib/mount-common.c b/contrib/fuse-lib/mount-common.c index c436cb16a5c..cffd4c01ed5 100644 --- a/contrib/fuse-lib/mount-common.c +++ b/contrib/fuse-lib/mount-common.c @@ -32,7 +32,7 @@ mtab_needs_update (const char *mnt) struct stat stbuf; /* If mtab is within new mount, don't touch it */ - if (strncmp (mnt, _PATH_MOUNTED, strlen (mnt)) == 0 && + if (strncmp (mnt, _PATH_MOUNTED, sizeof (_PATH_MOUNTED) - 1) == 0 && _PATH_MOUNTED[strlen (mnt)] == '/') return 0; @@ -105,7 +105,11 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, char *tmp; sigprocmask (SIG_SETMASK, &oldmask, NULL); - setuid (geteuid ()); + res = setuid (geteuid ()); + if (res != 0) { + GFFUSE_LOGERR ("%s: setuid: %s", progname, strerror (errno)); + exit (1); + } /* * hide in a directory, where mount isn't able to resolve @@ -245,18 +249,22 @@ fuse_mnt_umount (const char *progname, const char *abs_mnt, } if (res == 0) { sigprocmask (SIG_SETMASK, &oldmask, NULL); - setuid (geteuid ()); + res = setuid (geteuid ()); + if (res != 0) { + GFFUSE_LOGERR ("%s: setuid: %s", progname, strerror (errno)); + exit (1); + } #ifdef GF_LINUX_HOST_OS - execl ("/bin/umount", "/bin/umount", "-i", rel_mnt, + execl ("umount", "umount", "-i", rel_mnt, lazy ? "-l" : NULL, NULL); - GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s", + GFFUSE_LOGERR ("%s: failed to execute umount: %s", progname, strerror (errno)); #elif __NetBSD__ /* exitting the filesystem causes the umount */ exit (0); #else - execl ("/sbin/umount", "/sbin/umount", "-f", rel_mnt, NULL); - GFFUSE_LOGERR ("%s: failed to execute /sbin/umount: %s", + execl ("umount", "umount", "-f", rel_mnt, NULL); + GFFUSE_LOGERR ("%s: failed to execute umount: %s", progname, strerror (errno)); #endif /* GF_LINUX_HOST_OS */ exit (1); diff --git a/contrib/fuse-lib/mount-gluster-compat.h b/contrib/fuse-lib/mount-gluster-compat.h index 562f089dd1f..d3646d08d8e 100644 --- a/contrib/fuse-lib/mount-gluster-compat.h +++ b/contrib/fuse-lib/mount-gluster-compat.h @@ -30,17 +30,59 @@ #include <sys/wait.h> #include <sys/mount.h> +#ifdef GF_LINUX_HOST_OS +typedef unsigned long mount_flag_t; +#endif + #if defined(__NetBSD__) #include <perfuse.h> #define umount2(dir, flags) unmount(dir, ((flags) != 0) ? MNT_FORCE : 0) #define MS_RDONLY MNT_RDONLY +#define MS_NOSUID MNT_NOSUID +#define MS_NODEV MNT_NODEV +#define MS_NOATIME MNT_NOATIME +#define MS_NOEXEC MNT_NOEXEC +typedef int mount_flag_t; #endif #if defined(GF_DARWIN_HOST_OS) || defined(__FreeBSD__) #include <sys/param.h> #include <sys/mount.h> #define umount2(dir, flags) unmount(dir, ((flags) != 0) ? MNT_FORCE : 0) +#endif + +#if defined(__FreeBSD__) #define MS_RDONLY MNT_RDONLY +#define MS_NOSUID MNT_NOSUID +/* "nodev"/MNT_NODEV was removed from FreBSD, as it became unneeded because "As + * of FreeBSD 6.0 device nodes may be created in regular file systems but such + * nodes cannot be used to access devices." (See + * https://freebsd.org/cgi/man.cgi?query=mknod&sektion=8 . + * Also see: + * - https://github.com/freebsd/freebsd/commit/266790a + * - https://github.com/freebsd/freebsd/commit/a5e716d + * - 700008 in + * https://www.freebsd.org/doc/en/books/porters-handbook/versions-7.html .) + */ +#if __FreeBSD_version < 700008 +#define MS_NODEV MNT_NODEV +#else +#define MS_NODEV 0 +#endif +#define MS_NOATIME MNT_NOATIME +#define MS_NOEXEC MNT_NOEXEC +#if __FreeBSD_version < 1000715 +typedef int mount_flag_t; +#else +/* __FreeBSD_version was not bumped for this type change. Anyway, see + * https://github.com/freebsd/freebsd/commit/e8d76f8 + * and respective __FreeBSD_version: + * https://github.com/freebsd/freebsd/blob/e8d76f8/sys/sys/param.h#L61 . + * We use the subsequent value, 1000715, to switch. (Also see: + * https://www.freebsd.org/doc/en/books/porters-handbook/versions-10.html .) + */ +typedef long long mount_flag_t; +#endif #endif #ifdef GF_LINUX_HOST_OS @@ -54,9 +96,9 @@ #define FREE(ptr) free (ptr) #define GFFUSE_LOGERR(...) fprintf (stderr, ## __VA_ARGS__) #else /* FUSE_UTIL */ -#include "glusterfs.h" -#include "logging.h" -#include "common-utils.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/logging.h" +#include "glusterfs/common-utils.h" #define GFFUSE_LOGERR(...) \ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__) diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c index 1edde86014a..06ff191f542 100644 --- a/contrib/fuse-lib/mount.c +++ b/contrib/fuse-lib/mount.c @@ -52,12 +52,16 @@ gf_fuse_unmount (const char *mountpoint, int fd) if (geteuid () == 0) { fuse_mnt_umount ("fuse", mountpoint, mountpoint, 1); return; + } else { + GFFUSE_LOGERR ("fuse: Effective-uid: %d", geteuid()); } res = umount2 (mountpoint, 2); if (res == 0) return; + GFFUSE_LOGERR ("fuse: failed to unmount %s: %s", + mountpoint, strerror (errno)); pid = fork (); if (pid == -1) return; @@ -67,6 +71,8 @@ gf_fuse_unmount (const char *mountpoint, int fd) "--", mountpoint, NULL }; execvp (FUSERMOUNT_PROG, (char **)argv); + GFFUSE_LOGERR ("fuse: failed to execute fuserumount: %s", + strerror (errno)); _exit (1); } waitpid (pid, NULL, 0); @@ -75,6 +81,54 @@ gf_fuse_unmount (const char *mountpoint, int fd) /* gluster-specific routines */ +/* Unmounting in a daemon that lurks 'till main process exits */ +int +gf_fuse_unmount_daemon (const char *mountpoint, int fd) +{ + int ret = -1; + pid_t pid = -1; + + if (fd == -1) + return -1; + + int ump[2] = {0,}; + + ret = pipe(ump); + if (ret == -1) { + close (fd); + return -1; + } + + pid = fork (); + switch (pid) { + case 0: + { + char c = 0; + sigset_t sigset; + + close_fds_except (ump, 1); + + setsid(); + (void)chdir("/"); + sigfillset(&sigset); + sigprocmask(SIG_BLOCK, &sigset, NULL); + + read (ump[0], &c, 1); + + gf_fuse_unmount (mountpoint, fd); + exit (0); + } + case -1: + close (fd); + fd = -1; + ret = -1; + close (ump[1]); + } + close (ump[0]); + + return ret; +} + static char * escape (char *s) { @@ -106,8 +160,7 @@ escape (char *s) static int fuse_mount_fusermount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, - int fd) + char *mnt_param, int fd) { int pid = -1; int res = 0; @@ -130,8 +183,7 @@ fuse_mount_fusermount (const char *mountpoint, char *fsname, return -1; } ret = asprintf (&fm_mnt_params, - "%s%s,fsname=%s,nonempty,subtype=glusterfs", - (mountflags & MS_RDONLY) ? "ro," : "", + "%s,fsname=%s,nonempty,subtype=glusterfs", mnt_param, efsname); FREE (efsname); if (ret == -1) { @@ -224,19 +276,101 @@ build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, } #endif /* __FreeBSD__ */ +struct mount_flags { + const char *opt; + mount_flag_t flag; + int on; +} mount_flags[] = { + /* We provide best effort cross platform support for mount flags by + * defining the ones which are commonly used in Unix-like OS-es. + */ + {"ro", MS_RDONLY, 1}, + {"nosuid", MS_NOSUID, 1}, + {"nodev", MS_NODEV, 1}, + {"noatime", MS_NOATIME, 1}, + {"noexec", MS_NOEXEC, 1}, +#ifdef GF_LINUX_HOST_OS + {"rw", MS_RDONLY, 0}, + {"suid", MS_NOSUID, 0}, + {"dev", MS_NODEV, 0}, + {"exec", MS_NOEXEC, 0}, + {"async", MS_SYNCHRONOUS, 0}, + {"sync", MS_SYNCHRONOUS, 1}, + {"atime", MS_NOATIME, 0}, + {"dirsync", MS_DIRSYNC, 1}, +#endif + {NULL, 0, 0} +}; + +static int +mount_param_to_flag (char *mnt_param, mount_flag_t *mntflags, + char **mnt_param_new) +{ + gf_boolean_t found = _gf_false; + struct mount_flags *flag = NULL; + char *param_tok = NULL; + token_iter_t tit = {0,}; + gf_boolean_t iter_end = _gf_false; + + /* Allocate a buffer that will hold the mount parameters remaining + * after the ones corresponding to mount flags are processed and + * removed.The length of the original params are a good upper bound + * of the size needed. + */ + *mnt_param_new = strdup (mnt_param); + if (!*mnt_param_new) + return -1; + + for (param_tok = token_iter_init (*mnt_param_new, ',', &tit) ;;) { + iter_end = next_token (¶m_tok, &tit); + + found = _gf_false; + for (flag = mount_flags; flag->opt; flag++) { + /* Compare the mount flag name to the param + * name at hand. + */ + if (strcmp (flag->opt, param_tok) == 0) { + /* If there is a match, adjust mntflags + * accordingly and break. + */ + if (flag->on) { + *mntflags |= flag->flag; + } else { + *mntflags &= ~flag->flag; + } + found = _gf_true; + break; + } + } + /* Exclude flag names from new parameter list. */ + if (found) + drop_token (param_tok, &tit); + + if (iter_end) + break; + } + + return 0; +} + static int fuse_mount_sys (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, int fd) + char *mnt_param, int fd) { int ret = -1; unsigned mounted = 0; char *mnt_param_mnt = NULL; char *fstype = "fuse.glusterfs"; char *source = fsname; - - ret = asprintf (&mnt_param_mnt, - "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", - mnt_param, fd, S_IFDIR, getuid (), getgid ()); + mount_flag_t mountflags = 0; + char *mnt_param_new = NULL; + + ret = mount_param_to_flag (mnt_param, &mountflags, &mnt_param_new); + if (ret == 0) + ret = asprintf (&mnt_param_mnt, + "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", + mnt_param_new, fd, S_IFDIR, getuid (), + getgid ()); if (ret == -1) { GFFUSE_LOGERR ("Out of memory"); @@ -256,6 +390,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, build_iovec (&iov, &iovlen, "from", "/dev/fuse", -1); build_iovec (&iov, &iovlen, "volname", source, -1); build_iovec (&iov, &iovlen, "fd", fdstr, -1); + build_iovec (&iov, &iovlen, "allow_other", NULL, -1); ret = nmount (iov, iovlen, mountflags); #else ret = mount (source, mountpoint, fstype, mountflags, @@ -295,7 +430,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, ret = asprintf (&mnt_param_mtab, "%s%s", mountflags & MS_RDONLY ? "ro," : "", - mnt_param); + mnt_param_new); if (ret == -1) GFFUSE_LOGERR ("Out of memory"); else { @@ -320,6 +455,7 @@ out: umount2 (mountpoint, 2); /* lazy umount */ } FREE (mnt_param_mnt); + FREE (mnt_param_new); if (source != fsname) FREE (source); @@ -328,8 +464,7 @@ out: int gf_fuse_mount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, - pid_t *mnt_pid, int status_fd) + char *mnt_param, pid_t *mnt_pid, int status_fd) { int fd = -1; pid_t pid = -1; @@ -356,16 +491,19 @@ gf_fuse_mount (const char *mountpoint, char *fsname, exit (pid == -1 ? 1 : 0); } - ret = fuse_mount_sys (mountpoint, fsname, mountflags, mnt_param, - fd); + ret = fuse_mount_sys (mountpoint, fsname, mnt_param, fd); if (ret == -1) { gf_log ("glusterfs-fuse", GF_LOG_INFO, - "direct mount failed (%s) errno %d, " - "retry to mount via fusermount", + "direct mount failed (%s) errno %d", strerror (errno), errno); - ret = fuse_mount_fusermount (mountpoint, fsname, - mountflags, mnt_param, fd); + if (errno == EPERM) { + gf_log ("glusterfs-fuse", GF_LOG_INFO, + "retry to mount via fusermount"); + + ret = fuse_mount_fusermount (mountpoint, fsname, + mnt_param, fd); + } } if (ret == -1) diff --git a/contrib/fuse-util/fusermount.c b/contrib/fuse-util/fusermount.c index a64d8e102ff..ff743f75a21 100644 --- a/contrib/fuse-util/fusermount.c +++ b/contrib/fuse-util/fusermount.c @@ -520,20 +520,22 @@ static void parse_line(char *line, int linenum) static void read_conf(void) { + int len; FILE *fp = fopen(FUSE_CONF, "r"); if (fp != NULL) { int linenum = 1; char line[256]; int isnewline = 1; while (fgets(line, sizeof(line), fp) != NULL) { + len = strlen (line); if (isnewline) { - if (strlen(line) && line[strlen(line)-1] == '\n') { + if (len && line[len-1] == '\n') { strip_line(line); parse_line(line, linenum); } else { isnewline = 0; } - } else if(strlen(line) && line[strlen(line)-1] == '\n') { + } else if (len && line[len-1] == '\n') { fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum); isnewline = 1; diff --git a/contrib/ipaddr-py/COPYING b/contrib/ipaddr-py/COPYING deleted file mode 100644 index d6456956733..00000000000 --- a/contrib/ipaddr-py/COPYING +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/contrib/ipaddr-py/MANIFEST.in b/contrib/ipaddr-py/MANIFEST.in deleted file mode 100644 index f572804441b..00000000000 --- a/contrib/ipaddr-py/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include COPYING -include ipaddr_test.py -include RELEASENOTES diff --git a/contrib/ipaddr-py/OWNERS b/contrib/ipaddr-py/OWNERS deleted file mode 100644 index 501673e0395..00000000000 --- a/contrib/ipaddr-py/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -pmoody -harro -mshields -smart diff --git a/contrib/ipaddr-py/README b/contrib/ipaddr-py/README deleted file mode 100644 index 1b54294bb10..00000000000 --- a/contrib/ipaddr-py/README +++ /dev/null @@ -1,8 +0,0 @@ -ipaddr.py is a library for working with IP addresses, both IPv4 and IPv6. -It was developed by Google for internal use, and is now open source. - -Project home page: http://code.google.com/p/ipaddr-py/ - -Please send contributions to ipaddr-py-dev@googlegroups.com. Code should -include unit tests and follow the Google Python style guide: -http://code.google.com/p/soc/wiki/PythonStyleGuide diff --git a/contrib/ipaddr-py/ipaddr.py b/contrib/ipaddr-py/ipaddr.py deleted file mode 100644 index a89298a315d..00000000000 --- a/contrib/ipaddr-py/ipaddr.py +++ /dev/null @@ -1,1907 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2007 Google Inc. -# Licensed to PSF under a Contributor Agreement. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. - -"""A fast, lightweight IPv4/IPv6 manipulation library in Python. - -This library is used to create/poke/manipulate IPv4 and IPv6 addresses -and networks. - -""" - -__version__ = 'trunk' - -import struct - -IPV4LENGTH = 32 -IPV6LENGTH = 128 - - -class AddressValueError(ValueError): - """A Value Error related to the address.""" - - -class NetmaskValueError(ValueError): - """A Value Error related to the netmask.""" - - -def IPAddress(address, version=None): - """Take an IP string/int and return an object of the correct type. - - Args: - address: A string or integer, the IP address. Either IPv4 or - IPv6 addresses may be supplied; integers less than 2**32 will - be considered to be IPv4 by default. - version: An Integer, 4 or 6. If set, don't try to automatically - determine what the IP address type is. important for things - like IPAddress(1), which could be IPv4, '0.0.0.1', or IPv6, - '::1'. - - Returns: - An IPv4Address or IPv6Address object. - - Raises: - ValueError: if the string passed isn't either a v4 or a v6 - address. - - """ - if version: - if version == 4: - return IPv4Address(address) - elif version == 6: - return IPv6Address(address) - - try: - return IPv4Address(address) - except (AddressValueError, NetmaskValueError): - pass - - try: - return IPv6Address(address) - except (AddressValueError, NetmaskValueError): - pass - - raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % - address) - - -def IPNetwork(address, version=None, strict=False): - """Take an IP string/int and return an object of the correct type. - - Args: - address: A string or integer, the IP address. Either IPv4 or - IPv6 addresses may be supplied; integers less than 2**32 will - be considered to be IPv4 by default. - version: An Integer, if set, don't try to automatically - determine what the IP address type is. important for things - like IPNetwork(1), which could be IPv4, '0.0.0.1/32', or IPv6, - '::1/128'. - - Returns: - An IPv4Network or IPv6Network object. - - Raises: - ValueError: if the string passed isn't either a v4 or a v6 - address. Or if a strict network was requested and a strict - network wasn't given. - - """ - if version: - if version == 4: - return IPv4Network(address, strict) - elif version == 6: - return IPv6Network(address, strict) - - try: - return IPv4Network(address, strict) - except (AddressValueError, NetmaskValueError): - pass - - try: - return IPv6Network(address, strict) - except (AddressValueError, NetmaskValueError): - pass - - raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % - address) - - -def v4_int_to_packed(address): - """The binary representation of this address. - - Args: - address: An integer representation of an IPv4 IP address. - - Returns: - The binary representation of this address. - - Raises: - ValueError: If the integer is too large to be an IPv4 IP - address. - """ - if address > _BaseV4._ALL_ONES: - raise ValueError('Address too large for IPv4') - return struct.pack('!I', address) - - -def v6_int_to_packed(address): - """The binary representation of this address. - - Args: - address: An integer representation of an IPv4 IP address. - - Returns: - The binary representation of this address. - """ - return struct.pack('!QQ', address >> 64, address & (2**64 - 1)) - - -def _find_address_range(addresses): - """Find a sequence of addresses. - - Args: - addresses: a list of IPv4 or IPv6 addresses. - - Returns: - A tuple containing the first and last IP addresses in the sequence. - - """ - first = last = addresses[0] - for ip in addresses[1:]: - if ip._ip == last._ip + 1: - last = ip - else: - break - return (first, last) - -def _get_prefix_length(number1, number2, bits): - """Get the number of leading bits that are same for two numbers. - - Args: - number1: an integer. - number2: another integer. - bits: the maximum number of bits to compare. - - Returns: - The number of leading bits that are the same for two numbers. - - """ - for i in range(bits): - if number1 >> i == number2 >> i: - return bits - i - return 0 - -def _count_righthand_zero_bits(number, bits): - """Count the number of zero bits on the right hand side. - - Args: - number: an integer. - bits: maximum number of bits to count. - - Returns: - The number of zero bits on the right hand side of the number. - - """ - if number == 0: - return bits - for i in range(bits): - if (number >> i) % 2: - return i - -def summarize_address_range(first, last): - """Summarize a network range given the first and last IP addresses. - - Example: - >>> summarize_address_range(IPv4Address('1.1.1.0'), - IPv4Address('1.1.1.130')) - [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'), - IPv4Network('1.1.1.130/32')] - - Args: - first: the first IPv4Address or IPv6Address in the range. - last: the last IPv4Address or IPv6Address in the range. - - Returns: - The address range collapsed to a list of IPv4Network's or - IPv6Network's. - - Raise: - TypeError: - If the first and last objects are not IP addresses. - If the first and last objects are not the same version. - ValueError: - If the last object is not greater than the first. - If the version is not 4 or 6. - - """ - if not (isinstance(first, _BaseIP) and isinstance(last, _BaseIP)): - raise TypeError('first and last must be IP addresses, not networks') - if first.version != last.version: - raise TypeError("%s and %s are not of the same version" % ( - str(first), str(last))) - if first > last: - raise ValueError('last IP address must be greater than first') - - networks = [] - - if first.version == 4: - ip = IPv4Network - elif first.version == 6: - ip = IPv6Network - else: - raise ValueError('unknown IP version') - - ip_bits = first._max_prefixlen - first_int = first._ip - last_int = last._ip - while first_int <= last_int: - nbits = _count_righthand_zero_bits(first_int, ip_bits) - current = None - while nbits >= 0: - addend = 2**nbits - 1 - current = first_int + addend - nbits -= 1 - if current <= last_int: - break - prefix = _get_prefix_length(first_int, current, ip_bits) - net = ip('%s/%d' % (str(first), prefix)) - networks.append(net) - if current == ip._ALL_ONES: - break - first_int = current + 1 - first = IPAddress(first_int, version=first._version) - return networks - -def _collapse_address_list_recursive(addresses): - """Loops through the addresses, collapsing concurrent netblocks. - - Example: - - ip1 = IPv4Network('1.1.0.0/24') - ip2 = IPv4Network('1.1.1.0/24') - ip3 = IPv4Network('1.1.2.0/24') - ip4 = IPv4Network('1.1.3.0/24') - ip5 = IPv4Network('1.1.4.0/24') - ip6 = IPv4Network('1.1.0.1/22') - - _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) -> - [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')] - - This shouldn't be called directly; it is called via - collapse_address_list([]). - - Args: - addresses: A list of IPv4Network's or IPv6Network's - - Returns: - A list of IPv4Network's or IPv6Network's depending on what we were - passed. - - """ - ret_array = [] - optimized = False - - for cur_addr in addresses: - if not ret_array: - ret_array.append(cur_addr) - continue - if cur_addr in ret_array[-1]: - optimized = True - elif cur_addr == ret_array[-1].supernet().subnet()[1]: - ret_array.append(ret_array.pop().supernet()) - optimized = True - else: - ret_array.append(cur_addr) - - if optimized: - return _collapse_address_list_recursive(ret_array) - - return ret_array - - -def collapse_address_list(addresses): - """Collapse a list of IP objects. - - Example: - collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) -> - [IPv4('1.1.0.0/23')] - - Args: - addresses: A list of IPv4Network or IPv6Network objects. - - Returns: - A list of IPv4Network or IPv6Network objects depending on what we - were passed. - - Raises: - TypeError: If passed a list of mixed version objects. - - """ - i = 0 - addrs = [] - ips = [] - nets = [] - - # split IP addresses and networks - for ip in addresses: - if isinstance(ip, _BaseIP): - if ips and ips[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - str(ip), str(ips[-1]))) - ips.append(ip) - elif ip._prefixlen == ip._max_prefixlen: - if ips and ips[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - str(ip), str(ips[-1]))) - ips.append(ip.ip) - else: - if nets and nets[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - str(ip), str(ips[-1]))) - nets.append(ip) - - # sort and dedup - ips = sorted(set(ips)) - nets = sorted(set(nets)) - - while i < len(ips): - (first, last) = _find_address_range(ips[i:]) - i = ips.index(last) + 1 - addrs.extend(summarize_address_range(first, last)) - - return _collapse_address_list_recursive(sorted( - addrs + nets, key=_BaseNet._get_networks_key)) - -# backwards compatibility -CollapseAddrList = collapse_address_list - -# Test whether this Python implementation supports byte objects that -# are not identical to str ones. -# We need to exclude platforms where bytes == str so that we can -# distinguish between packed representations and strings, for example -# b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address). -try: - _compat_has_real_bytes = bytes is not str -except NameError: # <Python2.6 - _compat_has_real_bytes = False - -def get_mixed_type_key(obj): - """Return a key suitable for sorting between networks and addresses. - - Address and Network objects are not sortable by default; they're - fundamentally different so the expression - - IPv4Address('1.1.1.1') <= IPv4Network('1.1.1.1/24') - - doesn't make any sense. There are some times however, where you may wish - to have ipaddr sort these for you anyway. If you need to do this, you - can use this function as the key= argument to sorted(). - - Args: - obj: either a Network or Address object. - Returns: - appropriate key. - - """ - if isinstance(obj, _BaseNet): - return obj._get_networks_key() - elif isinstance(obj, _BaseIP): - return obj._get_address_key() - return NotImplemented - -class _IPAddrBase(object): - - """The mother class.""" - - def __index__(self): - return self._ip - - def __int__(self): - return self._ip - - def __hex__(self): - return hex(self._ip) - - @property - def exploded(self): - """Return the longhand version of the IP address as a string.""" - return self._explode_shorthand_ip_string() - - @property - def compressed(self): - """Return the shorthand version of the IP address as a string.""" - return str(self) - - -class _BaseIP(_IPAddrBase): - - """A generic IP object. - - This IP class contains the version independent methods which are - used by single IP addresses. - - """ - - def __init__(self, address): - if (not (_compat_has_real_bytes and isinstance(address, bytes)) - and '/' in str(address)): - raise AddressValueError(address) - - def __eq__(self, other): - try: - return (self._ip == other._ip - and self._version == other._version) - except AttributeError: - return NotImplemented - - def __ne__(self, other): - eq = self.__eq__(other) - if eq is NotImplemented: - return NotImplemented - return not eq - - def __le__(self, other): - gt = self.__gt__(other) - if gt is NotImplemented: - return NotImplemented - return not gt - - def __ge__(self, other): - lt = self.__lt__(other) - if lt is NotImplemented: - return NotImplemented - return not lt - - def __lt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - str(self), str(other))) - if not isinstance(other, _BaseIP): - raise TypeError('%s and %s are not of the same type' % ( - str(self), str(other))) - if self._ip != other._ip: - return self._ip < other._ip - return False - - def __gt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - str(self), str(other))) - if not isinstance(other, _BaseIP): - raise TypeError('%s and %s are not of the same type' % ( - str(self), str(other))) - if self._ip != other._ip: - return self._ip > other._ip - return False - - # Shorthand for Integer addition and subtraction. This is not - # meant to ever support addition/subtraction of addresses. - def __add__(self, other): - if not isinstance(other, int): - return NotImplemented - return IPAddress(int(self) + other, version=self._version) - - def __sub__(self, other): - if not isinstance(other, int): - return NotImplemented - return IPAddress(int(self) - other, version=self._version) - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, str(self)) - - def __str__(self): - return '%s' % self._string_from_ip_int(self._ip) - - def __hash__(self): - return hash(hex(long(self._ip))) - - def _get_address_key(self): - return (self._version, self) - - @property - def version(self): - raise NotImplementedError('BaseIP has no version') - - -class _BaseNet(_IPAddrBase): - - """A generic IP object. - - This IP class contains the version independent methods which are - used by networks. - - """ - - def __init__(self, address): - self._cache = {} - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, str(self)) - - def iterhosts(self): - """Generate Iterator over usable hosts in a network. - - This is like __iter__ except it doesn't return the network - or broadcast addresses. - - """ - cur = int(self.network) + 1 - bcast = int(self.broadcast) - 1 - while cur <= bcast: - cur += 1 - yield IPAddress(cur - 1, version=self._version) - - def __iter__(self): - cur = int(self.network) - bcast = int(self.broadcast) - while cur <= bcast: - cur += 1 - yield IPAddress(cur - 1, version=self._version) - - def __getitem__(self, n): - network = int(self.network) - broadcast = int(self.broadcast) - if n >= 0: - if network + n > broadcast: - raise IndexError - return IPAddress(network + n, version=self._version) - else: - n += 1 - if broadcast + n < network: - raise IndexError - return IPAddress(broadcast + n, version=self._version) - - def __lt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - str(self), str(other))) - if not isinstance(other, _BaseNet): - raise TypeError('%s and %s are not of the same type' % ( - str(self), str(other))) - if self.network != other.network: - return self.network < other.network - if self.netmask != other.netmask: - return self.netmask < other.netmask - return False - - def __gt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - str(self), str(other))) - if not isinstance(other, _BaseNet): - raise TypeError('%s and %s are not of the same type' % ( - str(self), str(other))) - if self.network != other.network: - return self.network > other.network - if self.netmask != other.netmask: - return self.netmask > other.netmask - return False - - def __le__(self, other): - gt = self.__gt__(other) - if gt is NotImplemented: - return NotImplemented - return not gt - - def __ge__(self, other): - lt = self.__lt__(other) - if lt is NotImplemented: - return NotImplemented - return not lt - - def __eq__(self, other): - try: - return (self._version == other._version - and self.network == other.network - and int(self.netmask) == int(other.netmask)) - except AttributeError: - if isinstance(other, _BaseIP): - return (self._version == other._version - and self._ip == other._ip) - - def __ne__(self, other): - eq = self.__eq__(other) - if eq is NotImplemented: - return NotImplemented - return not eq - - def __str__(self): - return '%s/%s' % (str(self.ip), - str(self._prefixlen)) - - def __hash__(self): - return hash(int(self.network) ^ int(self.netmask)) - - def __contains__(self, other): - # always false if one is v4 and the other is v6. - if self._version != other._version: - return False - # dealing with another network. - if isinstance(other, _BaseNet): - return (self.network <= other.network and - self.broadcast >= other.broadcast) - # dealing with another address - else: - return (int(self.network) <= int(other._ip) <= - int(self.broadcast)) - - def overlaps(self, other): - """Tell if self is partly contained in other.""" - return self.network in other or self.broadcast in other or ( - other.network in self or other.broadcast in self) - - @property - def network(self): - x = self._cache.get('network') - if x is None: - x = IPAddress(self._ip & int(self.netmask), version=self._version) - self._cache['network'] = x - return x - - @property - def broadcast(self): - x = self._cache.get('broadcast') - if x is None: - x = IPAddress(self._ip | int(self.hostmask), version=self._version) - self._cache['broadcast'] = x - return x - - @property - def hostmask(self): - x = self._cache.get('hostmask') - if x is None: - x = IPAddress(int(self.netmask) ^ self._ALL_ONES, - version=self._version) - self._cache['hostmask'] = x - return x - - @property - def with_prefixlen(self): - return '%s/%d' % (str(self.ip), self._prefixlen) - - @property - def with_netmask(self): - return '%s/%s' % (str(self.ip), str(self.netmask)) - - @property - def with_hostmask(self): - return '%s/%s' % (str(self.ip), str(self.hostmask)) - - @property - def numhosts(self): - """Number of hosts in the current subnet.""" - return int(self.broadcast) - int(self.network) + 1 - - @property - def version(self): - raise NotImplementedError('BaseNet has no version') - - @property - def prefixlen(self): - return self._prefixlen - - def address_exclude(self, other): - """Remove an address from a larger block. - - For example: - - addr1 = IPNetwork('10.1.1.0/24') - addr2 = IPNetwork('10.1.1.0/26') - addr1.address_exclude(addr2) = - [IPNetwork('10.1.1.64/26'), IPNetwork('10.1.1.128/25')] - - or IPv6: - - addr1 = IPNetwork('::1/32') - addr2 = IPNetwork('::1/128') - addr1.address_exclude(addr2) = [IPNetwork('::0/128'), - IPNetwork('::2/127'), - IPNetwork('::4/126'), - IPNetwork('::8/125'), - ... - IPNetwork('0:0:8000::/33')] - - Args: - other: An IPvXNetwork object of the same type. - - Returns: - A sorted list of IPvXNetwork objects addresses which is self - minus other. - - Raises: - TypeError: If self and other are of difffering address - versions, or if other is not a network object. - ValueError: If other is not completely contained by self. - - """ - if not self._version == other._version: - raise TypeError("%s and %s are not of the same version" % ( - str(self), str(other))) - - if not isinstance(other, _BaseNet): - raise TypeError("%s is not a network object" % str(other)) - - if other not in self: - raise ValueError('%s not contained in %s' % (str(other), - str(self))) - if other == self: - return [] - - ret_addrs = [] - - # Make sure we're comparing the network of other. - other = IPNetwork('%s/%s' % (str(other.network), str(other.prefixlen)), - version=other._version) - - s1, s2 = self.subnet() - while s1 != other and s2 != other: - if other in s1: - ret_addrs.append(s2) - s1, s2 = s1.subnet() - elif other in s2: - ret_addrs.append(s1) - s1, s2 = s2.subnet() - else: - # If we got here, there's a bug somewhere. - assert True == False, ('Error performing exclusion: ' - 's1: %s s2: %s other: %s' % - (str(s1), str(s2), str(other))) - if s1 == other: - ret_addrs.append(s2) - elif s2 == other: - ret_addrs.append(s1) - else: - # If we got here, there's a bug somewhere. - assert True == False, ('Error performing exclusion: ' - 's1: %s s2: %s other: %s' % - (str(s1), str(s2), str(other))) - - return sorted(ret_addrs, key=_BaseNet._get_networks_key) - - def compare_networks(self, other): - """Compare two IP objects. - - This is only concerned about the comparison of the integer - representation of the network addresses. This means that the - host bits aren't considered at all in this method. If you want - to compare host bits, you can easily enough do a - 'HostA._ip < HostB._ip' - - Args: - other: An IP object. - - Returns: - If the IP versions of self and other are the same, returns: - - -1 if self < other: - eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24') - IPv6('1080::200C:417A') < IPv6('1080::200B:417B') - 0 if self == other - eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24') - IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96') - 1 if self > other - eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24') - IPv6('1080::1:200C:417A/112') > - IPv6('1080::0:200C:417A/112') - - If the IP versions of self and other are different, returns: - - -1 if self._version < other._version - eg: IPv4('10.0.0.1/24') < IPv6('::1/128') - 1 if self._version > other._version - eg: IPv6('::1/128') > IPv4('255.255.255.0/24') - - """ - if self._version < other._version: - return -1 - if self._version > other._version: - return 1 - # self._version == other._version below here: - if self.network < other.network: - return -1 - if self.network > other.network: - return 1 - # self.network == other.network below here: - if self.netmask < other.netmask: - return -1 - if self.netmask > other.netmask: - return 1 - # self.network == other.network and self.netmask == other.netmask - return 0 - - def _get_networks_key(self): - """Network-only key function. - - Returns an object that identifies this address' network and - netmask. This function is a suitable "key" argument for sorted() - and list.sort(). - - """ - return (self._version, self.network, self.netmask) - - def _ip_int_from_prefix(self, prefixlen=None): - """Turn the prefix length netmask into a int for comparison. - - Args: - prefixlen: An integer, the prefix length. - - Returns: - An integer. - - """ - if not prefixlen and prefixlen != 0: - prefixlen = self._prefixlen - return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) - - def _prefix_from_ip_int(self, ip_int, mask=32): - """Return prefix length from the decimal netmask. - - Args: - ip_int: An integer, the IP address. - mask: The netmask. Defaults to 32. - - Returns: - An integer, the prefix length. - - """ - while mask: - if ip_int & 1 == 1: - break - ip_int >>= 1 - mask -= 1 - - return mask - - def _ip_string_from_prefix(self, prefixlen=None): - """Turn a prefix length into a dotted decimal string. - - Args: - prefixlen: An integer, the netmask prefix length. - - Returns: - A string, the dotted decimal netmask string. - - """ - if not prefixlen: - prefixlen = self._prefixlen - return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) - - def iter_subnets(self, prefixlen_diff=1, new_prefix=None): - """The subnets which join to make the current subnet. - - In the case that self contains only one IP - (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 - for IPv6), return a list with just ourself. - - Args: - prefixlen_diff: An integer, the amount the prefix length - should be increased by. This should not be set if - new_prefix is also set. - new_prefix: The desired new prefix length. This must be a - larger number (smaller prefix) than the existing prefix. - This should not be set if prefixlen_diff is also set. - - Returns: - An iterator of IPv(4|6) objects. - - Raises: - ValueError: The prefixlen_diff is too small or too large. - OR - prefixlen_diff and new_prefix are both set or new_prefix - is a smaller number than the current prefix (smaller - number means a larger network) - - """ - if self._prefixlen == self._max_prefixlen: - yield self - return - - if new_prefix is not None: - if new_prefix < self._prefixlen: - raise ValueError('new prefix must be longer') - if prefixlen_diff != 1: - raise ValueError('cannot set prefixlen_diff and new_prefix') - prefixlen_diff = new_prefix - self._prefixlen - - if prefixlen_diff < 0: - raise ValueError('prefix length diff must be > 0') - new_prefixlen = self._prefixlen + prefixlen_diff - - if not self._is_valid_netmask(str(new_prefixlen)): - raise ValueError( - 'prefix length diff %d is invalid for netblock %s' % ( - new_prefixlen, str(self))) - - first = IPNetwork('%s/%s' % (str(self.network), - str(self._prefixlen + prefixlen_diff)), - version=self._version) - - yield first - current = first - while True: - broadcast = current.broadcast - if broadcast == self.broadcast: - return - new_addr = IPAddress(int(broadcast) + 1, version=self._version) - current = IPNetwork('%s/%s' % (str(new_addr), str(new_prefixlen)), - version=self._version) - - yield current - - def masked(self): - """Return the network object with the host bits masked out.""" - return IPNetwork('%s/%d' % (self.network, self._prefixlen), - version=self._version) - - def subnet(self, prefixlen_diff=1, new_prefix=None): - """Return a list of subnets, rather than an iterator.""" - return list(self.iter_subnets(prefixlen_diff, new_prefix)) - - def supernet(self, prefixlen_diff=1, new_prefix=None): - """The supernet containing the current network. - - Args: - prefixlen_diff: An integer, the amount the prefix length of - the network should be decreased by. For example, given a - /24 network and a prefixlen_diff of 3, a supernet with a - /21 netmask is returned. - - Returns: - An IPv4 network object. - - Raises: - ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have a - negative prefix length. - OR - If prefixlen_diff and new_prefix are both set or new_prefix is a - larger number than the current prefix (larger number means a - smaller network) - - """ - if self._prefixlen == 0: - return self - - if new_prefix is not None: - if new_prefix > self._prefixlen: - raise ValueError('new prefix must be shorter') - if prefixlen_diff != 1: - raise ValueError('cannot set prefixlen_diff and new_prefix') - prefixlen_diff = self._prefixlen - new_prefix - - - if self.prefixlen - prefixlen_diff < 0: - raise ValueError( - 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % - (self.prefixlen, prefixlen_diff)) - return IPNetwork('%s/%s' % (str(self.network), - str(self.prefixlen - prefixlen_diff)), - version=self._version) - - # backwards compatibility - Subnet = subnet - Supernet = supernet - AddressExclude = address_exclude - CompareNetworks = compare_networks - Contains = __contains__ - - -class _BaseV4(object): - - """Base IPv4 object. - - The following methods are used by IPv4 objects in both single IP - addresses and networks. - - """ - - # Equivalent to 255.255.255.255 or 32 bits of 1's. - _ALL_ONES = (2**IPV4LENGTH) - 1 - _DECIMAL_DIGITS = frozenset('0123456789') - - def __init__(self, address): - self._version = 4 - self._max_prefixlen = IPV4LENGTH - - def _explode_shorthand_ip_string(self, ip_str=None): - if not ip_str: - ip_str = str(self) - return ip_str - - def _ip_int_from_string(self, ip_str): - """Turn the given IP string into an integer for comparison. - - Args: - ip_str: A string, the IP ip_str. - - Returns: - The IP ip_str as an integer. - - Raises: - AddressValueError: if ip_str isn't a valid IPv4 Address. - - """ - octets = ip_str.split('.') - if len(octets) != 4: - raise AddressValueError(ip_str) - - packed_ip = 0 - for oc in octets: - try: - packed_ip = (packed_ip << 8) | self._parse_octet(oc) - except ValueError: - raise AddressValueError(ip_str) - return packed_ip - - def _parse_octet(self, octet_str): - """Convert a decimal octet into an integer. - - Args: - octet_str: A string, the number to parse. - - Returns: - The octet as an integer. - - Raises: - ValueError: if the octet isn't strictly a decimal from [0..255]. - - """ - # Whitelist the characters, since int() allows a lot of bizarre stuff. - if not self._DECIMAL_DIGITS.issuperset(octet_str): - raise ValueError - octet_int = int(octet_str, 10) - # Disallow leading zeroes, because no clear standard exists on - # whether these should be interpreted as decimal or octal. - if octet_int > 255 or (octet_str[0] == '0' and len(octet_str) > 1): - raise ValueError - return octet_int - - def _string_from_ip_int(self, ip_int): - """Turns a 32-bit integer into dotted decimal notation. - - Args: - ip_int: An integer, the IP address. - - Returns: - The IP address as a string in dotted decimal notation. - - """ - octets = [] - for _ in xrange(4): - octets.insert(0, str(ip_int & 0xFF)) - ip_int >>= 8 - return '.'.join(octets) - - @property - def max_prefixlen(self): - return self._max_prefixlen - - @property - def packed(self): - """The binary representation of this address.""" - return v4_int_to_packed(self._ip) - - @property - def version(self): - return self._version - - @property - def is_reserved(self): - """Test if the address is otherwise IETF reserved. - - Returns: - A boolean, True if the address is within the - reserved IPv4 Network range. - - """ - return self in IPv4Network('240.0.0.0/4') - - @property - def is_private(self): - """Test if this address is allocated for private networks. - - Returns: - A boolean, True if the address is reserved per RFC 1918. - - """ - return (self in IPv4Network('10.0.0.0/8') or - self in IPv4Network('172.16.0.0/12') or - self in IPv4Network('192.168.0.0/16')) - - @property - def is_multicast(self): - """Test if the address is reserved for multicast use. - - Returns: - A boolean, True if the address is multicast. - See RFC 3171 for details. - - """ - return self in IPv4Network('224.0.0.0/4') - - @property - def is_unspecified(self): - """Test if the address is unspecified. - - Returns: - A boolean, True if this is the unspecified address as defined in - RFC 5735 3. - - """ - return self in IPv4Network('0.0.0.0') - - @property - def is_loopback(self): - """Test if the address is a loopback address. - - Returns: - A boolean, True if the address is a loopback per RFC 3330. - - """ - return self in IPv4Network('127.0.0.0/8') - - @property - def is_link_local(self): - """Test if the address is reserved for link-local. - - Returns: - A boolean, True if the address is link-local per RFC 3927. - - """ - return self in IPv4Network('169.254.0.0/16') - - -class IPv4Address(_BaseV4, _BaseIP): - - """Represent and manipulate single IPv4 Addresses.""" - - def __init__(self, address): - - """ - Args: - address: A string or integer representing the IP - '192.168.1.1' - - Additionally, an integer can be passed, so - IPv4Address('192.168.1.1') == IPv4Address(3232235777). - or, more generally - IPv4Address(int(IPv4Address('192.168.1.1'))) == - IPv4Address('192.168.1.1') - - Raises: - AddressValueError: If ipaddr isn't a valid IPv4 address. - - """ - _BaseIP.__init__(self, address) - _BaseV4.__init__(self, address) - - # Efficient constructor from integer. - if isinstance(address, (int, long)): - self._ip = address - if address < 0 or address > self._ALL_ONES: - raise AddressValueError(address) - return - - # Constructing from a packed address - if _compat_has_real_bytes: - if isinstance(address, bytes) and len(address) == 4: - self._ip = struct.unpack('!I', address)[0] - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP string. - addr_str = str(address) - self._ip = self._ip_int_from_string(addr_str) - - -class IPv4Network(_BaseV4, _BaseNet): - - """This class represents and manipulates 32-bit IPv4 networks. - - Attributes: [examples for IPv4Network('1.2.3.4/27')] - ._ip: 16909060 - .ip: IPv4Address('1.2.3.4') - .network: IPv4Address('1.2.3.0') - .hostmask: IPv4Address('0.0.0.31') - .broadcast: IPv4Address('1.2.3.31') - .netmask: IPv4Address('255.255.255.224') - .prefixlen: 27 - - """ - - # the valid octets for host and netmasks. only useful for IPv4. - _valid_mask_octets = set((255, 254, 252, 248, 240, 224, 192, 128, 0)) - - def __init__(self, address, strict=False): - """Instantiate a new IPv4 network object. - - Args: - address: A string or integer representing the IP [& network]. - '192.168.1.1/24' - '192.168.1.1/255.255.255.0' - '192.168.1.1/0.0.0.255' - are all functionally the same in IPv4. Similarly, - '192.168.1.1' - '192.168.1.1/255.255.255.255' - '192.168.1.1/32' - are also functionaly equivalent. That is to say, failing to - provide a subnetmask will create an object with a mask of /32. - - If the mask (portion after the / in the argument) is given in - dotted quad form, it is treated as a netmask if it starts with a - non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it - starts with a zero field (e.g. 0.255.255.255 == /8), with the - single exception of an all-zero mask which is treated as a - netmask == /0. If no mask is given, a default of /32 is used. - - Additionally, an integer can be passed, so - IPv4Network('192.168.1.1') == IPv4Network(3232235777). - or, more generally - IPv4Network(int(IPv4Network('192.168.1.1'))) == - IPv4Network('192.168.1.1') - - strict: A boolean. If true, ensure that we have been passed - A true network address, eg, 192.168.1.0/24 and not an - IP address on a network, eg, 192.168.1.1/24. - - Raises: - AddressValueError: If ipaddr isn't a valid IPv4 address. - NetmaskValueError: If the netmask isn't valid for - an IPv4 address. - ValueError: If strict was True and a network address was not - supplied. - - """ - _BaseNet.__init__(self, address) - _BaseV4.__init__(self, address) - - # Efficient constructor from integer. - if isinstance(address, (int, long)): - self._ip = address - self.ip = IPv4Address(self._ip) - self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ALL_ONES) - if address < 0 or address > self._ALL_ONES: - raise AddressValueError(address) - return - - # Constructing from a packed address - if _compat_has_real_bytes: - if isinstance(address, bytes) and len(address) == 4: - self._ip = struct.unpack('!I', address)[0] - self.ip = IPv4Address(self._ip) - self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ALL_ONES) - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - addr = str(address).split('/') - - if len(addr) > 2: - raise AddressValueError(address) - - self._ip = self._ip_int_from_string(addr[0]) - self.ip = IPv4Address(self._ip) - - if len(addr) == 2: - mask = addr[1].split('.') - if len(mask) == 4: - # We have dotted decimal netmask. - if self._is_valid_netmask(addr[1]): - self.netmask = IPv4Address(self._ip_int_from_string( - addr[1])) - elif self._is_hostmask(addr[1]): - self.netmask = IPv4Address( - self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) - else: - raise NetmaskValueError('%s is not a valid netmask' - % addr[1]) - - self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) - else: - # We have a netmask in prefix length form. - if not self._is_valid_netmask(addr[1]): - raise NetmaskValueError(addr[1]) - self._prefixlen = int(addr[1]) - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) - else: - self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) - if strict: - if self.ip != self.network: - raise ValueError('%s has host bits set' % - self.ip) - - def _is_hostmask(self, ip_str): - """Test if the IP string is a hostmask (rather than a netmask). - - Args: - ip_str: A string, the potential hostmask. - - Returns: - A boolean, True if the IP string is a hostmask. - - """ - bits = ip_str.split('.') - try: - parts = [int(x) for x in bits if int(x) in self._valid_mask_octets] - except ValueError: - return False - if len(parts) != len(bits): - return False - if parts[0] < parts[-1]: - return True - return False - - def _is_valid_netmask(self, netmask): - """Verify that the netmask is valid. - - Args: - netmask: A string, either a prefix or dotted decimal - netmask. - - Returns: - A boolean, True if the prefix represents a valid IPv4 - netmask. - - """ - mask = netmask.split('.') - if len(mask) == 4: - if [x for x in mask if int(x) not in self._valid_mask_octets]: - return False - if [y for idx, y in enumerate(mask) if idx > 0 and - y > mask[idx - 1]]: - return False - return True - try: - netmask = int(netmask) - except ValueError: - return False - return 0 <= netmask <= self._max_prefixlen - - # backwards compatibility - IsRFC1918 = lambda self: self.is_private - IsMulticast = lambda self: self.is_multicast - IsLoopback = lambda self: self.is_loopback - IsLinkLocal = lambda self: self.is_link_local - - -class _BaseV6(object): - - """Base IPv6 object. - - The following methods are used by IPv6 objects in both single IP - addresses and networks. - - """ - - _ALL_ONES = (2**IPV6LENGTH) - 1 - _HEXTET_COUNT = 8 - _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef') - - def __init__(self, address): - self._version = 6 - self._max_prefixlen = IPV6LENGTH - - def _ip_int_from_string(self, ip_str): - """Turn an IPv6 ip_str into an integer. - - Args: - ip_str: A string, the IPv6 ip_str. - - Returns: - A long, the IPv6 ip_str. - - Raises: - AddressValueError: if ip_str isn't a valid IPv6 Address. - - """ - parts = ip_str.split(':') - - # An IPv6 address needs at least 2 colons (3 parts). - if len(parts) < 3: - raise AddressValueError(ip_str) - - # If the address has an IPv4-style suffix, convert it to hexadecimal. - if '.' in parts[-1]: - ipv4_int = IPv4Address(parts.pop())._ip - parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) - parts.append('%x' % (ipv4_int & 0xFFFF)) - - # An IPv6 address can't have more than 8 colons (9 parts). - if len(parts) > self._HEXTET_COUNT + 1: - raise AddressValueError(ip_str) - - # Disregarding the endpoints, find '::' with nothing in between. - # This indicates that a run of zeroes has been skipped. - try: - skip_index, = ( - [i for i in xrange(1, len(parts) - 1) if not parts[i]] or - [None]) - except ValueError: - # Can't have more than one '::' - raise AddressValueError(ip_str) - - # parts_hi is the number of parts to copy from above/before the '::' - # parts_lo is the number of parts to copy from below/after the '::' - if skip_index is not None: - # If we found a '::', then check if it also covers the endpoints. - parts_hi = skip_index - parts_lo = len(parts) - skip_index - 1 - if not parts[0]: - parts_hi -= 1 - if parts_hi: - raise AddressValueError(ip_str) # ^: requires ^:: - if not parts[-1]: - parts_lo -= 1 - if parts_lo: - raise AddressValueError(ip_str) # :$ requires ::$ - parts_skipped = self._HEXTET_COUNT - (parts_hi + parts_lo) - if parts_skipped < 1: - raise AddressValueError(ip_str) - else: - # Otherwise, allocate the entire address to parts_hi. The endpoints - # could still be empty, but _parse_hextet() will check for that. - if len(parts) != self._HEXTET_COUNT: - raise AddressValueError(ip_str) - parts_hi = len(parts) - parts_lo = 0 - parts_skipped = 0 - - try: - # Now, parse the hextets into a 128-bit integer. - ip_int = 0L - for i in xrange(parts_hi): - ip_int <<= 16 - ip_int |= self._parse_hextet(parts[i]) - ip_int <<= 16 * parts_skipped - for i in xrange(-parts_lo, 0): - ip_int <<= 16 - ip_int |= self._parse_hextet(parts[i]) - return ip_int - except ValueError: - raise AddressValueError(ip_str) - - def _parse_hextet(self, hextet_str): - """Convert an IPv6 hextet string into an integer. - - Args: - hextet_str: A string, the number to parse. - - Returns: - The hextet as an integer. - - Raises: - ValueError: if the input isn't strictly a hex number from [0..FFFF]. - - """ - # Whitelist the characters, since int() allows a lot of bizarre stuff. - if not self._HEX_DIGITS.issuperset(hextet_str): - raise ValueError - hextet_int = int(hextet_str, 16) - if hextet_int > 0xFFFF: - raise ValueError - return hextet_int - - def _compress_hextets(self, hextets): - """Compresses a list of hextets. - - Compresses a list of strings, replacing the longest continuous - sequence of "0" in the list with "" and adding empty strings at - the beginning or at the end of the string such that subsequently - calling ":".join(hextets) will produce the compressed version of - the IPv6 address. - - Args: - hextets: A list of strings, the hextets to compress. - - Returns: - A list of strings. - - """ - best_doublecolon_start = -1 - best_doublecolon_len = 0 - doublecolon_start = -1 - doublecolon_len = 0 - for index in range(len(hextets)): - if hextets[index] == '0': - doublecolon_len += 1 - if doublecolon_start == -1: - # Start of a sequence of zeros. - doublecolon_start = index - if doublecolon_len > best_doublecolon_len: - # This is the longest sequence of zeros so far. - best_doublecolon_len = doublecolon_len - best_doublecolon_start = doublecolon_start - else: - doublecolon_len = 0 - doublecolon_start = -1 - - if best_doublecolon_len > 1: - best_doublecolon_end = (best_doublecolon_start + - best_doublecolon_len) - # For zeros at the end of the address. - if best_doublecolon_end == len(hextets): - hextets += [''] - hextets[best_doublecolon_start:best_doublecolon_end] = [''] - # For zeros at the beginning of the address. - if best_doublecolon_start == 0: - hextets = [''] + hextets - - return hextets - - def _string_from_ip_int(self, ip_int=None): - """Turns a 128-bit integer into hexadecimal notation. - - Args: - ip_int: An integer, the IP address. - - Returns: - A string, the hexadecimal representation of the address. - - Raises: - ValueError: The address is bigger than 128 bits of all ones. - - """ - if not ip_int and ip_int != 0: - ip_int = int(self._ip) - - if ip_int > self._ALL_ONES: - raise ValueError('IPv6 address is too large') - - hex_str = '%032x' % ip_int - hextets = [] - for x in range(0, 32, 4): - hextets.append('%x' % int(hex_str[x:x+4], 16)) - - hextets = self._compress_hextets(hextets) - return ':'.join(hextets) - - def _explode_shorthand_ip_string(self, ip_str=None): - """Expand a shortened IPv6 address. - - Args: - ip_str: A string, the IPv6 address. - - Returns: - A string, the expanded IPv6 address. - - """ - if not ip_str: - ip_str = str(self) - if isinstance(self, _BaseNet): - ip_str = str(self.ip) - - ip_int = self._ip_int_from_string(ip_str) - parts = [] - for i in xrange(self._HEXTET_COUNT): - parts.append('%04x' % (ip_int & 0xFFFF)) - ip_int >>= 16 - parts.reverse() - return ':'.join(parts) - - @property - def max_prefixlen(self): - return self._max_prefixlen - - @property - def packed(self): - """The binary representation of this address.""" - return v6_int_to_packed(self._ip) - - @property - def version(self): - return self._version - - @property - def is_multicast(self): - """Test if the address is reserved for multicast use. - - Returns: - A boolean, True if the address is a multicast address. - See RFC 2373 2.7 for details. - - """ - return self in IPv6Network('ff00::/8') - - @property - def is_reserved(self): - """Test if the address is otherwise IETF reserved. - - Returns: - A boolean, True if the address is within one of the - reserved IPv6 Network ranges. - - """ - return (self in IPv6Network('::/8') or - self in IPv6Network('100::/8') or - self in IPv6Network('200::/7') or - self in IPv6Network('400::/6') or - self in IPv6Network('800::/5') or - self in IPv6Network('1000::/4') or - self in IPv6Network('4000::/3') or - self in IPv6Network('6000::/3') or - self in IPv6Network('8000::/3') or - self in IPv6Network('A000::/3') or - self in IPv6Network('C000::/3') or - self in IPv6Network('E000::/4') or - self in IPv6Network('F000::/5') or - self in IPv6Network('F800::/6') or - self in IPv6Network('FE00::/9')) - - @property - def is_unspecified(self): - """Test if the address is unspecified. - - Returns: - A boolean, True if this is the unspecified address as defined in - RFC 2373 2.5.2. - - """ - return self._ip == 0 and getattr(self, '_prefixlen', 128) == 128 - - @property - def is_loopback(self): - """Test if the address is a loopback address. - - Returns: - A boolean, True if the address is a loopback address as defined in - RFC 2373 2.5.3. - - """ - return self._ip == 1 and getattr(self, '_prefixlen', 128) == 128 - - @property - def is_link_local(self): - """Test if the address is reserved for link-local. - - Returns: - A boolean, True if the address is reserved per RFC 4291. - - """ - return self in IPv6Network('fe80::/10') - - @property - def is_site_local(self): - """Test if the address is reserved for site-local. - - Note that the site-local address space has been deprecated by RFC 3879. - Use is_private to test if this address is in the space of unique local - addresses as defined by RFC 4193. - - Returns: - A boolean, True if the address is reserved per RFC 3513 2.5.6. - - """ - return self in IPv6Network('fec0::/10') - - @property - def is_private(self): - """Test if this address is allocated for private networks. - - Returns: - A boolean, True if the address is reserved per RFC 4193. - - """ - return self in IPv6Network('fc00::/7') - - @property - def ipv4_mapped(self): - """Return the IPv4 mapped address. - - Returns: - If the IPv6 address is a v4 mapped address, return the - IPv4 mapped address. Return None otherwise. - - """ - if (self._ip >> 32) != 0xFFFF: - return None - return IPv4Address(self._ip & 0xFFFFFFFF) - - @property - def teredo(self): - """Tuple of embedded teredo IPs. - - Returns: - Tuple of the (server, client) IPs or None if the address - doesn't appear to be a teredo address (doesn't start with - 2001::/32) - - """ - if (self._ip >> 96) != 0x20010000: - return None - return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF), - IPv4Address(~self._ip & 0xFFFFFFFF)) - - @property - def sixtofour(self): - """Return the IPv4 6to4 embedded address. - - Returns: - The IPv4 6to4-embedded address if present or None if the - address doesn't appear to contain a 6to4 embedded address. - - """ - if (self._ip >> 112) != 0x2002: - return None - return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) - - -class IPv6Address(_BaseV6, _BaseIP): - - """Represent and manipulate single IPv6 Addresses. - """ - - def __init__(self, address): - """Instantiate a new IPv6 address object. - - Args: - address: A string or integer representing the IP - - Additionally, an integer can be passed, so - IPv6Address('2001:4860::') == - IPv6Address(42541956101370907050197289607612071936L). - or, more generally - IPv6Address(IPv6Address('2001:4860::')._ip) == - IPv6Address('2001:4860::') - - Raises: - AddressValueError: If address isn't a valid IPv6 address. - - """ - _BaseIP.__init__(self, address) - _BaseV6.__init__(self, address) - - # Efficient constructor from integer. - if isinstance(address, (int, long)): - self._ip = address - if address < 0 or address > self._ALL_ONES: - raise AddressValueError(address) - return - - # Constructing from a packed address - if _compat_has_real_bytes: - if isinstance(address, bytes) and len(address) == 16: - tmp = struct.unpack('!QQ', address) - self._ip = (tmp[0] << 64) | tmp[1] - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP string. - addr_str = str(address) - if not addr_str: - raise AddressValueError('') - - self._ip = self._ip_int_from_string(addr_str) - - -class IPv6Network(_BaseV6, _BaseNet): - - """This class represents and manipulates 128-bit IPv6 networks. - - Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')] - .ip: IPv6Address('2001:658:22a:cafe:200::1') - .network: IPv6Address('2001:658:22a:cafe::') - .hostmask: IPv6Address('::ffff:ffff:ffff:ffff') - .broadcast: IPv6Address('2001:658:22a:cafe:ffff:ffff:ffff:ffff') - .netmask: IPv6Address('ffff:ffff:ffff:ffff::') - .prefixlen: 64 - - """ - - - def __init__(self, address, strict=False): - """Instantiate a new IPv6 Network object. - - Args: - address: A string or integer representing the IPv6 network or the IP - and prefix/netmask. - '2001:4860::/128' - '2001:4860:0000:0000:0000:0000:0000:0000/128' - '2001:4860::' - are all functionally the same in IPv6. That is to say, - failing to provide a subnetmask will create an object with - a mask of /128. - - Additionally, an integer can be passed, so - IPv6Network('2001:4860::') == - IPv6Network(42541956101370907050197289607612071936L). - or, more generally - IPv6Network(IPv6Network('2001:4860::')._ip) == - IPv6Network('2001:4860::') - - strict: A boolean. If true, ensure that we have been passed - A true network address, eg, 192.168.1.0/24 and not an - IP address on a network, eg, 192.168.1.1/24. - - Raises: - AddressValueError: If address isn't a valid IPv6 address. - NetmaskValueError: If the netmask isn't valid for - an IPv6 address. - ValueError: If strict was True and a network address was not - supplied. - - """ - _BaseNet.__init__(self, address) - _BaseV6.__init__(self, address) - - # Efficient constructor from integer. - if isinstance(address, (int, long)): - self._ip = address - self.ip = IPv6Address(self._ip) - self._prefixlen = self._max_prefixlen - self.netmask = IPv6Address(self._ALL_ONES) - if address < 0 or address > self._ALL_ONES: - raise AddressValueError(address) - return - - # Constructing from a packed address - if _compat_has_real_bytes: - if isinstance(address, bytes) and len(address) == 16: - tmp = struct.unpack('!QQ', address) - self._ip = (tmp[0] << 64) | tmp[1] - self.ip = IPv6Address(self._ip) - self._prefixlen = self._max_prefixlen - self.netmask = IPv6Address(self._ALL_ONES) - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - addr = str(address).split('/') - - if len(addr) > 2: - raise AddressValueError(address) - - self._ip = self._ip_int_from_string(addr[0]) - self.ip = IPv6Address(self._ip) - - if len(addr) == 2: - if self._is_valid_netmask(addr[1]): - self._prefixlen = int(addr[1]) - else: - raise NetmaskValueError(addr[1]) - else: - self._prefixlen = self._max_prefixlen - - self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen)) - - if strict: - if self.ip != self.network: - raise ValueError('%s has host bits set' % - self.ip) - - def _is_valid_netmask(self, prefixlen): - """Verify that the netmask/prefixlen is valid. - - Args: - prefixlen: A string, the netmask in prefix length format. - - Returns: - A boolean, True if the prefix represents a valid IPv6 - netmask. - - """ - try: - prefixlen = int(prefixlen) - except ValueError: - return False - return 0 <= prefixlen <= self._max_prefixlen - - @property - def with_netmask(self): - return self.with_prefixlen diff --git a/contrib/ipaddr-py/ipaddr_test.py b/contrib/ipaddr-py/ipaddr_test.py deleted file mode 100755 index 09bece0e751..00000000000 --- a/contrib/ipaddr-py/ipaddr_test.py +++ /dev/null @@ -1,1099 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2007 Google Inc. -# Licensed to PSF under a Contributor Agreement. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unittest for ipaddr module.""" - - -import unittest -import time -import ipaddr - -# Compatibility function to cast str to bytes objects -if ipaddr._compat_has_real_bytes: - _cb = lambda bytestr: bytes(bytestr, 'charmap') -else: - _cb = str - -class IpaddrUnitTest(unittest.TestCase): - - def setUp(self): - self.ipv4 = ipaddr.IPv4Network('1.2.3.4/24') - self.ipv4_hostmask = ipaddr.IPv4Network('10.0.0.1/0.255.255.255') - self.ipv6 = ipaddr.IPv6Network('2001:658:22a:cafe:200:0:0:1/64') - - def tearDown(self): - del(self.ipv4) - del(self.ipv4_hostmask) - del(self.ipv6) - del(self) - - def testRepr(self): - self.assertEqual("IPv4Network('1.2.3.4/32')", - repr(ipaddr.IPv4Network('1.2.3.4'))) - self.assertEqual("IPv6Network('::1/128')", - repr(ipaddr.IPv6Network('::1'))) - - def testAutoMasking(self): - addr1 = ipaddr.IPv4Network('1.1.1.255/24') - addr1_masked = ipaddr.IPv4Network('1.1.1.0/24') - self.assertEqual(addr1_masked, addr1.masked()) - - addr2 = ipaddr.IPv6Network('2000:cafe::efac:100/96') - addr2_masked = ipaddr.IPv6Network('2000:cafe::/96') - self.assertEqual(addr2_masked, addr2.masked()) - - # issue57 - def testAddressIntMath(self): - self.assertEqual(ipaddr.IPv4Address('1.1.1.1') + 255, - ipaddr.IPv4Address('1.1.2.0')) - self.assertEqual(ipaddr.IPv4Address('1.1.1.1') - 256, - ipaddr.IPv4Address('1.1.0.1')) - self.assertEqual(ipaddr.IPv6Address('::1') + (2**16 - 2), - ipaddr.IPv6Address('::ffff')) - self.assertEqual(ipaddr.IPv6Address('::ffff') - (2**16 - 2), - ipaddr.IPv6Address('::1')) - - def testInvalidStrings(self): - def AssertInvalidIP(ip_str): - self.assertRaises(ValueError, ipaddr.IPAddress, ip_str) - AssertInvalidIP("") - AssertInvalidIP("016.016.016.016") - AssertInvalidIP("016.016.016") - AssertInvalidIP("016.016") - AssertInvalidIP("016") - AssertInvalidIP("000.000.000.000") - AssertInvalidIP("000") - AssertInvalidIP("0x0a.0x0a.0x0a.0x0a") - AssertInvalidIP("0x0a.0x0a.0x0a") - AssertInvalidIP("0x0a.0x0a") - AssertInvalidIP("0x0a") - AssertInvalidIP("42.42.42.42.42") - AssertInvalidIP("42.42.42") - AssertInvalidIP("42.42") - AssertInvalidIP("42") - AssertInvalidIP("42..42.42") - AssertInvalidIP("42..42.42.42") - AssertInvalidIP("42.42.42.42.") - AssertInvalidIP("42.42.42.42...") - AssertInvalidIP(".42.42.42.42") - AssertInvalidIP("...42.42.42.42") - AssertInvalidIP("42.42.42.-0") - AssertInvalidIP("42.42.42.+0") - AssertInvalidIP(".") - AssertInvalidIP("...") - AssertInvalidIP("bogus") - AssertInvalidIP("bogus.com") - AssertInvalidIP("192.168.0.1.com") - AssertInvalidIP("12345.67899.-54321.-98765") - AssertInvalidIP("257.0.0.0") - AssertInvalidIP("42.42.42.-42") - AssertInvalidIP("3ffe::1.net") - AssertInvalidIP("3ffe::1::1") - AssertInvalidIP("1::2::3::4:5") - AssertInvalidIP("::7:6:5:4:3:2:") - AssertInvalidIP(":6:5:4:3:2:1::") - AssertInvalidIP("2001::db:::1") - AssertInvalidIP("FEDC:9878") - AssertInvalidIP("+1.+2.+3.4") - AssertInvalidIP("1.2.3.4e0") - AssertInvalidIP("::7:6:5:4:3:2:1:0") - AssertInvalidIP("7:6:5:4:3:2:1:0::") - AssertInvalidIP("9:8:7:6:5:4:3::2:1") - AssertInvalidIP("0:1:2:3::4:5:6:7") - AssertInvalidIP("3ffe:0:0:0:0:0:0:0:1") - AssertInvalidIP("3ffe::10000") - AssertInvalidIP("3ffe::goog") - AssertInvalidIP("3ffe::-0") - AssertInvalidIP("3ffe::+0") - AssertInvalidIP("3ffe::-1") - AssertInvalidIP(":") - AssertInvalidIP(":::") - AssertInvalidIP("::1.2.3") - AssertInvalidIP("::1.2.3.4.5") - AssertInvalidIP("::1.2.3.4:") - AssertInvalidIP("1.2.3.4::") - AssertInvalidIP("2001:db8::1:") - AssertInvalidIP(":2001:db8::1") - AssertInvalidIP(":1:2:3:4:5:6:7") - AssertInvalidIP("1:2:3:4:5:6:7:") - AssertInvalidIP(":1:2:3:4:5:6:") - - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network, '') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network, - 'google.com') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network, - '::1.2.3.4') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, '') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - 'google.com') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - '1.2.3.4') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - 'cafe:cafe::/128/190') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - '1234:axy::b') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Address, - '1234:axy::b') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Address, - '2001:db8:::1') - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Address, - '2001:888888::1') - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Address(1)._ip_int_from_string, - '1.a.2.3') - self.assertEqual(False, ipaddr.IPv4Network(1)._is_hostmask('1.a.2.3')) - - def testGetNetwork(self): - self.assertEqual(int(self.ipv4.network), 16909056) - self.assertEqual(str(self.ipv4.network), '1.2.3.0') - self.assertEqual(str(self.ipv4_hostmask.network), '10.0.0.0') - - self.assertEqual(int(self.ipv6.network), - 42540616829182469433403647294022090752) - self.assertEqual(str(self.ipv6.network), - '2001:658:22a:cafe::') - self.assertEqual(str(self.ipv6.hostmask), - '::ffff:ffff:ffff:ffff') - - def testBadVersionComparison(self): - # These should always raise TypeError - v4addr = ipaddr.IPAddress('1.1.1.1') - v4net = ipaddr.IPNetwork('1.1.1.1') - v6addr = ipaddr.IPAddress('::1') - v6net = ipaddr.IPAddress('::1') - - self.assertRaises(TypeError, v4addr.__lt__, v6addr) - self.assertRaises(TypeError, v4addr.__gt__, v6addr) - self.assertRaises(TypeError, v4net.__lt__, v6net) - self.assertRaises(TypeError, v4net.__gt__, v6net) - - self.assertRaises(TypeError, v6addr.__lt__, v4addr) - self.assertRaises(TypeError, v6addr.__gt__, v4addr) - self.assertRaises(TypeError, v6net.__lt__, v4net) - self.assertRaises(TypeError, v6net.__gt__, v4net) - - def testMixedTypeComparison(self): - v4addr = ipaddr.IPAddress('1.1.1.1') - v4net = ipaddr.IPNetwork('1.1.1.1/32') - v6addr = ipaddr.IPAddress('::1') - v6net = ipaddr.IPNetwork('::1/128') - - self.assertFalse(v4net.__contains__(v6net)) - self.assertFalse(v6net.__contains__(v4net)) - - self.assertRaises(TypeError, lambda: v4addr < v4net) - self.assertRaises(TypeError, lambda: v4addr > v4net) - self.assertRaises(TypeError, lambda: v4net < v4addr) - self.assertRaises(TypeError, lambda: v4net > v4addr) - - self.assertRaises(TypeError, lambda: v6addr < v6net) - self.assertRaises(TypeError, lambda: v6addr > v6net) - self.assertRaises(TypeError, lambda: v6net < v6addr) - self.assertRaises(TypeError, lambda: v6net > v6addr) - - # with get_mixed_type_key, you can sort addresses and network. - self.assertEqual([v4addr, v4net], sorted([v4net, v4addr], - key=ipaddr.get_mixed_type_key)) - self.assertEqual([v6addr, v6net], sorted([v6net, v6addr], - key=ipaddr.get_mixed_type_key)) - - def testIpFromInt(self): - self.assertEqual(self.ipv4.ip, ipaddr.IPv4Network(16909060).ip) - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Network, 2**32) - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Network, -1) - - ipv4 = ipaddr.IPNetwork('1.2.3.4') - ipv6 = ipaddr.IPNetwork('2001:658:22a:cafe:200:0:0:1') - self.assertEqual(ipv4, ipaddr.IPNetwork(int(ipv4))) - self.assertEqual(ipv6, ipaddr.IPNetwork(int(ipv6))) - - v6_int = 42540616829182469433547762482097946625 - self.assertEqual(self.ipv6.ip, ipaddr.IPv6Network(v6_int).ip) - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv6Network, 2**128) - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv6Network, -1) - - self.assertEqual(ipaddr.IPNetwork(self.ipv4.ip).version, 4) - self.assertEqual(ipaddr.IPNetwork(self.ipv6.ip).version, 6) - - if ipaddr._compat_has_real_bytes: # on python3+ - def testIpFromPacked(self): - ip = ipaddr.IPNetwork - - self.assertEqual(self.ipv4.ip, - ip(_cb('\x01\x02\x03\x04')).ip) - self.assertEqual(ip('255.254.253.252'), - ip(_cb('\xff\xfe\xfd\xfc'))) - self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 3)) - self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 5)) - self.assertEqual(self.ipv6.ip, - ip(_cb('\x20\x01\x06\x58\x02\x2a\xca\xfe' - '\x02\x00\x00\x00\x00\x00\x00\x01')).ip) - self.assertEqual(ip('ffff:2:3:4:ffff::'), - ip(_cb('\xff\xff\x00\x02\x00\x03\x00\x04' + - '\xff\xff' + '\x00' * 6))) - self.assertEqual(ip('::'), - ip(_cb('\x00' * 16))) - self.assertRaises(ValueError, ip, _cb('\x00' * 15)) - self.assertRaises(ValueError, ip, _cb('\x00' * 17)) - - def testGetIp(self): - self.assertEqual(int(self.ipv4.ip), 16909060) - self.assertEqual(str(self.ipv4.ip), '1.2.3.4') - self.assertEqual(str(self.ipv4_hostmask.ip), '10.0.0.1') - - self.assertEqual(int(self.ipv6.ip), - 42540616829182469433547762482097946625) - self.assertEqual(str(self.ipv6.ip), - '2001:658:22a:cafe:200::1') - - def testGetNetmask(self): - self.assertEqual(int(self.ipv4.netmask), 4294967040L) - self.assertEqual(str(self.ipv4.netmask), '255.255.255.0') - self.assertEqual(str(self.ipv4_hostmask.netmask), '255.0.0.0') - self.assertEqual(int(self.ipv6.netmask), - 340282366920938463444927863358058659840) - self.assertEqual(self.ipv6.prefixlen, 64) - - def testZeroNetmask(self): - ipv4_zero_netmask = ipaddr.IPv4Network('1.2.3.4/0') - self.assertEqual(int(ipv4_zero_netmask.netmask), 0) - self.assertTrue(ipv4_zero_netmask._is_valid_netmask(str(0))) - - ipv6_zero_netmask = ipaddr.IPv6Network('::1/0') - self.assertEqual(int(ipv6_zero_netmask.netmask), 0) - self.assertTrue(ipv6_zero_netmask._is_valid_netmask(str(0))) - - def testGetBroadcast(self): - self.assertEqual(int(self.ipv4.broadcast), 16909311L) - self.assertEqual(str(self.ipv4.broadcast), '1.2.3.255') - - self.assertEqual(int(self.ipv6.broadcast), - 42540616829182469451850391367731642367) - self.assertEqual(str(self.ipv6.broadcast), - '2001:658:22a:cafe:ffff:ffff:ffff:ffff') - - def testGetPrefixlen(self): - self.assertEqual(self.ipv4.prefixlen, 24) - - self.assertEqual(self.ipv6.prefixlen, 64) - - def testGetSupernet(self): - self.assertEqual(self.ipv4.supernet().prefixlen, 23) - self.assertEqual(str(self.ipv4.supernet().network), '1.2.2.0') - self.assertEqual(ipaddr.IPv4Network('0.0.0.0/0').supernet(), - ipaddr.IPv4Network('0.0.0.0/0')) - - self.assertEqual(self.ipv6.supernet().prefixlen, 63) - self.assertEqual(str(self.ipv6.supernet().network), - '2001:658:22a:cafe::') - self.assertEqual(ipaddr.IPv6Network('::0/0').supernet(), - ipaddr.IPv6Network('::0/0')) - - def testGetSupernet3(self): - self.assertEqual(self.ipv4.supernet(3).prefixlen, 21) - self.assertEqual(str(self.ipv4.supernet(3).network), '1.2.0.0') - - self.assertEqual(self.ipv6.supernet(3).prefixlen, 61) - self.assertEqual(str(self.ipv6.supernet(3).network), - '2001:658:22a:caf8::') - - def testGetSupernet4(self): - self.assertRaises(ValueError, self.ipv4.supernet, prefixlen_diff=2, - new_prefix=1) - self.assertRaises(ValueError, self.ipv4.supernet, new_prefix=25) - self.assertEqual(self.ipv4.supernet(prefixlen_diff=2), - self.ipv4.supernet(new_prefix=22)) - - self.assertRaises(ValueError, self.ipv6.supernet, prefixlen_diff=2, - new_prefix=1) - self.assertRaises(ValueError, self.ipv6.supernet, new_prefix=65) - self.assertEqual(self.ipv6.supernet(prefixlen_diff=2), - self.ipv6.supernet(new_prefix=62)) - - def testIterSubnets(self): - self.assertEqual(self.ipv4.subnet(), list(self.ipv4.iter_subnets())) - self.assertEqual(self.ipv6.subnet(), list(self.ipv6.iter_subnets())) - - def testFancySubnetting(self): - self.assertEqual(sorted(self.ipv4.subnet(prefixlen_diff=3)), - sorted(self.ipv4.subnet(new_prefix=27))) - self.assertRaises(ValueError, self.ipv4.subnet, new_prefix=23) - self.assertRaises(ValueError, self.ipv4.subnet, - prefixlen_diff=3, new_prefix=27) - self.assertEqual(sorted(self.ipv6.subnet(prefixlen_diff=4)), - sorted(self.ipv6.subnet(new_prefix=68))) - self.assertRaises(ValueError, self.ipv6.subnet, new_prefix=63) - self.assertRaises(ValueError, self.ipv6.subnet, - prefixlen_diff=4, new_prefix=68) - - def testGetSubnet(self): - self.assertEqual(self.ipv4.subnet()[0].prefixlen, 25) - self.assertEqual(str(self.ipv4.subnet()[0].network), '1.2.3.0') - self.assertEqual(str(self.ipv4.subnet()[1].network), '1.2.3.128') - - self.assertEqual(self.ipv6.subnet()[0].prefixlen, 65) - - def testGetSubnetForSingle32(self): - ip = ipaddr.IPv4Network('1.2.3.4/32') - subnets1 = [str(x) for x in ip.subnet()] - subnets2 = [str(x) for x in ip.subnet(2)] - self.assertEqual(subnets1, ['1.2.3.4/32']) - self.assertEqual(subnets1, subnets2) - - def testGetSubnetForSingle128(self): - ip = ipaddr.IPv6Network('::1/128') - subnets1 = [str(x) for x in ip.subnet()] - subnets2 = [str(x) for x in ip.subnet(2)] - self.assertEqual(subnets1, ['::1/128']) - self.assertEqual(subnets1, subnets2) - - def testSubnet2(self): - ips = [str(x) for x in self.ipv4.subnet(2)] - self.assertEqual( - ips, - ['1.2.3.0/26', '1.2.3.64/26', '1.2.3.128/26', '1.2.3.192/26']) - - ipsv6 = [str(x) for x in self.ipv6.subnet(2)] - self.assertEqual( - ipsv6, - ['2001:658:22a:cafe::/66', - '2001:658:22a:cafe:4000::/66', - '2001:658:22a:cafe:8000::/66', - '2001:658:22a:cafe:c000::/66']) - - def testSubnetFailsForLargeCidrDiff(self): - self.assertRaises(ValueError, self.ipv4.subnet, 9) - self.assertRaises(ValueError, self.ipv6.subnet, 65) - - def testSupernetFailsForLargeCidrDiff(self): - self.assertRaises(ValueError, self.ipv4.supernet, 25) - self.assertRaises(ValueError, self.ipv6.supernet, 65) - - def testSubnetFailsForNegativeCidrDiff(self): - self.assertRaises(ValueError, self.ipv4.subnet, -1) - self.assertRaises(ValueError, self.ipv6.subnet, -1) - - def testGetNumHosts(self): - self.assertEqual(self.ipv4.numhosts, 256) - self.assertEqual(self.ipv4.subnet()[0].numhosts, 128) - self.assertEqual(self.ipv4.supernet().numhosts, 512) - - self.assertEqual(self.ipv6.numhosts, 18446744073709551616) - self.assertEqual(self.ipv6.subnet()[0].numhosts, 9223372036854775808) - self.assertEqual(self.ipv6.supernet().numhosts, 36893488147419103232) - - def testContains(self): - self.assertTrue(ipaddr.IPv4Network('1.2.3.128/25') in self.ipv4) - self.assertFalse(ipaddr.IPv4Network('1.2.4.1/24') in self.ipv4) - self.assertTrue(self.ipv4 in self.ipv4) - self.assertTrue(self.ipv6 in self.ipv6) - # We can test addresses and string as well. - addr1 = ipaddr.IPv4Address('1.2.3.37') - self.assertTrue(addr1 in self.ipv4) - # issue 61, bad network comparison on like-ip'd network objects - # with identical broadcast addresses. - self.assertFalse(ipaddr.IPv4Network('1.1.0.0/16').__contains__( - ipaddr.IPv4Network('1.0.0.0/15'))) - - def testBadAddress(self): - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network, - 'poop') - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Network, '1.2.3.256') - - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - 'poopv6') - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Network, '1.2.3.4/32/24') - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv4Network, '10/8') - self.assertRaises(ipaddr.AddressValueError, - ipaddr.IPv6Network, '10/8') - - - def testBadNetMask(self): - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv4Network, '1.2.3.4/') - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv4Network, '1.2.3.4/33') - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv4Network, '1.2.3.4/254.254.255.256') - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv4Network, '1.1.1.1/240.255.0.0') - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv6Network, '::1/') - self.assertRaises(ipaddr.NetmaskValueError, - ipaddr.IPv6Network, '::1/129') - - def testNth(self): - self.assertEqual(str(self.ipv4[5]), '1.2.3.5') - self.assertRaises(IndexError, self.ipv4.__getitem__, 256) - - self.assertEqual(str(self.ipv6[5]), - '2001:658:22a:cafe::5') - - def testGetitem(self): - # http://code.google.com/p/ipaddr-py/issues/detail?id=15 - addr = ipaddr.IPv4Network('172.31.255.128/255.255.255.240') - self.assertEqual(28, addr.prefixlen) - addr_list = list(addr) - self.assertEqual('172.31.255.128', str(addr_list[0])) - self.assertEqual('172.31.255.128', str(addr[0])) - self.assertEqual('172.31.255.143', str(addr_list[-1])) - self.assertEqual('172.31.255.143', str(addr[-1])) - self.assertEqual(addr_list[-1], addr[-1]) - - def testEqual(self): - self.assertTrue(self.ipv4 == ipaddr.IPv4Network('1.2.3.4/24')) - self.assertFalse(self.ipv4 == ipaddr.IPv4Network('1.2.3.4/23')) - self.assertFalse(self.ipv4 == ipaddr.IPv6Network('::1.2.3.4/24')) - self.assertFalse(self.ipv4 == '') - self.assertFalse(self.ipv4 == []) - self.assertFalse(self.ipv4 == 2) - self.assertTrue(ipaddr.IPNetwork('1.1.1.1/32') == - ipaddr.IPAddress('1.1.1.1')) - self.assertTrue(ipaddr.IPNetwork('1.1.1.1/24') == - ipaddr.IPAddress('1.1.1.1')) - self.assertFalse(ipaddr.IPNetwork('1.1.1.0/24') == - ipaddr.IPAddress('1.1.1.1')) - - self.assertTrue(self.ipv6 == - ipaddr.IPv6Network('2001:658:22a:cafe:200::1/64')) - self.assertTrue(ipaddr.IPNetwork('::1/128') == - ipaddr.IPAddress('::1')) - self.assertTrue(ipaddr.IPNetwork('::1/127') == - ipaddr.IPAddress('::1')) - self.assertFalse(ipaddr.IPNetwork('::0/127') == - ipaddr.IPAddress('::1')) - self.assertFalse(self.ipv6 == - ipaddr.IPv6Network('2001:658:22a:cafe:200::1/63')) - self.assertFalse(self.ipv6 == ipaddr.IPv4Network('1.2.3.4/23')) - self.assertFalse(self.ipv6 == '') - self.assertFalse(self.ipv6 == []) - self.assertFalse(self.ipv6 == 2) - - def testNotEqual(self): - self.assertFalse(self.ipv4 != ipaddr.IPv4Network('1.2.3.4/24')) - self.assertTrue(self.ipv4 != ipaddr.IPv4Network('1.2.3.4/23')) - self.assertTrue(self.ipv4 != ipaddr.IPv6Network('::1.2.3.4/24')) - self.assertTrue(self.ipv4 != '') - self.assertTrue(self.ipv4 != []) - self.assertTrue(self.ipv4 != 2) - - addr2 = ipaddr.IPAddress('2001:658:22a:cafe:200::1') - self.assertFalse(self.ipv6 != - ipaddr.IPv6Network('2001:658:22a:cafe:200::1/64')) - self.assertTrue(self.ipv6 != - ipaddr.IPv6Network('2001:658:22a:cafe:200::1/63')) - self.assertTrue(self.ipv6 != ipaddr.IPv4Network('1.2.3.4/23')) - self.assertTrue(self.ipv6 != '') - self.assertTrue(self.ipv6 != []) - self.assertTrue(self.ipv6 != 2) - - def testSlash32Constructor(self): - self.assertEqual(str(ipaddr.IPv4Network('1.2.3.4/255.255.255.255')), - '1.2.3.4/32') - - def testSlash128Constructor(self): - self.assertEqual(str(ipaddr.IPv6Network('::1/128')), - '::1/128') - - def testSlash0Constructor(self): - self.assertEqual(str(ipaddr.IPv4Network('1.2.3.4/0.0.0.0')), - '1.2.3.4/0') - - def testCollapsing(self): - # test only IP addresses including some duplicates - ip1 = ipaddr.IPv4Address('1.1.1.0') - ip2 = ipaddr.IPv4Address('1.1.1.1') - ip3 = ipaddr.IPv4Address('1.1.1.2') - ip4 = ipaddr.IPv4Address('1.1.1.3') - ip5 = ipaddr.IPv4Address('1.1.1.4') - ip6 = ipaddr.IPv4Address('1.1.1.0') - # check that addreses are subsumed properly. - collapsed = ipaddr.collapse_address_list([ip1, ip2, ip3, ip4, ip5, ip6]) - self.assertEqual(collapsed, [ipaddr.IPv4Network('1.1.1.0/30'), - ipaddr.IPv4Network('1.1.1.4/32')]) - - # test a mix of IP addresses and networks including some duplicates - ip1 = ipaddr.IPv4Address('1.1.1.0') - ip2 = ipaddr.IPv4Address('1.1.1.1') - ip3 = ipaddr.IPv4Address('1.1.1.2') - ip4 = ipaddr.IPv4Address('1.1.1.3') - ip5 = ipaddr.IPv4Network('1.1.1.4/30') - ip6 = ipaddr.IPv4Network('1.1.1.4/30') - # check that addreses are subsumed properly. - collapsed = ipaddr.collapse_address_list([ip5, ip1, ip2, ip3, ip4, ip6]) - self.assertEqual(collapsed, [ipaddr.IPv4Network('1.1.1.0/29')]) - - # test only IP networks - ip1 = ipaddr.IPv4Network('1.1.0.0/24') - ip2 = ipaddr.IPv4Network('1.1.1.0/24') - ip3 = ipaddr.IPv4Network('1.1.2.0/24') - ip4 = ipaddr.IPv4Network('1.1.3.0/24') - ip5 = ipaddr.IPv4Network('1.1.4.0/24') - # stored in no particular order b/c we want CollapseAddr to call [].sort - ip6 = ipaddr.IPv4Network('1.1.0.0/22') - # check that addreses are subsumed properly. - collapsed = ipaddr.collapse_address_list([ip1, ip2, ip3, ip4, ip5, ip6]) - self.assertEqual(collapsed, [ipaddr.IPv4Network('1.1.0.0/22'), - ipaddr.IPv4Network('1.1.4.0/24')]) - - # test that two addresses are supernet'ed properly - collapsed = ipaddr.collapse_address_list([ip1, ip2]) - self.assertEqual(collapsed, [ipaddr.IPv4Network('1.1.0.0/23')]) - - # test same IP networks - ip_same1 = ip_same2 = ipaddr.IPv4Network('1.1.1.1/32') - self.assertEqual(ipaddr.collapse_address_list([ip_same1, ip_same2]), - [ip_same1]) - - # test same IP addresses - ip_same1 = ip_same2 = ipaddr.IPv4Address('1.1.1.1') - self.assertEqual(ipaddr.collapse_address_list([ip_same1, ip_same2]), - [ipaddr.IPNetwork('1.1.1.1/32')]) - ip1 = ipaddr.IPv6Network('::2001:1/100') - ip2 = ipaddr.IPv6Network('::2002:1/120') - ip3 = ipaddr.IPv6Network('::2001:1/96') - # test that ipv6 addresses are subsumed properly. - collapsed = ipaddr.collapse_address_list([ip1, ip2, ip3]) - self.assertEqual(collapsed, [ip3]) - - # the toejam test - ip1 = ipaddr.IPAddress('1.1.1.1') - ip2 = ipaddr.IPAddress('::1') - self.assertRaises(TypeError, ipaddr.collapse_address_list, - [ip1, ip2]) - - def testSummarizing(self): - #ip = ipaddr.IPAddress - #ipnet = ipaddr.IPNetwork - summarize = ipaddr.summarize_address_range - ip1 = ipaddr.IPAddress('1.1.1.0') - ip2 = ipaddr.IPAddress('1.1.1.255') - # test a /24 is sumamrized properly - self.assertEqual(summarize(ip1, ip2)[0], ipaddr.IPNetwork('1.1.1.0/24')) - # test an IPv4 range that isn't on a network byte boundary - ip2 = ipaddr.IPAddress('1.1.1.8') - self.assertEqual(summarize(ip1, ip2), [ipaddr.IPNetwork('1.1.1.0/29'), - ipaddr.IPNetwork('1.1.1.8')]) - - ip1 = ipaddr.IPAddress('1::') - ip2 = ipaddr.IPAddress('1:ffff:ffff:ffff:ffff:ffff:ffff:ffff') - # test a IPv6 is sumamrized properly - self.assertEqual(summarize(ip1, ip2)[0], ipaddr.IPNetwork('1::/16')) - # test an IPv6 range that isn't on a network byte boundary - ip2 = ipaddr.IPAddress('2::') - self.assertEqual(summarize(ip1, ip2), [ipaddr.IPNetwork('1::/16'), - ipaddr.IPNetwork('2::/128')]) - - # test exception raised when first is greater than last - self.assertRaises(ValueError, summarize, ipaddr.IPAddress('1.1.1.0'), - ipaddr.IPAddress('1.1.0.0')) - # test exception raised when first and last aren't IP addresses - self.assertRaises(TypeError, summarize, - ipaddr.IPNetwork('1.1.1.0'), - ipaddr.IPNetwork('1.1.0.0')) - self.assertRaises(TypeError, summarize, - ipaddr.IPNetwork('1.1.1.0'), ipaddr.IPNetwork('1.1.0.0')) - # test exception raised when first and last are not same version - self.assertRaises(TypeError, summarize, ipaddr.IPAddress('::'), - ipaddr.IPNetwork('1.1.0.0')) - - def testAddressComparison(self): - self.assertTrue(ipaddr.IPAddress('1.1.1.1') <= - ipaddr.IPAddress('1.1.1.1')) - self.assertTrue(ipaddr.IPAddress('1.1.1.1') <= - ipaddr.IPAddress('1.1.1.2')) - self.assertTrue(ipaddr.IPAddress('::1') <= ipaddr.IPAddress('::1')) - self.assertTrue(ipaddr.IPAddress('::1') <= ipaddr.IPAddress('::2')) - - def testNetworkComparison(self): - # ip1 and ip2 have the same network address - ip1 = ipaddr.IPv4Network('1.1.1.0/24') - ip2 = ipaddr.IPv4Network('1.1.1.1/24') - ip3 = ipaddr.IPv4Network('1.1.2.0/24') - - self.assertTrue(ip1 < ip3) - self.assertTrue(ip3 > ip2) - - self.assertEqual(ip1.compare_networks(ip2), 0) - self.assertTrue(ip1._get_networks_key() == ip2._get_networks_key()) - self.assertEqual(ip1.compare_networks(ip3), -1) - self.assertTrue(ip1._get_networks_key() < ip3._get_networks_key()) - - ip1 = ipaddr.IPv6Network('2001::2000/96') - ip2 = ipaddr.IPv6Network('2001::2001/96') - ip3 = ipaddr.IPv6Network('2001:ffff::2000/96') - - self.assertTrue(ip1 < ip3) - self.assertTrue(ip3 > ip2) - self.assertEqual(ip1.compare_networks(ip2), 0) - self.assertTrue(ip1._get_networks_key() == ip2._get_networks_key()) - self.assertEqual(ip1.compare_networks(ip3), -1) - self.assertTrue(ip1._get_networks_key() < ip3._get_networks_key()) - - # Test comparing different protocols. - # Should always raise a TypeError. - ipv6 = ipaddr.IPv6Network('::/0') - ipv4 = ipaddr.IPv4Network('0.0.0.0/0') - self.assertRaises(TypeError, ipv4.__lt__, ipv6) - self.assertRaises(TypeError, ipv4.__gt__, ipv6) - self.assertRaises(TypeError, ipv6.__lt__, ipv4) - self.assertRaises(TypeError, ipv6.__gt__, ipv4) - - # Regression test for issue 19. - ip1 = ipaddr.IPNetwork('10.1.2.128/25') - self.assertFalse(ip1 < ip1) - self.assertFalse(ip1 > ip1) - ip2 = ipaddr.IPNetwork('10.1.3.0/24') - self.assertTrue(ip1 < ip2) - self.assertFalse(ip2 < ip1) - self.assertFalse(ip1 > ip2) - self.assertTrue(ip2 > ip1) - ip3 = ipaddr.IPNetwork('10.1.3.0/25') - self.assertTrue(ip2 < ip3) - self.assertFalse(ip3 < ip2) - self.assertFalse(ip2 > ip3) - self.assertTrue(ip3 > ip2) - - # Regression test for issue 28. - ip1 = ipaddr.IPNetwork('10.10.10.0/31') - ip2 = ipaddr.IPNetwork('10.10.10.0') - ip3 = ipaddr.IPNetwork('10.10.10.2/31') - ip4 = ipaddr.IPNetwork('10.10.10.2') - sorted = [ip1, ip2, ip3, ip4] - unsorted = [ip2, ip4, ip1, ip3] - unsorted.sort() - self.assertEqual(sorted, unsorted) - unsorted = [ip4, ip1, ip3, ip2] - unsorted.sort() - self.assertEqual(sorted, unsorted) - self.assertRaises(TypeError, ip1.__lt__, ipaddr.IPAddress('10.10.10.0')) - self.assertRaises(TypeError, ip2.__lt__, ipaddr.IPAddress('10.10.10.0')) - - # <=, >= - self.assertTrue(ipaddr.IPNetwork('1.1.1.1') <= - ipaddr.IPNetwork('1.1.1.1')) - self.assertTrue(ipaddr.IPNetwork('1.1.1.1') <= - ipaddr.IPNetwork('1.1.1.2')) - self.assertFalse(ipaddr.IPNetwork('1.1.1.2') <= - ipaddr.IPNetwork('1.1.1.1')) - self.assertTrue(ipaddr.IPNetwork('::1') <= ipaddr.IPNetwork('::1')) - self.assertTrue(ipaddr.IPNetwork('::1') <= ipaddr.IPNetwork('::2')) - self.assertFalse(ipaddr.IPNetwork('::2') <= ipaddr.IPNetwork('::1')) - - def testStrictNetworks(self): - self.assertRaises(ValueError, ipaddr.IPNetwork, '192.168.1.1/24', - strict=True) - self.assertRaises(ValueError, ipaddr.IPNetwork, '::1/120', strict=True) - - def testOverlaps(self): - other = ipaddr.IPv4Network('1.2.3.0/30') - other2 = ipaddr.IPv4Network('1.2.2.0/24') - other3 = ipaddr.IPv4Network('1.2.2.64/26') - self.assertTrue(self.ipv4.overlaps(other)) - self.assertFalse(self.ipv4.overlaps(other2)) - self.assertTrue(other2.overlaps(other3)) - - def testEmbeddedIpv4(self): - ipv4_string = '192.168.0.1' - ipv4 = ipaddr.IPv4Network(ipv4_string) - v4compat_ipv6 = ipaddr.IPv6Network('::%s' % ipv4_string) - self.assertEqual(int(v4compat_ipv6.ip), int(ipv4.ip)) - v4mapped_ipv6 = ipaddr.IPv6Network('::ffff:%s' % ipv4_string) - self.assertNotEqual(v4mapped_ipv6.ip, ipv4.ip) - self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv6Network, - '2001:1.1.1.1:1.1.1.1') - - # Issue 67: IPv6 with embedded IPv4 address not recognized. - def testIPv6AddressTooLarge(self): - # RFC4291 2.5.5.2 - self.assertEqual(ipaddr.IPAddress('::FFFF:192.0.2.1'), - ipaddr.IPAddress('::FFFF:c000:201')) - # RFC4291 2.2 (part 3) x::d.d.d.d - self.assertEqual(ipaddr.IPAddress('FFFF::192.0.2.1'), - ipaddr.IPAddress('FFFF::c000:201')) - - def testIPVersion(self): - self.assertEqual(self.ipv4.version, 4) - self.assertEqual(self.ipv6.version, 6) - - def testMaxPrefixLength(self): - self.assertEqual(self.ipv4.max_prefixlen, 32) - self.assertEqual(self.ipv6.max_prefixlen, 128) - - def testPacked(self): - self.assertEqual(self.ipv4.packed, - _cb('\x01\x02\x03\x04')) - self.assertEqual(ipaddr.IPv4Network('255.254.253.252').packed, - _cb('\xff\xfe\xfd\xfc')) - self.assertEqual(self.ipv6.packed, - _cb('\x20\x01\x06\x58\x02\x2a\xca\xfe' - '\x02\x00\x00\x00\x00\x00\x00\x01')) - self.assertEqual(ipaddr.IPv6Network('ffff:2:3:4:ffff::').packed, - _cb('\xff\xff\x00\x02\x00\x03\x00\x04\xff\xff' - + '\x00' * 6)) - self.assertEqual(ipaddr.IPv6Network('::1:0:0:0:0').packed, - _cb('\x00' * 6 + '\x00\x01' + '\x00' * 8)) - - def testIpStrFromPrefixlen(self): - ipv4 = ipaddr.IPv4Network('1.2.3.4/24') - self.assertEqual(ipv4._ip_string_from_prefix(), '255.255.255.0') - self.assertEqual(ipv4._ip_string_from_prefix(28), '255.255.255.240') - - def testIpType(self): - ipv4net = ipaddr.IPNetwork('1.2.3.4') - ipv4addr = ipaddr.IPAddress('1.2.3.4') - ipv6net = ipaddr.IPNetwork('::1.2.3.4') - ipv6addr = ipaddr.IPAddress('::1.2.3.4') - self.assertEqual(ipaddr.IPv4Network, type(ipv4net)) - self.assertEqual(ipaddr.IPv4Address, type(ipv4addr)) - self.assertEqual(ipaddr.IPv6Network, type(ipv6net)) - self.assertEqual(ipaddr.IPv6Address, type(ipv6addr)) - - def testReservedIpv4(self): - # test networks - self.assertEqual(True, ipaddr.IPNetwork('224.1.1.1/31').is_multicast) - self.assertEqual(False, ipaddr.IPNetwork('240.0.0.0').is_multicast) - - self.assertEqual(True, ipaddr.IPNetwork('192.168.1.1/17').is_private) - self.assertEqual(False, ipaddr.IPNetwork('192.169.0.0').is_private) - self.assertEqual(True, ipaddr.IPNetwork('10.255.255.255').is_private) - self.assertEqual(False, ipaddr.IPNetwork('11.0.0.0').is_private) - self.assertEqual(True, ipaddr.IPNetwork('172.31.255.255').is_private) - self.assertEqual(False, ipaddr.IPNetwork('172.32.0.0').is_private) - - self.assertEqual(True, - ipaddr.IPNetwork('169.254.100.200/24').is_link_local) - self.assertEqual(False, - ipaddr.IPNetwork('169.255.100.200/24').is_link_local) - - self.assertEqual(True, - ipaddr.IPNetwork('127.100.200.254/32').is_loopback) - self.assertEqual(True, ipaddr.IPNetwork('127.42.0.0/16').is_loopback) - self.assertEqual(False, ipaddr.IPNetwork('128.0.0.0').is_loopback) - - # test addresses - self.assertEqual(True, ipaddr.IPAddress('224.1.1.1').is_multicast) - self.assertEqual(False, ipaddr.IPAddress('240.0.0.0').is_multicast) - - self.assertEqual(True, ipaddr.IPAddress('192.168.1.1').is_private) - self.assertEqual(False, ipaddr.IPAddress('192.169.0.0').is_private) - self.assertEqual(True, ipaddr.IPAddress('10.255.255.255').is_private) - self.assertEqual(False, ipaddr.IPAddress('11.0.0.0').is_private) - self.assertEqual(True, ipaddr.IPAddress('172.31.255.255').is_private) - self.assertEqual(False, ipaddr.IPAddress('172.32.0.0').is_private) - - self.assertEqual(True, - ipaddr.IPAddress('169.254.100.200').is_link_local) - self.assertEqual(False, - ipaddr.IPAddress('169.255.100.200').is_link_local) - - self.assertEqual(True, - ipaddr.IPAddress('127.100.200.254').is_loopback) - self.assertEqual(True, ipaddr.IPAddress('127.42.0.0').is_loopback) - self.assertEqual(False, ipaddr.IPAddress('128.0.0.0').is_loopback) - self.assertEqual(True, ipaddr.IPNetwork('0.0.0.0').is_unspecified) - - def testReservedIpv6(self): - - self.assertEqual(True, ipaddr.IPNetwork('ffff::').is_multicast) - self.assertEqual(True, ipaddr.IPNetwork(2**128-1).is_multicast) - self.assertEqual(True, ipaddr.IPNetwork('ff00::').is_multicast) - self.assertEqual(False, ipaddr.IPNetwork('fdff::').is_multicast) - - self.assertEqual(True, ipaddr.IPNetwork('fecf::').is_site_local) - self.assertEqual(True, ipaddr.IPNetwork( - 'feff:ffff:ffff:ffff::').is_site_local) - self.assertEqual(False, ipaddr.IPNetwork('fbf:ffff::').is_site_local) - self.assertEqual(False, ipaddr.IPNetwork('ff00::').is_site_local) - - self.assertEqual(True, ipaddr.IPNetwork('fc00::').is_private) - self.assertEqual(True, ipaddr.IPNetwork( - 'fc00:ffff:ffff:ffff::').is_private) - self.assertEqual(False, ipaddr.IPNetwork('fbff:ffff::').is_private) - self.assertEqual(False, ipaddr.IPNetwork('fe00::').is_private) - - self.assertEqual(True, ipaddr.IPNetwork('fea0::').is_link_local) - self.assertEqual(True, ipaddr.IPNetwork('febf:ffff::').is_link_local) - self.assertEqual(False, ipaddr.IPNetwork('fe7f:ffff::').is_link_local) - self.assertEqual(False, ipaddr.IPNetwork('fec0::').is_link_local) - - self.assertEqual(True, ipaddr.IPNetwork('0:0::0:01').is_loopback) - self.assertEqual(False, ipaddr.IPNetwork('::1/127').is_loopback) - self.assertEqual(False, ipaddr.IPNetwork('::').is_loopback) - self.assertEqual(False, ipaddr.IPNetwork('::2').is_loopback) - - self.assertEqual(True, ipaddr.IPNetwork('0::0').is_unspecified) - self.assertEqual(False, ipaddr.IPNetwork('::1').is_unspecified) - self.assertEqual(False, ipaddr.IPNetwork('::/127').is_unspecified) - - # test addresses - self.assertEqual(True, ipaddr.IPAddress('ffff::').is_multicast) - self.assertEqual(True, ipaddr.IPAddress(2**128-1).is_multicast) - self.assertEqual(True, ipaddr.IPAddress('ff00::').is_multicast) - self.assertEqual(False, ipaddr.IPAddress('fdff::').is_multicast) - - self.assertEqual(True, ipaddr.IPAddress('fecf::').is_site_local) - self.assertEqual(True, ipaddr.IPAddress( - 'feff:ffff:ffff:ffff::').is_site_local) - self.assertEqual(False, ipaddr.IPAddress('fbf:ffff::').is_site_local) - self.assertEqual(False, ipaddr.IPAddress('ff00::').is_site_local) - - self.assertEqual(True, ipaddr.IPAddress('fc00::').is_private) - self.assertEqual(True, ipaddr.IPAddress( - 'fc00:ffff:ffff:ffff::').is_private) - self.assertEqual(False, ipaddr.IPAddress('fbff:ffff::').is_private) - self.assertEqual(False, ipaddr.IPAddress('fe00::').is_private) - - self.assertEqual(True, ipaddr.IPAddress('fea0::').is_link_local) - self.assertEqual(True, ipaddr.IPAddress('febf:ffff::').is_link_local) - self.assertEqual(False, ipaddr.IPAddress('fe7f:ffff::').is_link_local) - self.assertEqual(False, ipaddr.IPAddress('fec0::').is_link_local) - - self.assertEqual(True, ipaddr.IPAddress('0:0::0:01').is_loopback) - self.assertEqual(True, ipaddr.IPAddress('::1').is_loopback) - self.assertEqual(False, ipaddr.IPAddress('::2').is_loopback) - - self.assertEqual(True, ipaddr.IPAddress('0::0').is_unspecified) - self.assertEqual(False, ipaddr.IPAddress('::1').is_unspecified) - - # some generic IETF reserved addresses - self.assertEqual(True, ipaddr.IPAddress('100::').is_reserved) - self.assertEqual(True, ipaddr.IPNetwork('4000::1/128').is_reserved) - - def testIpv4Mapped(self): - self.assertEqual(ipaddr.IPAddress('::ffff:192.168.1.1').ipv4_mapped, - ipaddr.IPAddress('192.168.1.1')) - self.assertEqual(ipaddr.IPAddress('::c0a8:101').ipv4_mapped, None) - self.assertEqual(ipaddr.IPAddress('::ffff:c0a8:101').ipv4_mapped, - ipaddr.IPAddress('192.168.1.1')) - - def testAddrExclude(self): - addr1 = ipaddr.IPNetwork('10.1.1.0/24') - addr2 = ipaddr.IPNetwork('10.1.1.0/26') - addr3 = ipaddr.IPNetwork('10.2.1.0/24') - addr4 = ipaddr.IPAddress('10.1.1.0') - self.assertEqual(addr1.address_exclude(addr2), - [ipaddr.IPNetwork('10.1.1.64/26'), - ipaddr.IPNetwork('10.1.1.128/25')]) - self.assertRaises(ValueError, addr1.address_exclude, addr3) - self.assertRaises(TypeError, addr1.address_exclude, addr4) - self.assertEqual(addr1.address_exclude(addr1), []) - - def testHash(self): - self.assertEqual(hash(ipaddr.IPNetwork('10.1.1.0/24')), - hash(ipaddr.IPNetwork('10.1.1.0/24'))) - self.assertEqual(hash(ipaddr.IPAddress('10.1.1.0')), - hash(ipaddr.IPAddress('10.1.1.0'))) - # i70 - self.assertEqual(hash(ipaddr.IPAddress('1.2.3.4')), - hash(ipaddr.IPAddress( - long(ipaddr.IPAddress('1.2.3.4')._ip)))) - ip1 = ipaddr.IPAddress('10.1.1.0') - ip2 = ipaddr.IPAddress('1::') - dummy = {} - dummy[self.ipv4] = None - dummy[self.ipv6] = None - dummy[ip1] = None - dummy[ip2] = None - self.assertTrue(self.ipv4 in dummy) - self.assertTrue(ip2 in dummy) - - def testCopyConstructor(self): - addr1 = ipaddr.IPNetwork('10.1.1.0/24') - addr2 = ipaddr.IPNetwork(addr1) - addr3 = ipaddr.IPNetwork('2001:658:22a:cafe:200::1/64') - addr4 = ipaddr.IPNetwork(addr3) - addr5 = ipaddr.IPv4Address('1.1.1.1') - addr6 = ipaddr.IPv6Address('2001:658:22a:cafe:200::1') - - self.assertEqual(addr1, addr2) - self.assertEqual(addr3, addr4) - self.assertEqual(addr5, ipaddr.IPv4Address(addr5)) - self.assertEqual(addr6, ipaddr.IPv6Address(addr6)) - - def testCompressIPv6Address(self): - test_addresses = { - '1:2:3:4:5:6:7:8': '1:2:3:4:5:6:7:8/128', - '2001:0:0:4:0:0:0:8': '2001:0:0:4::8/128', - '2001:0:0:4:5:6:7:8': '2001::4:5:6:7:8/128', - '2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128', - '2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128', - '0:0:3:0:0:0:0:ffff': '0:0:3::ffff/128', - '0:0:0:4:0:0:0:ffff': '::4:0:0:0:ffff/128', - '0:0:0:0:5:0:0:ffff': '::5:0:0:ffff/128', - '1:0:0:4:0:0:7:8': '1::4:0:0:7:8/128', - '0:0:0:0:0:0:0:0': '::/128', - '0:0:0:0:0:0:0:0/0': '::/0', - '0:0:0:0:0:0:0:1': '::1/128', - '2001:0658:022a:cafe:0000:0000:0000:0000/66': - '2001:658:22a:cafe::/66', - '::1.2.3.4': '::102:304/128', - '1:2:3:4:5:ffff:1.2.3.4': '1:2:3:4:5:ffff:102:304/128', - '::7:6:5:4:3:2:1': '0:7:6:5:4:3:2:1/128', - '::7:6:5:4:3:2:0': '0:7:6:5:4:3:2:0/128', - '7:6:5:4:3:2:1::': '7:6:5:4:3:2:1:0/128', - '0:6:5:4:3:2:1::': '0:6:5:4:3:2:1:0/128', - } - for uncompressed, compressed in test_addresses.items(): - self.assertEqual(compressed, str(ipaddr.IPv6Network(uncompressed))) - - def testExplodeShortHandIpStr(self): - addr1 = ipaddr.IPv6Network('2001::1') - addr2 = ipaddr.IPv6Address('2001:0:5ef5:79fd:0:59d:a0e5:ba1') - self.assertEqual('2001:0000:0000:0000:0000:0000:0000:0001', - addr1._explode_shorthand_ip_string(str(addr1.ip))) - self.assertEqual('0000:0000:0000:0000:0000:0000:0000:0001', - ipaddr.IPv6Network('::1/128').exploded) - # issue 77 - self.assertEqual('2001:0000:5ef5:79fd:0000:059d:a0e5:0ba1', - addr2.exploded) - - def testIntRepresentation(self): - self.assertEqual(16909060, int(self.ipv4)) - self.assertEqual(42540616829182469433547762482097946625, int(self.ipv6)) - - def testHexRepresentation(self): - self.assertEqual(hex(0x1020304), - hex(self.ipv4)) - - self.assertEqual(hex(0x20010658022ACAFE0200000000000001), - hex(self.ipv6)) - - # backwards compatibility - def testBackwardsCompability(self): - self.assertEqual(ipaddr.CollapseAddrList( - [ipaddr.IPNetwork('1.1.0.0/24'), ipaddr.IPNetwork('1.1.1.0/24')]), - [ipaddr.IPNetwork('1.1.0.0/23')]) - - self.assertEqual(ipaddr.IPNetwork('::42:0/112').AddressExclude( - ipaddr.IPNetwork('::42:8000/113')), - [ipaddr.IPNetwork('::42:0/113')]) - - self.assertTrue(ipaddr.IPNetwork('1::/8').CompareNetworks( - ipaddr.IPNetwork('2::/9')) < 0) - - self.assertEqual(ipaddr.IPNetwork('1::/16').Contains( - ipaddr.IPNetwork('2::/16')), False) - - self.assertEqual(ipaddr.IPNetwork('0.0.0.0/0').Subnet(), - [ipaddr.IPNetwork('0.0.0.0/1'), - ipaddr.IPNetwork('128.0.0.0/1')]) - self.assertEqual(ipaddr.IPNetwork('::/127').Subnet(), - [ipaddr.IPNetwork('::/128'), - ipaddr.IPNetwork('::1/128')]) - - self.assertEqual(ipaddr.IPNetwork('1.0.0.0/32').Supernet(), - ipaddr.IPNetwork('1.0.0.0/31')) - self.assertEqual(ipaddr.IPNetwork('::/121').Supernet(), - ipaddr.IPNetwork('::/120')) - - self.assertEqual(ipaddr.IPNetwork('10.0.0.2').IsRFC1918(), True) - self.assertEqual(ipaddr.IPNetwork('10.0.0.0').IsMulticast(), False) - self.assertEqual(ipaddr.IPNetwork('127.255.255.255').IsLoopback(), True) - self.assertEqual(ipaddr.IPNetwork('169.255.255.255').IsLinkLocal(), - False) - - def testForceVersion(self): - self.assertEqual(ipaddr.IPNetwork(1).version, 4) - self.assertEqual(ipaddr.IPNetwork(1, version=6).version, 6) - - def testWithStar(self): - self.assertEqual(str(self.ipv4.with_prefixlen), "1.2.3.4/24") - self.assertEqual(str(self.ipv4.with_netmask), "1.2.3.4/255.255.255.0") - self.assertEqual(str(self.ipv4.with_hostmask), "1.2.3.4/0.0.0.255") - - self.assertEqual(str(self.ipv6.with_prefixlen), - '2001:658:22a:cafe:200::1/64') - # rfc3513 sec 2.3 says that ipv6 only uses cidr notation for - # subnets - self.assertEqual(str(self.ipv6.with_netmask), - '2001:658:22a:cafe:200::1/64') - # this probably don't make much sense, but it's included for - # compatibility with ipv4 - self.assertEqual(str(self.ipv6.with_hostmask), - '2001:658:22a:cafe:200::1/::ffff:ffff:ffff:ffff') - - def testNetworkElementCaching(self): - # V4 - make sure we're empty - self.assertFalse(self.ipv4._cache.has_key('network')) - self.assertFalse(self.ipv4._cache.has_key('broadcast')) - self.assertFalse(self.ipv4._cache.has_key('hostmask')) - - # V4 - populate and test - self.assertEqual(self.ipv4.network, ipaddr.IPv4Address('1.2.3.0')) - self.assertEqual(self.ipv4.broadcast, ipaddr.IPv4Address('1.2.3.255')) - self.assertEqual(self.ipv4.hostmask, ipaddr.IPv4Address('0.0.0.255')) - - # V4 - check we're cached - self.assertTrue(self.ipv4._cache.has_key('network')) - self.assertTrue(self.ipv4._cache.has_key('broadcast')) - self.assertTrue(self.ipv4._cache.has_key('hostmask')) - - # V6 - make sure we're empty - self.assertFalse(self.ipv6._cache.has_key('network')) - self.assertFalse(self.ipv6._cache.has_key('broadcast')) - self.assertFalse(self.ipv6._cache.has_key('hostmask')) - - # V6 - populate and test - self.assertEqual(self.ipv6.network, - ipaddr.IPv6Address('2001:658:22a:cafe::')) - self.assertEqual(self.ipv6.broadcast, ipaddr.IPv6Address( - '2001:658:22a:cafe:ffff:ffff:ffff:ffff')) - self.assertEqual(self.ipv6.hostmask, - ipaddr.IPv6Address('::ffff:ffff:ffff:ffff')) - - # V6 - check we're cached - self.assertTrue(self.ipv6._cache.has_key('network')) - self.assertTrue(self.ipv6._cache.has_key('broadcast')) - self.assertTrue(self.ipv6._cache.has_key('hostmask')) - - def testTeredo(self): - # stolen from wikipedia - server = ipaddr.IPv4Address('65.54.227.120') - client = ipaddr.IPv4Address('192.0.2.45') - teredo_addr = '2001:0000:4136:e378:8000:63bf:3fff:fdd2' - self.assertEqual((server, client), - ipaddr.IPAddress(teredo_addr).teredo) - bad_addr = '2000::4136:e378:8000:63bf:3fff:fdd2' - self.assertFalse(ipaddr.IPAddress(bad_addr).teredo) - bad_addr = '2001:0001:4136:e378:8000:63bf:3fff:fdd2' - self.assertFalse(ipaddr.IPAddress(bad_addr).teredo) - - # i77 - teredo_addr = ipaddr.IPv6Address('2001:0:5ef5:79fd:0:59d:a0e5:ba1') - self.assertEqual((ipaddr.IPv4Address('94.245.121.253'), - ipaddr.IPv4Address('95.26.244.94')), - teredo_addr.teredo) - - - def testsixtofour(self): - sixtofouraddr = ipaddr.IPAddress('2002:ac1d:2d64::1') - bad_addr = ipaddr.IPAddress('2000:ac1d:2d64::1') - self.assertEqual(ipaddr.IPv4Address('172.29.45.100'), - sixtofouraddr.sixtofour) - self.assertFalse(bad_addr.sixtofour) - - -if __name__ == '__main__': - unittest.main() diff --git a/contrib/ipaddr-py/setup.py b/contrib/ipaddr-py/setup.py deleted file mode 100755 index 33564320e45..00000000000 --- a/contrib/ipaddr-py/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2008 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from distutils.core import setup - -import ipaddr - - -setup(name='ipaddr', - maintainer='Google', - maintainer_email='ipaddr-py-dev@googlegroups.com', - version=ipaddr.__version__, - url='http://code.google.com/p/ipaddr-py/', - license='Apache License, Version 2.0', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: OS Independent', - 'Topic :: Internet', - 'Topic :: Software Development :: Libraries', - 'Topic :: System :: Networking'], - py_modules=['ipaddr']) diff --git a/contrib/ipaddr-py/test-2to3.sh b/contrib/ipaddr-py/test-2to3.sh deleted file mode 100755 index 408d665bcc2..00000000000 --- a/contrib/ipaddr-py/test-2to3.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# Converts the python2 ipaddr files to python3 and runs the unit tests -# with both python versions. - -mkdir -p 2to3output && \ -cp -f *.py 2to3output && \ -( cd 2to3output && 2to3 . | patch -p0 ) && \ -py3version=$(python3 --version 2>&1) && \ -echo -e "\nTesting with ${py3version}" && \ -python3 2to3output/ipaddr_test.py && \ -rm -r 2to3output && \ -pyversion=$(python --version 2>&1) && \ -echo -e "\nTesting with ${pyversion}" && \ -./ipaddr_test.py diff --git a/contrib/macfuse/mount_darwin.c b/contrib/macfuse/mount_darwin.c index 10eff204bc6..d1d1c34e761 100644 --- a/contrib/macfuse/mount_darwin.c +++ b/contrib/macfuse/mount_darwin.c @@ -34,16 +34,15 @@ #include "fuse_param.h" #include "fuse_ioctl.h" -#include "glusterfs.h" -#include "logging.h" -#include "common-utils.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/logging.h" +#include "glusterfs/common-utils.h" #define GFFUSE_LOGERR(...) \ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__) int -gf_fuse_mount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, +gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mnt_pid, int status_fd) /* Not used on OS X */ { int fd = 0; @@ -95,7 +94,7 @@ gf_fuse_mount (const char *mountpoint, char *fsname, } /* sysctlbyname() includes the trailing '\0' in version_len */ - version_len_desired = strlen("2.x.y") + 1; + version_len_desired = sizeof ("2.x.y"); if (version_len != version_len_desired) { gf_log ("glusterfs-fuse", GF_LOG_ERROR, diff --git a/contrib/mount/mntent.c b/contrib/mount/mntent.c index e9b448845a7..9a7e5f39bdb 100644 --- a/contrib/mount/mntent.c +++ b/contrib/mount/mntent.c @@ -36,6 +36,7 @@ */ #if !defined(GF_LINUX_HOST_OS) + #include <stdlib.h> #include <string.h> #include <sys/param.h> @@ -49,166 +50,209 @@ typedef struct statvfs gf_statfs_t; typedef struct statfs gf_statfs_t; #endif -static int pos = -1; -static int mntsize = -1; -static struct mntent _mntent; +typedef struct _mntent_state { + struct mntent mntent; + gf_statfs_t *statfs; + int count; + int pos; + /* A buffer big enough to store all defined flags as a string. + * Increase it if necessary when more flags are defined. */ + char buf[256]; +} mntent_state_t; + +typedef struct _mntflag { + unsigned long value; + const char *on; + const char *off; +} mntflag_t; + +static mntflag_t mntflags[] = { + { MNT_RDONLY, "ro", "rw" }, + { MNT_SYNCHRONOUS, "sync", NULL }, + { MNT_NOEXEC, "noexec", NULL }, + { MNT_NOSUID, "nosuid", NULL }, +#if !defined(__FreeBSD__) + { MNT_NODEV, "nodev", NULL }, +#endif /* __FreeBSD__ */ + { MNT_UNION, "union", NULL }, + { MNT_ASYNC, "async", NULL }, +#if !defined(GF_DARWIN_HOST_OS) + { MNT_NOATIME, "noatime", NULL }, +#if !defined(__NetBSD__) + { MNT_NOCLUSTERR, "noclusterr", NULL }, + { MNT_NOCLUSTERW, "noclusterw", NULL }, + { MNT_NOSYMFOLLOW, "nosymfollow", NULL }, + { MNT_SUIDDIR, "suiddir", NULL }, +#endif /* !__NetBSD__ */ +#endif /* !GF_DARWIN_HOST_OS */ + { 0, NULL, NULL } +}; char * hasmntopt (const struct mntent *mnt, const char *option) { - int found; char *opt, *optbuf; + int len; optbuf = strdup(mnt->mnt_opts); - found = 0; - for (opt = optbuf; (opt = strtok(opt, " ")) != NULL; opt = NULL) { - if (!strcasecmp(opt, option)) { - opt = opt - optbuf + mnt->mnt_opts; - free (optbuf); - return (opt); + if (optbuf == NULL) { + return NULL; + } + + opt = optbuf; + len = 0; + while (*opt) { + while (opt[len] != 0) { + if (opt[len] == ' ') { + opt[len++] = 0; + break; + } + len++; + } + if ((*opt != 0) && (strcasecmp(opt, option) == 0)) { + break; } + opt += len; + len = 0; } - free (optbuf); - return (NULL); + free(optbuf); + if (len == 0) { + return NULL; + } + + return opt - optbuf + mnt->mnt_opts; } -static char * -concatopt (char *s0, const char *s1) +static int +writeopt(const char *text, char *buf, int buflen, int pos) { - size_t i; - char *cp; - - if (s1 == NULL || *s1 == '\0') - return s0; - if (s0 && *s0) { - i = strlen(s0) + strlen(s1) + 1 + 1; - if ((cp = (char *)malloc(i)) == NULL) - return (NULL); - (void)snprintf(cp, i, "%s %s", s0, s1); - } else - cp = strdup(s1); - - if (s0) - free(s0); - return (cp); -} + int len; + + /* buflen must be > 0 */ + + if (text == NULL) { + return pos; + } + + buf += pos; + if (pos > 0) { + /* We are sure we have at least one byte to store the space. + * We don't need to check buflen here. */ + *buf++ = ' '; + pos++; + } + len = strlen(text) + 1; + pos += len; + if (pos >= buflen) { + /* There won't be enough space for the text and the + * terminating null character. We copy as much as we can + * of the text and mark the end of the string with '...' */ + memcpy(buf, text, buflen - pos + len); + if (buflen > 3) { + strcpy(buf + buflen - 4, "..."); + } else { + strncpy(buf, "...", buflen - 1); + buf[buflen - 1] = 0; + } + pos = buflen; + } else { + memcpy(buf, text, len); + } + return pos; +} static char * -flags2opts (int flags) +flags2opts (int flags, char *buf, int buflen) { - char *res; - res = NULL; - res = concatopt(res, (flags & MNT_RDONLY) ? "ro" : "rw"); - if (flags & MNT_SYNCHRONOUS) res = concatopt(res, "sync"); - if (flags & MNT_NOEXEC) res = concatopt(res, "noexec"); - if (flags & MNT_NOSUID) res = concatopt(res, "nosuid"); -#if !defined(__FreeBSD__) - if (flags & MNT_NODEV) res = concatopt(res, "nodev"); -#endif /* __FreeBSD__ */ - if (flags & MNT_UNION) res = concatopt(res, "union"); - if (flags & MNT_ASYNC) res = concatopt(res, "async"); -#if !defined(GF_DARWIN_HOST_OS) - if (flags & MNT_NOATIME) res = concatopt(res, "noatime"); -#if !defined(__NetBSD__) - if (flags & MNT_NOCLUSTERR) res = concatopt(res, "noclusterr"); - if (flags & MNT_NOCLUSTERW) res = concatopt(res, "noclusterw"); - if (flags & MNT_NOSYMFOLLOW) res = concatopt(res, "nosymfollow"); - if (flags & MNT_SUIDDIR) res = concatopt(res, "suiddir"); -#endif /* !__NetBSD__ */ -#endif /* !GF_DARWIN_HOS_OS */ - return res; + char other[16]; + mntflag_t *flg; + int pos; + + if (buflen == 0) { + return NULL; + } + + pos = 0; + for (flg = mntflags; flg->value != 0; flg++) { + pos = writeopt((flags & flg->value) == 0 ? flg->off : flg->on, + buf, buflen, pos); + flags &= ~flg->value; + } + + if (flags != 0) { + sprintf(other, "[0x%x]", flags); + writeopt(other, buf, buflen, pos); + } + + return buf; } -static struct mntent * -statfs_to_mntent (gf_statfs_t *mntbuf) +static void +statfs_to_mntent (struct mntent *mntent, gf_statfs_t *mntbuf, char *buf, + int buflen) { - static char opts_buf[40], *tmp; int f_flags; - _mntent.mnt_fsname = mntbuf->f_mntfromname; - _mntent.mnt_dir = mntbuf->f_mntonname; - _mntent.mnt_type = mntbuf->f_fstypename; + mntent->mnt_fsname = mntbuf->f_mntfromname; + mntent->mnt_dir = mntbuf->f_mntonname; + mntent->mnt_type = mntbuf->f_fstypename; #ifdef __NetBSD__ f_flags = mntbuf->f_flag; #else f_flags = mntbuf->f_flags; #endif - tmp = flags2opts (f_flags); - if (tmp) { - opts_buf[sizeof(opts_buf)-1] = '\0'; - strncpy (opts_buf, tmp, sizeof(opts_buf)-1); - free (tmp); - } else { - *opts_buf = '\0'; - } - _mntent.mnt_opts = opts_buf; - _mntent.mnt_freq = _mntent.mnt_passno = 0; - return (&_mntent); + mntent->mnt_opts = flags2opts (f_flags, buf, buflen); + + mntent->mnt_freq = mntent->mnt_passno = 0; } struct mntent * -getmntent (FILE *fp) +getmntent_r (FILE *fp, struct mntent *mntent, char *buf, int buflen) { - gf_statfs_t *mntbuf; + mntent_state_t *state = (mntent_state_t *)fp; - if (!fp) + if (state->pos >= state->count) { return NULL; - - if (pos == -1 || mntsize == -1) - mntsize = getmntinfo (&mntbuf, MNT_NOWAIT); - - ++pos; - if (pos == mntsize) { - pos = mntsize = -1; - return (NULL); } - return (statfs_to_mntent (&mntbuf[pos])); + statfs_to_mntent(mntent, &state->statfs[state->pos++], buf, buflen); + + return mntent; } -/* - Careful using this function ``buffer`` and ``bufsize`` are - ignored since there is no stream with strings to populate - them on OSX or NetBSD, if one wishes to populate them then - perhaps a new function should be written in this source file - which uses 'getmntinfo()' to stringify the mntent's -*/ - -struct mntent *getmntent_r (FILE *fp, struct mntent *result, - char *buffer, int bufsize) +struct mntent * +getmntent (FILE *fp) { - struct mntent *ment = NULL; - - if (!fp) - return NULL; + mntent_state_t *state = (mntent_state_t *)fp; - flockfile (fp); - ment = getmntent (fp); - memcpy (result, ment, sizeof(*ment)); - funlockfile (fp); - - return result; + return getmntent_r(fp, &state->mntent, state->buf, + sizeof(state->buf)); } FILE * setmntent (const char *filename, const char *type) { - FILE *fp = NULL; -#ifdef GF_DARWIN_HOST_OS - fp = fopen (filename, "w"); -#else - fp = fopen (filename, type); -#endif - return fp; + mntent_state_t *state; + + /* We don't really need to access any file so we'll use the FILE* as + * a fake file to store state information. + */ + + state = malloc(sizeof(mntent_state_t)); + if (state != NULL) { + state->pos = 0; + state->count = getmntinfo(&state->statfs, MNT_NOWAIT); + } + + return (FILE *)state; } int endmntent (FILE *fp) { - if (fp) - fclose (fp); + free(fp); return 1; /* endmntent() always returns 1 */ } diff --git a/contrib/qemu/block.c b/contrib/qemu/block.c deleted file mode 100644 index b56024113b8..00000000000 --- a/contrib/qemu/block.c +++ /dev/null @@ -1,4604 +0,0 @@ -/* - * QEMU System Emulator block driver - * - * 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 "config-host.h" -#include "qemu-common.h" -#include "trace.h" -#include "monitor/monitor.h" -#include "block/block_int.h" -#include "block/blockjob.h" -#include "qemu/module.h" -#include "qapi/qmp/qjson.h" -#include "sysemu/sysemu.h" -#include "qemu/notify.h" -#include "block/coroutine.h" -#include "qmp-commands.h" -#include "qemu/timer.h" - -#ifdef CONFIG_BSD -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/queue.h> -#ifndef __DragonFly__ -#include <sys/disk.h> -#endif -#endif - -#ifdef _WIN32 -#include <windows.h> -#endif - -#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ - -typedef enum { - BDRV_REQ_COPY_ON_READ = 0x1, - BDRV_REQ_ZERO_WRITE = 0x2, -} BdrvRequestFlags; - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov); -static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov); -static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, - BdrvRequestFlags flags); -static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, - BdrvRequestFlags flags); -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - bool is_write); -static void coroutine_fn bdrv_co_do_rw(void *opaque); -static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, - int64_t sector_num, int nb_sectors); - -static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors, - bool is_write, double elapsed_time, uint64_t *wait); -static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write, - double elapsed_time, uint64_t *wait); -static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, - bool is_write, int64_t *wait); - -static QTAILQ_HEAD(, BlockDriverState) bdrv_states = - QTAILQ_HEAD_INITIALIZER(bdrv_states); - -static QLIST_HEAD(, BlockDriver) bdrv_drivers = - QLIST_HEAD_INITIALIZER(bdrv_drivers); - -/* If non-zero, use only whitelisted block drivers */ -static int use_bdrv_whitelist; - -#ifdef _WIN32 -static int is_windows_drive_prefix(const char *filename) -{ - return (((filename[0] >= 'a' && filename[0] <= 'z') || - (filename[0] >= 'A' && filename[0] <= 'Z')) && - filename[1] == ':'); -} - -int is_windows_drive(const char *filename) -{ - if (is_windows_drive_prefix(filename) && - filename[2] == '\0') - return 1; - if (strstart(filename, "\\\\.\\", NULL) || - strstart(filename, "//./", NULL)) - return 1; - return 0; -} -#endif - -/* throttling disk I/O limits */ -void bdrv_io_limits_disable(BlockDriverState *bs) -{ - bs->io_limits_enabled = false; - - while (qemu_co_queue_next(&bs->throttled_reqs)); - - if (bs->block_timer) { - qemu_del_timer(bs->block_timer); - qemu_free_timer(bs->block_timer); - bs->block_timer = NULL; - } - - bs->slice_start = 0; - bs->slice_end = 0; -} - -static void bdrv_block_timer(void *opaque) -{ - BlockDriverState *bs = opaque; - - qemu_co_queue_next(&bs->throttled_reqs); -} - -void bdrv_io_limits_enable(BlockDriverState *bs) -{ - qemu_co_queue_init(&bs->throttled_reqs); - bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs); - bs->io_limits_enabled = true; -} - -bool bdrv_io_limits_enabled(BlockDriverState *bs) -{ - BlockIOLimit *io_limits = &bs->io_limits; - return io_limits->bps[BLOCK_IO_LIMIT_READ] - || io_limits->bps[BLOCK_IO_LIMIT_WRITE] - || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] - || io_limits->iops[BLOCK_IO_LIMIT_READ] - || io_limits->iops[BLOCK_IO_LIMIT_WRITE] - || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; -} - -static void bdrv_io_limits_intercept(BlockDriverState *bs, - bool is_write, int nb_sectors) -{ - int64_t wait_time = -1; - - if (!qemu_co_queue_empty(&bs->throttled_reqs)) { - qemu_co_queue_wait(&bs->throttled_reqs); - } - - /* In fact, we hope to keep each request's timing, in FIFO mode. The next - * throttled requests will not be dequeued until the current request is - * allowed to be serviced. So if the current request still exceeds the - * limits, it will be inserted to the head. All requests followed it will - * be still in throttled_reqs queue. - */ - - while (bdrv_exceed_io_limits(bs, nb_sectors, is_write, &wait_time)) { - qemu_mod_timer(bs->block_timer, - wait_time + qemu_get_clock_ns(vm_clock)); - qemu_co_queue_wait_insert_head(&bs->throttled_reqs); - } - - qemu_co_queue_next(&bs->throttled_reqs); -} - -/* check if the path starts with "<protocol>:" */ -static int path_has_protocol(const char *path) -{ - const char *p; - -#ifdef _WIN32 - if (is_windows_drive(path) || - is_windows_drive_prefix(path)) { - return 0; - } - p = path + strcspn(path, ":/\\"); -#else - p = path + strcspn(path, ":/"); -#endif - - return *p == ':'; -} - -int path_is_absolute(const char *path) -{ -#ifdef _WIN32 - /* specific case for names like: "\\.\d:" */ - if (is_windows_drive(path) || is_windows_drive_prefix(path)) { - return 1; - } - return (*path == '/' || *path == '\\'); -#else - return (*path == '/'); -#endif -} - -/* if filename is absolute, just copy it to dest. Otherwise, build a - path to it by considering it is relative to base_path. URL are - supported. */ -void path_combine(char *dest, int dest_size, - const char *base_path, - const char *filename) -{ - const char *p, *p1; - int len; - - if (dest_size <= 0) - return; - if (path_is_absolute(filename)) { - pstrcpy(dest, dest_size, filename); - } else { - p = strchr(base_path, ':'); - if (p) - p++; - else - p = base_path; - p1 = strrchr(base_path, '/'); -#ifdef _WIN32 - { - const char *p2; - p2 = strrchr(base_path, '\\'); - if (!p1 || p2 > p1) - p1 = p2; - } -#endif - if (p1) - p1++; - else - p1 = base_path; - if (p1 > p) - p = p1; - len = p - base_path; - if (len > dest_size - 1) - len = dest_size - 1; - memcpy(dest, base_path, len); - dest[len] = '\0'; - pstrcat(dest, dest_size, filename); - } -} - -void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz) -{ - if (bs->backing_file[0] == '\0' || path_has_protocol(bs->backing_file)) { - pstrcpy(dest, sz, bs->backing_file); - } else { - path_combine(dest, sz, bs->filename, bs->backing_file); - } -} - -void bdrv_register(BlockDriver *bdrv) -{ - /* Block drivers without coroutine functions need emulation */ - if (!bdrv->bdrv_co_readv) { - bdrv->bdrv_co_readv = bdrv_co_readv_em; - bdrv->bdrv_co_writev = bdrv_co_writev_em; - - /* bdrv_co_readv_em()/brdv_co_writev_em() work in terms of aio, so if - * the block driver lacks aio we need to emulate that too. - */ - if (!bdrv->bdrv_aio_readv) { - /* add AIO emulation layer */ - bdrv->bdrv_aio_readv = bdrv_aio_readv_em; - bdrv->bdrv_aio_writev = bdrv_aio_writev_em; - } - } - - QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list); -} - -/* create a new block device (by default it is empty) */ -BlockDriverState *bdrv_new(const char *device_name) -{ - BlockDriverState *bs; - - bs = g_malloc0(sizeof(BlockDriverState)); - pstrcpy(bs->device_name, sizeof(bs->device_name), device_name); - if (device_name[0] != '\0') { - QTAILQ_INSERT_TAIL(&bdrv_states, bs, list); - } - bdrv_iostatus_disable(bs); - notifier_list_init(&bs->close_notifiers); - notifier_with_return_list_init(&bs->before_write_notifiers); - - return bs; -} - -void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify) -{ - notifier_list_add(&bs->close_notifiers, notify); -} - -BlockDriver *bdrv_find_format(const char *format_name) -{ - BlockDriver *drv1; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (!strcmp(drv1->format_name, format_name)) { - return drv1; - } - } - return NULL; -} - -static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only) -{ - static const char *whitelist_rw[] = { - CONFIG_BDRV_RW_WHITELIST - }; - static const char *whitelist_ro[] = { - CONFIG_BDRV_RO_WHITELIST - }; - const char **p; - - if (!whitelist_rw[0] && !whitelist_ro[0]) { - return 1; /* no whitelist, anything goes */ - } - - for (p = whitelist_rw; *p; p++) { - if (!strcmp(drv->format_name, *p)) { - return 1; - } - } - if (read_only) { - for (p = whitelist_ro; *p; p++) { - if (!strcmp(drv->format_name, *p)) { - return 1; - } - } - } - return 0; -} - -BlockDriver *bdrv_find_whitelisted_format(const char *format_name, - bool read_only) -{ - BlockDriver *drv = bdrv_find_format(format_name); - return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL; -} - -typedef struct CreateCo { - BlockDriver *drv; - char *filename; - QEMUOptionParameter *options; - int ret; -} CreateCo; - -static void coroutine_fn bdrv_create_co_entry(void *opaque) -{ - CreateCo *cco = opaque; - assert(cco->drv); - - cco->ret = cco->drv->bdrv_create(cco->filename, cco->options); -} - -int bdrv_create(BlockDriver *drv, const char* filename, - QEMUOptionParameter *options) -{ - int ret; - - Coroutine *co; - CreateCo cco = { - .drv = drv, - .filename = g_strdup(filename), - .options = options, - .ret = NOT_DONE, - }; - - if (!drv->bdrv_create) { - ret = -ENOTSUP; - goto out; - } - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_create_co_entry(&cco); - } else { - co = qemu_coroutine_create(bdrv_create_co_entry); - qemu_coroutine_enter(co, &cco); - while (cco.ret == NOT_DONE) { - qemu_aio_wait(); - } - } - - ret = cco.ret; - -out: - g_free(cco.filename); - return ret; -} - -int bdrv_create_file(const char* filename, QEMUOptionParameter *options) -{ - BlockDriver *drv; - - drv = bdrv_find_protocol(filename, true); - if (drv == NULL) { - return -ENOENT; - } - - return bdrv_create(drv, filename, options); -} - -/* - * Create a uniquely-named empty temporary file. - * Return 0 upon success, otherwise a negative errno value. - */ -int get_tmp_filename(char *filename, int size) -{ -#ifdef _WIN32 - char temp_dir[MAX_PATH]; - /* GetTempFileName requires that its output buffer (4th param) - have length MAX_PATH or greater. */ - assert(size >= MAX_PATH); - return (GetTempPath(MAX_PATH, temp_dir) - && GetTempFileName(temp_dir, "qem", 0, filename) - ? 0 : -GetLastError()); -#else - int fd; - const char *tmpdir; - tmpdir = getenv("TMPDIR"); - if (!tmpdir) - tmpdir = "/tmp"; - if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { - return -EOVERFLOW; - } - fd = mkstemp(filename); - if (fd < 0) { - return -errno; - } - if (close(fd) != 0) { - unlink(filename); - return -errno; - } - return 0; -#endif -} - -/* - * Detect host devices. By convention, /dev/cdrom[N] is always - * recognized as a host CDROM. - */ -static BlockDriver *find_hdev_driver(const char *filename) -{ - int score_max = 0, score; - BlockDriver *drv = NULL, *d; - - QLIST_FOREACH(d, &bdrv_drivers, list) { - if (d->bdrv_probe_device) { - score = d->bdrv_probe_device(filename); - if (score > score_max) { - score_max = score; - drv = d; - } - } - } - - return drv; -} - -BlockDriver *bdrv_find_protocol(const char *filename, - bool allow_protocol_prefix) -{ - BlockDriver *drv1; - char protocol[128]; - int len; - const char *p; - - /* TODO Drivers without bdrv_file_open must be specified explicitly */ - - /* - * XXX(hch): we really should not let host device detection - * override an explicit protocol specification, but moving this - * later breaks access to device names with colons in them. - * Thanks to the brain-dead persistent naming schemes on udev- - * based Linux systems those actually are quite common. - */ - drv1 = find_hdev_driver(filename); - if (drv1) { - return drv1; - } - - if (!path_has_protocol(filename) || !allow_protocol_prefix) { - return bdrv_find_format("file"); - } - - p = strchr(filename, ':'); - assert(p != NULL); - len = p - filename; - if (len > sizeof(protocol) - 1) - len = sizeof(protocol) - 1; - memcpy(protocol, filename, len); - protocol[len] = '\0'; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (drv1->protocol_name && - !strcmp(drv1->protocol_name, protocol)) { - return drv1; - } - } - return NULL; -} - -static int find_image_format(BlockDriverState *bs, const char *filename, - BlockDriver **pdrv) -{ - int score, score_max; - BlockDriver *drv1, *drv; - uint8_t buf[2048]; - int ret = 0; - - /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ - if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { - drv = bdrv_find_format("raw"); - if (!drv) { - ret = -ENOENT; - } - *pdrv = drv; - return ret; - } - - ret = bdrv_pread(bs, 0, buf, sizeof(buf)); - if (ret < 0) { - *pdrv = NULL; - return ret; - } - - score_max = 0; - drv = NULL; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (drv1->bdrv_probe) { - score = drv1->bdrv_probe(buf, ret, filename); - if (score > score_max) { - score_max = score; - drv = drv1; - } - } - } - if (!drv) { - ret = -ENOENT; - } - *pdrv = drv; - return ret; -} - -/** - * Set the current 'total_sectors' value - */ -static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) -{ - BlockDriver *drv = bs->drv; - - /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */ - if (bs->sg) - return 0; - - /* query actual device if possible, otherwise just trust the hint */ - if (drv->bdrv_getlength) { - int64_t length = drv->bdrv_getlength(bs); - if (length < 0) { - return length; - } - hint = length >> BDRV_SECTOR_BITS; - } - - bs->total_sectors = hint; - return 0; -} - -/** - * Set open flags for a given discard mode - * - * Return 0 on success, -1 if the discard mode was invalid. - */ -int bdrv_parse_discard_flags(const char *mode, int *flags) -{ - *flags &= ~BDRV_O_UNMAP; - - if (!strcmp(mode, "off") || !strcmp(mode, "ignore")) { - /* do nothing */ - } else if (!strcmp(mode, "on") || !strcmp(mode, "unmap")) { - *flags |= BDRV_O_UNMAP; - } else { - return -1; - } - - return 0; -} - -/** - * Set open flags for a given cache mode - * - * Return 0 on success, -1 if the cache mode was invalid. - */ -int bdrv_parse_cache_flags(const char *mode, int *flags) -{ - *flags &= ~BDRV_O_CACHE_MASK; - - if (!strcmp(mode, "off") || !strcmp(mode, "none")) { - *flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; - } else if (!strcmp(mode, "directsync")) { - *flags |= BDRV_O_NOCACHE; - } else if (!strcmp(mode, "writeback")) { - *flags |= BDRV_O_CACHE_WB; - } else if (!strcmp(mode, "unsafe")) { - *flags |= BDRV_O_CACHE_WB; - *flags |= BDRV_O_NO_FLUSH; - } else if (!strcmp(mode, "writethrough")) { - /* this is the default */ - } else { - return -1; - } - - return 0; -} - -/** - * The copy-on-read flag is actually a reference count so multiple users may - * use the feature without worrying about clobbering its previous state. - * Copy-on-read stays enabled until all users have called to disable it. - */ -void bdrv_enable_copy_on_read(BlockDriverState *bs) -{ - bs->copy_on_read++; -} - -void bdrv_disable_copy_on_read(BlockDriverState *bs) -{ - assert(bs->copy_on_read > 0); - bs->copy_on_read--; -} - -static int bdrv_open_flags(BlockDriverState *bs, int flags) -{ - int open_flags = flags | BDRV_O_CACHE_WB; - - /* - * Clear flags that are internal to the block layer before opening the - * image. - */ - open_flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); - - /* - * Snapshots should be writable. - */ - if (bs->is_temporary) { - open_flags |= BDRV_O_RDWR; - } - - return open_flags; -} - -/* - * Common part for opening disk images and files - * - * Removes all processed options from *options. - */ -static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, - QDict *options, int flags, BlockDriver *drv) -{ - int ret, open_flags; - const char *filename; - - assert(drv != NULL); - assert(bs->file == NULL); - assert(options != NULL && bs->options != options); - - if (file != NULL) { - filename = file->filename; - } else { - filename = qdict_get_try_str(options, "filename"); - } - - trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); - - /* bdrv_open() with directly using a protocol as drv. This layer is already - * opened, so assign it to bs (while file becomes a closed BlockDriverState) - * and return immediately. */ - if (file != NULL && drv->bdrv_file_open) { - bdrv_swap(file, bs); - return 0; - } - - bs->open_flags = flags; - bs->buffer_alignment = 512; - open_flags = bdrv_open_flags(bs, flags); - bs->read_only = !(open_flags & BDRV_O_RDWR); - - if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) { - return -ENOTSUP; - } - - assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ - if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) { - bdrv_enable_copy_on_read(bs); - } - - if (filename != NULL) { - pstrcpy(bs->filename, sizeof(bs->filename), filename); - } else { - bs->filename[0] = '\0'; - } - - bs->drv = drv; - bs->opaque = g_malloc0(drv->instance_size); - - bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB); - - /* Open the image, either directly or using a protocol */ - if (drv->bdrv_file_open) { - assert(file == NULL); - assert(drv->bdrv_parse_filename || filename != NULL); - ret = drv->bdrv_file_open(bs, options, open_flags); - } else { - if (file == NULL) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't use '%s' as a " - "block driver for the protocol level", - drv->format_name); - ret = -EINVAL; - goto free_and_fail; - } - assert(file != NULL); - bs->file = file; - ret = drv->bdrv_open(bs, options, open_flags); - } - - if (ret < 0) { - goto free_and_fail; - } - - ret = refresh_total_sectors(bs, bs->total_sectors); - if (ret < 0) { - goto free_and_fail; - } - -#ifndef _WIN32 - if (bs->is_temporary) { - assert(filename != NULL); - unlink(filename); - } -#endif - return 0; - -free_and_fail: - bs->file = NULL; - g_free(bs->opaque); - bs->opaque = NULL; - bs->drv = NULL; - return ret; -} - -/* - * Opens a file using a protocol (file, host_device, nbd, ...) - * - * options is a QDict of options to pass to the block drivers, or NULL for an - * empty set of options. The reference to the QDict belongs to the block layer - * after the call (even on failure), so if the caller intends to reuse the - * dictionary, it needs to use QINCREF() before calling bdrv_file_open. - */ -int bdrv_file_open(BlockDriverState **pbs, const char *filename, - QDict *options, int flags) -{ - BlockDriverState *bs; - BlockDriver *drv; - const char *drvname; - bool allow_protocol_prefix = false; - int ret; - - /* NULL means an empty set of options */ - if (options == NULL) { - options = qdict_new(); - } - - bs = bdrv_new(""); - bs->options = options; - options = qdict_clone_shallow(options); - - /* Fetch the file name from the options QDict if necessary */ - if (!filename) { - filename = qdict_get_try_str(options, "filename"); - } else if (filename && !qdict_haskey(options, "filename")) { - qdict_put(options, "filename", qstring_from_str(filename)); - allow_protocol_prefix = true; - } else { - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and " - "'filename' options at the same time"); - ret = -EINVAL; - goto fail; - } - - /* Find the right block driver */ - drvname = qdict_get_try_str(options, "driver"); - if (drvname) { - drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); - qdict_del(options, "driver"); - } else if (filename) { - drv = bdrv_find_protocol(filename, allow_protocol_prefix); - if (!drv) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol"); - } - } else { - qerror_report(ERROR_CLASS_GENERIC_ERROR, - "Must specify either driver or file"); - drv = NULL; - } - - if (!drv) { - ret = -ENOENT; - goto fail; - } - - /* Parse the filename and open it */ - if (drv->bdrv_parse_filename && filename) { - Error *local_err = NULL; - drv->bdrv_parse_filename(filename, options, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - ret = -EINVAL; - goto fail; - } - qdict_del(options, "filename"); - } else if (!drv->bdrv_parse_filename && !filename) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, - "The '%s' block driver requires a file name", - drv->format_name); - ret = -EINVAL; - goto fail; - } - - ret = bdrv_open_common(bs, NULL, options, flags, drv); - if (ret < 0) { - goto fail; - } - - /* Check if any unknown options were used */ - if (qdict_size(options) != 0) { - const QDictEntry *entry = qdict_first(options); - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block protocol '%s' doesn't " - "support the option '%s'", - drv->format_name, entry->key); - ret = -EINVAL; - goto fail; - } - QDECREF(options); - - bs->growable = 1; - *pbs = bs; - return 0; - -fail: - QDECREF(options); - if (!bs->drv) { - QDECREF(bs->options); - } - bdrv_delete(bs); - return ret; -} - -/* - * Opens the backing file for a BlockDriverState if not yet open - * - * options is a QDict of options to pass to the block drivers, or NULL for an - * empty set of options. The reference to the QDict is transferred to this - * function (even on failure), so if the caller intends to reuse the dictionary, - * it needs to use QINCREF() before calling bdrv_file_open. - */ -int bdrv_open_backing_file(BlockDriverState *bs, QDict *options) -{ - char backing_filename[PATH_MAX]; - int back_flags, ret; - BlockDriver *back_drv = NULL; - - if (bs->backing_hd != NULL) { - QDECREF(options); - return 0; - } - - /* NULL means an empty set of options */ - if (options == NULL) { - options = qdict_new(); - } - - bs->open_flags &= ~BDRV_O_NO_BACKING; - if (qdict_haskey(options, "file.filename")) { - backing_filename[0] = '\0'; - } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) { - QDECREF(options); - return 0; - } - - bs->backing_hd = bdrv_new(""); - bdrv_get_full_backing_filename(bs, backing_filename, - sizeof(backing_filename)); - - if (bs->backing_format[0] != '\0') { - back_drv = bdrv_find_format(bs->backing_format); - } - - /* backing files always opened read-only */ - back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT); - - ret = bdrv_open(bs->backing_hd, - *backing_filename ? backing_filename : NULL, options, - back_flags, back_drv); - if (ret < 0) { - bdrv_delete(bs->backing_hd); - bs->backing_hd = NULL; - bs->open_flags |= BDRV_O_NO_BACKING; - return ret; - } - return 0; -} - -static void extract_subqdict(QDict *src, QDict **dst, const char *start) -{ - const QDictEntry *entry, *next; - const char *p; - - *dst = qdict_new(); - entry = qdict_first(src); - - while (entry != NULL) { - next = qdict_next(src, entry); - if (strstart(entry->key, start, &p)) { - qobject_incref(entry->value); - qdict_put_obj(*dst, p, entry->value); - qdict_del(src, entry->key); - } - entry = next; - } -} - -/* - * Opens a disk image (raw, qcow2, vmdk, ...) - * - * options is a QDict of options to pass to the block drivers, or NULL for an - * empty set of options. The reference to the QDict belongs to the block layer - * after the call (even on failure), so if the caller intends to reuse the - * dictionary, it needs to use QINCREF() before calling bdrv_open. - */ -int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, - int flags, BlockDriver *drv) -{ - int ret; - /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ - char tmp_filename[PATH_MAX + 1]; - BlockDriverState *file = NULL; - QDict *file_options = NULL; - - /* NULL means an empty set of options */ - if (options == NULL) { - options = qdict_new(); - } - - bs->options = options; - options = qdict_clone_shallow(options); - - /* For snapshot=on, create a temporary qcow2 overlay */ - if (flags & BDRV_O_SNAPSHOT) { - BlockDriverState *bs1; - int64_t total_size; - BlockDriver *bdrv_qcow2; - QEMUOptionParameter *create_options; - char backing_filename[PATH_MAX]; - - if (qdict_size(options) != 0) { - error_report("Can't use snapshot=on with driver-specific options"); - ret = -EINVAL; - goto fail; - } - assert(filename != NULL); - - /* if snapshot, we create a temporary backing file and open it - instead of opening 'filename' directly */ - - /* if there is a backing file, use it */ - bs1 = bdrv_new(""); - ret = bdrv_open(bs1, filename, NULL, 0, drv); - if (ret < 0) { - bdrv_delete(bs1); - goto fail; - } - total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK; - - bdrv_delete(bs1); - - ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); - if (ret < 0) { - goto fail; - } - - /* Real path is meaningless for protocols */ - if (path_has_protocol(filename)) { - snprintf(backing_filename, sizeof(backing_filename), - "%s", filename); - } else if (!realpath(filename, backing_filename)) { - ret = -errno; - goto fail; - } - - bdrv_qcow2 = bdrv_find_format("qcow2"); - create_options = parse_option_parameters("", bdrv_qcow2->create_options, - NULL); - - set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size); - set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE, - backing_filename); - if (drv) { - set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT, - drv->format_name); - } - - ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options); - free_option_parameters(create_options); - if (ret < 0) { - goto fail; - } - - filename = tmp_filename; - drv = bdrv_qcow2; - bs->is_temporary = 1; - } - - /* Open image file without format layer */ - if (flags & BDRV_O_RDWR) { - flags |= BDRV_O_ALLOW_RDWR; - } - - extract_subqdict(options, &file_options, "file."); - - ret = bdrv_file_open(&file, filename, file_options, - bdrv_open_flags(bs, flags | BDRV_O_UNMAP)); - if (ret < 0) { - goto fail; - } - - /* Find the right image format driver */ - if (!drv) { - ret = find_image_format(file, filename, &drv); - } - - if (!drv) { - goto unlink_and_fail; - } - - /* Open the image */ - ret = bdrv_open_common(bs, file, options, flags, drv); - if (ret < 0) { - goto unlink_and_fail; - } - - if (bs->file != file) { - bdrv_delete(file); - file = NULL; - } - - /* If there is a backing file, use it */ - if ((flags & BDRV_O_NO_BACKING) == 0) { - QDict *backing_options; - - extract_subqdict(options, &backing_options, "backing."); - ret = bdrv_open_backing_file(bs, backing_options); - if (ret < 0) { - goto close_and_fail; - } - } - - /* Check if any unknown options were used */ - if (qdict_size(options) != 0) { - const QDictEntry *entry = qdict_first(options); - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by " - "device '%s' doesn't support the option '%s'", - drv->format_name, bs->device_name, entry->key); - - ret = -EINVAL; - goto close_and_fail; - } - QDECREF(options); - - if (!bdrv_key_required(bs)) { - bdrv_dev_change_media_cb(bs, true); - } - - /* throttling disk I/O limits */ - if (bs->io_limits_enabled) { - bdrv_io_limits_enable(bs); - } - - return 0; - -unlink_and_fail: - if (file != NULL) { - bdrv_delete(file); - } - if (bs->is_temporary) { - unlink(filename); - } -fail: - QDECREF(bs->options); - QDECREF(options); - bs->options = NULL; - return ret; - -close_and_fail: - bdrv_close(bs); - QDECREF(options); - return ret; -} - -typedef struct BlockReopenQueueEntry { - bool prepared; - BDRVReopenState state; - QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry; -} BlockReopenQueueEntry; - -/* - * Adds a BlockDriverState to a simple queue for an atomic, transactional - * reopen of multiple devices. - * - * bs_queue can either be an existing BlockReopenQueue that has had QSIMPLE_INIT - * already performed, or alternatively may be NULL a new BlockReopenQueue will - * be created and initialized. This newly created BlockReopenQueue should be - * passed back in for subsequent calls that are intended to be of the same - * atomic 'set'. - * - * bs is the BlockDriverState to add to the reopen queue. - * - * flags contains the open flags for the associated bs - * - * returns a pointer to bs_queue, which is either the newly allocated - * bs_queue, or the existing bs_queue being used. - * - */ -BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, - BlockDriverState *bs, int flags) -{ - assert(bs != NULL); - - BlockReopenQueueEntry *bs_entry; - if (bs_queue == NULL) { - bs_queue = g_new0(BlockReopenQueue, 1); - QSIMPLEQ_INIT(bs_queue); - } - - if (bs->file) { - bdrv_reopen_queue(bs_queue, bs->file, flags); - } - - bs_entry = g_new0(BlockReopenQueueEntry, 1); - QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry); - - bs_entry->state.bs = bs; - bs_entry->state.flags = flags; - - return bs_queue; -} - -/* - * Reopen multiple BlockDriverStates atomically & transactionally. - * - * The queue passed in (bs_queue) must have been built up previous - * via bdrv_reopen_queue(). - * - * Reopens all BDS specified in the queue, with the appropriate - * flags. All devices are prepared for reopen, and failure of any - * device will cause all device changes to be abandonded, and intermediate - * data cleaned up. - * - * If all devices prepare successfully, then the changes are committed - * to all devices. - * - */ -int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) -{ - int ret = -1; - BlockReopenQueueEntry *bs_entry, *next; - Error *local_err = NULL; - - assert(bs_queue != NULL); - - bdrv_drain_all(); - - QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) { - if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) { - error_propagate(errp, local_err); - goto cleanup; - } - bs_entry->prepared = true; - } - - /* If we reach this point, we have success and just need to apply the - * changes - */ - QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) { - bdrv_reopen_commit(&bs_entry->state); - } - - ret = 0; - -cleanup: - QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { - if (ret && bs_entry->prepared) { - bdrv_reopen_abort(&bs_entry->state); - } - g_free(bs_entry); - } - g_free(bs_queue); - return ret; -} - - -/* Reopen a single BlockDriverState with the specified flags. */ -int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp) -{ - int ret = -1; - Error *local_err = NULL; - BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, bdrv_flags); - - ret = bdrv_reopen_multiple(queue, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - } - return ret; -} - - -/* - * Prepares a BlockDriverState for reopen. All changes are staged in the - * 'opaque' field of the BDRVReopenState, which is used and allocated by - * the block driver layer .bdrv_reopen_prepare() - * - * bs is the BlockDriverState to reopen - * flags are the new open flags - * queue is the reopen queue - * - * Returns 0 on success, non-zero on error. On error errp will be set - * as well. - * - * On failure, bdrv_reopen_abort() will be called to clean up any data. - * It is the responsibility of the caller to then call the abort() or - * commit() for any other BDS that have been left in a prepare() state - * - */ -int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, - Error **errp) -{ - int ret = -1; - Error *local_err = NULL; - BlockDriver *drv; - - assert(reopen_state != NULL); - assert(reopen_state->bs->drv != NULL); - drv = reopen_state->bs->drv; - - /* if we are to stay read-only, do not allow permission change - * to r/w */ - if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) && - reopen_state->flags & BDRV_O_RDWR) { - error_set(errp, QERR_DEVICE_IS_READ_ONLY, - reopen_state->bs->device_name); - goto error; - } - - - ret = bdrv_flush(reopen_state->bs); - if (ret) { - error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Error (%s) flushing drive", - strerror(-ret)); - goto error; - } - - if (drv->bdrv_reopen_prepare) { - ret = drv->bdrv_reopen_prepare(reopen_state, queue, &local_err); - if (ret) { - if (local_err != NULL) { - error_propagate(errp, local_err); - } else { - error_setg(errp, "failed while preparing to reopen image '%s'", - reopen_state->bs->filename); - } - goto error; - } - } else { - /* It is currently mandatory to have a bdrv_reopen_prepare() - * handler for each supported drv. */ - error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - drv->format_name, reopen_state->bs->device_name, - "reopening of file"); - ret = -1; - goto error; - } - - ret = 0; - -error: - return ret; -} - -/* - * Takes the staged changes for the reopen from bdrv_reopen_prepare(), and - * makes them final by swapping the staging BlockDriverState contents into - * the active BlockDriverState contents. - */ -void bdrv_reopen_commit(BDRVReopenState *reopen_state) -{ - BlockDriver *drv; - - assert(reopen_state != NULL); - drv = reopen_state->bs->drv; - assert(drv != NULL); - - /* If there are any driver level actions to take */ - if (drv->bdrv_reopen_commit) { - drv->bdrv_reopen_commit(reopen_state); - } - - /* set BDS specific flags now */ - reopen_state->bs->open_flags = reopen_state->flags; - reopen_state->bs->enable_write_cache = !!(reopen_state->flags & - BDRV_O_CACHE_WB); - reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); -} - -/* - * Abort the reopen, and delete and free the staged changes in - * reopen_state - */ -void bdrv_reopen_abort(BDRVReopenState *reopen_state) -{ - BlockDriver *drv; - - assert(reopen_state != NULL); - drv = reopen_state->bs->drv; - assert(drv != NULL); - - if (drv->bdrv_reopen_abort) { - drv->bdrv_reopen_abort(reopen_state); - } -} - - -void bdrv_close(BlockDriverState *bs) -{ - if (bs->job) { - block_job_cancel_sync(bs->job); - } - bdrv_drain_all(); /* complete I/O */ - bdrv_flush(bs); - bdrv_drain_all(); /* in case flush left pending I/O */ - notifier_list_notify(&bs->close_notifiers, bs); - - if (bs->drv) { - if (bs->backing_hd) { - bdrv_delete(bs->backing_hd); - bs->backing_hd = NULL; - } - bs->drv->bdrv_close(bs); - g_free(bs->opaque); -#ifdef _WIN32 - if (bs->is_temporary) { - unlink(bs->filename); - } -#endif - bs->opaque = NULL; - bs->drv = NULL; - bs->copy_on_read = 0; - bs->backing_file[0] = '\0'; - bs->backing_format[0] = '\0'; - bs->total_sectors = 0; - bs->encrypted = 0; - bs->valid_key = 0; - bs->sg = 0; - bs->growable = 0; - QDECREF(bs->options); - bs->options = NULL; - - if (bs->file != NULL) { - bdrv_delete(bs->file); - bs->file = NULL; - } - } - - bdrv_dev_change_media_cb(bs, false); - - /*throttling disk I/O limits*/ - if (bs->io_limits_enabled) { - bdrv_io_limits_disable(bs); - } -} - -void bdrv_close_all(void) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - bdrv_close(bs); - } -} - -/* - * Wait for pending requests to complete across all BlockDriverStates - * - * This function does not flush data to disk, use bdrv_flush_all() for that - * after calling this function. - * - * Note that completion of an asynchronous I/O operation can trigger any - * number of other I/O operations on other devices---for example a coroutine - * can be arbitrarily complex and a constant flow of I/O can come until the - * coroutine is complete. Because of this, it is not possible to have a - * function to drain a single device's I/O queue. - */ -void bdrv_drain_all(void) -{ - BlockDriverState *bs; - bool busy; - - do { - busy = qemu_aio_wait(); - - /* FIXME: We do not have timer support here, so this is effectively - * a busy wait. - */ - QTAILQ_FOREACH(bs, &bdrv_states, list) { - if (!qemu_co_queue_empty(&bs->throttled_reqs)) { - qemu_co_queue_restart_all(&bs->throttled_reqs); - busy = true; - } - } - } while (busy); - - /* If requests are still pending there is a bug somewhere */ - QTAILQ_FOREACH(bs, &bdrv_states, list) { - assert(QLIST_EMPTY(&bs->tracked_requests)); - assert(qemu_co_queue_empty(&bs->throttled_reqs)); - } -} - -/* make a BlockDriverState anonymous by removing from bdrv_state list. - Also, NULL terminate the device_name to prevent double remove */ -void bdrv_make_anon(BlockDriverState *bs) -{ - if (bs->device_name[0] != '\0') { - QTAILQ_REMOVE(&bdrv_states, bs, list); - } - bs->device_name[0] = '\0'; -} - -static void bdrv_rebind(BlockDriverState *bs) -{ - if (bs->drv && bs->drv->bdrv_rebind) { - bs->drv->bdrv_rebind(bs); - } -} - -static void bdrv_move_feature_fields(BlockDriverState *bs_dest, - BlockDriverState *bs_src) -{ - /* move some fields that need to stay attached to the device */ - bs_dest->open_flags = bs_src->open_flags; - - /* dev info */ - bs_dest->dev_ops = bs_src->dev_ops; - bs_dest->dev_opaque = bs_src->dev_opaque; - bs_dest->dev = bs_src->dev; - bs_dest->buffer_alignment = bs_src->buffer_alignment; - bs_dest->copy_on_read = bs_src->copy_on_read; - - bs_dest->enable_write_cache = bs_src->enable_write_cache; - - /* i/o timing parameters */ - bs_dest->slice_start = bs_src->slice_start; - bs_dest->slice_end = bs_src->slice_end; - bs_dest->slice_submitted = bs_src->slice_submitted; - bs_dest->io_limits = bs_src->io_limits; - bs_dest->throttled_reqs = bs_src->throttled_reqs; - bs_dest->block_timer = bs_src->block_timer; - bs_dest->io_limits_enabled = bs_src->io_limits_enabled; - - /* r/w error */ - bs_dest->on_read_error = bs_src->on_read_error; - bs_dest->on_write_error = bs_src->on_write_error; - - /* i/o status */ - bs_dest->iostatus_enabled = bs_src->iostatus_enabled; - bs_dest->iostatus = bs_src->iostatus; - - /* dirty bitmap */ - bs_dest->dirty_bitmap = bs_src->dirty_bitmap; - - /* job */ - bs_dest->in_use = bs_src->in_use; - bs_dest->job = bs_src->job; - - /* keep the same entry in bdrv_states */ - pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), - bs_src->device_name); - bs_dest->list = bs_src->list; -} - -/* - * Swap bs contents for two image chains while they are live, - * while keeping required fields on the BlockDriverState that is - * actually attached to a device. - * - * This will modify the BlockDriverState fields, and swap contents - * between bs_new and bs_old. Both bs_new and bs_old are modified. - * - * bs_new is required to be anonymous. - * - * This function does not create any image files. - */ -void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) -{ - BlockDriverState tmp; - - /* bs_new must be anonymous and shouldn't have anything fancy enabled */ - assert(bs_new->device_name[0] == '\0'); - assert(bs_new->dirty_bitmap == NULL); - assert(bs_new->job == NULL); - assert(bs_new->dev == NULL); - assert(bs_new->in_use == 0); - assert(bs_new->io_limits_enabled == false); - assert(bs_new->block_timer == NULL); - - tmp = *bs_new; - *bs_new = *bs_old; - *bs_old = tmp; - - /* there are some fields that should not be swapped, move them back */ - bdrv_move_feature_fields(&tmp, bs_old); - bdrv_move_feature_fields(bs_old, bs_new); - bdrv_move_feature_fields(bs_new, &tmp); - - /* bs_new shouldn't be in bdrv_states even after the swap! */ - assert(bs_new->device_name[0] == '\0'); - - /* Check a few fields that should remain attached to the device */ - assert(bs_new->dev == NULL); - assert(bs_new->job == NULL); - assert(bs_new->in_use == 0); - assert(bs_new->io_limits_enabled == false); - assert(bs_new->block_timer == NULL); - - bdrv_rebind(bs_new); - bdrv_rebind(bs_old); -} - -/* - * Add new bs contents at the top of an image chain while the chain is - * live, while keeping required fields on the top layer. - * - * This will modify the BlockDriverState fields, and swap contents - * between bs_new and bs_top. Both bs_new and bs_top are modified. - * - * bs_new is required to be anonymous. - * - * This function does not create any image files. - */ -void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) -{ - bdrv_swap(bs_new, bs_top); - - /* The contents of 'tmp' will become bs_top, as we are - * swapping bs_new and bs_top contents. */ - bs_top->backing_hd = bs_new; - bs_top->open_flags &= ~BDRV_O_NO_BACKING; - pstrcpy(bs_top->backing_file, sizeof(bs_top->backing_file), - bs_new->filename); - pstrcpy(bs_top->backing_format, sizeof(bs_top->backing_format), - bs_new->drv ? bs_new->drv->format_name : ""); -} - -void bdrv_delete(BlockDriverState *bs) -{ - assert(!bs->dev); - assert(!bs->job); - assert(!bs->in_use); - - /* remove from list, if necessary */ - bdrv_make_anon(bs); - - bdrv_close(bs); - - g_free(bs); -} - -int bdrv_attach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - if (bs->dev) { - return -EBUSY; - } - bs->dev = dev; - bdrv_iostatus_reset(bs); - return 0; -} - -/* TODO qdevified devices don't use this, remove when devices are qdevified */ -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev) -{ - if (bdrv_attach_dev(bs, dev) < 0) { - abort(); - } -} - -void bdrv_detach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - assert(bs->dev == dev); - bs->dev = NULL; - bs->dev_ops = NULL; - bs->dev_opaque = NULL; - bs->buffer_alignment = 512; -} - -/* TODO change to return DeviceState * when all users are qdevified */ -void *bdrv_get_attached_dev(BlockDriverState *bs) -{ - return bs->dev; -} - -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, - void *opaque) -{ - bs->dev_ops = ops; - bs->dev_opaque = opaque; -} - -void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - enum MonitorEvent ev, - BlockErrorAction action, bool is_read) -{ - QObject *data; - const char *action_str; - - switch (action) { - case BDRV_ACTION_REPORT: - action_str = "report"; - break; - case BDRV_ACTION_IGNORE: - action_str = "ignore"; - break; - case BDRV_ACTION_STOP: - action_str = "stop"; - break; - default: - abort(); - } - - data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }", - bdrv->device_name, - action_str, - is_read ? "read" : "write"); - monitor_protocol_event(ev, data); - - qobject_decref(data); -} - -static void bdrv_emit_qmp_eject_event(BlockDriverState *bs, bool ejected) -{ - QObject *data; - - data = qobject_from_jsonf("{ 'device': %s, 'tray-open': %i }", - bdrv_get_device_name(bs), ejected); - monitor_protocol_event(QEVENT_DEVICE_TRAY_MOVED, data); - - qobject_decref(data); -} - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) -{ - if (bs->dev_ops && bs->dev_ops->change_media_cb) { - bool tray_was_closed = !bdrv_dev_is_tray_open(bs); - bs->dev_ops->change_media_cb(bs->dev_opaque, load); - if (tray_was_closed) { - /* tray open */ - bdrv_emit_qmp_eject_event(bs, true); - } - if (load) { - /* tray close */ - bdrv_emit_qmp_eject_event(bs, false); - } - } -} - -bool bdrv_dev_has_removable_media(BlockDriverState *bs) -{ - return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); -} - -void bdrv_dev_eject_request(BlockDriverState *bs, bool force) -{ - if (bs->dev_ops && bs->dev_ops->eject_request_cb) { - bs->dev_ops->eject_request_cb(bs->dev_opaque, force); - } -} - -bool bdrv_dev_is_tray_open(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->is_tray_open) { - return bs->dev_ops->is_tray_open(bs->dev_opaque); - } - return false; -} - -static void bdrv_dev_resize_cb(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->resize_cb) { - bs->dev_ops->resize_cb(bs->dev_opaque); - } -} - -bool bdrv_dev_is_medium_locked(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->is_medium_locked) { - return bs->dev_ops->is_medium_locked(bs->dev_opaque); - } - return false; -} - -/* - * Run consistency checks on an image - * - * Returns 0 if the check could be completed (it doesn't mean that the image is - * free of errors) or -errno when an internal error occurred. The results of the - * check are stored in res. - */ -int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) -{ - if (bs->drv->bdrv_check == NULL) { - return -ENOTSUP; - } - - memset(res, 0, sizeof(*res)); - return bs->drv->bdrv_check(bs, res, fix); -} - -#define COMMIT_BUF_SECTORS 2048 - -/* commit COW file into the raw image */ -int bdrv_commit(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - int64_t sector, total_sectors; - int n, ro, open_flags; - int ret = 0; - uint8_t *buf; - char filename[PATH_MAX]; - - if (!drv) - return -ENOMEDIUM; - - if (!bs->backing_hd) { - return -ENOTSUP; - } - - if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) { - return -EBUSY; - } - - ro = bs->backing_hd->read_only; - /* Use pstrcpy (not strncpy): filename must be NUL-terminated. */ - pstrcpy(filename, sizeof(filename), bs->backing_hd->filename); - open_flags = bs->backing_hd->open_flags; - - if (ro) { - if (bdrv_reopen(bs->backing_hd, open_flags | BDRV_O_RDWR, NULL)) { - return -EACCES; - } - } - - total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; - buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE); - - for (sector = 0; sector < total_sectors; sector += n) { - if (bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) { - - if (bdrv_read(bs, sector, buf, n) != 0) { - ret = -EIO; - goto ro_cleanup; - } - - if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) { - ret = -EIO; - goto ro_cleanup; - } - } - } - - if (drv->bdrv_make_empty) { - ret = drv->bdrv_make_empty(bs); - bdrv_flush(bs); - } - - /* - * Make sure all data we wrote to the backing device is actually - * stable on disk. - */ - if (bs->backing_hd) - bdrv_flush(bs->backing_hd); - -ro_cleanup: - g_free(buf); - - if (ro) { - /* ignoring error return here */ - bdrv_reopen(bs->backing_hd, open_flags & ~BDRV_O_RDWR, NULL); - } - - return ret; -} - -int bdrv_commit_all(void) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - if (bs->drv && bs->backing_hd) { - int ret = bdrv_commit(bs); - if (ret < 0) { - return ret; - } - } - } - return 0; -} - -/** - * Remove an active request from the tracked requests list - * - * This function should be called when a tracked request is completing. - */ -static void tracked_request_end(BdrvTrackedRequest *req) -{ - QLIST_REMOVE(req, list); - qemu_co_queue_restart_all(&req->wait_queue); -} - -/** - * Add an active request to the tracked requests list - */ -static void tracked_request_begin(BdrvTrackedRequest *req, - BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, bool is_write) -{ - *req = (BdrvTrackedRequest){ - .bs = bs, - .sector_num = sector_num, - .nb_sectors = nb_sectors, - .is_write = is_write, - .co = qemu_coroutine_self(), - }; - - qemu_co_queue_init(&req->wait_queue); - - QLIST_INSERT_HEAD(&bs->tracked_requests, req, list); -} - -/** - * Round a region to cluster boundaries - */ -void bdrv_round_to_clusters(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - int64_t *cluster_sector_num, - int *cluster_nb_sectors) -{ - BlockDriverInfo bdi; - - if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) { - *cluster_sector_num = sector_num; - *cluster_nb_sectors = nb_sectors; - } else { - int64_t c = bdi.cluster_size / BDRV_SECTOR_SIZE; - *cluster_sector_num = QEMU_ALIGN_DOWN(sector_num, c); - *cluster_nb_sectors = QEMU_ALIGN_UP(sector_num - *cluster_sector_num + - nb_sectors, c); - } -} - -static bool tracked_request_overlaps(BdrvTrackedRequest *req, - int64_t sector_num, int nb_sectors) { - /* aaaa bbbb */ - if (sector_num >= req->sector_num + req->nb_sectors) { - return false; - } - /* bbbb aaaa */ - if (req->sector_num >= sector_num + nb_sectors) { - return false; - } - return true; -} - -static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ - BdrvTrackedRequest *req; - int64_t cluster_sector_num; - int cluster_nb_sectors; - bool retry; - - /* If we touch the same cluster it counts as an overlap. This guarantees - * that allocating writes will be serialized and not race with each other - * for the same cluster. For example, in copy-on-read it ensures that the - * CoR read and write operations are atomic and guest writes cannot - * interleave between them. - */ - bdrv_round_to_clusters(bs, sector_num, nb_sectors, - &cluster_sector_num, &cluster_nb_sectors); - - do { - retry = false; - QLIST_FOREACH(req, &bs->tracked_requests, list) { - if (tracked_request_overlaps(req, cluster_sector_num, - cluster_nb_sectors)) { - /* Hitting this means there was a reentrant request, for - * example, a block driver issuing nested requests. This must - * never happen since it means deadlock. - */ - assert(qemu_coroutine_self() != req->co); - - qemu_co_queue_wait(&req->wait_queue); - retry = true; - break; - } - } - } while (retry); -} - -/* - * Return values: - * 0 - success - * -EINVAL - backing format specified, but no file - * -ENOSPC - can't update the backing file because no space is left in the - * image file header - * -ENOTSUP - format driver doesn't support changing the backing file - */ -int bdrv_change_backing_file(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt) -{ - BlockDriver *drv = bs->drv; - int ret; - - /* Backing file format doesn't make sense without a backing file */ - if (backing_fmt && !backing_file) { - return -EINVAL; - } - - if (drv->bdrv_change_backing_file != NULL) { - ret = drv->bdrv_change_backing_file(bs, backing_file, backing_fmt); - } else { - ret = -ENOTSUP; - } - - if (ret == 0) { - pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: ""); - pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: ""); - } - return ret; -} - -/* - * Finds the image layer in the chain that has 'bs' as its backing file. - * - * active is the current topmost image. - * - * Returns NULL if bs is not found in active's image chain, - * or if active == bs. - */ -BlockDriverState *bdrv_find_overlay(BlockDriverState *active, - BlockDriverState *bs) -{ - BlockDriverState *overlay = NULL; - BlockDriverState *intermediate; - - assert(active != NULL); - assert(bs != NULL); - - /* if bs is the same as active, then by definition it has no overlay - */ - if (active == bs) { - return NULL; - } - - intermediate = active; - while (intermediate->backing_hd) { - if (intermediate->backing_hd == bs) { - overlay = intermediate; - break; - } - intermediate = intermediate->backing_hd; - } - - return overlay; -} - -typedef struct BlkIntermediateStates { - BlockDriverState *bs; - QSIMPLEQ_ENTRY(BlkIntermediateStates) entry; -} BlkIntermediateStates; - - -/* - * Drops images above 'base' up to and including 'top', and sets the image - * above 'top' to have base as its backing file. - * - * Requires that the overlay to 'top' is opened r/w, so that the backing file - * information in 'bs' can be properly updated. - * - * E.g., this will convert the following chain: - * bottom <- base <- intermediate <- top <- active - * - * to - * - * bottom <- base <- active - * - * It is allowed for bottom==base, in which case it converts: - * - * base <- intermediate <- top <- active - * - * to - * - * base <- active - * - * Error conditions: - * if active == top, that is considered an error - * - */ -int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, - BlockDriverState *base) -{ - BlockDriverState *intermediate; - BlockDriverState *base_bs = NULL; - BlockDriverState *new_top_bs = NULL; - BlkIntermediateStates *intermediate_state, *next; - int ret = -EIO; - - QSIMPLEQ_HEAD(states_to_delete, BlkIntermediateStates) states_to_delete; - QSIMPLEQ_INIT(&states_to_delete); - - if (!top->drv || !base->drv) { - goto exit; - } - - new_top_bs = bdrv_find_overlay(active, top); - - if (new_top_bs == NULL) { - /* we could not find the image above 'top', this is an error */ - goto exit; - } - - /* special case of new_top_bs->backing_hd already pointing to base - nothing - * to do, no intermediate images */ - if (new_top_bs->backing_hd == base) { - ret = 0; - goto exit; - } - - intermediate = top; - - /* now we will go down through the list, and add each BDS we find - * into our deletion queue, until we hit the 'base' - */ - while (intermediate) { - intermediate_state = g_malloc0(sizeof(BlkIntermediateStates)); - intermediate_state->bs = intermediate; - QSIMPLEQ_INSERT_TAIL(&states_to_delete, intermediate_state, entry); - - if (intermediate->backing_hd == base) { - base_bs = intermediate->backing_hd; - break; - } - intermediate = intermediate->backing_hd; - } - if (base_bs == NULL) { - /* something went wrong, we did not end at the base. safely - * unravel everything, and exit with error */ - goto exit; - } - - /* success - we can delete the intermediate states, and link top->base */ - ret = bdrv_change_backing_file(new_top_bs, base_bs->filename, - base_bs->drv ? base_bs->drv->format_name : ""); - if (ret) { - goto exit; - } - new_top_bs->backing_hd = base_bs; - - - QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { - /* so that bdrv_close() does not recursively close the chain */ - intermediate_state->bs->backing_hd = NULL; - bdrv_delete(intermediate_state->bs); - } - ret = 0; - -exit: - QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { - g_free(intermediate_state); - } - return ret; -} - - -static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, - size_t size) -{ - int64_t len; - - if (!bdrv_is_inserted(bs)) - return -ENOMEDIUM; - - if (bs->growable) - return 0; - - len = bdrv_getlength(bs); - - if (offset < 0) - return -EIO; - - if ((offset > len) || (len - offset < size)) - return -EIO; - - return 0; -} - -static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num, - int nb_sectors) -{ - return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE, - nb_sectors * BDRV_SECTOR_SIZE); -} - -typedef struct RwCo { - BlockDriverState *bs; - int64_t sector_num; - int nb_sectors; - QEMUIOVector *qiov; - bool is_write; - int ret; -} RwCo; - -static void coroutine_fn bdrv_rw_co_entry(void *opaque) -{ - RwCo *rwco = opaque; - - if (!rwco->is_write) { - rwco->ret = bdrv_co_do_readv(rwco->bs, rwco->sector_num, - rwco->nb_sectors, rwco->qiov, 0); - } else { - rwco->ret = bdrv_co_do_writev(rwco->bs, rwco->sector_num, - rwco->nb_sectors, rwco->qiov, 0); - } -} - -/* - * Process a vectored synchronous request using coroutines - */ -static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, bool is_write) -{ - Coroutine *co; - RwCo rwco = { - .bs = bs, - .sector_num = sector_num, - .nb_sectors = qiov->size >> BDRV_SECTOR_BITS, - .qiov = qiov, - .is_write = is_write, - .ret = NOT_DONE, - }; - assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0); - - /** - * In sync call context, when the vcpu is blocked, this throttling timer - * will not fire; so the I/O throttling function has to be disabled here - * if it has been enabled. - */ - if (bs->io_limits_enabled) { - fprintf(stderr, "Disabling I/O throttling on '%s' due " - "to synchronous I/O.\n", bdrv_get_device_name(bs)); - bdrv_io_limits_disable(bs); - } - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_rw_co_entry(&rwco); - } else { - co = qemu_coroutine_create(bdrv_rw_co_entry); - qemu_coroutine_enter(co, &rwco); - while (rwco.ret == NOT_DONE) { - qemu_aio_wait(); - } - } - return rwco.ret; -} - -/* - * Process a synchronous request using coroutines - */ -static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, - int nb_sectors, bool is_write) -{ - QEMUIOVector qiov; - struct iovec iov = { - .iov_base = (void *)buf, - .iov_len = nb_sectors * BDRV_SECTOR_SIZE, - }; - - qemu_iovec_init_external(&qiov, &iov, 1); - return bdrv_rwv_co(bs, sector_num, &qiov, is_write); -} - -/* return < 0 if error. See bdrv_write() for the return codes */ -int bdrv_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false); -} - -/* Just like bdrv_read(), but with I/O throttling temporarily disabled */ -int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - bool enabled; - int ret; - - enabled = bs->io_limits_enabled; - bs->io_limits_enabled = false; - ret = bdrv_read(bs, 0, buf, 1); - bs->io_limits_enabled = enabled; - return ret; -} - -/* Return < 0 if error. Important errors are: - -EIO generic I/O error (may happen for all errors) - -ENOMEDIUM No media inserted. - -EINVAL Invalid sector number or nb_sectors - -EACCES Trying to write a read-only device -*/ -int bdrv_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true); -} - -int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov) -{ - return bdrv_rwv_co(bs, sector_num, qiov, true); -} - -int bdrv_pread(BlockDriverState *bs, int64_t offset, - void *buf, int count1) -{ - uint8_t tmp_buf[BDRV_SECTOR_SIZE]; - int len, nb_sectors, count; - int64_t sector_num; - int ret; - - count = count1; - /* first read to align to sector start */ - len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1); - if (len > count) - len = count; - sector_num = offset >> BDRV_SECTOR_BITS; - if (len > 0) { - if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len); - count -= len; - if (count == 0) - return count1; - sector_num++; - buf += len; - } - - /* read the sectors "in place" */ - nb_sectors = count >> BDRV_SECTOR_BITS; - if (nb_sectors > 0) { - if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0) - return ret; - sector_num += nb_sectors; - len = nb_sectors << BDRV_SECTOR_BITS; - buf += len; - count -= len; - } - - /* add data from the last sector */ - if (count > 0) { - if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - memcpy(buf, tmp_buf, count); - } - return count1; -} - -int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov) -{ - uint8_t tmp_buf[BDRV_SECTOR_SIZE]; - int len, nb_sectors, count; - int64_t sector_num; - int ret; - - count = qiov->size; - - /* first write to align to sector start */ - len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1); - if (len > count) - len = count; - sector_num = offset >> BDRV_SECTOR_BITS; - if (len > 0) { - if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - qemu_iovec_to_buf(qiov, 0, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), - len); - if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - count -= len; - if (count == 0) - return qiov->size; - sector_num++; - } - - /* write the sectors "in place" */ - nb_sectors = count >> BDRV_SECTOR_BITS; - if (nb_sectors > 0) { - QEMUIOVector qiov_inplace; - - qemu_iovec_init(&qiov_inplace, qiov->niov); - qemu_iovec_concat(&qiov_inplace, qiov, len, - nb_sectors << BDRV_SECTOR_BITS); - ret = bdrv_writev(bs, sector_num, &qiov_inplace); - qemu_iovec_destroy(&qiov_inplace); - if (ret < 0) { - return ret; - } - - sector_num += nb_sectors; - len = nb_sectors << BDRV_SECTOR_BITS; - count -= len; - } - - /* add data from the last sector */ - if (count > 0) { - if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - qemu_iovec_to_buf(qiov, qiov->size - count, tmp_buf, count); - if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0) - return ret; - } - return qiov->size; -} - -int bdrv_pwrite(BlockDriverState *bs, int64_t offset, - const void *buf, int count1) -{ - QEMUIOVector qiov; - struct iovec iov = { - .iov_base = (void *) buf, - .iov_len = count1, - }; - - qemu_iovec_init_external(&qiov, &iov, 1); - return bdrv_pwritev(bs, offset, &qiov); -} - -/* - * Writes to the file and ensures that no writes are reordered across this - * request (acts as a barrier) - * - * Returns 0 on success, -errno in error cases. - */ -int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, - const void *buf, int count) -{ - int ret; - - ret = bdrv_pwrite(bs, offset, buf, count); - if (ret < 0) { - return ret; - } - - /* No flush needed for cache modes that already do it */ - if (bs->enable_write_cache) { - bdrv_flush(bs); - } - - return 0; -} - -static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) -{ - /* Perform I/O through a temporary buffer so that users who scribble over - * their read buffer while the operation is in progress do not end up - * modifying the image file. This is critical for zero-copy guest I/O - * where anything might happen inside guest memory. - */ - void *bounce_buffer; - - BlockDriver *drv = bs->drv; - struct iovec iov; - QEMUIOVector bounce_qiov; - int64_t cluster_sector_num; - int cluster_nb_sectors; - size_t skip_bytes; - int ret; - - /* Cover entire cluster so no additional backing file I/O is required when - * allocating cluster in the image file. - */ - bdrv_round_to_clusters(bs, sector_num, nb_sectors, - &cluster_sector_num, &cluster_nb_sectors); - - trace_bdrv_co_do_copy_on_readv(bs, sector_num, nb_sectors, - cluster_sector_num, cluster_nb_sectors); - - iov.iov_len = cluster_nb_sectors * BDRV_SECTOR_SIZE; - iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len); - qemu_iovec_init_external(&bounce_qiov, &iov, 1); - - ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors, - &bounce_qiov); - if (ret < 0) { - goto err; - } - - if (drv->bdrv_co_write_zeroes && - buffer_is_zero(bounce_buffer, iov.iov_len)) { - ret = bdrv_co_do_write_zeroes(bs, cluster_sector_num, - cluster_nb_sectors); - } else { - /* This does not change the data on the disk, it is not necessary - * to flush even in cache=writethrough mode. - */ - ret = drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors, - &bounce_qiov); - } - - if (ret < 0) { - /* It might be okay to ignore write errors for guest requests. If this - * is a deliberate copy-on-read then we don't want to ignore the error. - * Simply report it in all cases. - */ - goto err; - } - - skip_bytes = (sector_num - cluster_sector_num) * BDRV_SECTOR_SIZE; - qemu_iovec_from_buf(qiov, 0, bounce_buffer + skip_bytes, - nb_sectors * BDRV_SECTOR_SIZE); - -err: - qemu_vfree(bounce_buffer); - return ret; -} - -/* - * Handle a read request in coroutine context - */ -static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, - BdrvRequestFlags flags) -{ - BlockDriver *drv = bs->drv; - BdrvTrackedRequest req; - int ret; - - if (!drv) { - return -ENOMEDIUM; - } - if (bdrv_check_request(bs, sector_num, nb_sectors)) { - return -EIO; - } - - /* throttling disk read I/O */ - if (bs->io_limits_enabled) { - bdrv_io_limits_intercept(bs, false, nb_sectors); - } - - if (bs->copy_on_read) { - flags |= BDRV_REQ_COPY_ON_READ; - } - if (flags & BDRV_REQ_COPY_ON_READ) { - bs->copy_on_read_in_flight++; - } - - if (bs->copy_on_read_in_flight) { - wait_for_overlapping_requests(bs, sector_num, nb_sectors); - } - - tracked_request_begin(&req, bs, sector_num, nb_sectors, false); - - if (flags & BDRV_REQ_COPY_ON_READ) { - int pnum; - - ret = bdrv_co_is_allocated(bs, sector_num, nb_sectors, &pnum); - if (ret < 0) { - goto out; - } - - if (!ret || pnum != nb_sectors) { - ret = bdrv_co_do_copy_on_readv(bs, sector_num, nb_sectors, qiov); - goto out; - } - } - - ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); - -out: - tracked_request_end(&req); - - if (flags & BDRV_REQ_COPY_ON_READ) { - bs->copy_on_read_in_flight--; - } - - return ret; -} - -int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - trace_bdrv_co_readv(bs, sector_num, nb_sectors); - - return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, 0); -} - -int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) -{ - trace_bdrv_co_copy_on_readv(bs, sector_num, nb_sectors); - - return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, - BDRV_REQ_COPY_ON_READ); -} - -static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ - BlockDriver *drv = bs->drv; - QEMUIOVector qiov; - struct iovec iov; - int ret; - - /* TODO Emulate only part of misaligned requests instead of letting block - * drivers return -ENOTSUP and emulate everything */ - - /* First try the efficient write zeroes operation */ - if (drv->bdrv_co_write_zeroes) { - ret = drv->bdrv_co_write_zeroes(bs, sector_num, nb_sectors); - if (ret != -ENOTSUP) { - return ret; - } - } - - /* Fall back to bounce buffer if write zeroes is unsupported */ - iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE; - iov.iov_base = qemu_blockalign(bs, iov.iov_len); - memset(iov.iov_base, 0, iov.iov_len); - qemu_iovec_init_external(&qiov, &iov, 1); - - ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, &qiov); - - qemu_vfree(iov.iov_base); - return ret; -} - -/* - * Handle a write request in coroutine context - */ -static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, - BdrvRequestFlags flags) -{ - BlockDriver *drv = bs->drv; - BdrvTrackedRequest req; - int ret; - - if (!bs->drv) { - return -ENOMEDIUM; - } - if (bs->read_only) { - return -EACCES; - } - if (bdrv_check_request(bs, sector_num, nb_sectors)) { - return -EIO; - } - - /* throttling disk write I/O */ - if (bs->io_limits_enabled) { - bdrv_io_limits_intercept(bs, true, nb_sectors); - } - - if (bs->copy_on_read_in_flight) { - wait_for_overlapping_requests(bs, sector_num, nb_sectors); - } - - tracked_request_begin(&req, bs, sector_num, nb_sectors, true); - - ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req); - - if (ret < 0) { - /* Do nothing, write notifier decided to fail this request */ - } else if (flags & BDRV_REQ_ZERO_WRITE) { - ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors); - } else { - ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); - } - - if (ret == 0 && !bs->enable_write_cache) { - ret = bdrv_co_flush(bs); - } - - if (bs->dirty_bitmap) { - bdrv_set_dirty(bs, sector_num, nb_sectors); - } - - if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { - bs->wr_highest_sector = sector_num + nb_sectors - 1; - } - - tracked_request_end(&req); - - return ret; -} - -int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - trace_bdrv_co_writev(bs, sector_num, nb_sectors); - - return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov, 0); -} - -int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ - trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors); - - return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL, - BDRV_REQ_ZERO_WRITE); -} - -/** - * Truncate file to 'offset' bytes (needed only for file protocols) - */ -int bdrv_truncate(BlockDriverState *bs, int64_t offset) -{ - BlockDriver *drv = bs->drv; - int ret; - if (!drv) - return -ENOMEDIUM; - if (!drv->bdrv_truncate) - return -ENOTSUP; - if (bs->read_only) - return -EACCES; - if (bdrv_in_use(bs)) - return -EBUSY; - ret = drv->bdrv_truncate(bs, offset); - if (ret == 0) { - ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); - bdrv_dev_resize_cb(bs); - } - return ret; -} - -/** - * Length of a allocated file in bytes. Sparse files are counted by actual - * allocated space. Return < 0 if error or unknown. - */ -int64_t bdrv_get_allocated_file_size(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (drv->bdrv_get_allocated_file_size) { - return drv->bdrv_get_allocated_file_size(bs); - } - if (bs->file) { - return bdrv_get_allocated_file_size(bs->file); - } - return -ENOTSUP; -} - -/** - * Length of a file in bytes. Return < 0 if error or unknown. - */ -int64_t bdrv_getlength(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - - if (bs->growable || bdrv_dev_has_removable_media(bs)) { - if (drv->bdrv_getlength) { - return drv->bdrv_getlength(bs); - } - } - return bs->total_sectors * BDRV_SECTOR_SIZE; -} - -/* return 0 as number of sectors if no device present or error */ -void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) -{ - int64_t length; - length = bdrv_getlength(bs); - if (length < 0) - length = 0; - else - length = length >> BDRV_SECTOR_BITS; - *nb_sectors_ptr = length; -} - -/* throttling disk io limits */ -void bdrv_set_io_limits(BlockDriverState *bs, - BlockIOLimit *io_limits) -{ - bs->io_limits = *io_limits; - bs->io_limits_enabled = bdrv_io_limits_enabled(bs); -} - -void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, - BlockdevOnError on_write_error) -{ - bs->on_read_error = on_read_error; - bs->on_write_error = on_write_error; -} - -BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read) -{ - return is_read ? bs->on_read_error : bs->on_write_error; -} - -BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error) -{ - BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error; - - switch (on_err) { - case BLOCKDEV_ON_ERROR_ENOSPC: - return (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT; - case BLOCKDEV_ON_ERROR_STOP: - return BDRV_ACTION_STOP; - case BLOCKDEV_ON_ERROR_REPORT: - return BDRV_ACTION_REPORT; - case BLOCKDEV_ON_ERROR_IGNORE: - return BDRV_ACTION_IGNORE; - default: - abort(); - } -} - -/* This is done by device models because, while the block layer knows - * about the error, it does not know whether an operation comes from - * the device or the block layer (from a job, for example). - */ -void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, - bool is_read, int error) -{ - assert(error >= 0); - bdrv_emit_qmp_error_event(bs, QEVENT_BLOCK_IO_ERROR, action, is_read); - if (action == BDRV_ACTION_STOP) { - vm_stop(RUN_STATE_IO_ERROR); - bdrv_iostatus_set_err(bs, error); - } -} - -int bdrv_is_read_only(BlockDriverState *bs) -{ - return bs->read_only; -} - -int bdrv_is_sg(BlockDriverState *bs) -{ - return bs->sg; -} - -int bdrv_enable_write_cache(BlockDriverState *bs) -{ - return bs->enable_write_cache; -} - -void bdrv_set_enable_write_cache(BlockDriverState *bs, bool wce) -{ - bs->enable_write_cache = wce; - - /* so a reopen() will preserve wce */ - if (wce) { - bs->open_flags |= BDRV_O_CACHE_WB; - } else { - bs->open_flags &= ~BDRV_O_CACHE_WB; - } -} - -int bdrv_is_encrypted(BlockDriverState *bs) -{ - if (bs->backing_hd && bs->backing_hd->encrypted) - return 1; - return bs->encrypted; -} - -int bdrv_key_required(BlockDriverState *bs) -{ - BlockDriverState *backing_hd = bs->backing_hd; - - if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key) - return 1; - return (bs->encrypted && !bs->valid_key); -} - -int bdrv_set_key(BlockDriverState *bs, const char *key) -{ - int ret; - if (bs->backing_hd && bs->backing_hd->encrypted) { - ret = bdrv_set_key(bs->backing_hd, key); - if (ret < 0) - return ret; - if (!bs->encrypted) - return 0; - } - if (!bs->encrypted) { - return -EINVAL; - } else if (!bs->drv || !bs->drv->bdrv_set_key) { - return -ENOMEDIUM; - } - ret = bs->drv->bdrv_set_key(bs, key); - if (ret < 0) { - bs->valid_key = 0; - } else if (!bs->valid_key) { - bs->valid_key = 1; - /* call the change callback now, we skipped it on open */ - bdrv_dev_change_media_cb(bs, true); - } - return ret; -} - -const char *bdrv_get_format_name(BlockDriverState *bs) -{ - return bs->drv ? bs->drv->format_name : NULL; -} - -void bdrv_iterate_format(void (*it)(void *opaque, const char *name), - void *opaque) -{ - BlockDriver *drv; - - QLIST_FOREACH(drv, &bdrv_drivers, list) { - it(opaque, drv->format_name); - } -} - -BlockDriverState *bdrv_find(const char *name) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - if (!strcmp(name, bs->device_name)) { - return bs; - } - } - return NULL; -} - -BlockDriverState *bdrv_next(BlockDriverState *bs) -{ - if (!bs) { - return QTAILQ_FIRST(&bdrv_states); - } - return QTAILQ_NEXT(bs, list); -} - -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - it(opaque, bs); - } -} - -const char *bdrv_get_device_name(BlockDriverState *bs) -{ - return bs->device_name; -} - -int bdrv_get_flags(BlockDriverState *bs) -{ - return bs->open_flags; -} - -int bdrv_flush_all(void) -{ - BlockDriverState *bs; - int result = 0; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - int ret = bdrv_flush(bs); - if (ret < 0 && !result) { - result = ret; - } - } - - return result; -} - -int bdrv_has_zero_init_1(BlockDriverState *bs) -{ - return 1; -} - -int bdrv_has_zero_init(BlockDriverState *bs) -{ - assert(bs->drv); - - if (bs->drv->bdrv_has_zero_init) { - return bs->drv->bdrv_has_zero_init(bs); - } - - /* safe default */ - return 0; -} - -typedef struct BdrvCoIsAllocatedData { - BlockDriverState *bs; - BlockDriverState *base; - int64_t sector_num; - int nb_sectors; - int *pnum; - int ret; - bool done; -} BdrvCoIsAllocatedData; - -/* - * Returns true iff the specified sector is present in the disk image. Drivers - * not implementing the functionality are assumed to not support backing files, - * hence all their sectors are reported as allocated. - * - * If 'sector_num' is beyond the end of the disk image the return value is 0 - * and 'pnum' is set to 0. - * - * 'pnum' is set to the number of sectors (including and immediately following - * the specified sector) that are known to be in the same - * allocated/unallocated state. - * - * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes - * beyond the end of the disk image it will be clamped. - */ -int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum) -{ - int64_t n; - - if (sector_num >= bs->total_sectors) { - *pnum = 0; - return 0; - } - - n = bs->total_sectors - sector_num; - if (n < nb_sectors) { - nb_sectors = n; - } - - if (!bs->drv->bdrv_co_is_allocated) { - *pnum = nb_sectors; - return 1; - } - - return bs->drv->bdrv_co_is_allocated(bs, sector_num, nb_sectors, pnum); -} - -/* Coroutine wrapper for bdrv_is_allocated() */ -static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque) -{ - BdrvCoIsAllocatedData *data = opaque; - BlockDriverState *bs = data->bs; - - data->ret = bdrv_co_is_allocated(bs, data->sector_num, data->nb_sectors, - data->pnum); - data->done = true; -} - -/* - * Synchronous wrapper around bdrv_co_is_allocated(). - * - * See bdrv_co_is_allocated() for details. - */ -int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - int *pnum) -{ - Coroutine *co; - BdrvCoIsAllocatedData data = { - .bs = bs, - .sector_num = sector_num, - .nb_sectors = nb_sectors, - .pnum = pnum, - .done = false, - }; - - co = qemu_coroutine_create(bdrv_is_allocated_co_entry); - qemu_coroutine_enter(co, &data); - while (!data.done) { - qemu_aio_wait(); - } - return data.ret; -} - -/* - * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] - * - * Return true if the given sector is allocated in any image between - * BASE and TOP (inclusive). BASE can be NULL to check if the given - * sector is allocated in any image of the chain. Return false otherwise. - * - * 'pnum' is set to the number of sectors (including and immediately following - * the specified sector) that are known to be in the same - * allocated/unallocated state. - * - */ -int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, int *pnum) -{ - BlockDriverState *intermediate; - int ret, n = nb_sectors; - - intermediate = top; - while (intermediate && intermediate != base) { - int pnum_inter; - ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors, - &pnum_inter); - if (ret < 0) { - return ret; - } else if (ret) { - *pnum = pnum_inter; - return 1; - } - - /* - * [sector_num, nb_sectors] is unallocated on top but intermediate - * might have - * - * [sector_num+x, nr_sectors] allocated. - */ - if (n > pnum_inter && - (intermediate == top || - sector_num + pnum_inter < intermediate->total_sectors)) { - n = pnum_inter; - } - - intermediate = intermediate->backing_hd; - } - - *pnum = n; - return 0; -} - -/* Coroutine wrapper for bdrv_is_allocated_above() */ -static void coroutine_fn bdrv_is_allocated_above_co_entry(void *opaque) -{ - BdrvCoIsAllocatedData *data = opaque; - BlockDriverState *top = data->bs; - BlockDriverState *base = data->base; - - data->ret = bdrv_co_is_allocated_above(top, base, data->sector_num, - data->nb_sectors, data->pnum); - data->done = true; -} - -/* - * Synchronous wrapper around bdrv_co_is_allocated_above(). - * - * See bdrv_co_is_allocated_above() for details. - */ -int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, - int64_t sector_num, int nb_sectors, int *pnum) -{ - Coroutine *co; - BdrvCoIsAllocatedData data = { - .bs = top, - .base = base, - .sector_num = sector_num, - .nb_sectors = nb_sectors, - .pnum = pnum, - .done = false, - }; - - co = qemu_coroutine_create(bdrv_is_allocated_above_co_entry); - qemu_coroutine_enter(co, &data); - while (!data.done) { - qemu_aio_wait(); - } - return data.ret; -} - -const char *bdrv_get_encrypted_filename(BlockDriverState *bs) -{ - if (bs->backing_hd && bs->backing_hd->encrypted) - return bs->backing_file; - else if (bs->encrypted) - return bs->filename; - else - return NULL; -} - -void bdrv_get_backing_filename(BlockDriverState *bs, - char *filename, int filename_size) -{ - pstrcpy(filename, filename_size, bs->backing_file); -} - -int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (!drv->bdrv_write_compressed) - return -ENOTSUP; - if (bdrv_check_request(bs, sector_num, nb_sectors)) - return -EIO; - - assert(!bs->dirty_bitmap); - - return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors); -} - -int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (!drv->bdrv_get_info) - return -ENOTSUP; - memset(bdi, 0, sizeof(*bdi)); - return drv->bdrv_get_info(bs, bdi); -} - -int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, - int64_t pos, int size) -{ - QEMUIOVector qiov; - struct iovec iov = { - .iov_base = (void *) buf, - .iov_len = size, - }; - - qemu_iovec_init_external(&qiov, &iov, 1); - return bdrv_writev_vmstate(bs, &qiov, pos); -} - -int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) -{ - BlockDriver *drv = bs->drv; - - if (!drv) { - return -ENOMEDIUM; - } else if (drv->bdrv_save_vmstate) { - return drv->bdrv_save_vmstate(bs, qiov, pos); - } else if (bs->file) { - return bdrv_writev_vmstate(bs->file, qiov, pos); - } - - return -ENOTSUP; -} - -int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, - int64_t pos, int size) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (drv->bdrv_load_vmstate) - return drv->bdrv_load_vmstate(bs, buf, pos, size); - if (bs->file) - return bdrv_load_vmstate(bs->file, buf, pos, size); - return -ENOTSUP; -} - -void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event) -{ - if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) { - return; - } - - bs->drv->bdrv_debug_event(bs, event); -} - -int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event, - const char *tag) -{ - while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) { - bs = bs->file; - } - - if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) { - return bs->drv->bdrv_debug_breakpoint(bs, event, tag); - } - - return -ENOTSUP; -} - -int bdrv_debug_resume(BlockDriverState *bs, const char *tag) -{ - while (bs && bs->drv && !bs->drv->bdrv_debug_resume) { - bs = bs->file; - } - - if (bs && bs->drv && bs->drv->bdrv_debug_resume) { - return bs->drv->bdrv_debug_resume(bs, tag); - } - - return -ENOTSUP; -} - -bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag) -{ - while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) { - bs = bs->file; - } - - if (bs && bs->drv && bs->drv->bdrv_debug_is_suspended) { - return bs->drv->bdrv_debug_is_suspended(bs, tag); - } - - return false; -} - -int bdrv_is_snapshot(BlockDriverState *bs) -{ - return !!(bs->open_flags & BDRV_O_SNAPSHOT); -} - -/* backing_file can either be relative, or absolute, or a protocol. If it is - * relative, it must be relative to the chain. So, passing in bs->filename - * from a BDS as backing_file should not be done, as that may be relative to - * the CWD rather than the chain. */ -BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, - const char *backing_file) -{ - char *filename_full = NULL; - char *backing_file_full = NULL; - char *filename_tmp = NULL; - int is_protocol = 0; - BlockDriverState *curr_bs = NULL; - BlockDriverState *retval = NULL; - - if (!bs || !bs->drv || !backing_file) { - return NULL; - } - - filename_full = g_malloc(PATH_MAX); - backing_file_full = g_malloc(PATH_MAX); - filename_tmp = g_malloc(PATH_MAX); - - is_protocol = path_has_protocol(backing_file); - - for (curr_bs = bs; curr_bs->backing_hd; curr_bs = curr_bs->backing_hd) { - - /* If either of the filename paths is actually a protocol, then - * compare unmodified paths; otherwise make paths relative */ - if (is_protocol || path_has_protocol(curr_bs->backing_file)) { - if (strcmp(backing_file, curr_bs->backing_file) == 0) { - retval = curr_bs->backing_hd; - break; - } - } else { - /* If not an absolute filename path, make it relative to the current - * image's filename path */ - path_combine(filename_tmp, PATH_MAX, curr_bs->filename, - backing_file); - - /* We are going to compare absolute pathnames */ - if (!realpath(filename_tmp, filename_full)) { - continue; - } - - /* We need to make sure the backing filename we are comparing against - * is relative to the current image filename (or absolute) */ - path_combine(filename_tmp, PATH_MAX, curr_bs->filename, - curr_bs->backing_file); - - if (!realpath(filename_tmp, backing_file_full)) { - continue; - } - - if (strcmp(backing_file_full, filename_full) == 0) { - retval = curr_bs->backing_hd; - break; - } - } - } - - g_free(filename_full); - g_free(backing_file_full); - g_free(filename_tmp); - return retval; -} - -int bdrv_get_backing_file_depth(BlockDriverState *bs) -{ - if (!bs->drv) { - return 0; - } - - if (!bs->backing_hd) { - return 0; - } - - return 1 + bdrv_get_backing_file_depth(bs->backing_hd); -} - -BlockDriverState *bdrv_find_base(BlockDriverState *bs) -{ - BlockDriverState *curr_bs = NULL; - - if (!bs) { - return NULL; - } - - curr_bs = bs; - - while (curr_bs->backing_hd) { - curr_bs = curr_bs->backing_hd; - } - return curr_bs; -} - -/**************************************************************/ -/* async I/Os */ - -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque); - - return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, - cb, opaque, false); -} - -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque); - - return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, - cb, opaque, true); -} - - -typedef struct MultiwriteCB { - int error; - int num_requests; - int num_callbacks; - struct { - BlockDriverCompletionFunc *cb; - void *opaque; - QEMUIOVector *free_qiov; - } callbacks[]; -} MultiwriteCB; - -static void multiwrite_user_cb(MultiwriteCB *mcb) -{ - int i; - - for (i = 0; i < mcb->num_callbacks; i++) { - mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error); - if (mcb->callbacks[i].free_qiov) { - qemu_iovec_destroy(mcb->callbacks[i].free_qiov); - } - g_free(mcb->callbacks[i].free_qiov); - } -} - -static void multiwrite_cb(void *opaque, int ret) -{ - MultiwriteCB *mcb = opaque; - - trace_multiwrite_cb(mcb, ret); - - if (ret < 0 && !mcb->error) { - mcb->error = ret; - } - - mcb->num_requests--; - if (mcb->num_requests == 0) { - multiwrite_user_cb(mcb); - g_free(mcb); - } -} - -static int multiwrite_req_compare(const void *a, const void *b) -{ - const BlockRequest *req1 = a, *req2 = b; - - /* - * Note that we can't simply subtract req2->sector from req1->sector - * here as that could overflow the return value. - */ - if (req1->sector > req2->sector) { - return 1; - } else if (req1->sector < req2->sector) { - return -1; - } else { - return 0; - } -} - -/* - * Takes a bunch of requests and tries to merge them. Returns the number of - * requests that remain after merging. - */ -static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs, - int num_reqs, MultiwriteCB *mcb) -{ - int i, outidx; - - // Sort requests by start sector - qsort(reqs, num_reqs, sizeof(*reqs), &multiwrite_req_compare); - - // Check if adjacent requests touch the same clusters. If so, combine them, - // filling up gaps with zero sectors. - outidx = 0; - for (i = 1; i < num_reqs; i++) { - int merge = 0; - int64_t oldreq_last = reqs[outidx].sector + reqs[outidx].nb_sectors; - - // Handle exactly sequential writes and overlapping writes. - if (reqs[i].sector <= oldreq_last) { - merge = 1; - } - - if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) { - merge = 0; - } - - if (merge) { - size_t size; - QEMUIOVector *qiov = g_malloc0(sizeof(*qiov)); - qemu_iovec_init(qiov, - reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1); - - // Add the first request to the merged one. If the requests are - // overlapping, drop the last sectors of the first request. - size = (reqs[i].sector - reqs[outidx].sector) << 9; - qemu_iovec_concat(qiov, reqs[outidx].qiov, 0, size); - - // We should need to add any zeros between the two requests - assert (reqs[i].sector <= oldreq_last); - - // Add the second request - qemu_iovec_concat(qiov, reqs[i].qiov, 0, reqs[i].qiov->size); - - reqs[outidx].nb_sectors = qiov->size >> 9; - reqs[outidx].qiov = qiov; - - mcb->callbacks[i].free_qiov = reqs[outidx].qiov; - } else { - outidx++; - reqs[outidx].sector = reqs[i].sector; - reqs[outidx].nb_sectors = reqs[i].nb_sectors; - reqs[outidx].qiov = reqs[i].qiov; - } - } - - return outidx + 1; -} - -/* - * Submit multiple AIO write requests at once. - * - * On success, the function returns 0 and all requests in the reqs array have - * been submitted. In error case this function returns -1, and any of the - * requests may or may not be submitted yet. In particular, this means that the - * callback will be called for some of the requests, for others it won't. The - * caller must check the error field of the BlockRequest to wait for the right - * callbacks (if error != 0, no callback will be called). - * - * The implementation may modify the contents of the reqs array, e.g. to merge - * requests. However, the fields opaque and error are left unmodified as they - * are used to signal failure for a single request to the caller. - */ -int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) -{ - MultiwriteCB *mcb; - int i; - - /* don't submit writes if we don't have a medium */ - if (bs->drv == NULL) { - for (i = 0; i < num_reqs; i++) { - reqs[i].error = -ENOMEDIUM; - } - return -1; - } - - if (num_reqs == 0) { - return 0; - } - - // Create MultiwriteCB structure - mcb = g_malloc0(sizeof(*mcb) + num_reqs * sizeof(*mcb->callbacks)); - mcb->num_requests = 0; - mcb->num_callbacks = num_reqs; - - for (i = 0; i < num_reqs; i++) { - mcb->callbacks[i].cb = reqs[i].cb; - mcb->callbacks[i].opaque = reqs[i].opaque; - } - - // Check for mergable requests - num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); - - trace_bdrv_aio_multiwrite(mcb, mcb->num_callbacks, num_reqs); - - /* Run the aio requests. */ - mcb->num_requests = num_reqs; - for (i = 0; i < num_reqs; i++) { - bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov, - reqs[i].nb_sectors, multiwrite_cb, mcb); - } - - return 0; -} - -void bdrv_aio_cancel(BlockDriverAIOCB *acb) -{ - acb->aiocb_info->cancel(acb); -} - -/* block I/O throttling */ -static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors, - bool is_write, double elapsed_time, uint64_t *wait) -{ - uint64_t bps_limit = 0; - uint64_t extension; - double bytes_limit, bytes_base, bytes_res; - double slice_time, wait_time; - - if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) { - bps_limit = bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; - } else if (bs->io_limits.bps[is_write]) { - bps_limit = bs->io_limits.bps[is_write]; - } else { - if (wait) { - *wait = 0; - } - - return false; - } - - slice_time = bs->slice_end - bs->slice_start; - slice_time /= (NANOSECONDS_PER_SECOND); - bytes_limit = bps_limit * slice_time; - bytes_base = bs->slice_submitted.bytes[is_write]; - if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) { - bytes_base += bs->slice_submitted.bytes[!is_write]; - } - - /* bytes_base: the bytes of data which have been read/written; and - * it is obtained from the history statistic info. - * bytes_res: the remaining bytes of data which need to be read/written. - * (bytes_base + bytes_res) / bps_limit: used to calcuate - * the total time for completing reading/writting all data. - */ - bytes_res = (unsigned) nb_sectors * BDRV_SECTOR_SIZE; - - if (bytes_base + bytes_res <= bytes_limit) { - if (wait) { - *wait = 0; - } - - return false; - } - - /* Calc approx time to dispatch */ - wait_time = (bytes_base + bytes_res) / bps_limit - elapsed_time; - - /* When the I/O rate at runtime exceeds the limits, - * bs->slice_end need to be extended in order that the current statistic - * info can be kept until the timer fire, so it is increased and tuned - * based on the result of experiment. - */ - extension = wait_time * NANOSECONDS_PER_SECOND; - extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) * - BLOCK_IO_SLICE_TIME; - bs->slice_end += extension; - if (wait) { - *wait = wait_time * NANOSECONDS_PER_SECOND; - } - - return true; -} - -static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write, - double elapsed_time, uint64_t *wait) -{ - uint64_t iops_limit = 0; - double ios_limit, ios_base; - double slice_time, wait_time; - - if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) { - iops_limit = bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; - } else if (bs->io_limits.iops[is_write]) { - iops_limit = bs->io_limits.iops[is_write]; - } else { - if (wait) { - *wait = 0; - } - - return false; - } - - slice_time = bs->slice_end - bs->slice_start; - slice_time /= (NANOSECONDS_PER_SECOND); - ios_limit = iops_limit * slice_time; - ios_base = bs->slice_submitted.ios[is_write]; - if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) { - ios_base += bs->slice_submitted.ios[!is_write]; - } - - if (ios_base + 1 <= ios_limit) { - if (wait) { - *wait = 0; - } - - return false; - } - - /* Calc approx time to dispatch, in seconds */ - wait_time = (ios_base + 1) / iops_limit; - if (wait_time > elapsed_time) { - wait_time = wait_time - elapsed_time; - } else { - wait_time = 0; - } - - /* Exceeded current slice, extend it by another slice time */ - bs->slice_end += BLOCK_IO_SLICE_TIME; - if (wait) { - *wait = wait_time * NANOSECONDS_PER_SECOND; - } - - return true; -} - -static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, - bool is_write, int64_t *wait) -{ - int64_t now, max_wait; - uint64_t bps_wait = 0, iops_wait = 0; - double elapsed_time; - int bps_ret, iops_ret; - - now = qemu_get_clock_ns(vm_clock); - if (now > bs->slice_end) { - bs->slice_start = now; - bs->slice_end = now + BLOCK_IO_SLICE_TIME; - memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted)); - } - - elapsed_time = now - bs->slice_start; - elapsed_time /= (NANOSECONDS_PER_SECOND); - - bps_ret = bdrv_exceed_bps_limits(bs, nb_sectors, - is_write, elapsed_time, &bps_wait); - iops_ret = bdrv_exceed_iops_limits(bs, is_write, - elapsed_time, &iops_wait); - if (bps_ret || iops_ret) { - max_wait = bps_wait > iops_wait ? bps_wait : iops_wait; - if (wait) { - *wait = max_wait; - } - - now = qemu_get_clock_ns(vm_clock); - if (bs->slice_end < now + max_wait) { - bs->slice_end = now + max_wait; - } - - return true; - } - - if (wait) { - *wait = 0; - } - - bs->slice_submitted.bytes[is_write] += (int64_t)nb_sectors * - BDRV_SECTOR_SIZE; - bs->slice_submitted.ios[is_write]++; - - return false; -} - -/**************************************************************/ -/* async block device emulation */ - -typedef struct BlockDriverAIOCBSync { - BlockDriverAIOCB common; - QEMUBH *bh; - int ret; - /* vector translation state */ - QEMUIOVector *qiov; - uint8_t *bounce; - int is_write; -} BlockDriverAIOCBSync; - -static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) -{ - BlockDriverAIOCBSync *acb = - container_of(blockacb, BlockDriverAIOCBSync, common); - qemu_bh_delete(acb->bh); - acb->bh = NULL; - qemu_aio_release(acb); -} - -static const AIOCBInfo bdrv_em_aiocb_info = { - .aiocb_size = sizeof(BlockDriverAIOCBSync), - .cancel = bdrv_aio_cancel_em, -}; - -static void bdrv_aio_bh_cb(void *opaque) -{ - BlockDriverAIOCBSync *acb = opaque; - - if (!acb->is_write) - qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size); - qemu_vfree(acb->bounce); - acb->common.cb(acb->common.opaque, acb->ret); - qemu_bh_delete(acb->bh); - acb->bh = NULL; - qemu_aio_release(acb); -} - -static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - int is_write) - -{ - BlockDriverAIOCBSync *acb; - - acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque); - acb->is_write = is_write; - acb->qiov = qiov; - acb->bounce = qemu_blockalign(bs, qiov->size); - acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); - - if (is_write) { - qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size); - acb->ret = bs->drv->bdrv_write(bs, sector_num, acb->bounce, nb_sectors); - } else { - acb->ret = bs->drv->bdrv_read(bs, sector_num, acb->bounce, nb_sectors); - } - - qemu_bh_schedule(acb->bh); - - return &acb->common; -} - -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); -} - -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); -} - - -typedef struct BlockDriverAIOCBCoroutine { - BlockDriverAIOCB common; - BlockRequest req; - bool is_write; - bool *done; - QEMUBH* bh; -} BlockDriverAIOCBCoroutine; - -static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb) -{ - BlockDriverAIOCBCoroutine *acb = - container_of(blockacb, BlockDriverAIOCBCoroutine, common); - bool done = false; - - acb->done = &done; - while (!done) { - qemu_aio_wait(); - } -} - -static const AIOCBInfo bdrv_em_co_aiocb_info = { - .aiocb_size = sizeof(BlockDriverAIOCBCoroutine), - .cancel = bdrv_aio_co_cancel_em, -}; - -static void bdrv_co_em_bh(void *opaque) -{ - BlockDriverAIOCBCoroutine *acb = opaque; - - acb->common.cb(acb->common.opaque, acb->req.error); - - if (acb->done) { - *acb->done = true; - } - - qemu_bh_delete(acb->bh); - qemu_aio_release(acb); -} - -/* Invoke bdrv_co_do_readv/bdrv_co_do_writev */ -static void coroutine_fn bdrv_co_do_rw(void *opaque) -{ - BlockDriverAIOCBCoroutine *acb = opaque; - BlockDriverState *bs = acb->common.bs; - - if (!acb->is_write) { - acb->req.error = bdrv_co_do_readv(bs, acb->req.sector, - acb->req.nb_sectors, acb->req.qiov, 0); - } else { - acb->req.error = bdrv_co_do_writev(bs, acb->req.sector, - acb->req.nb_sectors, acb->req.qiov, 0); - } - - acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); - qemu_bh_schedule(acb->bh); -} - -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - bool is_write) -{ - Coroutine *co; - BlockDriverAIOCBCoroutine *acb; - - acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); - acb->req.sector = sector_num; - acb->req.nb_sectors = nb_sectors; - acb->req.qiov = qiov; - acb->is_write = is_write; - acb->done = NULL; - - co = qemu_coroutine_create(bdrv_co_do_rw); - qemu_coroutine_enter(co, acb); - - return &acb->common; -} - -static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque) -{ - BlockDriverAIOCBCoroutine *acb = opaque; - BlockDriverState *bs = acb->common.bs; - - acb->req.error = bdrv_co_flush(bs); - acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); - qemu_bh_schedule(acb->bh); -} - -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) -{ - trace_bdrv_aio_flush(bs, opaque); - - Coroutine *co; - BlockDriverAIOCBCoroutine *acb; - - acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); - acb->done = NULL; - - co = qemu_coroutine_create(bdrv_aio_flush_co_entry); - qemu_coroutine_enter(co, acb); - - return &acb->common; -} - -static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque) -{ - BlockDriverAIOCBCoroutine *acb = opaque; - BlockDriverState *bs = acb->common.bs; - - acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors); - acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); - qemu_bh_schedule(acb->bh); -} - -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - Coroutine *co; - BlockDriverAIOCBCoroutine *acb; - - trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque); - - acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); - acb->req.sector = sector_num; - acb->req.nb_sectors = nb_sectors; - acb->done = NULL; - co = qemu_coroutine_create(bdrv_aio_discard_co_entry); - qemu_coroutine_enter(co, acb); - - return &acb->common; -} - -void bdrv_init(void) -{ - module_call_init(MODULE_INIT_BLOCK); -} - -void bdrv_init_with_whitelist(void) -{ - use_bdrv_whitelist = 1; - bdrv_init(); -} - -void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) -{ - BlockDriverAIOCB *acb; - - acb = g_slice_alloc(aiocb_info->aiocb_size); - acb->aiocb_info = aiocb_info; - acb->bs = bs; - acb->cb = cb; - acb->opaque = opaque; - return acb; -} - -void qemu_aio_release(void *p) -{ - BlockDriverAIOCB *acb = p; - g_slice_free1(acb->aiocb_info->aiocb_size, acb); -} - -/**************************************************************/ -/* Coroutine block device emulation */ - -typedef struct CoroutineIOCompletion { - Coroutine *coroutine; - int ret; -} CoroutineIOCompletion; - -static void bdrv_co_io_em_complete(void *opaque, int ret) -{ - CoroutineIOCompletion *co = opaque; - - co->ret = ret; - qemu_coroutine_enter(co->coroutine, NULL); -} - -static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *iov, - bool is_write) -{ - CoroutineIOCompletion co = { - .coroutine = qemu_coroutine_self(), - }; - BlockDriverAIOCB *acb; - - if (is_write) { - acb = bs->drv->bdrv_aio_writev(bs, sector_num, iov, nb_sectors, - bdrv_co_io_em_complete, &co); - } else { - acb = bs->drv->bdrv_aio_readv(bs, sector_num, iov, nb_sectors, - bdrv_co_io_em_complete, &co); - } - - trace_bdrv_co_io_em(bs, sector_num, nb_sectors, is_write, acb); - if (!acb) { - return -EIO; - } - qemu_coroutine_yield(); - - return co.ret; -} - -static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov) -{ - return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, false); -} - -static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov) -{ - return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); -} - -static void coroutine_fn bdrv_flush_co_entry(void *opaque) -{ - RwCo *rwco = opaque; - - rwco->ret = bdrv_co_flush(rwco->bs); -} - -int coroutine_fn bdrv_co_flush(BlockDriverState *bs) -{ - int ret; - - if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { - return 0; - } - - /* Write back cached data to the OS even with cache=unsafe */ - BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS); - if (bs->drv->bdrv_co_flush_to_os) { - ret = bs->drv->bdrv_co_flush_to_os(bs); - if (ret < 0) { - return ret; - } - } - - /* But don't actually force it to the disk with cache=unsafe */ - if (bs->open_flags & BDRV_O_NO_FLUSH) { - goto flush_parent; - } - - BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK); - if (bs->drv->bdrv_co_flush_to_disk) { - ret = bs->drv->bdrv_co_flush_to_disk(bs); - } else if (bs->drv->bdrv_aio_flush) { - BlockDriverAIOCB *acb; - CoroutineIOCompletion co = { - .coroutine = qemu_coroutine_self(), - }; - - acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); - if (acb == NULL) { - ret = -EIO; - } else { - qemu_coroutine_yield(); - ret = co.ret; - } - } else { - /* - * Some block drivers always operate in either writethrough or unsafe - * mode and don't support bdrv_flush therefore. Usually qemu doesn't - * know how the server works (because the behaviour is hardcoded or - * depends on server-side configuration), so we can't ensure that - * everything is safe on disk. Returning an error doesn't work because - * that would break guests even if the server operates in writethrough - * mode. - * - * Let's hope the user knows what he's doing. - */ - ret = 0; - } - if (ret < 0) { - return ret; - } - - /* Now flush the underlying protocol. It will also have BDRV_O_NO_FLUSH - * in the case of cache=unsafe, so there are no useless flushes. - */ -flush_parent: - return bdrv_co_flush(bs->file); -} - -void bdrv_invalidate_cache(BlockDriverState *bs) -{ - if (bs->drv && bs->drv->bdrv_invalidate_cache) { - bs->drv->bdrv_invalidate_cache(bs); - } -} - -void bdrv_invalidate_cache_all(void) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - bdrv_invalidate_cache(bs); - } -} - -void bdrv_clear_incoming_migration_all(void) -{ - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING); - } -} - -int bdrv_flush(BlockDriverState *bs) -{ - Coroutine *co; - RwCo rwco = { - .bs = bs, - .ret = NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_flush_co_entry(&rwco); - } else { - co = qemu_coroutine_create(bdrv_flush_co_entry); - qemu_coroutine_enter(co, &rwco); - while (rwco.ret == NOT_DONE) { - qemu_aio_wait(); - } - } - - return rwco.ret; -} - -static void coroutine_fn bdrv_discard_co_entry(void *opaque) -{ - RwCo *rwco = opaque; - - rwco->ret = bdrv_co_discard(rwco->bs, rwco->sector_num, rwco->nb_sectors); -} - -int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, - int nb_sectors) -{ - if (!bs->drv) { - return -ENOMEDIUM; - } else if (bdrv_check_request(bs, sector_num, nb_sectors)) { - return -EIO; - } else if (bs->read_only) { - return -EROFS; - } - - if (bs->dirty_bitmap) { - bdrv_reset_dirty(bs, sector_num, nb_sectors); - } - - /* Do nothing if disabled. */ - if (!(bs->open_flags & BDRV_O_UNMAP)) { - return 0; - } - - if (bs->drv->bdrv_co_discard) { - return bs->drv->bdrv_co_discard(bs, sector_num, nb_sectors); - } else if (bs->drv->bdrv_aio_discard) { - BlockDriverAIOCB *acb; - CoroutineIOCompletion co = { - .coroutine = qemu_coroutine_self(), - }; - - acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors, - bdrv_co_io_em_complete, &co); - if (acb == NULL) { - return -EIO; - } else { - qemu_coroutine_yield(); - return co.ret; - } - } else { - return 0; - } -} - -int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) -{ - Coroutine *co; - RwCo rwco = { - .bs = bs, - .sector_num = sector_num, - .nb_sectors = nb_sectors, - .ret = NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_discard_co_entry(&rwco); - } else { - co = qemu_coroutine_create(bdrv_discard_co_entry); - qemu_coroutine_enter(co, &rwco); - while (rwco.ret == NOT_DONE) { - qemu_aio_wait(); - } - } - - return rwco.ret; -} - -/**************************************************************/ -/* removable device support */ - -/** - * Return TRUE if the media is present - */ -int bdrv_is_inserted(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - - if (!drv) - return 0; - if (!drv->bdrv_is_inserted) - return 1; - return drv->bdrv_is_inserted(bs); -} - -/** - * Return whether the media changed since the last call to this - * function, or -ENOTSUP if we don't know. Most drivers don't know. - */ -int bdrv_media_changed(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - - if (drv && drv->bdrv_media_changed) { - return drv->bdrv_media_changed(bs); - } - return -ENOTSUP; -} - -/** - * If eject_flag is TRUE, eject the media. Otherwise, close the tray - */ -void bdrv_eject(BlockDriverState *bs, bool eject_flag) -{ - BlockDriver *drv = bs->drv; - - if (drv && drv->bdrv_eject) { - drv->bdrv_eject(bs, eject_flag); - } - - if (bs->device_name[0] != '\0') { - bdrv_emit_qmp_eject_event(bs, eject_flag); - } -} - -/** - * Lock or unlock the media (if it is locked, the user won't be able - * to eject it manually). - */ -void bdrv_lock_medium(BlockDriverState *bs, bool locked) -{ - BlockDriver *drv = bs->drv; - - trace_bdrv_lock_medium(bs, locked); - - if (drv && drv->bdrv_lock_medium) { - drv->bdrv_lock_medium(bs, locked); - } -} - -/* needed for generic scsi interface */ - -int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) -{ - BlockDriver *drv = bs->drv; - - if (drv && drv->bdrv_ioctl) - return drv->bdrv_ioctl(bs, req, buf); - return -ENOTSUP; -} - -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque) -{ - BlockDriver *drv = bs->drv; - - if (drv && drv->bdrv_aio_ioctl) - return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque); - return NULL; -} - -void bdrv_set_buffer_alignment(BlockDriverState *bs, int align) -{ - bs->buffer_alignment = align; -} - -void *qemu_blockalign(BlockDriverState *bs, size_t size) -{ - return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size); -} - -/* - * Check if all memory in this vector is sector aligned. - */ -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) -{ - int i; - - for (i = 0; i < qiov->niov; i++) { - if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) { - return false; - } - } - - return true; -} - -void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity) -{ - int64_t bitmap_size; - - assert((granularity & (granularity - 1)) == 0); - - if (granularity) { - granularity >>= BDRV_SECTOR_BITS; - assert(!bs->dirty_bitmap); - bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS); - bs->dirty_bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1); - } else { - if (bs->dirty_bitmap) { - hbitmap_free(bs->dirty_bitmap); - bs->dirty_bitmap = NULL; - } - } -} - -int bdrv_get_dirty(BlockDriverState *bs, int64_t sector) -{ - if (bs->dirty_bitmap) { - return hbitmap_get(bs->dirty_bitmap, sector); - } else { - return 0; - } -} - -void bdrv_dirty_iter_init(BlockDriverState *bs, HBitmapIter *hbi) -{ - hbitmap_iter_init(hbi, bs->dirty_bitmap, 0); -} - -void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, - int nr_sectors) -{ - hbitmap_set(bs->dirty_bitmap, cur_sector, nr_sectors); -} - -void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, - int nr_sectors) -{ - hbitmap_reset(bs->dirty_bitmap, cur_sector, nr_sectors); -} - -int64_t bdrv_get_dirty_count(BlockDriverState *bs) -{ - if (bs->dirty_bitmap) { - return hbitmap_count(bs->dirty_bitmap); - } else { - return 0; - } -} - -void bdrv_set_in_use(BlockDriverState *bs, int in_use) -{ - assert(bs->in_use != in_use); - bs->in_use = in_use; -} - -int bdrv_in_use(BlockDriverState *bs) -{ - return bs->in_use; -} - -void bdrv_iostatus_enable(BlockDriverState *bs) -{ - bs->iostatus_enabled = true; - bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK; -} - -/* The I/O status is only enabled if the drive explicitly - * enables it _and_ the VM is configured to stop on errors */ -bool bdrv_iostatus_is_enabled(const BlockDriverState *bs) -{ - return (bs->iostatus_enabled && - (bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC || - bs->on_write_error == BLOCKDEV_ON_ERROR_STOP || - bs->on_read_error == BLOCKDEV_ON_ERROR_STOP)); -} - -void bdrv_iostatus_disable(BlockDriverState *bs) -{ - bs->iostatus_enabled = false; -} - -void bdrv_iostatus_reset(BlockDriverState *bs) -{ - if (bdrv_iostatus_is_enabled(bs)) { - bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK; - if (bs->job) { - block_job_iostatus_reset(bs->job); - } - } -} - -void bdrv_iostatus_set_err(BlockDriverState *bs, int error) -{ - assert(bdrv_iostatus_is_enabled(bs)); - if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { - bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : - BLOCK_DEVICE_IO_STATUS_FAILED; - } -} - -void -bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, int64_t bytes, - enum BlockAcctType type) -{ - assert(type < BDRV_MAX_IOTYPE); - - cookie->bytes = bytes; - cookie->start_time_ns = get_clock(); - cookie->type = type; -} - -void -bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie) -{ - assert(cookie->type < BDRV_MAX_IOTYPE); - - bs->nr_bytes[cookie->type] += cookie->bytes; - bs->nr_ops[cookie->type]++; - bs->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns; -} - -void bdrv_img_create(const char *filename, const char *fmt, - const char *base_filename, const char *base_fmt, - char *options, uint64_t img_size, int flags, - Error **errp, bool quiet) -{ - QEMUOptionParameter *param = NULL, *create_options = NULL; - QEMUOptionParameter *backing_fmt, *backing_file, *size; - BlockDriverState *bs = NULL; - BlockDriver *drv, *proto_drv; - BlockDriver *backing_drv = NULL; - int ret = 0; - - /* Find driver and parse its options */ - drv = bdrv_find_format(fmt); - if (!drv) { - error_setg(errp, "Unknown file format '%s'", fmt); - return; - } - - proto_drv = bdrv_find_protocol(filename, true); - if (!proto_drv) { - error_setg(errp, "Unknown protocol '%s'", filename); - return; - } - - create_options = append_option_parameters(create_options, - drv->create_options); - create_options = append_option_parameters(create_options, - proto_drv->create_options); - - /* Create parameter list with default values */ - param = parse_option_parameters("", create_options, param); - - set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size); - - /* Parse -o options */ - if (options) { - param = parse_option_parameters(options, create_options, param); - if (param == NULL) { - error_setg(errp, "Invalid options for file format '%s'.", fmt); - goto out; - } - } - - if (base_filename) { - if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, - base_filename)) { - error_setg(errp, "Backing file not supported for file format '%s'", - fmt); - goto out; - } - } - - if (base_fmt) { - if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) { - error_setg(errp, "Backing file format not supported for file " - "format '%s'", fmt); - goto out; - } - } - - backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); - if (backing_file && backing_file->value.s) { - if (!strcmp(filename, backing_file->value.s)) { - error_setg(errp, "Error: Trying to create an image with the " - "same filename as the backing file"); - goto out; - } - } - - backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); - if (backing_fmt && backing_fmt->value.s) { - backing_drv = bdrv_find_format(backing_fmt->value.s); - if (!backing_drv) { - error_setg(errp, "Unknown backing file format '%s'", - backing_fmt->value.s); - goto out; - } - } - - // The size for the image must always be specified, with one exception: - // If we are using a backing file, we can obtain the size from there - size = get_option_parameter(param, BLOCK_OPT_SIZE); - if (size && size->value.n == -1) { - if (backing_file && backing_file->value.s) { - uint64_t size; - char buf[32]; - int back_flags; - - /* backing files always opened read-only */ - back_flags = - flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); - - bs = bdrv_new(""); - - ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags, - backing_drv); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not open '%s'", - backing_file->value.s); - goto out; - } - bdrv_get_geometry(bs, &size); - size *= 512; - - snprintf(buf, sizeof(buf), "%" PRId64, size); - set_option_parameter(param, BLOCK_OPT_SIZE, buf); - } else { - error_setg(errp, "Image creation needs a size parameter"); - goto out; - } - } - - if (!quiet) { - printf("Formatting '%s', fmt=%s ", filename, fmt); - print_option_parameters(param); - puts(""); - } - ret = bdrv_create(drv, filename, param); - if (ret < 0) { - if (ret == -ENOTSUP) { - error_setg(errp,"Formatting or formatting option not supported for " - "file format '%s'", fmt); - } else if (ret == -EFBIG) { - const char *cluster_size_hint = ""; - if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) { - cluster_size_hint = " (try using a larger cluster size)"; - } - error_setg(errp, "The image size is too large for file format '%s'%s", - fmt, cluster_size_hint); - } else { - error_setg(errp, "%s: error while creating %s: %s", filename, fmt, - strerror(-ret)); - } - } - -out: - free_option_parameters(create_options); - free_option_parameters(param); - - if (bs) { - bdrv_delete(bs); - } -} - -AioContext *bdrv_get_aio_context(BlockDriverState *bs) -{ - /* Currently BlockDriverState always uses the main loop AioContext */ - return qemu_get_aio_context(); -} - -void bdrv_add_before_write_notifier(BlockDriverState *bs, - NotifierWithReturn *notifier) -{ - notifier_with_return_list_add(&bs->before_write_notifiers, notifier); -} diff --git a/contrib/qemu/block/qcow.c b/contrib/qemu/block/qcow.c deleted file mode 100644 index 5239bd68f1c..00000000000 --- a/contrib/qemu/block/qcow.c +++ /dev/null @@ -1,914 +0,0 @@ -/* - * Block driver for the QCOW format - * - * Copyright (c) 2004-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-common.h" -#include "block/block_int.h" -#include "qemu/module.h" -#include <zlib.h> -#include "qemu/aes.h" -#include "migration/migration.h" - -/**************************************************************/ -/* QEMU COW block driver with compression and encryption support */ - -#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) -#define QCOW_VERSION 1 - -#define QCOW_CRYPT_NONE 0 -#define QCOW_CRYPT_AES 1 - -#define QCOW_OFLAG_COMPRESSED (1LL << 63) - -typedef struct QCowHeader { - uint32_t magic; - uint32_t version; - uint64_t backing_file_offset; - uint32_t backing_file_size; - uint32_t mtime; - uint64_t size; /* in bytes */ - uint8_t cluster_bits; - uint8_t l2_bits; - uint32_t crypt_method; - uint64_t l1_table_offset; -} QCowHeader; - -#define L2_CACHE_SIZE 16 - -typedef struct BDRVQcowState { - int cluster_bits; - int cluster_size; - int cluster_sectors; - int l2_bits; - int l2_size; - int l1_size; - uint64_t cluster_offset_mask; - uint64_t l1_table_offset; - uint64_t *l1_table; - uint64_t *l2_cache; - uint64_t l2_cache_offsets[L2_CACHE_SIZE]; - uint32_t l2_cache_counts[L2_CACHE_SIZE]; - uint8_t *cluster_cache; - uint8_t *cluster_data; - uint64_t cluster_cache_offset; - uint32_t crypt_method; /* current crypt method, 0 if no key yet */ - uint32_t crypt_method_header; - AES_KEY aes_encrypt_key; - AES_KEY aes_decrypt_key; - CoMutex lock; - Error *migration_blocker; -} BDRVQcowState; - -static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); - -static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) -{ - const QCowHeader *cow_header = (const void *)buf; - - if (buf_size >= sizeof(QCowHeader) && - be32_to_cpu(cow_header->magic) == QCOW_MAGIC && - be32_to_cpu(cow_header->version) == QCOW_VERSION) - return 100; - else - return 0; -} - -static int qcow_open(BlockDriverState *bs, QDict *options, int flags) -{ - BDRVQcowState *s = bs->opaque; - int len, i, shift, ret; - QCowHeader header; - - ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); - if (ret < 0) { - goto fail; - } - be32_to_cpus(&header.magic); - be32_to_cpus(&header.version); - be64_to_cpus(&header.backing_file_offset); - be32_to_cpus(&header.backing_file_size); - be32_to_cpus(&header.mtime); - be64_to_cpus(&header.size); - be32_to_cpus(&header.crypt_method); - be64_to_cpus(&header.l1_table_offset); - - if (header.magic != QCOW_MAGIC) { - ret = -EMEDIUMTYPE; - goto fail; - } - if (header.version != QCOW_VERSION) { - char version[64]; - snprintf(version, sizeof(version), "QCOW version %d", header.version); - qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "qcow", version); - ret = -ENOTSUP; - goto fail; - } - - if (header.size <= 1 || header.cluster_bits < 9) { - ret = -EINVAL; - goto fail; - } - if (header.crypt_method > QCOW_CRYPT_AES) { - ret = -EINVAL; - goto fail; - } - s->crypt_method_header = header.crypt_method; - if (s->crypt_method_header) { - bs->encrypted = 1; - } - s->cluster_bits = header.cluster_bits; - s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); - s->l2_bits = header.l2_bits; - s->l2_size = 1 << s->l2_bits; - bs->total_sectors = header.size / 512; - s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1; - - /* read the level 1 table */ - shift = s->cluster_bits + s->l2_bits; - s->l1_size = (header.size + (1LL << shift) - 1) >> shift; - - s->l1_table_offset = header.l1_table_offset; - s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t)); - - ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, - s->l1_size * sizeof(uint64_t)); - if (ret < 0) { - goto fail; - } - - for(i = 0;i < s->l1_size; i++) { - be64_to_cpus(&s->l1_table[i]); - } - /* alloc L2 cache */ - s->l2_cache = g_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); - s->cluster_cache = g_malloc(s->cluster_size); - s->cluster_data = g_malloc(s->cluster_size); - s->cluster_cache_offset = -1; - - /* read the backing file name */ - if (header.backing_file_offset != 0) { - len = header.backing_file_size; - if (len > 1023) { - len = 1023; - } - ret = bdrv_pread(bs->file, header.backing_file_offset, - bs->backing_file, len); - if (ret < 0) { - goto fail; - } - bs->backing_file[len] = '\0'; - } - - /* Disable migration when qcow images are used */ - error_set(&s->migration_blocker, - QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "qcow", bs->device_name, "live migration"); - migrate_add_blocker(s->migration_blocker); - - qemu_co_mutex_init(&s->lock); - return 0; - - fail: - g_free(s->l1_table); - g_free(s->l2_cache); - g_free(s->cluster_cache); - g_free(s->cluster_data); - return ret; -} - - -/* We have nothing to do for QCOW reopen, stubs just return - * success */ -static int qcow_reopen_prepare(BDRVReopenState *state, - BlockReopenQueue *queue, Error **errp) -{ - return 0; -} - -static int qcow_set_key(BlockDriverState *bs, const char *key) -{ - BDRVQcowState *s = bs->opaque; - uint8_t keybuf[16]; - int len, i; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for(i = 0;i < len;i++) { - keybuf[i] = key[i]; - } - s->crypt_method = s->crypt_method_header; - - if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0) - return -1; - if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) - return -1; - return 0; -} - -/* The crypt function is compatible with the linux cryptoloop - algorithm for < 4 GB images. NOTE: out_buf == in_buf is - supported */ -static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, int enc, - const AES_KEY *key) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - - for(i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - AES_cbc_encrypt(in_buf, out_buf, 512, key, - ivec.b, enc); - sector_num++; - in_buf += 512; - out_buf += 512; - } -} - -/* 'allocate' is: - * - * 0 to not allocate. - * - * 1 to allocate a normal cluster (for sector indexes 'n_start' to - * 'n_end') - * - * 2 to allocate a compressed cluster of size - * 'compressed_size'. 'compressed_size' must be > 0 and < - * cluster_size - * - * return 0 if not allocated. - */ -static uint64_t get_cluster_offset(BlockDriverState *bs, - uint64_t offset, int allocate, - int compressed_size, - int n_start, int n_end) -{ - BDRVQcowState *s = bs->opaque; - int min_index, i, j, l1_index, l2_index; - uint64_t l2_offset, *l2_table, cluster_offset, tmp; - uint32_t min_count; - int new_l2_table; - - l1_index = offset >> (s->l2_bits + s->cluster_bits); - l2_offset = s->l1_table[l1_index]; - new_l2_table = 0; - if (!l2_offset) { - if (!allocate) - return 0; - /* allocate a new l2 entry */ - l2_offset = bdrv_getlength(bs->file); - /* round to cluster size */ - l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1); - /* update the L1 entry */ - s->l1_table[l1_index] = l2_offset; - tmp = cpu_to_be64(l2_offset); - if (bdrv_pwrite_sync(bs->file, - s->l1_table_offset + l1_index * sizeof(tmp), - &tmp, sizeof(tmp)) < 0) - return 0; - new_l2_table = 1; - } - for(i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == s->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++s->l2_cache_counts[i] == 0xffffffff) { - for(j = 0; j < L2_CACHE_SIZE; j++) { - s->l2_cache_counts[j] >>= 1; - } - } - l2_table = s->l2_cache + (i << s->l2_bits); - goto found; - } - } - /* not found: load a new entry in the least used one */ - min_index = 0; - min_count = 0xffffffff; - for(i = 0; i < L2_CACHE_SIZE; i++) { - if (s->l2_cache_counts[i] < min_count) { - min_count = s->l2_cache_counts[i]; - min_index = i; - } - } - l2_table = s->l2_cache + (min_index << s->l2_bits); - if (new_l2_table) { - memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); - if (bdrv_pwrite_sync(bs->file, l2_offset, l2_table, - s->l2_size * sizeof(uint64_t)) < 0) - return 0; - } else { - if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - return 0; - } - s->l2_cache_offsets[min_index] = l2_offset; - s->l2_cache_counts[min_index] = 1; - found: - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - cluster_offset = be64_to_cpu(l2_table[l2_index]); - if (!cluster_offset || - ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) { - if (!allocate) - return 0; - /* allocate a new cluster */ - if ((cluster_offset & QCOW_OFLAG_COMPRESSED) && - (n_end - n_start) < s->cluster_sectors) { - /* if the cluster is already compressed, we must - decompress it in the case it is not completely - overwritten */ - if (decompress_cluster(bs, cluster_offset) < 0) - return 0; - cluster_offset = bdrv_getlength(bs->file); - cluster_offset = (cluster_offset + s->cluster_size - 1) & - ~(s->cluster_size - 1); - /* write the cluster content */ - if (bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache, s->cluster_size) != - s->cluster_size) - return -1; - } else { - cluster_offset = bdrv_getlength(bs->file); - if (allocate == 1) { - /* round to cluster size */ - cluster_offset = (cluster_offset + s->cluster_size - 1) & - ~(s->cluster_size - 1); - bdrv_truncate(bs->file, cluster_offset + s->cluster_size); - /* if encrypted, we must initialize the cluster - content which won't be written */ - if (s->crypt_method && - (n_end - n_start) < s->cluster_sectors) { - uint64_t start_sect; - start_sect = (offset & ~(s->cluster_size - 1)) >> 9; - memset(s->cluster_data + 512, 0x00, 512); - for(i = 0; i < s->cluster_sectors; i++) { - if (i < n_start || i >= n_end) { - encrypt_sectors(s, start_sect + i, - s->cluster_data, - s->cluster_data + 512, 1, 1, - &s->aes_encrypt_key); - if (bdrv_pwrite(bs->file, cluster_offset + i * 512, - s->cluster_data, 512) != 512) - return -1; - } - } - } - } else if (allocate == 2) { - cluster_offset |= QCOW_OFLAG_COMPRESSED | - (uint64_t)compressed_size << (63 - s->cluster_bits); - } - } - /* update L2 table */ - tmp = cpu_to_be64(cluster_offset); - l2_table[l2_index] = tmp; - if (bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp), - &tmp, sizeof(tmp)) < 0) - return 0; - } - return cluster_offset; -} - -static int coroutine_fn qcow_co_is_allocated(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, int *pnum) -{ - BDRVQcowState *s = bs->opaque; - int index_in_cluster, n; - uint64_t cluster_offset; - - qemu_co_mutex_lock(&s->lock); - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); - qemu_co_mutex_unlock(&s->lock); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - *pnum = n; - return (cluster_offset != 0); -} - -static int decompress_buffer(uint8_t *out_buf, int out_buf_size, - const uint8_t *buf, int buf_size) -{ - z_stream strm1, *strm = &strm1; - int ret, out_len; - - memset(strm, 0, sizeof(*strm)); - - strm->next_in = (uint8_t *)buf; - strm->avail_in = buf_size; - strm->next_out = out_buf; - strm->avail_out = out_buf_size; - - ret = inflateInit2(strm, -12); - if (ret != Z_OK) - return -1; - ret = inflate(strm, Z_FINISH); - out_len = strm->next_out - out_buf; - if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || - out_len != out_buf_size) { - inflateEnd(strm); - return -1; - } - inflateEnd(strm); - return 0; -} - -static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) -{ - BDRVQcowState *s = bs->opaque; - int ret, csize; - uint64_t coffset; - - coffset = cluster_offset & s->cluster_offset_mask; - if (s->cluster_cache_offset != coffset) { - csize = cluster_offset >> (63 - s->cluster_bits); - csize &= (s->cluster_size - 1); - ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize); - if (ret != csize) - return -1; - if (decompress_buffer(s->cluster_cache, s->cluster_size, - s->cluster_data, csize) < 0) { - return -1; - } - s->cluster_cache_offset = coffset; - } - return 0; -} - -static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - int index_in_cluster; - int ret = 0, n; - uint64_t cluster_offset; - struct iovec hd_iov; - QEMUIOVector hd_qiov; - uint8_t *buf; - void *orig_buf; - - if (qiov->niov > 1) { - buf = orig_buf = qemu_blockalign(bs, qiov->size); - } else { - orig_buf = NULL; - buf = (uint8_t *)qiov->iov->iov_base; - } - - qemu_co_mutex_lock(&s->lock); - - while (nb_sectors != 0) { - /* prepare next request */ - cluster_offset = get_cluster_offset(bs, sector_num << 9, - 0, 0, 0, 0); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) { - n = nb_sectors; - } - - if (!cluster_offset) { - if (bs->backing_hd) { - /* read from the base image */ - hd_iov.iov_base = (void *)buf; - hd_iov.iov_len = n * 512; - qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->backing_hd, sector_num, - n, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - goto fail; - } - } else { - /* Note: in this case, no need to wait */ - memset(buf, 0, 512 * n); - } - } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - /* add AIO support for compressed blocks ? */ - if (decompress_cluster(bs, cluster_offset) < 0) { - goto fail; - } - memcpy(buf, - s->cluster_cache + index_in_cluster * 512, 512 * n); - } else { - if ((cluster_offset & 511) != 0) { - goto fail; - } - hd_iov.iov_base = (void *)buf; - hd_iov.iov_len = n * 512; - qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->file, - (cluster_offset >> 9) + index_in_cluster, - n, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - break; - } - if (s->crypt_method) { - encrypt_sectors(s, sector_num, buf, buf, - n, 0, - &s->aes_decrypt_key); - } - } - ret = 0; - - nb_sectors -= n; - sector_num += n; - buf += n * 512; - } - -done: - qemu_co_mutex_unlock(&s->lock); - - if (qiov->niov > 1) { - qemu_iovec_from_buf(qiov, 0, orig_buf, qiov->size); - qemu_vfree(orig_buf); - } - - return ret; - -fail: - ret = -EIO; - goto done; -} - -static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - int index_in_cluster; - uint64_t cluster_offset; - const uint8_t *src_buf; - int ret = 0, n; - uint8_t *cluster_data = NULL; - struct iovec hd_iov; - QEMUIOVector hd_qiov; - uint8_t *buf; - void *orig_buf; - - s->cluster_cache_offset = -1; /* disable compressed cache */ - - if (qiov->niov > 1) { - buf = orig_buf = qemu_blockalign(bs, qiov->size); - qemu_iovec_to_buf(qiov, 0, buf, qiov->size); - } else { - orig_buf = NULL; - buf = (uint8_t *)qiov->iov->iov_base; - } - - qemu_co_mutex_lock(&s->lock); - - while (nb_sectors != 0) { - - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) { - n = nb_sectors; - } - cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, - index_in_cluster, - index_in_cluster + n); - if (!cluster_offset || (cluster_offset & 511) != 0) { - ret = -EIO; - break; - } - if (s->crypt_method) { - if (!cluster_data) { - cluster_data = g_malloc0(s->cluster_size); - } - encrypt_sectors(s, sector_num, cluster_data, buf, - n, 1, &s->aes_encrypt_key); - src_buf = cluster_data; - } else { - src_buf = buf; - } - - hd_iov.iov_base = (void *)src_buf; - hd_iov.iov_len = n * 512; - qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_writev(bs->file, - (cluster_offset >> 9) + index_in_cluster, - n, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - break; - } - ret = 0; - - nb_sectors -= n; - sector_num += n; - buf += n * 512; - } - qemu_co_mutex_unlock(&s->lock); - - if (qiov->niov > 1) { - qemu_vfree(orig_buf); - } - g_free(cluster_data); - - return ret; -} - -static void qcow_close(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - - g_free(s->l1_table); - g_free(s->l2_cache); - g_free(s->cluster_cache); - g_free(s->cluster_data); - - migrate_del_blocker(s->migration_blocker); - error_free(s->migration_blocker); -} - -static int qcow_create(const char *filename, QEMUOptionParameter *options) -{ - int header_size, backing_filename_len, l1_size, shift, i; - QCowHeader header; - uint8_t *tmp; - int64_t total_size = 0; - const char *backing_file = NULL; - int flags = 0; - int ret; - BlockDriverState *qcow_bs; - - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / 512; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { - flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; - } - options++; - } - - ret = bdrv_create_file(filename, options); - if (ret < 0) { - return ret; - } - - ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR); - if (ret < 0) { - return ret; - } - - ret = bdrv_truncate(qcow_bs, 0); - if (ret < 0) { - goto exit; - } - - memset(&header, 0, sizeof(header)); - header.magic = cpu_to_be32(QCOW_MAGIC); - header.version = cpu_to_be32(QCOW_VERSION); - header.size = cpu_to_be64(total_size * 512); - header_size = sizeof(header); - backing_filename_len = 0; - if (backing_file) { - if (strcmp(backing_file, "fat:")) { - header.backing_file_offset = cpu_to_be64(header_size); - backing_filename_len = strlen(backing_file); - header.backing_file_size = cpu_to_be32(backing_filename_len); - header_size += backing_filename_len; - } else { - /* special backing file for vvfat */ - backing_file = NULL; - } - header.cluster_bits = 9; /* 512 byte cluster to avoid copying - unmodifyed sectors */ - header.l2_bits = 12; /* 32 KB L2 tables */ - } else { - header.cluster_bits = 12; /* 4 KB clusters */ - header.l2_bits = 9; /* 4 KB L2 tables */ - } - header_size = (header_size + 7) & ~7; - shift = header.cluster_bits + header.l2_bits; - l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift; - - header.l1_table_offset = cpu_to_be64(header_size); - if (flags & BLOCK_FLAG_ENCRYPT) { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); - } else { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); - } - - /* write all the data */ - ret = bdrv_pwrite(qcow_bs, 0, &header, sizeof(header)); - if (ret != sizeof(header)) { - goto exit; - } - - if (backing_file) { - ret = bdrv_pwrite(qcow_bs, sizeof(header), - backing_file, backing_filename_len); - if (ret != backing_filename_len) { - goto exit; - } - } - - tmp = g_malloc0(BDRV_SECTOR_SIZE); - for (i = 0; i < ((sizeof(uint64_t)*l1_size + BDRV_SECTOR_SIZE - 1)/ - BDRV_SECTOR_SIZE); i++) { - ret = bdrv_pwrite(qcow_bs, header_size + - BDRV_SECTOR_SIZE*i, tmp, BDRV_SECTOR_SIZE); - if (ret != BDRV_SECTOR_SIZE) { - g_free(tmp); - goto exit; - } - } - - g_free(tmp); - ret = 0; -exit: - bdrv_delete(qcow_bs); - return ret; -} - -static int qcow_make_empty(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - uint32_t l1_length = s->l1_size * sizeof(uint64_t); - int ret; - - memset(s->l1_table, 0, l1_length); - if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table, - l1_length) < 0) - return -1; - ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length); - if (ret < 0) - return ret; - - memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t)); - - return 0; -} - -/* XXX: put compressed sectors first, then all the cluster aligned - tables to avoid losing bytes in alignment */ -static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - BDRVQcowState *s = bs->opaque; - z_stream strm; - int ret, out_len; - uint8_t *out_buf; - uint64_t cluster_offset; - - if (nb_sectors != s->cluster_sectors) { - ret = -EINVAL; - - /* Zero-pad last write if image size is not cluster aligned */ - if (sector_num + nb_sectors == bs->total_sectors && - nb_sectors < s->cluster_sectors) { - uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size); - memset(pad_buf, 0, s->cluster_size); - memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE); - ret = qcow_write_compressed(bs, sector_num, - pad_buf, s->cluster_sectors); - qemu_vfree(pad_buf); - } - return ret; - } - - out_buf = g_malloc(s->cluster_size + (s->cluster_size / 1000) + 128); - - /* best compression, small window, no zlib header */ - memset(&strm, 0, sizeof(strm)); - ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, -12, - 9, Z_DEFAULT_STRATEGY); - if (ret != 0) { - ret = -EINVAL; - goto fail; - } - - strm.avail_in = s->cluster_size; - strm.next_in = (uint8_t *)buf; - strm.avail_out = s->cluster_size; - strm.next_out = out_buf; - - ret = deflate(&strm, Z_FINISH); - if (ret != Z_STREAM_END && ret != Z_OK) { - deflateEnd(&strm); - ret = -EINVAL; - goto fail; - } - out_len = strm.next_out - out_buf; - - deflateEnd(&strm); - - if (ret != Z_STREAM_END || out_len >= s->cluster_size) { - /* could not compress: write normal cluster */ - ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors); - if (ret < 0) { - goto fail; - } - } else { - cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, - out_len, 0, 0); - if (cluster_offset == 0) { - ret = -EIO; - goto fail; - } - - cluster_offset &= s->cluster_offset_mask; - ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len); - if (ret < 0) { - goto fail; - } - } - - ret = 0; -fail: - g_free(out_buf); - return ret; -} - -static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) -{ - BDRVQcowState *s = bs->opaque; - bdi->cluster_size = s->cluster_size; - return 0; -} - - -static QEMUOptionParameter qcow_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_ENCRYPT, - .type = OPT_FLAG, - .help = "Encrypt the image" - }, - { NULL } -}; - -static BlockDriver bdrv_qcow = { - .format_name = "qcow", - .instance_size = sizeof(BDRVQcowState), - .bdrv_probe = qcow_probe, - .bdrv_open = qcow_open, - .bdrv_close = qcow_close, - .bdrv_reopen_prepare = qcow_reopen_prepare, - .bdrv_create = qcow_create, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - - .bdrv_co_readv = qcow_co_readv, - .bdrv_co_writev = qcow_co_writev, - .bdrv_co_is_allocated = qcow_co_is_allocated, - - .bdrv_set_key = qcow_set_key, - .bdrv_make_empty = qcow_make_empty, - .bdrv_write_compressed = qcow_write_compressed, - .bdrv_get_info = qcow_get_info, - - .create_options = qcow_create_options, -}; - -static void bdrv_qcow_init(void) -{ - bdrv_register(&bdrv_qcow); -} - -block_init(bdrv_qcow_init); diff --git a/contrib/qemu/block/qcow2-cache.c b/contrib/qemu/block/qcow2-cache.c deleted file mode 100644 index 2f3114ecc24..00000000000 --- a/contrib/qemu/block/qcow2-cache.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * L2/refcount table cache for the QCOW2 format - * - * Copyright (c) 2010 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 "block/block_int.h" -#include "qemu-common.h" -#include "qcow2.h" -#include "trace.h" - -typedef struct Qcow2CachedTable { - void* table; - int64_t offset; - bool dirty; - int cache_hits; - int ref; -} Qcow2CachedTable; - -struct Qcow2Cache { - Qcow2CachedTable* entries; - struct Qcow2Cache* depends; - int size; - bool depends_on_flush; -}; - -Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables) -{ - BDRVQcowState *s = bs->opaque; - Qcow2Cache *c; - int i; - - c = g_malloc0(sizeof(*c)); - c->size = num_tables; - c->entries = g_malloc0(sizeof(*c->entries) * num_tables); - - for (i = 0; i < c->size; i++) { - c->entries[i].table = qemu_blockalign(bs, s->cluster_size); - } - - return c; -} - -int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c) -{ - int i; - - for (i = 0; i < c->size; i++) { - assert(c->entries[i].ref == 0); - qemu_vfree(c->entries[i].table); - } - - g_free(c->entries); - g_free(c); - - return 0; -} - -static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c) -{ - int ret; - - ret = qcow2_cache_flush(bs, c->depends); - if (ret < 0) { - return ret; - } - - c->depends = NULL; - c->depends_on_flush = false; - - return 0; -} - -static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) -{ - BDRVQcowState *s = bs->opaque; - int ret = 0; - - if (!c->entries[i].dirty || !c->entries[i].offset) { - return 0; - } - - trace_qcow2_cache_entry_flush(qemu_coroutine_self(), - c == s->l2_table_cache, i); - - if (c->depends) { - ret = qcow2_cache_flush_dependency(bs, c); - } else if (c->depends_on_flush) { - ret = bdrv_flush(bs->file); - if (ret >= 0) { - c->depends_on_flush = false; - } - } - - if (ret < 0) { - return ret; - } - - if (c == s->refcount_block_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); - } else if (c == s->l2_table_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); - } - - ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table, - s->cluster_size); - if (ret < 0) { - return ret; - } - - c->entries[i].dirty = false; - - return 0; -} - -int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c) -{ - BDRVQcowState *s = bs->opaque; - int result = 0; - int ret; - int i; - - trace_qcow2_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache); - - for (i = 0; i < c->size; i++) { - ret = qcow2_cache_entry_flush(bs, c, i); - if (ret < 0 && result != -ENOSPC) { - result = ret; - } - } - - if (result == 0) { - ret = bdrv_flush(bs->file); - if (ret < 0) { - result = ret; - } - } - - return result; -} - -int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c, - Qcow2Cache *dependency) -{ - int ret; - - if (dependency->depends) { - ret = qcow2_cache_flush_dependency(bs, dependency); - if (ret < 0) { - return ret; - } - } - - if (c->depends && (c->depends != dependency)) { - ret = qcow2_cache_flush_dependency(bs, c); - if (ret < 0) { - return ret; - } - } - - c->depends = dependency; - return 0; -} - -void qcow2_cache_depends_on_flush(Qcow2Cache *c) -{ - c->depends_on_flush = true; -} - -static int qcow2_cache_find_entry_to_replace(Qcow2Cache *c) -{ - int i; - int min_count = INT_MAX; - int min_index = -1; - - - for (i = 0; i < c->size; i++) { - if (c->entries[i].ref) { - continue; - } - - if (c->entries[i].cache_hits < min_count) { - min_index = i; - min_count = c->entries[i].cache_hits; - } - - /* Give newer hits priority */ - /* TODO Check how to optimize the replacement strategy */ - c->entries[i].cache_hits /= 2; - } - - if (min_index == -1) { - /* This can't happen in current synchronous code, but leave the check - * here as a reminder for whoever starts using AIO with the cache */ - abort(); - } - return min_index; -} - -static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, - uint64_t offset, void **table, bool read_from_disk) -{ - BDRVQcowState *s = bs->opaque; - int i; - int ret; - - trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache, - offset, read_from_disk); - - /* Check if the table is already cached */ - for (i = 0; i < c->size; i++) { - if (c->entries[i].offset == offset) { - goto found; - } - } - - /* If not, write a table back and replace it */ - i = qcow2_cache_find_entry_to_replace(c); - trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(), - c == s->l2_table_cache, i); - if (i < 0) { - return i; - } - - ret = qcow2_cache_entry_flush(bs, c, i); - if (ret < 0) { - return ret; - } - - trace_qcow2_cache_get_read(qemu_coroutine_self(), - c == s->l2_table_cache, i); - c->entries[i].offset = 0; - if (read_from_disk) { - if (c == s->l2_table_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); - } - - ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size); - if (ret < 0) { - return ret; - } - } - - /* Give the table some hits for the start so that it won't be replaced - * immediately. The number 32 is completely arbitrary. */ - c->entries[i].cache_hits = 32; - c->entries[i].offset = offset; - - /* And return the right table */ -found: - c->entries[i].cache_hits++; - c->entries[i].ref++; - *table = c->entries[i].table; - - trace_qcow2_cache_get_done(qemu_coroutine_self(), - c == s->l2_table_cache, i); - - return 0; -} - -int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table) -{ - return qcow2_cache_do_get(bs, c, offset, table, true); -} - -int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table) -{ - return qcow2_cache_do_get(bs, c, offset, table, false); -} - -int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table) -{ - int i; - - for (i = 0; i < c->size; i++) { - if (c->entries[i].table == *table) { - goto found; - } - } - return -ENOENT; - -found: - c->entries[i].ref--; - *table = NULL; - - assert(c->entries[i].ref >= 0); - return 0; -} - -void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table) -{ - int i; - - for (i = 0; i < c->size; i++) { - if (c->entries[i].table == table) { - goto found; - } - } - abort(); - -found: - c->entries[i].dirty = true; -} diff --git a/contrib/qemu/block/qcow2-cluster.c b/contrib/qemu/block/qcow2-cluster.c deleted file mode 100644 index cca76d4fcdd..00000000000 --- a/contrib/qemu/block/qcow2-cluster.c +++ /dev/null @@ -1,1478 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-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 <zlib.h> - -#include "qemu-common.h" -#include "block/block_int.h" -#include "block/qcow2.h" -#include "trace.h" - -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, - bool exact_size) -{ - BDRVQcowState *s = bs->opaque; - int new_l1_size2, ret, i; - uint64_t *new_l1_table; - int64_t new_l1_table_offset, new_l1_size; - uint8_t data[12]; - - if (min_size <= s->l1_size) - return 0; - - if (exact_size) { - new_l1_size = min_size; - } else { - /* Bump size up to reduce the number of times we have to grow */ - new_l1_size = s->l1_size; - if (new_l1_size == 0) { - new_l1_size = 1; - } - while (min_size > new_l1_size) { - new_l1_size = (new_l1_size * 3 + 1) / 2; - } - } - - if (new_l1_size > INT_MAX) { - return -EFBIG; - } - -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "grow l1_table from %d to %" PRId64 "\n", - s->l1_size, new_l1_size); -#endif - - new_l1_size2 = sizeof(uint64_t) * new_l1_size; - new_l1_table = g_malloc0(align_offset(new_l1_size2, 512)); - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); - - /* write new table (align to cluster) */ - BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE); - new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2); - if (new_l1_table_offset < 0) { - g_free(new_l1_table); - return new_l1_table_offset; - } - - ret = qcow2_cache_flush(bs, s->refcount_block_cache); - if (ret < 0) { - goto fail; - } - - BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE); - for(i = 0; i < s->l1_size; i++) - new_l1_table[i] = cpu_to_be64(new_l1_table[i]); - ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_table, new_l1_size2); - if (ret < 0) - goto fail; - for(i = 0; i < s->l1_size; i++) - new_l1_table[i] = be64_to_cpu(new_l1_table[i]); - - /* set new table */ - BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE); - cpu_to_be32w((uint32_t*)data, new_l1_size); - cpu_to_be64wu((uint64_t*)(data + 4), new_l1_table_offset); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data)); - if (ret < 0) { - goto fail; - } - g_free(s->l1_table); - qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t), - QCOW2_DISCARD_OTHER); - s->l1_table_offset = new_l1_table_offset; - s->l1_table = new_l1_table; - s->l1_size = new_l1_size; - return 0; - fail: - g_free(new_l1_table); - qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2, - QCOW2_DISCARD_OTHER); - return ret; -} - -/* - * l2_load - * - * Loads a L2 table into memory. If the table is in the cache, the cache - * is used; otherwise the L2 table is loaded from the image file. - * - * Returns a pointer to the L2 table on success, or NULL if the read from - * the image file failed. - */ - -static int l2_load(BlockDriverState *bs, uint64_t l2_offset, - uint64_t **l2_table) -{ - BDRVQcowState *s = bs->opaque; - int ret; - - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, (void**) l2_table); - - return ret; -} - -/* - * Writes one sector of the L1 table to the disk (can't update single entries - * and we really don't want bdrv_pread to perform a read-modify-write) - */ -#define L1_ENTRIES_PER_SECTOR (512 / 8) -static int write_l1_entry(BlockDriverState *bs, int l1_index) -{ - BDRVQcowState *s = bs->opaque; - uint64_t buf[L1_ENTRIES_PER_SECTOR]; - int l1_start_index; - int i, ret; - - l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1); - for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) { - buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); - } - - BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); - ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset + 8 * l1_start_index, - buf, sizeof(buf)); - if (ret < 0) { - return ret; - } - - return 0; -} - -/* - * l2_allocate - * - * Allocate a new l2 entry in the file. If l1_index points to an already - * used entry in the L2 table (i.e. we are doing a copy on write for the L2 - * table) copy the contents of the old L2 table into the newly allocated one. - * Otherwise the new table is initialized with zeros. - * - */ - -static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) -{ - BDRVQcowState *s = bs->opaque; - uint64_t old_l2_offset; - uint64_t *l2_table; - int64_t l2_offset; - int ret; - - old_l2_offset = s->l1_table[l1_index]; - - trace_qcow2_l2_allocate(bs, l1_index); - - /* allocate a new l2 entry */ - - l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t)); - if (l2_offset < 0) { - return l2_offset; - } - - ret = qcow2_cache_flush(bs, s->refcount_block_cache); - if (ret < 0) { - goto fail; - } - - /* allocate a new entry in the l2 cache */ - - trace_qcow2_l2_allocate_get_empty(bs, l1_index); - ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table); - if (ret < 0) { - return ret; - } - - l2_table = *table; - - if ((old_l2_offset & L1E_OFFSET_MASK) == 0) { - /* if there was no old l2 table, clear the new table */ - memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); - } else { - uint64_t* old_table; - - /* if there was an old l2 table, read it from the disk */ - BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ); - ret = qcow2_cache_get(bs, s->l2_table_cache, - old_l2_offset & L1E_OFFSET_MASK, - (void**) &old_table); - if (ret < 0) { - goto fail; - } - - memcpy(l2_table, old_table, s->cluster_size); - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &old_table); - if (ret < 0) { - goto fail; - } - } - - /* write the l2 table to the file */ - BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE); - - trace_qcow2_l2_allocate_write_l2(bs, l1_index); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - ret = qcow2_cache_flush(bs, s->l2_table_cache); - if (ret < 0) { - goto fail; - } - - /* update the L1 entry */ - trace_qcow2_l2_allocate_write_l1(bs, l1_index); - s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; - ret = write_l1_entry(bs, l1_index); - if (ret < 0) { - goto fail; - } - - *table = l2_table; - trace_qcow2_l2_allocate_done(bs, l1_index, 0); - return 0; - -fail: - trace_qcow2_l2_allocate_done(bs, l1_index, ret); - qcow2_cache_put(bs, s->l2_table_cache, (void**) table); - s->l1_table[l1_index] = old_l2_offset; - return ret; -} - -/* - * Checks how many clusters in a given L2 table are contiguous in the image - * file. As soon as one of the flags in the bitmask stop_flags changes compared - * to the first cluster, the search is stopped and the cluster is not counted - * as contiguous. (This allows it, for example, to stop at the first compressed - * cluster which may require a different handling) - */ -static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size, - uint64_t *l2_table, uint64_t start, uint64_t stop_flags) -{ - int i; - uint64_t mask = stop_flags | L2E_OFFSET_MASK; - uint64_t offset = be64_to_cpu(l2_table[0]) & mask; - - if (!offset) - return 0; - - for (i = start; i < start + nb_clusters; i++) { - uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask; - if (offset + (uint64_t) i * cluster_size != l2_entry) { - break; - } - } - - return (i - start); -} - -static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table) -{ - int i; - - for (i = 0; i < nb_clusters; i++) { - int type = qcow2_get_cluster_type(be64_to_cpu(l2_table[i])); - - if (type != QCOW2_CLUSTER_UNALLOCATED) { - break; - } - } - - return i; -} - -/* The crypt function is compatible with the linux cryptoloop - algorithm for < 4 GB images. NOTE: out_buf == in_buf is - supported */ -void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, int enc, - const AES_KEY *key) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - - for(i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - AES_cbc_encrypt(in_buf, out_buf, 512, key, - ivec.b, enc); - sector_num++; - in_buf += 512; - out_buf += 512; - } -} - -static int coroutine_fn copy_sectors(BlockDriverState *bs, - uint64_t start_sect, - uint64_t cluster_offset, - int n_start, int n_end) -{ - BDRVQcowState *s = bs->opaque; - QEMUIOVector qiov; - struct iovec iov; - int n, ret; - - /* - * If this is the last cluster and it is only partially used, we must only - * copy until the end of the image, or bdrv_check_request will fail for the - * bdrv_read/write calls below. - */ - if (start_sect + n_end > bs->total_sectors) { - n_end = bs->total_sectors - start_sect; - } - - n = n_end - n_start; - if (n <= 0) { - return 0; - } - - iov.iov_len = n * BDRV_SECTOR_SIZE; - iov.iov_base = qemu_blockalign(bs, iov.iov_len); - - qemu_iovec_init_external(&qiov, &iov, 1); - - BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); - - /* Call .bdrv_co_readv() directly instead of using the public block-layer - * interface. This avoids double I/O throttling and request tracking, - * which can lead to deadlock when block layer copy-on-read is enabled. - */ - ret = bs->drv->bdrv_co_readv(bs, start_sect + n_start, n, &qiov); - if (ret < 0) { - goto out; - } - - if (s->crypt_method) { - qcow2_encrypt_sectors(s, start_sect + n_start, - iov.iov_base, iov.iov_base, n, 1, - &s->aes_encrypt_key); - } - - BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); - ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov); - if (ret < 0) { - goto out; - } - - ret = 0; -out: - qemu_vfree(iov.iov_base); - return ret; -} - - -/* - * get_cluster_offset - * - * For a given offset of the disk image, find the cluster offset in - * qcow2 file. The offset is stored in *cluster_offset. - * - * on entry, *num is the number of contiguous sectors we'd like to - * access following offset. - * - * on exit, *num is the number of contiguous sectors we can read. - * - * Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error - * cases. - */ -int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, - int *num, uint64_t *cluster_offset) -{ - BDRVQcowState *s = bs->opaque; - unsigned int l2_index; - uint64_t l1_index, l2_offset, *l2_table; - int l1_bits, c; - unsigned int index_in_cluster, nb_clusters; - uint64_t nb_available, nb_needed; - int ret; - - index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1); - nb_needed = *num + index_in_cluster; - - l1_bits = s->l2_bits + s->cluster_bits; - - /* compute how many bytes there are between the offset and - * the end of the l1 entry - */ - - nb_available = (1ULL << l1_bits) - (offset & ((1ULL << l1_bits) - 1)); - - /* compute the number of available sectors */ - - nb_available = (nb_available >> 9) + index_in_cluster; - - if (nb_needed > nb_available) { - nb_needed = nb_available; - } - - *cluster_offset = 0; - - /* seek the the l2 offset in the l1 table */ - - l1_index = offset >> l1_bits; - if (l1_index >= s->l1_size) { - ret = QCOW2_CLUSTER_UNALLOCATED; - goto out; - } - - l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; - if (!l2_offset) { - ret = QCOW2_CLUSTER_UNALLOCATED; - goto out; - } - - /* load the l2 table in memory */ - - ret = l2_load(bs, l2_offset, &l2_table); - if (ret < 0) { - return ret; - } - - /* find the cluster offset for the given disk offset */ - - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - *cluster_offset = be64_to_cpu(l2_table[l2_index]); - nb_clusters = size_to_clusters(s, nb_needed << 9); - - ret = qcow2_get_cluster_type(*cluster_offset); - switch (ret) { - case QCOW2_CLUSTER_COMPRESSED: - /* Compressed clusters can only be processed one by one */ - c = 1; - *cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK; - break; - case QCOW2_CLUSTER_ZERO: - if (s->qcow_version < 3) { - return -EIO; - } - c = count_contiguous_clusters(nb_clusters, s->cluster_size, - &l2_table[l2_index], 0, - QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); - *cluster_offset = 0; - break; - case QCOW2_CLUSTER_UNALLOCATED: - /* how many empty clusters ? */ - c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]); - *cluster_offset = 0; - break; - case QCOW2_CLUSTER_NORMAL: - /* how many allocated clusters ? */ - c = count_contiguous_clusters(nb_clusters, s->cluster_size, - &l2_table[l2_index], 0, - QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); - *cluster_offset &= L2E_OFFSET_MASK; - break; - default: - abort(); - } - - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - - nb_available = (c * s->cluster_sectors); - -out: - if (nb_available > nb_needed) - nb_available = nb_needed; - - *num = nb_available - index_in_cluster; - - return ret; -} - -/* - * get_cluster_table - * - * for a given disk offset, load (and allocate if needed) - * the l2 table. - * - * the l2 table offset in the qcow2 file and the cluster index - * in the l2 table are given to the caller. - * - * Returns 0 on success, -errno in failure case - */ -static int get_cluster_table(BlockDriverState *bs, uint64_t offset, - uint64_t **new_l2_table, - int *new_l2_index) -{ - BDRVQcowState *s = bs->opaque; - unsigned int l2_index; - uint64_t l1_index, l2_offset; - uint64_t *l2_table = NULL; - int ret; - - /* seek the the l2 offset in the l1 table */ - - l1_index = offset >> (s->l2_bits + s->cluster_bits); - if (l1_index >= s->l1_size) { - ret = qcow2_grow_l1_table(bs, l1_index + 1, false); - if (ret < 0) { - return ret; - } - } - - assert(l1_index < s->l1_size); - l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; - - /* seek the l2 table of the given l2 offset */ - - if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) { - /* load the l2 table in memory */ - ret = l2_load(bs, l2_offset, &l2_table); - if (ret < 0) { - return ret; - } - } else { - /* First allocate a new L2 table (and do COW if needed) */ - ret = l2_allocate(bs, l1_index, &l2_table); - if (ret < 0) { - return ret; - } - - /* Then decrease the refcount of the old table */ - if (l2_offset) { - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), - QCOW2_DISCARD_OTHER); - } - } - - /* find the cluster offset for the given disk offset */ - - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - - *new_l2_table = l2_table; - *new_l2_index = l2_index; - - return 0; -} - -/* - * alloc_compressed_cluster_offset - * - * For a given offset of the disk image, return cluster offset in - * qcow2 file. - * - * If the offset is not found, allocate a new compressed cluster. - * - * Return the cluster offset if successful, - * Return 0, otherwise. - * - */ - -uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, - uint64_t offset, - int compressed_size) -{ - BDRVQcowState *s = bs->opaque; - int l2_index, ret; - uint64_t *l2_table; - int64_t cluster_offset; - int nb_csectors; - - ret = get_cluster_table(bs, offset, &l2_table, &l2_index); - if (ret < 0) { - return 0; - } - - /* Compression can't overwrite anything. Fail if the cluster was already - * allocated. */ - cluster_offset = be64_to_cpu(l2_table[l2_index]); - if (cluster_offset & L2E_OFFSET_MASK) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - return 0; - } - - cluster_offset = qcow2_alloc_bytes(bs, compressed_size); - if (cluster_offset < 0) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - return 0; - } - - nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - - (cluster_offset >> 9); - - cluster_offset |= QCOW_OFLAG_COMPRESSED | - ((uint64_t)nb_csectors << s->csize_shift); - - /* update L2 table */ - - /* compressed clusters never have the copied flag */ - - BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - l2_table[l2_index] = cpu_to_be64(cluster_offset); - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - return 0; - } - - return cluster_offset; -} - -static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion *r) -{ - BDRVQcowState *s = bs->opaque; - int ret; - - if (r->nb_sectors == 0) { - return 0; - } - - qemu_co_mutex_unlock(&s->lock); - ret = copy_sectors(bs, m->offset / BDRV_SECTOR_SIZE, m->alloc_offset, - r->offset / BDRV_SECTOR_SIZE, - r->offset / BDRV_SECTOR_SIZE + r->nb_sectors); - qemu_co_mutex_lock(&s->lock); - - if (ret < 0) { - return ret; - } - - /* - * Before we update the L2 table to actually point to the new cluster, we - * need to be sure that the refcounts have been increased and COW was - * handled. - */ - qcow2_cache_depends_on_flush(s->l2_table_cache); - - return 0; -} - -int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) -{ - BDRVQcowState *s = bs->opaque; - int i, j = 0, l2_index, ret; - uint64_t *old_cluster, *l2_table; - uint64_t cluster_offset = m->alloc_offset; - - trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters); - assert(m->nb_clusters > 0); - - old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t)); - - /* copy content of unmodified sectors */ - ret = perform_cow(bs, m, &m->cow_start); - if (ret < 0) { - goto err; - } - - ret = perform_cow(bs, m, &m->cow_end); - if (ret < 0) { - goto err; - } - - /* Update L2 table. */ - if (s->use_lazy_refcounts) { - qcow2_mark_dirty(bs); - } - if (qcow2_need_accurate_refcounts(s)) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, - s->refcount_block_cache); - } - - ret = get_cluster_table(bs, m->offset, &l2_table, &l2_index); - if (ret < 0) { - goto err; - } - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - - for (i = 0; i < m->nb_clusters; i++) { - /* if two concurrent writes happen to the same unallocated cluster - * each write allocates separate cluster and writes data concurrently. - * The first one to complete updates l2 table with pointer to its - * cluster the second one has to do RMW (which is done above by - * copy_sectors()), update l2 table with its cluster pointer and free - * old cluster. This is what this loop does */ - if(l2_table[l2_index + i] != 0) - old_cluster[j++] = l2_table[l2_index + i]; - - l2_table[l2_index + i] = cpu_to_be64((cluster_offset + - (i << s->cluster_bits)) | QCOW_OFLAG_COPIED); - } - - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - goto err; - } - - /* - * If this was a COW, we need to decrease the refcount of the old cluster. - * Also flush bs->file to get the right order for L2 and refcount update. - * - * Don't discard clusters that reach a refcount of 0 (e.g. compressed - * clusters), the next write will reuse them anyway. - */ - if (j != 0) { - for (i = 0; i < j; i++) { - qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1, - QCOW2_DISCARD_NEVER); - } - } - - ret = 0; -err: - g_free(old_cluster); - return ret; - } - -/* - * Returns the number of contiguous clusters that can be used for an allocating - * write, but require COW to be performed (this includes yet unallocated space, - * which must copy from the backing file) - */ -static int count_cow_clusters(BDRVQcowState *s, int nb_clusters, - uint64_t *l2_table, int l2_index) -{ - int i; - - for (i = 0; i < nb_clusters; i++) { - uint64_t l2_entry = be64_to_cpu(l2_table[l2_index + i]); - int cluster_type = qcow2_get_cluster_type(l2_entry); - - switch(cluster_type) { - case QCOW2_CLUSTER_NORMAL: - if (l2_entry & QCOW_OFLAG_COPIED) { - goto out; - } - break; - case QCOW2_CLUSTER_UNALLOCATED: - case QCOW2_CLUSTER_COMPRESSED: - case QCOW2_CLUSTER_ZERO: - break; - default: - abort(); - } - } - -out: - assert(i <= nb_clusters); - return i; -} - -/* - * Check if there already is an AIO write request in flight which allocates - * the same cluster. In this case we need to wait until the previous - * request has completed and updated the L2 table accordingly. - * - * Returns: - * 0 if there was no dependency. *cur_bytes indicates the number of - * bytes from guest_offset that can be read before the next - * dependency must be processed (or the request is complete) - * - * -EAGAIN if we had to wait for another request, previously gathered - * information on cluster allocation may be invalid now. The caller - * must start over anyway, so consider *cur_bytes undefined. - */ -static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, - uint64_t *cur_bytes, QCowL2Meta **m) -{ - BDRVQcowState *s = bs->opaque; - QCowL2Meta *old_alloc; - uint64_t bytes = *cur_bytes; - - QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) { - - uint64_t start = guest_offset; - uint64_t end = start + bytes; - uint64_t old_start = l2meta_cow_start(old_alloc); - uint64_t old_end = l2meta_cow_end(old_alloc); - - if (end <= old_start || start >= old_end) { - /* No intersection */ - } else { - if (start < old_start) { - /* Stop at the start of a running allocation */ - bytes = old_start - start; - } else { - bytes = 0; - } - - /* Stop if already an l2meta exists. After yielding, it wouldn't - * be valid any more, so we'd have to clean up the old L2Metas - * and deal with requests depending on them before starting to - * gather new ones. Not worth the trouble. */ - if (bytes == 0 && *m) { - *cur_bytes = 0; - return 0; - } - - if (bytes == 0) { - /* Wait for the dependency to complete. We need to recheck - * the free/allocated clusters when we continue. */ - qemu_co_mutex_unlock(&s->lock); - qemu_co_queue_wait(&old_alloc->dependent_requests); - qemu_co_mutex_lock(&s->lock); - return -EAGAIN; - } - } - } - - /* Make sure that existing clusters and new allocations are only used up to - * the next dependency if we shortened the request above */ - *cur_bytes = bytes; - - return 0; -} - -/* - * Checks how many already allocated clusters that don't require a copy on - * write there are at the given guest_offset (up to *bytes). If - * *host_offset is not zero, only physically contiguous clusters beginning at - * this host offset are counted. - * - * Note that guest_offset may not be cluster aligned. In this case, the - * returned *host_offset points to exact byte referenced by guest_offset and - * therefore isn't cluster aligned as well. - * - * Returns: - * 0: if no allocated clusters are available at the given offset. - * *bytes is normally unchanged. It is set to 0 if the cluster - * is allocated and doesn't need COW, but doesn't have the right - * physical offset. - * - * 1: if allocated clusters that don't require a COW are available at - * the requested offset. *bytes may have decreased and describes - * the length of the area that can be written to. - * - * -errno: in error cases - */ -static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, - uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m) -{ - BDRVQcowState *s = bs->opaque; - int l2_index; - uint64_t cluster_offset; - uint64_t *l2_table; - unsigned int nb_clusters; - unsigned int keep_clusters; - int ret, pret; - - trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset, - *bytes); - - assert(*host_offset == 0 || offset_into_cluster(s, guest_offset) - == offset_into_cluster(s, *host_offset)); - - /* - * Calculate the number of clusters to look for. We stop at L2 table - * boundaries to keep things simple. - */ - nb_clusters = - size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes); - - l2_index = offset_to_l2_index(s, guest_offset); - nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); - - /* Find L2 entry for the first involved cluster */ - ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index); - if (ret < 0) { - return ret; - } - - cluster_offset = be64_to_cpu(l2_table[l2_index]); - - /* Check how many clusters are already allocated and don't need COW */ - if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL - && (cluster_offset & QCOW_OFLAG_COPIED)) - { - /* If a specific host_offset is required, check it */ - bool offset_matches = - (cluster_offset & L2E_OFFSET_MASK) == *host_offset; - - if (*host_offset != 0 && !offset_matches) { - *bytes = 0; - ret = 0; - goto out; - } - - /* We keep all QCOW_OFLAG_COPIED clusters */ - keep_clusters = - count_contiguous_clusters(nb_clusters, s->cluster_size, - &l2_table[l2_index], 0, - QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO); - assert(keep_clusters <= nb_clusters); - - *bytes = MIN(*bytes, - keep_clusters * s->cluster_size - - offset_into_cluster(s, guest_offset)); - - ret = 1; - } else { - ret = 0; - } - - /* Cleanup */ -out: - pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (pret < 0) { - return pret; - } - - /* Only return a host offset if we actually made progress. Otherwise we - * would make requirements for handle_alloc() that it can't fulfill */ - if (ret) { - *host_offset = (cluster_offset & L2E_OFFSET_MASK) - + offset_into_cluster(s, guest_offset); - } - - return ret; -} - -/* - * Allocates new clusters for the given guest_offset. - * - * At most *nb_clusters are allocated, and on return *nb_clusters is updated to - * contain the number of clusters that have been allocated and are contiguous - * in the image file. - * - * If *host_offset is non-zero, it specifies the offset in the image file at - * which the new clusters must start. *nb_clusters can be 0 on return in this - * case if the cluster at host_offset is already in use. If *host_offset is - * zero, the clusters can be allocated anywhere in the image file. - * - * *host_offset is updated to contain the offset into the image file at which - * the first allocated cluster starts. - * - * Return 0 on success and -errno in error cases. -EAGAIN means that the - * function has been waiting for another request and the allocation must be - * restarted, but the whole request should not be failed. - */ -static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, - uint64_t *host_offset, unsigned int *nb_clusters) -{ - BDRVQcowState *s = bs->opaque; - - trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset, - *host_offset, *nb_clusters); - - /* Allocate new clusters */ - trace_qcow2_cluster_alloc_phys(qemu_coroutine_self()); - if (*host_offset == 0) { - int64_t cluster_offset = - qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); - if (cluster_offset < 0) { - return cluster_offset; - } - *host_offset = cluster_offset; - return 0; - } else { - int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters); - if (ret < 0) { - return ret; - } - *nb_clusters = ret; - return 0; - } -} - -/* - * Allocates new clusters for an area that either is yet unallocated or needs a - * copy on write. If *host_offset is non-zero, clusters are only allocated if - * the new allocation can match the specified host offset. - * - * Note that guest_offset may not be cluster aligned. In this case, the - * returned *host_offset points to exact byte referenced by guest_offset and - * therefore isn't cluster aligned as well. - * - * Returns: - * 0: if no clusters could be allocated. *bytes is set to 0, - * *host_offset is left unchanged. - * - * 1: if new clusters were allocated. *bytes may be decreased if the - * new allocation doesn't cover all of the requested area. - * *host_offset is updated to contain the host offset of the first - * newly allocated cluster. - * - * -errno: in error cases - */ -static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, - uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m) -{ - BDRVQcowState *s = bs->opaque; - int l2_index; - uint64_t *l2_table; - uint64_t entry; - unsigned int nb_clusters; - int ret; - - uint64_t alloc_cluster_offset; - - trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset, - *bytes); - assert(*bytes > 0); - - /* - * Calculate the number of clusters to look for. We stop at L2 table - * boundaries to keep things simple. - */ - nb_clusters = - size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes); - - l2_index = offset_to_l2_index(s, guest_offset); - nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); - - /* Find L2 entry for the first involved cluster */ - ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index); - if (ret < 0) { - return ret; - } - - entry = be64_to_cpu(l2_table[l2_index]); - - /* For the moment, overwrite compressed clusters one by one */ - if (entry & QCOW_OFLAG_COMPRESSED) { - nb_clusters = 1; - } else { - nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index); - } - - /* This function is only called when there were no non-COW clusters, so if - * we can't find any unallocated or COW clusters either, something is - * wrong with our code. */ - assert(nb_clusters > 0); - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - return ret; - } - - /* Allocate, if necessary at a given offset in the image file */ - alloc_cluster_offset = start_of_cluster(s, *host_offset); - ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset, - &nb_clusters); - if (ret < 0) { - goto fail; - } - - /* Can't extend contiguous allocation */ - if (nb_clusters == 0) { - *bytes = 0; - return 0; - } - - /* - * Save info needed for meta data update. - * - * requested_sectors: Number of sectors from the start of the first - * newly allocated cluster to the end of the (possibly shortened - * before) write request. - * - * avail_sectors: Number of sectors from the start of the first - * newly allocated to the end of the last newly allocated cluster. - * - * nb_sectors: The number of sectors from the start of the first - * newly allocated cluster to the end of the area that the write - * request actually writes to (excluding COW at the end) - */ - int requested_sectors = - (*bytes + offset_into_cluster(s, guest_offset)) - >> BDRV_SECTOR_BITS; - int avail_sectors = nb_clusters - << (s->cluster_bits - BDRV_SECTOR_BITS); - int alloc_n_start = offset_into_cluster(s, guest_offset) - >> BDRV_SECTOR_BITS; - int nb_sectors = MIN(requested_sectors, avail_sectors); - QCowL2Meta *old_m = *m; - - *m = g_malloc0(sizeof(**m)); - - **m = (QCowL2Meta) { - .next = old_m, - - .alloc_offset = alloc_cluster_offset, - .offset = start_of_cluster(s, guest_offset), - .nb_clusters = nb_clusters, - .nb_available = nb_sectors, - - .cow_start = { - .offset = 0, - .nb_sectors = alloc_n_start, - }, - .cow_end = { - .offset = nb_sectors * BDRV_SECTOR_SIZE, - .nb_sectors = avail_sectors - nb_sectors, - }, - }; - qemu_co_queue_init(&(*m)->dependent_requests); - QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight); - - *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset); - *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE) - - offset_into_cluster(s, guest_offset)); - assert(*bytes != 0); - - return 1; - -fail: - if (*m && (*m)->nb_clusters > 0) { - QLIST_REMOVE(*m, next_in_flight); - } - return ret; -} - -/* - * alloc_cluster_offset - * - * For a given offset on the virtual disk, find the cluster offset in qcow2 - * file. If the offset is not found, allocate a new cluster. - * - * If the cluster was already allocated, m->nb_clusters is set to 0 and - * other fields in m are meaningless. - * - * If the cluster is newly allocated, m->nb_clusters is set to the number of - * contiguous clusters that have been allocated. In this case, the other - * fields of m are valid and contain information about the first allocated - * cluster. - * - * If the request conflicts with another write request in flight, the coroutine - * is queued and will be reentered when the dependency has completed. - * - * Return 0 on success and -errno in error cases - */ -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m) -{ - BDRVQcowState *s = bs->opaque; - uint64_t start, remaining; - uint64_t cluster_offset; - uint64_t cur_bytes; - int ret; - - trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, - n_start, n_end); - - assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset)); - offset = start_of_cluster(s, offset); - -again: - start = offset + (n_start << BDRV_SECTOR_BITS); - remaining = (n_end - n_start) << BDRV_SECTOR_BITS; - cluster_offset = 0; - *host_offset = 0; - cur_bytes = 0; - *m = NULL; - - while (true) { - - if (!*host_offset) { - *host_offset = start_of_cluster(s, cluster_offset); - } - - assert(remaining >= cur_bytes); - - start += cur_bytes; - remaining -= cur_bytes; - cluster_offset += cur_bytes; - - if (remaining == 0) { - break; - } - - cur_bytes = remaining; - - /* - * Now start gathering as many contiguous clusters as possible: - * - * 1. Check for overlaps with in-flight allocations - * - * a) Overlap not in the first cluster -> shorten this request and - * let the caller handle the rest in its next loop iteration. - * - * b) Real overlaps of two requests. Yield and restart the search - * for contiguous clusters (the situation could have changed - * while we were sleeping) - * - * c) TODO: Request starts in the same cluster as the in-flight - * allocation ends. Shorten the COW of the in-fight allocation, - * set cluster_offset to write to the same cluster and set up - * the right synchronisation between the in-flight request and - * the new one. - */ - ret = handle_dependencies(bs, start, &cur_bytes, m); - if (ret == -EAGAIN) { - /* Currently handle_dependencies() doesn't yield if we already had - * an allocation. If it did, we would have to clean up the L2Meta - * structs before starting over. */ - assert(*m == NULL); - goto again; - } else if (ret < 0) { - return ret; - } else if (cur_bytes == 0) { - break; - } else { - /* handle_dependencies() may have decreased cur_bytes (shortened - * the allocations below) so that the next dependency is processed - * correctly during the next loop iteration. */ - } - - /* - * 2. Count contiguous COPIED clusters. - */ - ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m); - if (ret < 0) { - return ret; - } else if (ret) { - continue; - } else if (cur_bytes == 0) { - break; - } - - /* - * 3. If the request still hasn't completed, allocate new clusters, - * considering any cluster_offset of steps 1c or 2. - */ - ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m); - if (ret < 0) { - return ret; - } else if (ret) { - continue; - } else { - assert(cur_bytes == 0); - break; - } - } - - *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS); - assert(*num > 0); - assert(*host_offset != 0); - - return 0; -} - -static int decompress_buffer(uint8_t *out_buf, int out_buf_size, - const uint8_t *buf, int buf_size) -{ - z_stream strm1, *strm = &strm1; - int ret, out_len; - - memset(strm, 0, sizeof(*strm)); - - strm->next_in = (uint8_t *)buf; - strm->avail_in = buf_size; - strm->next_out = out_buf; - strm->avail_out = out_buf_size; - - ret = inflateInit2(strm, -12); - if (ret != Z_OK) - return -1; - ret = inflate(strm, Z_FINISH); - out_len = strm->next_out - out_buf; - if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || - out_len != out_buf_size) { - inflateEnd(strm); - return -1; - } - inflateEnd(strm); - return 0; -} - -int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) -{ - BDRVQcowState *s = bs->opaque; - int ret, csize, nb_csectors, sector_offset; - uint64_t coffset; - - coffset = cluster_offset & s->cluster_offset_mask; - if (s->cluster_cache_offset != coffset) { - nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1; - sector_offset = coffset & 511; - csize = nb_csectors * 512 - sector_offset; - BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED); - ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors); - if (ret < 0) { - return ret; - } - if (decompress_buffer(s->cluster_cache, s->cluster_size, - s->cluster_data + sector_offset, csize) < 0) { - return -EIO; - } - s->cluster_cache_offset = coffset; - } - return 0; -} - -/* - * This discards as many clusters of nb_clusters as possible at once (i.e. - * all clusters in the same L2 table) and returns the number of discarded - * clusters. - */ -static int discard_single_l2(BlockDriverState *bs, uint64_t offset, - unsigned int nb_clusters) -{ - BDRVQcowState *s = bs->opaque; - uint64_t *l2_table; - int l2_index; - int ret; - int i; - - ret = get_cluster_table(bs, offset, &l2_table, &l2_index); - if (ret < 0) { - return ret; - } - - /* Limit nb_clusters to one L2 table */ - nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); - - for (i = 0; i < nb_clusters; i++) { - uint64_t old_offset; - - old_offset = be64_to_cpu(l2_table[l2_index + i]); - if ((old_offset & L2E_OFFSET_MASK) == 0) { - continue; - } - - /* First remove L2 entries */ - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - l2_table[l2_index + i] = cpu_to_be64(0); - - /* Then decrease the refcount */ - qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); - } - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - return ret; - } - - return nb_clusters; -} - -int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, - int nb_sectors) -{ - BDRVQcowState *s = bs->opaque; - uint64_t end_offset; - unsigned int nb_clusters; - int ret; - - end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS); - - /* Round start up and end down */ - offset = align_offset(offset, s->cluster_size); - end_offset &= ~(s->cluster_size - 1); - - if (offset > end_offset) { - return 0; - } - - nb_clusters = size_to_clusters(s, end_offset - offset); - - s->cache_discards = true; - - /* Each L2 table is handled by its own loop iteration */ - while (nb_clusters > 0) { - ret = discard_single_l2(bs, offset, nb_clusters); - if (ret < 0) { - goto fail; - } - - nb_clusters -= ret; - offset += (ret * s->cluster_size); - } - - ret = 0; -fail: - s->cache_discards = false; - qcow2_process_discards(bs, ret); - - return ret; -} - -/* - * This zeroes as many clusters of nb_clusters as possible at once (i.e. - * all clusters in the same L2 table) and returns the number of zeroed - * clusters. - */ -static int zero_single_l2(BlockDriverState *bs, uint64_t offset, - unsigned int nb_clusters) -{ - BDRVQcowState *s = bs->opaque; - uint64_t *l2_table; - int l2_index; - int ret; - int i; - - ret = get_cluster_table(bs, offset, &l2_table, &l2_index); - if (ret < 0) { - return ret; - } - - /* Limit nb_clusters to one L2 table */ - nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); - - for (i = 0; i < nb_clusters; i++) { - uint64_t old_offset; - - old_offset = be64_to_cpu(l2_table[l2_index + i]); - - /* Update L2 entries */ - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - if (old_offset & QCOW_OFLAG_COMPRESSED) { - l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); - qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); - } else { - l2_table[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO); - } - } - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - return ret; - } - - return nb_clusters; -} - -int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors) -{ - BDRVQcowState *s = bs->opaque; - unsigned int nb_clusters; - int ret; - - /* The zero flag is only supported by version 3 and newer */ - if (s->qcow_version < 3) { - return -ENOTSUP; - } - - /* Each L2 table is handled by its own loop iteration */ - nb_clusters = size_to_clusters(s, nb_sectors << BDRV_SECTOR_BITS); - - s->cache_discards = true; - - while (nb_clusters > 0) { - ret = zero_single_l2(bs, offset, nb_clusters); - if (ret < 0) { - goto fail; - } - - nb_clusters -= ret; - offset += (ret * s->cluster_size); - } - - ret = 0; -fail: - s->cache_discards = false; - qcow2_process_discards(bs, ret); - - return ret; -} diff --git a/contrib/qemu/block/qcow2-refcount.c b/contrib/qemu/block/qcow2-refcount.c deleted file mode 100644 index 1244693f39e..00000000000 --- a/contrib/qemu/block/qcow2-refcount.c +++ /dev/null @@ -1,1374 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-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-common.h" -#include "block/block_int.h" -#include "block/qcow2.h" - -static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); -static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, - int64_t offset, int64_t length, - int addend, enum qcow2_discard_type type); - - -/*********************************************************/ -/* refcount handling */ - -int qcow2_refcount_init(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - int ret, refcount_table_size2, i; - - refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t); - s->refcount_table = g_malloc(refcount_table_size2); - if (s->refcount_table_size > 0) { - BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD); - ret = bdrv_pread(bs->file, s->refcount_table_offset, - s->refcount_table, refcount_table_size2); - if (ret != refcount_table_size2) - goto fail; - for(i = 0; i < s->refcount_table_size; i++) - be64_to_cpus(&s->refcount_table[i]); - } - return 0; - fail: - return -ENOMEM; -} - -void qcow2_refcount_close(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - g_free(s->refcount_table); -} - - -static int load_refcount_block(BlockDriverState *bs, - int64_t refcount_block_offset, - void **refcount_block) -{ - BDRVQcowState *s = bs->opaque; - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD); - ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset, - refcount_block); - - return ret; -} - -/* - * Returns the refcount of the cluster given by its index. Any non-negative - * return value is the refcount of the cluster, negative values are -errno - * and indicate an error. - */ -static int get_refcount(BlockDriverState *bs, int64_t cluster_index) -{ - BDRVQcowState *s = bs->opaque; - int refcount_table_index, block_index; - int64_t refcount_block_offset; - int ret; - uint16_t *refcount_block; - uint16_t refcount; - - refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - if (refcount_table_index >= s->refcount_table_size) - return 0; - refcount_block_offset = s->refcount_table[refcount_table_index]; - if (!refcount_block_offset) - return 0; - - ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset, - (void**) &refcount_block); - if (ret < 0) { - return ret; - } - - block_index = cluster_index & - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); - refcount = be16_to_cpu(refcount_block[block_index]); - - ret = qcow2_cache_put(bs, s->refcount_block_cache, - (void**) &refcount_block); - if (ret < 0) { - return ret; - } - - return refcount; -} - -/* - * Rounds the refcount table size up to avoid growing the table for each single - * refcount block that is allocated. - */ -static unsigned int next_refcount_table_size(BDRVQcowState *s, - unsigned int min_size) -{ - unsigned int min_clusters = (min_size >> (s->cluster_bits - 3)) + 1; - unsigned int refcount_table_clusters = - MAX(1, s->refcount_table_size >> (s->cluster_bits - 3)); - - while (min_clusters > refcount_table_clusters) { - refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2; - } - - return refcount_table_clusters << (s->cluster_bits - 3); -} - - -/* Checks if two offsets are described by the same refcount block */ -static int in_same_refcount_block(BDRVQcowState *s, uint64_t offset_a, - uint64_t offset_b) -{ - uint64_t block_a = offset_a >> (2 * s->cluster_bits - REFCOUNT_SHIFT); - uint64_t block_b = offset_b >> (2 * s->cluster_bits - REFCOUNT_SHIFT); - - return (block_a == block_b); -} - -/* - * Loads a refcount block. If it doesn't exist yet, it is allocated first - * (including growing the refcount table if needed). - * - * Returns 0 on success or -errno in error case - */ -static int alloc_refcount_block(BlockDriverState *bs, - int64_t cluster_index, uint16_t **refcount_block) -{ - BDRVQcowState *s = bs->opaque; - unsigned int refcount_table_index; - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC); - - /* Find the refcount block for the given cluster */ - refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - - if (refcount_table_index < s->refcount_table_size) { - - uint64_t refcount_block_offset = - s->refcount_table[refcount_table_index] & REFT_OFFSET_MASK; - - /* If it's already there, we're done */ - if (refcount_block_offset) { - return load_refcount_block(bs, refcount_block_offset, - (void**) refcount_block); - } - } - - /* - * If we came here, we need to allocate something. Something is at least - * a cluster for the new refcount block. It may also include a new refcount - * table if the old refcount table is too small. - * - * Note that allocating clusters here needs some special care: - * - * - We can't use the normal qcow2_alloc_clusters(), it would try to - * increase the refcount and very likely we would end up with an endless - * recursion. Instead we must place the refcount blocks in a way that - * they can describe them themselves. - * - * - We need to consider that at this point we are inside update_refcounts - * and doing the initial refcount increase. This means that some clusters - * have already been allocated by the caller, but their refcount isn't - * accurate yet. free_cluster_index tells us where this allocation ends - * as long as we don't overwrite it by freeing clusters. - * - * - alloc_clusters_noref and qcow2_free_clusters may load a different - * refcount block into the cache - */ - - *refcount_block = NULL; - - /* We write to the refcount table, so we might depend on L2 tables */ - ret = qcow2_cache_flush(bs, s->l2_table_cache); - if (ret < 0) { - return ret; - } - - /* Allocate the refcount block itself and mark it as used */ - int64_t new_block = alloc_clusters_noref(bs, s->cluster_size); - if (new_block < 0) { - return new_block; - } - -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64 - " at %" PRIx64 "\n", - refcount_table_index, cluster_index << s->cluster_bits, new_block); -#endif - - if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) { - /* Zero the new refcount block before updating it */ - ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, - (void**) refcount_block); - if (ret < 0) { - goto fail_block; - } - - memset(*refcount_block, 0, s->cluster_size); - - /* The block describes itself, need to update the cache */ - int block_index = (new_block >> s->cluster_bits) & - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); - (*refcount_block)[block_index] = cpu_to_be16(1); - } else { - /* Described somewhere else. This can recurse at most twice before we - * arrive at a block that describes itself. */ - ret = update_refcount(bs, new_block, s->cluster_size, 1, - QCOW2_DISCARD_NEVER); - if (ret < 0) { - goto fail_block; - } - - ret = qcow2_cache_flush(bs, s->refcount_block_cache); - if (ret < 0) { - goto fail_block; - } - - /* Initialize the new refcount block only after updating its refcount, - * update_refcount uses the refcount cache itself */ - ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, - (void**) refcount_block); - if (ret < 0) { - goto fail_block; - } - - memset(*refcount_block, 0, s->cluster_size); - } - - /* Now the new refcount block needs to be written to disk */ - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE); - qcow2_cache_entry_mark_dirty(s->refcount_block_cache, *refcount_block); - ret = qcow2_cache_flush(bs, s->refcount_block_cache); - if (ret < 0) { - goto fail_block; - } - - /* If the refcount table is big enough, just hook the block up there */ - if (refcount_table_index < s->refcount_table_size) { - uint64_t data64 = cpu_to_be64(new_block); - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP); - ret = bdrv_pwrite_sync(bs->file, - s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), - &data64, sizeof(data64)); - if (ret < 0) { - goto fail_block; - } - - s->refcount_table[refcount_table_index] = new_block; - return 0; - } - - ret = qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); - if (ret < 0) { - goto fail_block; - } - - /* - * If we come here, we need to grow the refcount table. Again, a new - * refcount table needs some space and we can't simply allocate to avoid - * endless recursion. - * - * Therefore let's grab new refcount blocks at the end of the image, which - * will describe themselves and the new refcount table. This way we can - * reference them only in the new table and do the switch to the new - * refcount table at once without producing an inconsistent state in - * between. - */ - BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW); - - /* Calculate the number of refcount blocks needed so far */ - uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT); - uint64_t blocks_used = (s->free_cluster_index + - refcount_block_clusters - 1) / refcount_block_clusters; - - /* And now we need at least one block more for the new metadata */ - uint64_t table_size = next_refcount_table_size(s, blocks_used + 1); - uint64_t last_table_size; - uint64_t blocks_clusters; - do { - uint64_t table_clusters = - size_to_clusters(s, table_size * sizeof(uint64_t)); - blocks_clusters = 1 + - ((table_clusters + refcount_block_clusters - 1) - / refcount_block_clusters); - uint64_t meta_clusters = table_clusters + blocks_clusters; - - last_table_size = table_size; - table_size = next_refcount_table_size(s, blocks_used + - ((meta_clusters + refcount_block_clusters - 1) - / refcount_block_clusters)); - - } while (last_table_size != table_size); - -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n", - s->refcount_table_size, table_size); -#endif - - /* Create the new refcount table and blocks */ - uint64_t meta_offset = (blocks_used * refcount_block_clusters) * - s->cluster_size; - uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size; - uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size); - uint64_t *new_table = g_malloc0(table_size * sizeof(uint64_t)); - - assert(meta_offset >= (s->free_cluster_index * s->cluster_size)); - - /* Fill the new refcount table */ - memcpy(new_table, s->refcount_table, - s->refcount_table_size * sizeof(uint64_t)); - new_table[refcount_table_index] = new_block; - - int i; - for (i = 0; i < blocks_clusters; i++) { - new_table[blocks_used + i] = meta_offset + (i * s->cluster_size); - } - - /* Fill the refcount blocks */ - uint64_t table_clusters = size_to_clusters(s, table_size * sizeof(uint64_t)); - int block = 0; - for (i = 0; i < table_clusters + blocks_clusters; i++) { - new_blocks[block++] = cpu_to_be16(1); - } - - /* Write refcount blocks to disk */ - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS); - ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks, - blocks_clusters * s->cluster_size); - g_free(new_blocks); - if (ret < 0) { - goto fail_table; - } - - /* Write refcount table to disk */ - for(i = 0; i < table_size; i++) { - cpu_to_be64s(&new_table[i]); - } - - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE); - ret = bdrv_pwrite_sync(bs->file, table_offset, new_table, - table_size * sizeof(uint64_t)); - if (ret < 0) { - goto fail_table; - } - - for(i = 0; i < table_size; i++) { - be64_to_cpus(&new_table[i]); - } - - /* Hook up the new refcount table in the qcow2 header */ - uint8_t data[12]; - cpu_to_be64w((uint64_t*)data, table_offset); - cpu_to_be32w((uint32_t*)(data + 8), table_clusters); - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, refcount_table_offset), - data, sizeof(data)); - if (ret < 0) { - goto fail_table; - } - - /* And switch it in memory */ - uint64_t old_table_offset = s->refcount_table_offset; - uint64_t old_table_size = s->refcount_table_size; - - g_free(s->refcount_table); - s->refcount_table = new_table; - s->refcount_table_size = table_size; - s->refcount_table_offset = table_offset; - - /* Free old table. Remember, we must not change free_cluster_index */ - uint64_t old_free_cluster_index = s->free_cluster_index; - qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), - QCOW2_DISCARD_OTHER); - s->free_cluster_index = old_free_cluster_index; - - ret = load_refcount_block(bs, new_block, (void**) refcount_block); - if (ret < 0) { - return ret; - } - - return 0; - -fail_table: - g_free(new_table); -fail_block: - if (*refcount_block != NULL) { - qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); - } - return ret; -} - -void qcow2_process_discards(BlockDriverState *bs, int ret) -{ - BDRVQcowState *s = bs->opaque; - Qcow2DiscardRegion *d, *next; - - QTAILQ_FOREACH_SAFE(d, &s->discards, next, next) { - QTAILQ_REMOVE(&s->discards, d, next); - - /* Discard is optional, ignore the return value */ - if (ret >= 0) { - bdrv_discard(bs->file, - d->offset >> BDRV_SECTOR_BITS, - d->bytes >> BDRV_SECTOR_BITS); - } - - g_free(d); - } -} - -static void update_refcount_discard(BlockDriverState *bs, - uint64_t offset, uint64_t length) -{ - BDRVQcowState *s = bs->opaque; - Qcow2DiscardRegion *d, *p, *next; - - QTAILQ_FOREACH(d, &s->discards, next) { - uint64_t new_start = MIN(offset, d->offset); - uint64_t new_end = MAX(offset + length, d->offset + d->bytes); - - if (new_end - new_start <= length + d->bytes) { - /* There can't be any overlap, areas ending up here have no - * references any more and therefore shouldn't get freed another - * time. */ - assert(d->bytes + length == new_end - new_start); - d->offset = new_start; - d->bytes = new_end - new_start; - goto found; - } - } - - d = g_malloc(sizeof(*d)); - *d = (Qcow2DiscardRegion) { - .bs = bs, - .offset = offset, - .bytes = length, - }; - QTAILQ_INSERT_TAIL(&s->discards, d, next); - -found: - /* Merge discard requests if they are adjacent now */ - QTAILQ_FOREACH_SAFE(p, &s->discards, next, next) { - if (p == d - || p->offset > d->offset + d->bytes - || d->offset > p->offset + p->bytes) - { - continue; - } - - /* Still no overlap possible */ - assert(p->offset == d->offset + d->bytes - || d->offset == p->offset + p->bytes); - - QTAILQ_REMOVE(&s->discards, p, next); - d->offset = MIN(d->offset, p->offset); - d->bytes += p->bytes; - } -} - -/* XXX: cache several refcount block clusters ? */ -static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, - int64_t offset, int64_t length, int addend, enum qcow2_discard_type type) -{ - BDRVQcowState *s = bs->opaque; - int64_t start, last, cluster_offset; - uint16_t *refcount_block = NULL; - int64_t old_table_index = -1; - int ret; - -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n", - offset, length, addend); -#endif - if (length < 0) { - return -EINVAL; - } else if (length == 0) { - return 0; - } - - if (addend < 0) { - qcow2_cache_set_dependency(bs, s->refcount_block_cache, - s->l2_table_cache); - } - - start = offset & ~(s->cluster_size - 1); - last = (offset + length - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) - { - int block_index, refcount; - int64_t cluster_index = cluster_offset >> s->cluster_bits; - int64_t table_index = - cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - - /* Load the refcount block and allocate it if needed */ - if (table_index != old_table_index) { - if (refcount_block) { - ret = qcow2_cache_put(bs, s->refcount_block_cache, - (void**) &refcount_block); - if (ret < 0) { - goto fail; - } - } - - ret = alloc_refcount_block(bs, cluster_index, &refcount_block); - if (ret < 0) { - goto fail; - } - } - old_table_index = table_index; - - qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block); - - /* we can update the count and save it */ - block_index = cluster_index & - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); - - refcount = be16_to_cpu(refcount_block[block_index]); - refcount += addend; - if (refcount < 0 || refcount > 0xffff) { - ret = -EINVAL; - goto fail; - } - if (refcount == 0 && cluster_index < s->free_cluster_index) { - s->free_cluster_index = cluster_index; - } - refcount_block[block_index] = cpu_to_be16(refcount); - - if (refcount == 0 && s->discard_passthrough[type]) { - update_refcount_discard(bs, cluster_offset, s->cluster_size); - } - } - - ret = 0; -fail: - if (!s->cache_discards) { - qcow2_process_discards(bs, ret); - } - - /* Write last changed block to disk */ - if (refcount_block) { - int wret; - wret = qcow2_cache_put(bs, s->refcount_block_cache, - (void**) &refcount_block); - if (wret < 0) { - return ret < 0 ? ret : wret; - } - } - - /* - * Try do undo any updates if an error is returned (This may succeed in - * some cases like ENOSPC for allocating a new refcount block) - */ - if (ret < 0) { - int dummy; - dummy = update_refcount(bs, offset, cluster_offset - offset, -addend, - QCOW2_DISCARD_NEVER); - (void)dummy; - } - - return ret; -} - -/* - * Increases or decreases the refcount of a given cluster by one. - * addend must be 1 or -1. - * - * If the return value is non-negative, it is the new refcount of the cluster. - * If it is negative, it is -errno and indicates an error. - */ -static int update_cluster_refcount(BlockDriverState *bs, - int64_t cluster_index, - int addend, - enum qcow2_discard_type type) -{ - BDRVQcowState *s = bs->opaque; - int ret; - - ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend, - type); - if (ret < 0) { - return ret; - } - - return get_refcount(bs, cluster_index); -} - - - -/*********************************************************/ -/* cluster allocation functions */ - - - -/* return < 0 if error */ -static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size) -{ - BDRVQcowState *s = bs->opaque; - int i, nb_clusters, refcount; - - nb_clusters = size_to_clusters(s, size); -retry: - for(i = 0; i < nb_clusters; i++) { - int64_t next_cluster_index = s->free_cluster_index++; - refcount = get_refcount(bs, next_cluster_index); - - if (refcount < 0) { - return refcount; - } else if (refcount != 0) { - goto retry; - } - } -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n", - size, - (s->free_cluster_index - nb_clusters) << s->cluster_bits); -#endif - return (s->free_cluster_index - nb_clusters) << s->cluster_bits; -} - -int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size) -{ - int64_t offset; - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC); - offset = alloc_clusters_noref(bs, size); - if (offset < 0) { - return offset; - } - - ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER); - if (ret < 0) { - return ret; - } - - return offset; -} - -int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, - int nb_clusters) -{ - BDRVQcowState *s = bs->opaque; - uint64_t cluster_index; - uint64_t old_free_cluster_index; - int i, refcount, ret; - - /* Check how many clusters there are free */ - cluster_index = offset >> s->cluster_bits; - for(i = 0; i < nb_clusters; i++) { - refcount = get_refcount(bs, cluster_index++); - - if (refcount < 0) { - return refcount; - } else if (refcount != 0) { - break; - } - } - - /* And then allocate them */ - old_free_cluster_index = s->free_cluster_index; - s->free_cluster_index = cluster_index + i; - - ret = update_refcount(bs, offset, i << s->cluster_bits, 1, - QCOW2_DISCARD_NEVER); - if (ret < 0) { - return ret; - } - - s->free_cluster_index = old_free_cluster_index; - - return i; -} - -/* only used to allocate compressed sectors. We try to allocate - contiguous sectors. size must be <= cluster_size */ -int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) -{ - BDRVQcowState *s = bs->opaque; - int64_t offset, cluster_offset; - int free_in_cluster; - - BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES); - assert(size > 0 && size <= s->cluster_size); - if (s->free_byte_offset == 0) { - offset = qcow2_alloc_clusters(bs, s->cluster_size); - if (offset < 0) { - return offset; - } - s->free_byte_offset = offset; - } - redo: - free_in_cluster = s->cluster_size - - (s->free_byte_offset & (s->cluster_size - 1)); - if (size <= free_in_cluster) { - /* enough space in current cluster */ - offset = s->free_byte_offset; - s->free_byte_offset += size; - free_in_cluster -= size; - if (free_in_cluster == 0) - s->free_byte_offset = 0; - if ((offset & (s->cluster_size - 1)) != 0) - update_cluster_refcount(bs, offset >> s->cluster_bits, 1, - QCOW2_DISCARD_NEVER); - } else { - offset = qcow2_alloc_clusters(bs, s->cluster_size); - if (offset < 0) { - return offset; - } - cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1); - if ((cluster_offset + s->cluster_size) == offset) { - /* we are lucky: contiguous data */ - offset = s->free_byte_offset; - update_cluster_refcount(bs, offset >> s->cluster_bits, 1, - QCOW2_DISCARD_NEVER); - s->free_byte_offset += size; - } else { - s->free_byte_offset = offset; - goto redo; - } - } - - /* The cluster refcount was incremented, either by qcow2_alloc_clusters() - * or explicitly by update_cluster_refcount(). Refcount blocks must be - * flushed before the caller's L2 table updates. - */ - qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); - return offset; -} - -void qcow2_free_clusters(BlockDriverState *bs, - int64_t offset, int64_t size, - enum qcow2_discard_type type) -{ - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_FREE); - ret = update_refcount(bs, offset, size, -1, type); - if (ret < 0) { - fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret)); - /* TODO Remember the clusters to free them later and avoid leaking */ - } -} - -/* - * Free a cluster using its L2 entry (handles clusters of all types, e.g. - * normal cluster, compressed cluster, etc.) - */ -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, - int nb_clusters, enum qcow2_discard_type type) -{ - BDRVQcowState *s = bs->opaque; - - switch (qcow2_get_cluster_type(l2_entry)) { - case QCOW2_CLUSTER_COMPRESSED: - { - int nb_csectors; - nb_csectors = ((l2_entry >> s->csize_shift) & - s->csize_mask) + 1; - qcow2_free_clusters(bs, - (l2_entry & s->cluster_offset_mask) & ~511, - nb_csectors * 512, type); - } - break; - case QCOW2_CLUSTER_NORMAL: - qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, - nb_clusters << s->cluster_bits, type); - break; - case QCOW2_CLUSTER_UNALLOCATED: - case QCOW2_CLUSTER_ZERO: - break; - default: - abort(); - } -} - - - -/*********************************************************/ -/* snapshots and image creation */ - - - -/* update the refcounts of snapshots and the copied flag */ -int qcow2_update_snapshot_refcount(BlockDriverState *bs, - int64_t l1_table_offset, int l1_size, int addend) -{ - BDRVQcowState *s = bs->opaque; - uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated; - int64_t old_offset, old_l2_offset; - int i, j, l1_modified = 0, nb_csectors, refcount; - int ret; - - l2_table = NULL; - l1_table = NULL; - l1_size2 = l1_size * sizeof(uint64_t); - - s->cache_discards = true; - - /* WARNING: qcow2_snapshot_goto relies on this function not using the - * l1_table_offset when it is the current s->l1_table_offset! Be careful - * when changing this! */ - if (l1_table_offset != s->l1_table_offset) { - l1_table = g_malloc0(align_offset(l1_size2, 512)); - l1_allocated = 1; - - ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2); - if (ret < 0) { - goto fail; - } - - for(i = 0;i < l1_size; i++) - be64_to_cpus(&l1_table[i]); - } else { - assert(l1_size == s->l1_size); - l1_table = s->l1_table; - l1_allocated = 0; - } - - for(i = 0; i < l1_size; i++) { - l2_offset = l1_table[i]; - if (l2_offset) { - old_l2_offset = l2_offset; - l2_offset &= L1E_OFFSET_MASK; - - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, - (void**) &l2_table); - if (ret < 0) { - goto fail; - } - - for(j = 0; j < s->l2_size; j++) { - offset = be64_to_cpu(l2_table[j]); - if (offset != 0) { - old_offset = offset; - offset &= ~QCOW_OFLAG_COPIED; - if (offset & QCOW_OFLAG_COMPRESSED) { - nb_csectors = ((offset >> s->csize_shift) & - s->csize_mask) + 1; - if (addend != 0) { - int ret; - ret = update_refcount(bs, - (offset & s->cluster_offset_mask) & ~511, - nb_csectors * 512, addend, - QCOW2_DISCARD_SNAPSHOT); - if (ret < 0) { - goto fail; - } - } - /* compressed clusters are never modified */ - refcount = 2; - } else { - uint64_t cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits; - if (addend != 0) { - refcount = update_cluster_refcount(bs, cluster_index, addend, - QCOW2_DISCARD_SNAPSHOT); - } else { - refcount = get_refcount(bs, cluster_index); - } - - if (refcount < 0) { - ret = refcount; - goto fail; - } - } - - if (refcount == 1) { - offset |= QCOW_OFLAG_COPIED; - } - if (offset != old_offset) { - if (addend > 0) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, - s->refcount_block_cache); - } - l2_table[j] = cpu_to_be64(offset); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - } - } - } - - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - if (ret < 0) { - goto fail; - } - - - if (addend != 0) { - refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend, - QCOW2_DISCARD_SNAPSHOT); - } else { - refcount = get_refcount(bs, l2_offset >> s->cluster_bits); - } - if (refcount < 0) { - ret = refcount; - goto fail; - } else if (refcount == 1) { - l2_offset |= QCOW_OFLAG_COPIED; - } - if (l2_offset != old_l2_offset) { - l1_table[i] = l2_offset; - l1_modified = 1; - } - } - } - - ret = bdrv_flush(bs); -fail: - if (l2_table) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - } - - s->cache_discards = false; - qcow2_process_discards(bs, ret); - - /* Update L1 only if it isn't deleted anyway (addend = -1) */ - if (ret == 0 && addend >= 0 && l1_modified) { - for (i = 0; i < l1_size; i++) { - cpu_to_be64s(&l1_table[i]); - } - - ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2); - - for (i = 0; i < l1_size; i++) { - be64_to_cpus(&l1_table[i]); - } - } - if (l1_allocated) - g_free(l1_table); - return ret; -} - - - - -/*********************************************************/ -/* refcount checking functions */ - - - -/* - * Increases the refcount for a range of clusters in a given refcount table. - * This is used to construct a temporary refcount table out of L1 and L2 tables - * which can be compared the the refcount table saved in the image. - * - * Modifies the number of errors in res. - */ -static void inc_refcounts(BlockDriverState *bs, - BdrvCheckResult *res, - uint16_t *refcount_table, - int refcount_table_size, - int64_t offset, int64_t size) -{ - BDRVQcowState *s = bs->opaque; - int64_t start, last, cluster_offset; - int k; - - if (size <= 0) - return; - - start = offset & ~(s->cluster_size - 1); - last = (offset + size - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) { - k = cluster_offset >> s->cluster_bits; - if (k < 0) { - fprintf(stderr, "ERROR: invalid cluster offset=0x%" PRIx64 "\n", - cluster_offset); - res->corruptions++; - } else if (k >= refcount_table_size) { - fprintf(stderr, "Warning: cluster offset=0x%" PRIx64 " is after " - "the end of the image file, can't properly check refcounts.\n", - cluster_offset); - res->check_errors++; - } else { - if (++refcount_table[k] == 0) { - fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64 - "\n", cluster_offset); - res->corruptions++; - } - } - } -} - -/* Flags for check_refcounts_l1() and check_refcounts_l2() */ -enum { - CHECK_OFLAG_COPIED = 0x1, /* check QCOW_OFLAG_COPIED matches refcount */ - CHECK_FRAG_INFO = 0x2, /* update BlockFragInfo counters */ -}; - -/* - * Increases the refcount in the given refcount table for the all clusters - * referenced in the L2 table. While doing so, performs some checks on L2 - * entries. - * - * Returns the number of errors found by the checks or -errno if an internal - * error occurred. - */ -static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, - uint16_t *refcount_table, int refcount_table_size, int64_t l2_offset, - int flags) -{ - BDRVQcowState *s = bs->opaque; - uint64_t *l2_table, l2_entry; - uint64_t next_contiguous_offset = 0; - int i, l2_size, nb_csectors, refcount; - - /* Read L2 table from disk */ - l2_size = s->l2_size * sizeof(uint64_t); - l2_table = g_malloc(l2_size); - - if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size) - goto fail; - - /* Do the actual checks */ - for(i = 0; i < s->l2_size; i++) { - l2_entry = be64_to_cpu(l2_table[i]); - - switch (qcow2_get_cluster_type(l2_entry)) { - case QCOW2_CLUSTER_COMPRESSED: - /* Compressed clusters don't have QCOW_OFLAG_COPIED */ - if (l2_entry & QCOW_OFLAG_COPIED) { - fprintf(stderr, "ERROR: cluster %" PRId64 ": " - "copied flag must never be set for compressed " - "clusters\n", l2_entry >> s->cluster_bits); - l2_entry &= ~QCOW_OFLAG_COPIED; - res->corruptions++; - } - - /* Mark cluster as used */ - nb_csectors = ((l2_entry >> s->csize_shift) & - s->csize_mask) + 1; - l2_entry &= s->cluster_offset_mask; - inc_refcounts(bs, res, refcount_table, refcount_table_size, - l2_entry & ~511, nb_csectors * 512); - - if (flags & CHECK_FRAG_INFO) { - res->bfi.allocated_clusters++; - res->bfi.compressed_clusters++; - - /* Compressed clusters are fragmented by nature. Since they - * take up sub-sector space but we only have sector granularity - * I/O we need to re-read the same sectors even for adjacent - * compressed clusters. - */ - res->bfi.fragmented_clusters++; - } - break; - - case QCOW2_CLUSTER_ZERO: - if ((l2_entry & L2E_OFFSET_MASK) == 0) { - break; - } - /* fall through */ - - case QCOW2_CLUSTER_NORMAL: - { - /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ - uint64_t offset = l2_entry & L2E_OFFSET_MASK; - - if (flags & CHECK_OFLAG_COPIED) { - refcount = get_refcount(bs, offset >> s->cluster_bits); - if (refcount < 0) { - fprintf(stderr, "Can't get refcount for offset %" - PRIx64 ": %s\n", l2_entry, strerror(-refcount)); - goto fail; - } - if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { - fprintf(stderr, "ERROR OFLAG_COPIED: offset=%" - PRIx64 " refcount=%d\n", l2_entry, refcount); - res->corruptions++; - } - } - - if (flags & CHECK_FRAG_INFO) { - res->bfi.allocated_clusters++; - if (next_contiguous_offset && - offset != next_contiguous_offset) { - res->bfi.fragmented_clusters++; - } - next_contiguous_offset = offset + s->cluster_size; - } - - /* Mark cluster as used */ - inc_refcounts(bs, res, refcount_table,refcount_table_size, - offset, s->cluster_size); - - /* Correct offsets are cluster aligned */ - if (offset & (s->cluster_size - 1)) { - fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not " - "properly aligned; L2 entry corrupted.\n", offset); - res->corruptions++; - } - break; - } - - case QCOW2_CLUSTER_UNALLOCATED: - break; - - default: - abort(); - } - } - - g_free(l2_table); - return 0; - -fail: - fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n"); - g_free(l2_table); - return -EIO; -} - -/* - * Increases the refcount for the L1 table, its L2 tables and all referenced - * clusters in the given refcount table. While doing so, performs some checks - * on L1 and L2 entries. - * - * Returns the number of errors found by the checks or -errno if an internal - * error occurred. - */ -static int check_refcounts_l1(BlockDriverState *bs, - BdrvCheckResult *res, - uint16_t *refcount_table, - int refcount_table_size, - int64_t l1_table_offset, int l1_size, - int flags) -{ - BDRVQcowState *s = bs->opaque; - uint64_t *l1_table, l2_offset, l1_size2; - int i, refcount, ret; - - l1_size2 = l1_size * sizeof(uint64_t); - - /* Mark L1 table as used */ - inc_refcounts(bs, res, refcount_table, refcount_table_size, - l1_table_offset, l1_size2); - - /* Read L1 table entries from disk */ - if (l1_size2 == 0) { - l1_table = NULL; - } else { - l1_table = g_malloc(l1_size2); - if (bdrv_pread(bs->file, l1_table_offset, - l1_table, l1_size2) != l1_size2) - goto fail; - for(i = 0;i < l1_size; i++) - be64_to_cpus(&l1_table[i]); - } - - /* Do the actual checks */ - for(i = 0; i < l1_size; i++) { - l2_offset = l1_table[i]; - if (l2_offset) { - /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ - if (flags & CHECK_OFLAG_COPIED) { - refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) - >> s->cluster_bits); - if (refcount < 0) { - fprintf(stderr, "Can't get refcount for l2_offset %" - PRIx64 ": %s\n", l2_offset, strerror(-refcount)); - goto fail; - } - if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) { - fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64 - " refcount=%d\n", l2_offset, refcount); - res->corruptions++; - } - } - - /* Mark L2 table as used */ - l2_offset &= L1E_OFFSET_MASK; - inc_refcounts(bs, res, refcount_table, refcount_table_size, - l2_offset, s->cluster_size); - - /* L2 tables are cluster aligned */ - if (l2_offset & (s->cluster_size - 1)) { - fprintf(stderr, "ERROR l2_offset=%" PRIx64 ": Table is not " - "cluster aligned; L1 entry corrupted\n", l2_offset); - res->corruptions++; - } - - /* Process and check L2 entries */ - ret = check_refcounts_l2(bs, res, refcount_table, - refcount_table_size, l2_offset, flags); - if (ret < 0) { - goto fail; - } - } - } - g_free(l1_table); - return 0; - -fail: - fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n"); - res->check_errors++; - g_free(l1_table); - return -EIO; -} - -/* - * Checks an image for refcount consistency. - * - * Returns 0 if no errors are found, the number of errors in case the image is - * detected as corrupted, and -errno when an internal error occurred. - */ -int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, - BdrvCheckMode fix) -{ - BDRVQcowState *s = bs->opaque; - int64_t size, i, highest_cluster; - int nb_clusters, refcount1, refcount2; - QCowSnapshot *sn; - uint16_t *refcount_table; - int ret; - - size = bdrv_getlength(bs->file); - nb_clusters = size_to_clusters(s, size); - refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t)); - - res->bfi.total_clusters = - size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE); - - /* header */ - inc_refcounts(bs, res, refcount_table, nb_clusters, - 0, s->cluster_size); - - /* current L1 table */ - ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, - s->l1_table_offset, s->l1_size, - CHECK_OFLAG_COPIED | CHECK_FRAG_INFO); - if (ret < 0) { - goto fail; - } - - /* snapshots */ - for(i = 0; i < s->nb_snapshots; i++) { - sn = s->snapshots + i; - ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, - sn->l1_table_offset, sn->l1_size, 0); - if (ret < 0) { - goto fail; - } - } - inc_refcounts(bs, res, refcount_table, nb_clusters, - s->snapshots_offset, s->snapshots_size); - - /* refcount data */ - inc_refcounts(bs, res, refcount_table, nb_clusters, - s->refcount_table_offset, - s->refcount_table_size * sizeof(uint64_t)); - - for(i = 0; i < s->refcount_table_size; i++) { - uint64_t offset, cluster; - offset = s->refcount_table[i]; - cluster = offset >> s->cluster_bits; - - /* Refcount blocks are cluster aligned */ - if (offset & (s->cluster_size - 1)) { - fprintf(stderr, "ERROR refcount block %" PRId64 " is not " - "cluster aligned; refcount table entry corrupted\n", i); - res->corruptions++; - continue; - } - - if (cluster >= nb_clusters) { - fprintf(stderr, "ERROR refcount block %" PRId64 - " is outside image\n", i); - res->corruptions++; - continue; - } - - if (offset != 0) { - inc_refcounts(bs, res, refcount_table, nb_clusters, - offset, s->cluster_size); - if (refcount_table[cluster] != 1) { - fprintf(stderr, "ERROR refcount block %" PRId64 - " refcount=%d\n", - i, refcount_table[cluster]); - res->corruptions++; - } - } - } - - /* compare ref counts */ - for (i = 0, highest_cluster = 0; i < nb_clusters; i++) { - refcount1 = get_refcount(bs, i); - if (refcount1 < 0) { - fprintf(stderr, "Can't get refcount for cluster %" PRId64 ": %s\n", - i, strerror(-refcount1)); - res->check_errors++; - continue; - } - - refcount2 = refcount_table[i]; - - if (refcount1 > 0 || refcount2 > 0) { - highest_cluster = i; - } - - if (refcount1 != refcount2) { - - /* Check if we're allowed to fix the mismatch */ - int *num_fixed = NULL; - if (refcount1 > refcount2 && (fix & BDRV_FIX_LEAKS)) { - num_fixed = &res->leaks_fixed; - } else if (refcount1 < refcount2 && (fix & BDRV_FIX_ERRORS)) { - num_fixed = &res->corruptions_fixed; - } - - fprintf(stderr, "%s cluster %" PRId64 " refcount=%d reference=%d\n", - num_fixed != NULL ? "Repairing" : - refcount1 < refcount2 ? "ERROR" : - "Leaked", - i, refcount1, refcount2); - - if (num_fixed) { - ret = update_refcount(bs, i << s->cluster_bits, 1, - refcount2 - refcount1, - QCOW2_DISCARD_ALWAYS); - if (ret >= 0) { - (*num_fixed)++; - continue; - } - } - - /* And if we couldn't, print an error */ - if (refcount1 < refcount2) { - res->corruptions++; - } else { - res->leaks++; - } - } - } - - res->image_end_offset = (highest_cluster + 1) * s->cluster_size; - ret = 0; - -fail: - g_free(refcount_table); - - return ret; -} - diff --git a/contrib/qemu/block/qcow2-snapshot.c b/contrib/qemu/block/qcow2-snapshot.c deleted file mode 100644 index 0caac9055f8..00000000000 --- a/contrib/qemu/block/qcow2-snapshot.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-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-common.h" -#include "block/block_int.h" -#include "block/qcow2.h" - -typedef struct QEMU_PACKED QCowSnapshotHeader { - /* header is 8 byte aligned */ - uint64_t l1_table_offset; - - uint32_t l1_size; - uint16_t id_str_size; - uint16_t name_size; - - uint32_t date_sec; - uint32_t date_nsec; - - uint64_t vm_clock_nsec; - - uint32_t vm_state_size; - uint32_t extra_data_size; /* for extension */ - /* extra data follows */ - /* id_str follows */ - /* name follows */ -} QCowSnapshotHeader; - -typedef struct QEMU_PACKED QCowSnapshotExtraData { - uint64_t vm_state_size_large; - uint64_t disk_size; -} QCowSnapshotExtraData; - -void qcow2_free_snapshots(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - int i; - - for(i = 0; i < s->nb_snapshots; i++) { - g_free(s->snapshots[i].name); - g_free(s->snapshots[i].id_str); - } - g_free(s->snapshots); - s->snapshots = NULL; - s->nb_snapshots = 0; -} - -int qcow2_read_snapshots(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshotHeader h; - QCowSnapshotExtraData extra; - QCowSnapshot *sn; - int i, id_str_size, name_size; - int64_t offset; - uint32_t extra_data_size; - int ret; - - if (!s->nb_snapshots) { - s->snapshots = NULL; - s->snapshots_size = 0; - return 0; - } - - offset = s->snapshots_offset; - s->snapshots = g_malloc0(s->nb_snapshots * sizeof(QCowSnapshot)); - - for(i = 0; i < s->nb_snapshots; i++) { - /* Read statically sized part of the snapshot header */ - offset = align_offset(offset, 8); - ret = bdrv_pread(bs->file, offset, &h, sizeof(h)); - if (ret < 0) { - goto fail; - } - - offset += sizeof(h); - sn = s->snapshots + i; - sn->l1_table_offset = be64_to_cpu(h.l1_table_offset); - sn->l1_size = be32_to_cpu(h.l1_size); - sn->vm_state_size = be32_to_cpu(h.vm_state_size); - sn->date_sec = be32_to_cpu(h.date_sec); - sn->date_nsec = be32_to_cpu(h.date_nsec); - sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec); - extra_data_size = be32_to_cpu(h.extra_data_size); - - id_str_size = be16_to_cpu(h.id_str_size); - name_size = be16_to_cpu(h.name_size); - - /* Read extra data */ - ret = bdrv_pread(bs->file, offset, &extra, - MIN(sizeof(extra), extra_data_size)); - if (ret < 0) { - goto fail; - } - offset += extra_data_size; - - if (extra_data_size >= 8) { - sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large); - } - - if (extra_data_size >= 16) { - sn->disk_size = be64_to_cpu(extra.disk_size); - } else { - sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; - } - - /* Read snapshot ID */ - sn->id_str = g_malloc(id_str_size + 1); - ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size); - if (ret < 0) { - goto fail; - } - offset += id_str_size; - sn->id_str[id_str_size] = '\0'; - - /* Read snapshot name */ - sn->name = g_malloc(name_size + 1); - ret = bdrv_pread(bs->file, offset, sn->name, name_size); - if (ret < 0) { - goto fail; - } - offset += name_size; - sn->name[name_size] = '\0'; - } - - s->snapshots_size = offset - s->snapshots_offset; - return 0; - -fail: - qcow2_free_snapshots(bs); - return ret; -} - -/* add at the end of the file a new list of snapshots */ -static int qcow2_write_snapshots(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshot *sn; - QCowSnapshotHeader h; - QCowSnapshotExtraData extra; - int i, name_size, id_str_size, snapshots_size; - struct { - uint32_t nb_snapshots; - uint64_t snapshots_offset; - } QEMU_PACKED header_data; - int64_t offset, snapshots_offset; - int ret; - - /* compute the size of the snapshots */ - offset = 0; - for(i = 0; i < s->nb_snapshots; i++) { - sn = s->snapshots + i; - offset = align_offset(offset, 8); - offset += sizeof(h); - offset += sizeof(extra); - offset += strlen(sn->id_str); - offset += strlen(sn->name); - } - snapshots_size = offset; - - /* Allocate space for the new snapshot list */ - snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size); - offset = snapshots_offset; - if (offset < 0) { - return offset; - } - ret = bdrv_flush(bs); - if (ret < 0) { - return ret; - } - - /* Write all snapshots to the new list */ - for(i = 0; i < s->nb_snapshots; i++) { - sn = s->snapshots + i; - memset(&h, 0, sizeof(h)); - h.l1_table_offset = cpu_to_be64(sn->l1_table_offset); - h.l1_size = cpu_to_be32(sn->l1_size); - /* If it doesn't fit in 32 bit, older implementations should treat it - * as a disk-only snapshot rather than truncate the VM state */ - if (sn->vm_state_size <= 0xffffffff) { - h.vm_state_size = cpu_to_be32(sn->vm_state_size); - } - h.date_sec = cpu_to_be32(sn->date_sec); - h.date_nsec = cpu_to_be32(sn->date_nsec); - h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec); - h.extra_data_size = cpu_to_be32(sizeof(extra)); - - memset(&extra, 0, sizeof(extra)); - extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size); - extra.disk_size = cpu_to_be64(sn->disk_size); - - id_str_size = strlen(sn->id_str); - name_size = strlen(sn->name); - h.id_str_size = cpu_to_be16(id_str_size); - h.name_size = cpu_to_be16(name_size); - offset = align_offset(offset, 8); - - ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h)); - if (ret < 0) { - goto fail; - } - offset += sizeof(h); - - ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra)); - if (ret < 0) { - goto fail; - } - offset += sizeof(extra); - - ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size); - if (ret < 0) { - goto fail; - } - offset += id_str_size; - - ret = bdrv_pwrite(bs->file, offset, sn->name, name_size); - if (ret < 0) { - goto fail; - } - offset += name_size; - } - - /* - * Update the header to point to the new snapshot table. This requires the - * new table and its refcounts to be stable on disk. - */ - ret = bdrv_flush(bs); - if (ret < 0) { - goto fail; - } - - QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) != - offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots)); - - header_data.nb_snapshots = cpu_to_be32(s->nb_snapshots); - header_data.snapshots_offset = cpu_to_be64(snapshots_offset); - - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots), - &header_data, sizeof(header_data)); - if (ret < 0) { - goto fail; - } - - /* free the old snapshot table */ - qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size, - QCOW2_DISCARD_SNAPSHOT); - s->snapshots_offset = snapshots_offset; - s->snapshots_size = snapshots_size; - return 0; - -fail: - return ret; -} - -static void find_new_snapshot_id(BlockDriverState *bs, - char *id_str, int id_str_size) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshot *sn; - int i, id, id_max = 0; - - for(i = 0; i < s->nb_snapshots; i++) { - sn = s->snapshots + i; - id = strtoul(sn->id_str, NULL, 10); - if (id > id_max) - id_max = id; - } - snprintf(id_str, id_str_size, "%d", id_max + 1); -} - -static int find_snapshot_by_id(BlockDriverState *bs, const char *id_str) -{ - BDRVQcowState *s = bs->opaque; - int i; - - for(i = 0; i < s->nb_snapshots; i++) { - if (!strcmp(s->snapshots[i].id_str, id_str)) - return i; - } - return -1; -} - -static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name) -{ - BDRVQcowState *s = bs->opaque; - int i, ret; - - ret = find_snapshot_by_id(bs, name); - if (ret >= 0) - return ret; - for(i = 0; i < s->nb_snapshots; i++) { - if (!strcmp(s->snapshots[i].name, name)) - return i; - } - return -1; -} - -/* if no id is provided, a new one is constructed */ -int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshot *new_snapshot_list = NULL; - QCowSnapshot *old_snapshot_list = NULL; - QCowSnapshot sn1, *sn = &sn1; - int i, ret; - uint64_t *l1_table = NULL; - int64_t l1_table_offset; - - memset(sn, 0, sizeof(*sn)); - - /* Generate an ID if it wasn't passed */ - if (sn_info->id_str[0] == '\0') { - find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str)); - } - - /* Check that the ID is unique */ - if (find_snapshot_by_id(bs, sn_info->id_str) >= 0) { - return -EEXIST; - } - - /* Populate sn with passed data */ - sn->id_str = g_strdup(sn_info->id_str); - sn->name = g_strdup(sn_info->name); - - sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; - sn->vm_state_size = sn_info->vm_state_size; - sn->date_sec = sn_info->date_sec; - sn->date_nsec = sn_info->date_nsec; - sn->vm_clock_nsec = sn_info->vm_clock_nsec; - - /* Allocate the L1 table of the snapshot and copy the current one there. */ - l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t)); - if (l1_table_offset < 0) { - ret = l1_table_offset; - goto fail; - } - - sn->l1_table_offset = l1_table_offset; - sn->l1_size = s->l1_size; - - l1_table = g_malloc(s->l1_size * sizeof(uint64_t)); - for(i = 0; i < s->l1_size; i++) { - l1_table[i] = cpu_to_be64(s->l1_table[i]); - } - - ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table, - s->l1_size * sizeof(uint64_t)); - if (ret < 0) { - goto fail; - } - - g_free(l1_table); - l1_table = NULL; - - /* - * Increase the refcounts of all clusters and make sure everything is - * stable on disk before updating the snapshot table to contain a pointer - * to the new L1 table. - */ - ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1); - if (ret < 0) { - goto fail; - } - - /* Append the new snapshot to the snapshot list */ - new_snapshot_list = g_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot)); - if (s->snapshots) { - memcpy(new_snapshot_list, s->snapshots, - s->nb_snapshots * sizeof(QCowSnapshot)); - old_snapshot_list = s->snapshots; - } - s->snapshots = new_snapshot_list; - s->snapshots[s->nb_snapshots++] = *sn; - - ret = qcow2_write_snapshots(bs); - if (ret < 0) { - g_free(s->snapshots); - s->snapshots = old_snapshot_list; - goto fail; - } - - g_free(old_snapshot_list); - -#ifdef DEBUG_ALLOC - { - BdrvCheckResult result = {0}; - qcow2_check_refcounts(bs, &result, 0); - } -#endif - return 0; - -fail: - g_free(sn->id_str); - g_free(sn->name); - g_free(l1_table); - - return ret; -} - -/* copy the snapshot 'snapshot_name' into the current disk image */ -int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshot *sn; - int i, snapshot_index; - int cur_l1_bytes, sn_l1_bytes; - int ret; - uint64_t *sn_l1_table = NULL; - - /* Search the snapshot */ - snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); - if (snapshot_index < 0) { - return -ENOENT; - } - sn = &s->snapshots[snapshot_index]; - - if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) { - error_report("qcow2: Loading snapshots with different disk " - "size is not implemented"); - ret = -ENOTSUP; - goto fail; - } - - /* - * Make sure that the current L1 table is big enough to contain the whole - * L1 table of the snapshot. If the snapshot L1 table is smaller, the - * current one must be padded with zeros. - */ - ret = qcow2_grow_l1_table(bs, sn->l1_size, true); - if (ret < 0) { - goto fail; - } - - cur_l1_bytes = s->l1_size * sizeof(uint64_t); - sn_l1_bytes = sn->l1_size * sizeof(uint64_t); - - /* - * Copy the snapshot L1 table to the current L1 table. - * - * Before overwriting the old current L1 table on disk, make sure to - * increase all refcounts for the clusters referenced by the new one. - * Decrease the refcount referenced by the old one only when the L1 - * table is overwritten. - */ - sn_l1_table = g_malloc0(cur_l1_bytes); - - ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_table, sn_l1_bytes); - if (ret < 0) { - goto fail; - } - - ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset, - sn->l1_size, 1); - if (ret < 0) { - goto fail; - } - - ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table, - cur_l1_bytes); - if (ret < 0) { - goto fail; - } - - /* - * Decrease refcount of clusters of current L1 table. - * - * At this point, the in-memory s->l1_table points to the old L1 table, - * whereas on disk we already have the new one. - * - * qcow2_update_snapshot_refcount special cases the current L1 table to use - * the in-memory data instead of really using the offset to load a new one, - * which is why this works. - */ - ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, - s->l1_size, -1); - - /* - * Now update the in-memory L1 table to be in sync with the on-disk one. We - * need to do this even if updating refcounts failed. - */ - for(i = 0;i < s->l1_size; i++) { - s->l1_table[i] = be64_to_cpu(sn_l1_table[i]); - } - - if (ret < 0) { - goto fail; - } - - g_free(sn_l1_table); - sn_l1_table = NULL; - - /* - * Update QCOW_OFLAG_COPIED in the active L1 table (it may have changed - * when we decreased the refcount of the old snapshot. - */ - ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0); - if (ret < 0) { - goto fail; - } - -#ifdef DEBUG_ALLOC - { - BdrvCheckResult result = {0}; - qcow2_check_refcounts(bs, &result, 0); - } -#endif - return 0; - -fail: - g_free(sn_l1_table); - return ret; -} - -int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) -{ - BDRVQcowState *s = bs->opaque; - QCowSnapshot sn; - int snapshot_index, ret; - - /* Search the snapshot */ - snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); - if (snapshot_index < 0) { - return -ENOENT; - } - sn = s->snapshots[snapshot_index]; - - /* Remove it from the snapshot list */ - memmove(s->snapshots + snapshot_index, - s->snapshots + snapshot_index + 1, - (s->nb_snapshots - snapshot_index - 1) * sizeof(sn)); - s->nb_snapshots--; - ret = qcow2_write_snapshots(bs); - if (ret < 0) { - return ret; - } - - /* - * The snapshot is now unused, clean up. If we fail after this point, we - * won't recover but just leak clusters. - */ - g_free(sn.id_str); - g_free(sn.name); - - /* - * Now decrease the refcounts of clusters referenced by the snapshot and - * free the L1 table. - */ - ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset, - sn.l1_size, -1); - if (ret < 0) { - return ret; - } - qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t), - QCOW2_DISCARD_SNAPSHOT); - - /* must update the copied flag on the current cluster offsets */ - ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0); - if (ret < 0) { - return ret; - } - -#ifdef DEBUG_ALLOC - { - BdrvCheckResult result = {0}; - qcow2_check_refcounts(bs, &result, 0); - } -#endif - return 0; -} - -int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) -{ - BDRVQcowState *s = bs->opaque; - QEMUSnapshotInfo *sn_tab, *sn_info; - QCowSnapshot *sn; - int i; - - if (!s->nb_snapshots) { - *psn_tab = NULL; - return s->nb_snapshots; - } - - sn_tab = g_malloc0(s->nb_snapshots * sizeof(QEMUSnapshotInfo)); - for(i = 0; i < s->nb_snapshots; i++) { - sn_info = sn_tab + i; - sn = s->snapshots + i; - pstrcpy(sn_info->id_str, sizeof(sn_info->id_str), - sn->id_str); - pstrcpy(sn_info->name, sizeof(sn_info->name), - sn->name); - sn_info->vm_state_size = sn->vm_state_size; - sn_info->date_sec = sn->date_sec; - sn_info->date_nsec = sn->date_nsec; - sn_info->vm_clock_nsec = sn->vm_clock_nsec; - } - *psn_tab = sn_tab; - return s->nb_snapshots; -} - -int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name) -{ - int i, snapshot_index; - BDRVQcowState *s = bs->opaque; - QCowSnapshot *sn; - uint64_t *new_l1_table; - int new_l1_bytes; - int ret; - - assert(bs->read_only); - - /* Search the snapshot */ - snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_name); - if (snapshot_index < 0) { - return -ENOENT; - } - sn = &s->snapshots[snapshot_index]; - - /* Allocate and read in the snapshot's L1 table */ - new_l1_bytes = s->l1_size * sizeof(uint64_t); - new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512)); - - ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes); - if (ret < 0) { - g_free(new_l1_table); - return ret; - } - - /* Switch the L1 table */ - g_free(s->l1_table); - - s->l1_size = sn->l1_size; - s->l1_table_offset = sn->l1_table_offset; - s->l1_table = new_l1_table; - - for(i = 0;i < s->l1_size; i++) { - be64_to_cpus(&s->l1_table[i]); - } - - return 0; -} diff --git a/contrib/qemu/block/qcow2.c b/contrib/qemu/block/qcow2.c deleted file mode 100644 index 0eceefe2cd9..00000000000 --- a/contrib/qemu/block/qcow2.c +++ /dev/null @@ -1,1825 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-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-common.h" -#include "block/block_int.h" -#include "qemu/module.h" -#include <zlib.h> -#include "qemu/aes.h" -#include "block/qcow2.h" -#include "qemu/error-report.h" -#include "qapi/qmp/qerror.h" -#include "qapi/qmp/qbool.h" -#include "trace.h" - -/* - Differences with QCOW: - - - Support for multiple incremental snapshots. - - Memory management by reference counts. - - Clusters which have a reference count of one have the bit - QCOW_OFLAG_COPIED to optimize write performance. - - Size of compressed clusters is stored in sectors to reduce bit usage - in the cluster offsets. - - Support for storing additional data (such as the VM state) in the - snapshots. - - If a backing store is used, the cluster size is not constrained - (could be backported to QCOW). - - L2 tables have always a size of one cluster. -*/ - - -typedef struct { - uint32_t magic; - uint32_t len; -} QCowExtension; - -#define QCOW2_EXT_MAGIC_END 0 -#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA -#define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 - -static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) -{ - const QCowHeader *cow_header = (const void *)buf; - - if (buf_size >= sizeof(QCowHeader) && - be32_to_cpu(cow_header->magic) == QCOW_MAGIC && - be32_to_cpu(cow_header->version) >= 2) - return 100; - else - return 0; -} - - -/* - * read qcow2 extension and fill bs - * start reading from start_offset - * finish reading upon magic of value 0 or when end_offset reached - * unknown magic is skipped (future extension this version knows nothing about) - * return 0 upon success, non-0 otherwise - */ -static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, - uint64_t end_offset, void **p_feature_table) -{ - BDRVQcowState *s = bs->opaque; - QCowExtension ext; - uint64_t offset; - int ret; - -#ifdef DEBUG_EXT - printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset); -#endif - offset = start_offset; - while (offset < end_offset) { - -#ifdef DEBUG_EXT - /* Sanity check */ - if (offset > s->cluster_size) - printf("qcow2_read_extension: suspicious offset %lu\n", offset); - - printf("attempting to read extended header in offset %lu\n", offset); -#endif - - if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) { - fprintf(stderr, "qcow2_read_extension: ERROR: " - "pread fail from offset %" PRIu64 "\n", - offset); - return 1; - } - be32_to_cpus(&ext.magic); - be32_to_cpus(&ext.len); - offset += sizeof(ext); -#ifdef DEBUG_EXT - printf("ext.magic = 0x%x\n", ext.magic); -#endif - if (ext.len > end_offset - offset) { - error_report("Header extension too large"); - return -EINVAL; - } - - switch (ext.magic) { - case QCOW2_EXT_MAGIC_END: - return 0; - - case QCOW2_EXT_MAGIC_BACKING_FORMAT: - if (ext.len >= sizeof(bs->backing_format)) { - fprintf(stderr, "ERROR: ext_backing_format: len=%u too large" - " (>=%zu)\n", - ext.len, sizeof(bs->backing_format)); - return 2; - } - if (bdrv_pread(bs->file, offset , bs->backing_format, - ext.len) != ext.len) - return 3; - bs->backing_format[ext.len] = '\0'; -#ifdef DEBUG_EXT - printf("Qcow2: Got format extension %s\n", bs->backing_format); -#endif - break; - - case QCOW2_EXT_MAGIC_FEATURE_TABLE: - if (p_feature_table != NULL) { - void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); - ret = bdrv_pread(bs->file, offset , feature_table, ext.len); - if (ret < 0) { - return ret; - } - - *p_feature_table = feature_table; - } - break; - - default: - /* unknown magic - save it in case we need to rewrite the header */ - { - Qcow2UnknownHeaderExtension *uext; - - uext = g_malloc0(sizeof(*uext) + ext.len); - uext->magic = ext.magic; - uext->len = ext.len; - QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next); - - ret = bdrv_pread(bs->file, offset , uext->data, uext->len); - if (ret < 0) { - return ret; - } - } - break; - } - - offset += ((ext.len + 7) & ~7); - } - - return 0; -} - -static void cleanup_unknown_header_ext(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - Qcow2UnknownHeaderExtension *uext, *next; - - QLIST_FOREACH_SAFE(uext, &s->unknown_header_ext, next, next) { - QLIST_REMOVE(uext, next); - g_free(uext); - } -} - -static void GCC_FMT_ATTR(2, 3) report_unsupported(BlockDriverState *bs, - const char *fmt, ...) -{ - char msg[64]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - - qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "qcow2", msg); -} - -static void report_unsupported_feature(BlockDriverState *bs, - Qcow2Feature *table, uint64_t mask) -{ - while (table && table->name[0] != '\0') { - if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) { - if (mask & (1 << table->bit)) { - report_unsupported(bs, "%.46s",table->name); - mask &= ~(1 << table->bit); - } - } - table++; - } - - if (mask) { - report_unsupported(bs, "Unknown incompatible feature: %" PRIx64, mask); - } -} - -/* - * Sets the dirty bit and flushes afterwards if necessary. - * - * The incompatible_features bit is only set if the image file header was - * updated successfully. Therefore it is not required to check the return - * value of this function. - */ -int qcow2_mark_dirty(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - uint64_t val; - int ret; - - assert(s->qcow_version >= 3); - - if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) { - return 0; /* already dirty */ - } - - val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY); - ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features), - &val, sizeof(val)); - if (ret < 0) { - return ret; - } - ret = bdrv_flush(bs->file); - if (ret < 0) { - return ret; - } - - /* Only treat image as dirty if the header was updated successfully */ - s->incompatible_features |= QCOW2_INCOMPAT_DIRTY; - return 0; -} - -/* - * Clears the dirty bit and flushes before if necessary. Only call this - * function when there are no pending requests, it does not guard against - * concurrent requests dirtying the image. - */ -static int qcow2_mark_clean(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - - if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) { - int ret = bdrv_flush(bs); - if (ret < 0) { - return ret; - } - - s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY; - return qcow2_update_header(bs); - } - return 0; -} - -static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, - BdrvCheckMode fix) -{ - int ret = qcow2_check_refcounts(bs, result, fix); - if (ret < 0) { - return ret; - } - - if (fix && result->check_errors == 0 && result->corruptions == 0) { - return qcow2_mark_clean(bs); - } - return ret; -} - -static QemuOptsList qcow2_runtime_opts = { - .name = "qcow2", - .head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head), - .desc = { - { - .name = "lazy_refcounts", - .type = QEMU_OPT_BOOL, - .help = "Postpone refcount updates", - }, - { - .name = QCOW2_OPT_DISCARD_REQUEST, - .type = QEMU_OPT_BOOL, - .help = "Pass guest discard requests to the layer below", - }, - { - .name = QCOW2_OPT_DISCARD_SNAPSHOT, - .type = QEMU_OPT_BOOL, - .help = "Generate discard requests when snapshot related space " - "is freed", - }, - { - .name = QCOW2_OPT_DISCARD_OTHER, - .type = QEMU_OPT_BOOL, - .help = "Generate discard requests when other clusters are freed", - }, - { /* end of list */ } - }, -}; - -static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) -{ - BDRVQcowState *s = bs->opaque; - int len, i, ret = 0; - QCowHeader header; - QemuOpts *opts; - Error *local_err = NULL; - uint64_t ext_end; - uint64_t l1_vm_state_index; - - ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); - if (ret < 0) { - goto fail; - } - be32_to_cpus(&header.magic); - be32_to_cpus(&header.version); - be64_to_cpus(&header.backing_file_offset); - be32_to_cpus(&header.backing_file_size); - be64_to_cpus(&header.size); - be32_to_cpus(&header.cluster_bits); - be32_to_cpus(&header.crypt_method); - be64_to_cpus(&header.l1_table_offset); - be32_to_cpus(&header.l1_size); - be64_to_cpus(&header.refcount_table_offset); - be32_to_cpus(&header.refcount_table_clusters); - be64_to_cpus(&header.snapshots_offset); - be32_to_cpus(&header.nb_snapshots); - - if (header.magic != QCOW_MAGIC) { - ret = -EMEDIUMTYPE; - goto fail; - } - if (header.version < 2 || header.version > 3) { - report_unsupported(bs, "QCOW version %d", header.version); - ret = -ENOTSUP; - goto fail; - } - - s->qcow_version = header.version; - - /* Initialise version 3 header fields */ - if (header.version == 2) { - header.incompatible_features = 0; - header.compatible_features = 0; - header.autoclear_features = 0; - header.refcount_order = 4; - header.header_length = 72; - } else { - be64_to_cpus(&header.incompatible_features); - be64_to_cpus(&header.compatible_features); - be64_to_cpus(&header.autoclear_features); - be32_to_cpus(&header.refcount_order); - be32_to_cpus(&header.header_length); - } - - if (header.header_length > sizeof(header)) { - s->unknown_header_fields_size = header.header_length - sizeof(header); - s->unknown_header_fields = g_malloc(s->unknown_header_fields_size); - ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields, - s->unknown_header_fields_size); - if (ret < 0) { - goto fail; - } - } - - if (header.backing_file_offset) { - ext_end = header.backing_file_offset; - } else { - ext_end = 1 << header.cluster_bits; - } - - /* Handle feature bits */ - s->incompatible_features = header.incompatible_features; - s->compatible_features = header.compatible_features; - s->autoclear_features = header.autoclear_features; - - if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { - void *feature_table = NULL; - qcow2_read_extensions(bs, header.header_length, ext_end, - &feature_table); - report_unsupported_feature(bs, feature_table, - s->incompatible_features & - ~QCOW2_INCOMPAT_MASK); - ret = -ENOTSUP; - goto fail; - } - - /* Check support for various header values */ - if (header.refcount_order != 4) { - report_unsupported(bs, "%d bit reference counts", - 1 << header.refcount_order); - ret = -ENOTSUP; - goto fail; - } - - if (header.cluster_bits < MIN_CLUSTER_BITS || - header.cluster_bits > MAX_CLUSTER_BITS) { - ret = -EINVAL; - goto fail; - } - if (header.crypt_method > QCOW_CRYPT_AES) { - ret = -EINVAL; - goto fail; - } - s->crypt_method_header = header.crypt_method; - if (s->crypt_method_header) { - bs->encrypted = 1; - } - s->cluster_bits = header.cluster_bits; - s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); - s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */ - s->l2_size = 1 << s->l2_bits; - bs->total_sectors = header.size / 512; - s->csize_shift = (62 - (s->cluster_bits - 8)); - s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; - s->cluster_offset_mask = (1LL << s->csize_shift) - 1; - s->refcount_table_offset = header.refcount_table_offset; - s->refcount_table_size = - header.refcount_table_clusters << (s->cluster_bits - 3); - - s->snapshots_offset = header.snapshots_offset; - s->nb_snapshots = header.nb_snapshots; - - /* read the level 1 table */ - s->l1_size = header.l1_size; - - l1_vm_state_index = size_to_l1(s, header.size); - if (l1_vm_state_index > INT_MAX) { - ret = -EFBIG; - goto fail; - } - s->l1_vm_state_index = l1_vm_state_index; - - /* the L1 table must contain at least enough entries to put - header.size bytes */ - if (s->l1_size < s->l1_vm_state_index) { - ret = -EINVAL; - goto fail; - } - s->l1_table_offset = header.l1_table_offset; - if (s->l1_size > 0) { - s->l1_table = g_malloc0( - align_offset(s->l1_size * sizeof(uint64_t), 512)); - ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, - s->l1_size * sizeof(uint64_t)); - if (ret < 0) { - goto fail; - } - for(i = 0;i < s->l1_size; i++) { - be64_to_cpus(&s->l1_table[i]); - } - } - - /* alloc L2 table/refcount block cache */ - s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE); - s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE); - - s->cluster_cache = g_malloc(s->cluster_size); - /* one more sector for decompressed data alignment */ - s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size - + 512); - s->cluster_cache_offset = -1; - s->flags = flags; - - ret = qcow2_refcount_init(bs); - if (ret != 0) { - goto fail; - } - - QLIST_INIT(&s->cluster_allocs); - QTAILQ_INIT(&s->discards); - - /* read qcow2 extensions */ - if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) { - ret = -EINVAL; - goto fail; - } - - /* read the backing file name */ - if (header.backing_file_offset != 0) { - len = header.backing_file_size; - if (len > 1023) { - len = 1023; - } - ret = bdrv_pread(bs->file, header.backing_file_offset, - bs->backing_file, len); - if (ret < 0) { - goto fail; - } - bs->backing_file[len] = '\0'; - } - - ret = qcow2_read_snapshots(bs); - if (ret < 0) { - goto fail; - } - - /* Clear unknown autoclear feature bits */ - if (!bs->read_only && s->autoclear_features != 0) { - s->autoclear_features = 0; - ret = qcow2_update_header(bs); - if (ret < 0) { - goto fail; - } - } - - /* Initialise locks */ - qemu_co_mutex_init(&s->lock); - - /* Repair image if dirty */ - if (!(flags & BDRV_O_CHECK) && !bs->read_only && - (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { - BdrvCheckResult result = {0}; - - ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS); - if (ret < 0) { - goto fail; - } - } - - /* Enable lazy_refcounts according to image and command line options */ - opts = qemu_opts_create_nofail(&qcow2_runtime_opts); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - ret = -EINVAL; - goto fail; - } - - s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS, - (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)); - - s->discard_passthrough[QCOW2_DISCARD_NEVER] = false; - s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true; - s->discard_passthrough[QCOW2_DISCARD_REQUEST] = - qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST, - flags & BDRV_O_UNMAP); - s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] = - qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true); - s->discard_passthrough[QCOW2_DISCARD_OTHER] = - qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); - - qemu_opts_del(opts); - - if (s->use_lazy_refcounts && s->qcow_version < 3) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require " - "a qcow2 image with at least qemu 1.1 compatibility level"); - ret = -EINVAL; - goto fail; - } - -#ifdef DEBUG_ALLOC - { - BdrvCheckResult result = {0}; - qcow2_check_refcounts(bs, &result, 0); - } -#endif - return ret; - - fail: - g_free(s->unknown_header_fields); - cleanup_unknown_header_ext(bs); - qcow2_free_snapshots(bs); - qcow2_refcount_close(bs); - g_free(s->l1_table); - if (s->l2_table_cache) { - qcow2_cache_destroy(bs, s->l2_table_cache); - } - g_free(s->cluster_cache); - qemu_vfree(s->cluster_data); - return ret; -} - -static int qcow2_set_key(BlockDriverState *bs, const char *key) -{ - BDRVQcowState *s = bs->opaque; - uint8_t keybuf[16]; - int len, i; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for(i = 0;i < len;i++) { - keybuf[i] = key[i]; - } - s->crypt_method = s->crypt_method_header; - - if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0) - return -1; - if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) - return -1; -#if 0 - /* test */ - { - uint8_t in[16]; - uint8_t out[16]; - uint8_t tmp[16]; - for(i=0;i<16;i++) - in[i] = i; - AES_encrypt(in, tmp, &s->aes_encrypt_key); - AES_decrypt(tmp, out, &s->aes_decrypt_key); - for(i = 0; i < 16; i++) - printf(" %02x", tmp[i]); - printf("\n"); - for(i = 0; i < 16; i++) - printf(" %02x", out[i]); - printf("\n"); - } -#endif - return 0; -} - -/* We have nothing to do for QCOW2 reopen, stubs just return - * success */ -static int qcow2_reopen_prepare(BDRVReopenState *state, - BlockReopenQueue *queue, Error **errp) -{ - return 0; -} - -static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, int *pnum) -{ - BDRVQcowState *s = bs->opaque; - uint64_t cluster_offset; - int ret; - - *pnum = nb_sectors; - /* FIXME We can get errors here, but the bdrv_co_is_allocated interface - * can't pass them on today */ - qemu_co_mutex_lock(&s->lock); - ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset); - qemu_co_mutex_unlock(&s->lock); - if (ret < 0) { - *pnum = 0; - } - - return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO); -} - -/* handle reading after the end of the backing file */ -int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t sector_num, int nb_sectors) -{ - int n1; - if ((sector_num + nb_sectors) <= bs->total_sectors) - return nb_sectors; - if (sector_num >= bs->total_sectors) - n1 = 0; - else - n1 = bs->total_sectors - sector_num; - - qemu_iovec_memset(qiov, 512 * n1, 0, 512 * (nb_sectors - n1)); - - return n1; -} - -static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num, - int remaining_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - int index_in_cluster, n1; - int ret; - int cur_nr_sectors; /* number of sectors in current iteration */ - uint64_t cluster_offset = 0; - uint64_t bytes_done = 0; - QEMUIOVector hd_qiov; - uint8_t *cluster_data = NULL; - - qemu_iovec_init(&hd_qiov, qiov->niov); - - qemu_co_mutex_lock(&s->lock); - - while (remaining_sectors != 0) { - - /* prepare next request */ - cur_nr_sectors = remaining_sectors; - if (s->crypt_method) { - cur_nr_sectors = MIN(cur_nr_sectors, - QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); - } - - ret = qcow2_get_cluster_offset(bs, sector_num << 9, - &cur_nr_sectors, &cluster_offset); - if (ret < 0) { - goto fail; - } - - index_in_cluster = sector_num & (s->cluster_sectors - 1); - - qemu_iovec_reset(&hd_qiov); - qemu_iovec_concat(&hd_qiov, qiov, bytes_done, - cur_nr_sectors * 512); - - switch (ret) { - case QCOW2_CLUSTER_UNALLOCATED: - - if (bs->backing_hd) { - /* read from the base image */ - n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov, - sector_num, cur_nr_sectors); - if (n1 > 0) { - BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->backing_hd, sector_num, - n1, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - goto fail; - } - } - } else { - /* Note: in this case, no need to wait */ - qemu_iovec_memset(&hd_qiov, 0, 0, 512 * cur_nr_sectors); - } - break; - - case QCOW2_CLUSTER_ZERO: - qemu_iovec_memset(&hd_qiov, 0, 0, 512 * cur_nr_sectors); - break; - - case QCOW2_CLUSTER_COMPRESSED: - /* add AIO support for compressed blocks ? */ - ret = qcow2_decompress_cluster(bs, cluster_offset); - if (ret < 0) { - goto fail; - } - - qemu_iovec_from_buf(&hd_qiov, 0, - s->cluster_cache + index_in_cluster * 512, - 512 * cur_nr_sectors); - break; - - case QCOW2_CLUSTER_NORMAL: - if ((cluster_offset & 511) != 0) { - ret = -EIO; - goto fail; - } - - if (s->crypt_method) { - /* - * For encrypted images, read everything into a temporary - * contiguous buffer on which the AES functions can work. - */ - if (!cluster_data) { - cluster_data = - qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); - } - - assert(cur_nr_sectors <= - QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); - qemu_iovec_reset(&hd_qiov); - qemu_iovec_add(&hd_qiov, cluster_data, - 512 * cur_nr_sectors); - } - - BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->file, - (cluster_offset >> 9) + index_in_cluster, - cur_nr_sectors, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - goto fail; - } - if (s->crypt_method) { - qcow2_encrypt_sectors(s, sector_num, cluster_data, - cluster_data, cur_nr_sectors, 0, &s->aes_decrypt_key); - qemu_iovec_from_buf(qiov, bytes_done, - cluster_data, 512 * cur_nr_sectors); - } - break; - - default: - g_assert_not_reached(); - ret = -EIO; - goto fail; - } - - remaining_sectors -= cur_nr_sectors; - sector_num += cur_nr_sectors; - bytes_done += cur_nr_sectors * 512; - } - ret = 0; - -fail: - qemu_co_mutex_unlock(&s->lock); - - qemu_iovec_destroy(&hd_qiov); - qemu_vfree(cluster_data); - - return ret; -} - -static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, - int64_t sector_num, - int remaining_sectors, - QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - int index_in_cluster; - int n_end; - int ret; - int cur_nr_sectors; /* number of sectors in current iteration */ - uint64_t cluster_offset; - QEMUIOVector hd_qiov; - uint64_t bytes_done = 0; - uint8_t *cluster_data = NULL; - QCowL2Meta *l2meta = NULL; - - trace_qcow2_writev_start_req(qemu_coroutine_self(), sector_num, - remaining_sectors); - - qemu_iovec_init(&hd_qiov, qiov->niov); - - s->cluster_cache_offset = -1; /* disable compressed cache */ - - qemu_co_mutex_lock(&s->lock); - - while (remaining_sectors != 0) { - - l2meta = NULL; - - trace_qcow2_writev_start_part(qemu_coroutine_self()); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n_end = index_in_cluster + remaining_sectors; - if (s->crypt_method && - n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { - n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; - } - - ret = qcow2_alloc_cluster_offset(bs, sector_num << 9, - index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta); - if (ret < 0) { - goto fail; - } - - assert((cluster_offset & 511) == 0); - - qemu_iovec_reset(&hd_qiov); - qemu_iovec_concat(&hd_qiov, qiov, bytes_done, - cur_nr_sectors * 512); - - if (s->crypt_method) { - if (!cluster_data) { - cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * - s->cluster_size); - } - - assert(hd_qiov.size <= - QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); - qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size); - - qcow2_encrypt_sectors(s, sector_num, cluster_data, - cluster_data, cur_nr_sectors, 1, &s->aes_encrypt_key); - - qemu_iovec_reset(&hd_qiov); - qemu_iovec_add(&hd_qiov, cluster_data, - cur_nr_sectors * 512); - } - - qemu_co_mutex_unlock(&s->lock); - BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - trace_qcow2_writev_data(qemu_coroutine_self(), - (cluster_offset >> 9) + index_in_cluster); - ret = bdrv_co_writev(bs->file, - (cluster_offset >> 9) + index_in_cluster, - cur_nr_sectors, &hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - goto fail; - } - - while (l2meta != NULL) { - QCowL2Meta *next; - - ret = qcow2_alloc_cluster_link_l2(bs, l2meta); - if (ret < 0) { - goto fail; - } - - /* Take the request off the list of running requests */ - if (l2meta->nb_clusters != 0) { - QLIST_REMOVE(l2meta, next_in_flight); - } - - qemu_co_queue_restart_all(&l2meta->dependent_requests); - - next = l2meta->next; - g_free(l2meta); - l2meta = next; - } - - remaining_sectors -= cur_nr_sectors; - sector_num += cur_nr_sectors; - bytes_done += cur_nr_sectors * 512; - trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_nr_sectors); - } - ret = 0; - -fail: - qemu_co_mutex_unlock(&s->lock); - - while (l2meta != NULL) { - QCowL2Meta *next; - - if (l2meta->nb_clusters != 0) { - QLIST_REMOVE(l2meta, next_in_flight); - } - qemu_co_queue_restart_all(&l2meta->dependent_requests); - - next = l2meta->next; - g_free(l2meta); - l2meta = next; - } - - qemu_iovec_destroy(&hd_qiov); - qemu_vfree(cluster_data); - trace_qcow2_writev_done_req(qemu_coroutine_self(), ret); - - return ret; -} - -static void qcow2_close(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - g_free(s->l1_table); - - qcow2_cache_flush(bs, s->l2_table_cache); - qcow2_cache_flush(bs, s->refcount_block_cache); - - qcow2_mark_clean(bs); - - qcow2_cache_destroy(bs, s->l2_table_cache); - qcow2_cache_destroy(bs, s->refcount_block_cache); - - g_free(s->unknown_header_fields); - cleanup_unknown_header_ext(bs); - - g_free(s->cluster_cache); - qemu_vfree(s->cluster_data); - qcow2_refcount_close(bs); - qcow2_free_snapshots(bs); -} - -static void qcow2_invalidate_cache(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - int flags = s->flags; - AES_KEY aes_encrypt_key; - AES_KEY aes_decrypt_key; - uint32_t crypt_method = 0; - QDict *options; - - /* - * Backing files are read-only which makes all of their metadata immutable, - * that means we don't have to worry about reopening them here. - */ - - if (s->crypt_method) { - crypt_method = s->crypt_method; - memcpy(&aes_encrypt_key, &s->aes_encrypt_key, sizeof(aes_encrypt_key)); - memcpy(&aes_decrypt_key, &s->aes_decrypt_key, sizeof(aes_decrypt_key)); - } - - qcow2_close(bs); - - options = qdict_new(); - qdict_put(options, QCOW2_OPT_LAZY_REFCOUNTS, - qbool_from_int(s->use_lazy_refcounts)); - - memset(s, 0, sizeof(BDRVQcowState)); - qcow2_open(bs, options, flags); - - QDECREF(options); - - if (crypt_method) { - s->crypt_method = crypt_method; - memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key)); - memcpy(&s->aes_decrypt_key, &aes_decrypt_key, sizeof(aes_decrypt_key)); - } -} - -static size_t header_ext_add(char *buf, uint32_t magic, const void *s, - size_t len, size_t buflen) -{ - QCowExtension *ext_backing_fmt = (QCowExtension*) buf; - size_t ext_len = sizeof(QCowExtension) + ((len + 7) & ~7); - - if (buflen < ext_len) { - return -ENOSPC; - } - - *ext_backing_fmt = (QCowExtension) { - .magic = cpu_to_be32(magic), - .len = cpu_to_be32(len), - }; - memcpy(buf + sizeof(QCowExtension), s, len); - - return ext_len; -} - -/* - * Updates the qcow2 header, including the variable length parts of it, i.e. - * the backing file name and all extensions. qcow2 was not designed to allow - * such changes, so if we run out of space (we can only use the first cluster) - * this function may fail. - * - * Returns 0 on success, -errno in error cases. - */ -int qcow2_update_header(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - QCowHeader *header; - char *buf; - size_t buflen = s->cluster_size; - int ret; - uint64_t total_size; - uint32_t refcount_table_clusters; - size_t header_length; - Qcow2UnknownHeaderExtension *uext; - - buf = qemu_blockalign(bs, buflen); - - /* Header structure */ - header = (QCowHeader*) buf; - - if (buflen < sizeof(*header)) { - ret = -ENOSPC; - goto fail; - } - - header_length = sizeof(*header) + s->unknown_header_fields_size; - total_size = bs->total_sectors * BDRV_SECTOR_SIZE; - refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3); - - *header = (QCowHeader) { - /* Version 2 fields */ - .magic = cpu_to_be32(QCOW_MAGIC), - .version = cpu_to_be32(s->qcow_version), - .backing_file_offset = 0, - .backing_file_size = 0, - .cluster_bits = cpu_to_be32(s->cluster_bits), - .size = cpu_to_be64(total_size), - .crypt_method = cpu_to_be32(s->crypt_method_header), - .l1_size = cpu_to_be32(s->l1_size), - .l1_table_offset = cpu_to_be64(s->l1_table_offset), - .refcount_table_offset = cpu_to_be64(s->refcount_table_offset), - .refcount_table_clusters = cpu_to_be32(refcount_table_clusters), - .nb_snapshots = cpu_to_be32(s->nb_snapshots), - .snapshots_offset = cpu_to_be64(s->snapshots_offset), - - /* Version 3 fields */ - .incompatible_features = cpu_to_be64(s->incompatible_features), - .compatible_features = cpu_to_be64(s->compatible_features), - .autoclear_features = cpu_to_be64(s->autoclear_features), - .refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT), - .header_length = cpu_to_be32(header_length), - }; - - /* For older versions, write a shorter header */ - switch (s->qcow_version) { - case 2: - ret = offsetof(QCowHeader, incompatible_features); - break; - case 3: - ret = sizeof(*header); - break; - default: - ret = -EINVAL; - goto fail; - } - - buf += ret; - buflen -= ret; - memset(buf, 0, buflen); - - /* Preserve any unknown field in the header */ - if (s->unknown_header_fields_size) { - if (buflen < s->unknown_header_fields_size) { - ret = -ENOSPC; - goto fail; - } - - memcpy(buf, s->unknown_header_fields, s->unknown_header_fields_size); - buf += s->unknown_header_fields_size; - buflen -= s->unknown_header_fields_size; - } - - /* Backing file format header extension */ - if (*bs->backing_format) { - ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT, - bs->backing_format, strlen(bs->backing_format), - buflen); - if (ret < 0) { - goto fail; - } - - buf += ret; - buflen -= ret; - } - - /* Feature table */ - Qcow2Feature features[] = { - { - .type = QCOW2_FEAT_TYPE_INCOMPATIBLE, - .bit = QCOW2_INCOMPAT_DIRTY_BITNR, - .name = "dirty bit", - }, - { - .type = QCOW2_FEAT_TYPE_COMPATIBLE, - .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, - .name = "lazy refcounts", - }, - }; - - ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE, - features, sizeof(features), buflen); - if (ret < 0) { - goto fail; - } - buf += ret; - buflen -= ret; - - /* Keep unknown header extensions */ - QLIST_FOREACH(uext, &s->unknown_header_ext, next) { - ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen); - if (ret < 0) { - goto fail; - } - - buf += ret; - buflen -= ret; - } - - /* End of header extensions */ - ret = header_ext_add(buf, QCOW2_EXT_MAGIC_END, NULL, 0, buflen); - if (ret < 0) { - goto fail; - } - - buf += ret; - buflen -= ret; - - /* Backing file name */ - if (*bs->backing_file) { - size_t backing_file_len = strlen(bs->backing_file); - - if (buflen < backing_file_len) { - ret = -ENOSPC; - goto fail; - } - - /* Using strncpy is ok here, since buf is not NUL-terminated. */ - strncpy(buf, bs->backing_file, buflen); - - header->backing_file_offset = cpu_to_be64(buf - ((char*) header)); - header->backing_file_size = cpu_to_be32(backing_file_len); - } - - /* Write the new header */ - ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size); - if (ret < 0) { - goto fail; - } - - ret = 0; -fail: - qemu_vfree(header); - return ret; -} - -static int qcow2_change_backing_file(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt) -{ - pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: ""); - pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: ""); - - return qcow2_update_header(bs); -} - -static int preallocate(BlockDriverState *bs) -{ - uint64_t nb_sectors; - uint64_t offset; - uint64_t host_offset = 0; - int num; - int ret; - QCowL2Meta *meta; - - nb_sectors = bdrv_getlength(bs) >> 9; - offset = 0; - - while (nb_sectors) { - num = MIN(nb_sectors, INT_MAX >> 9); - ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, - &host_offset, &meta); - if (ret < 0) { - return ret; - } - - ret = qcow2_alloc_cluster_link_l2(bs, meta); - if (ret < 0) { - qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, - QCOW2_DISCARD_NEVER); - return ret; - } - - /* There are no dependent requests, but we need to remove our request - * from the list of in-flight requests */ - if (meta != NULL) { - QLIST_REMOVE(meta, next_in_flight); - } - - /* TODO Preallocate data if requested */ - - nb_sectors -= num; - offset += num << 9; - } - - /* - * It is expected that the image file is large enough to actually contain - * all of the allocated clusters (otherwise we get failing reads after - * EOF). Extend the image to the last allocated sector. - */ - if (host_offset != 0) { - uint8_t buf[512]; - memset(buf, 0, 512); - ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1); - if (ret < 0) { - return ret; - } - } - - return 0; -} - -static int qcow2_create2(const char *filename, int64_t total_size, - const char *backing_file, const char *backing_format, - int flags, size_t cluster_size, int prealloc, - QEMUOptionParameter *options, int version) -{ - /* Calculate cluster_bits */ - int cluster_bits; - cluster_bits = ffs(cluster_size) - 1; - if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS || - (1 << cluster_bits) != cluster_size) - { - error_report( - "Cluster size must be a power of two between %d and %dk", - 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); - return -EINVAL; - } - - /* - * Open the image file and write a minimal qcow2 header. - * - * We keep things simple and start with a zero-sized image. We also - * do without refcount blocks or a L1 table for now. We'll fix the - * inconsistency later. - * - * We do need a refcount table because growing the refcount table means - * allocating two new refcount blocks - the seconds of which would be at - * 2 GB for 64k clusters, and we don't want to have a 2 GB initial file - * size for any qcow2 image. - */ - BlockDriverState* bs; - QCowHeader header; - uint8_t* refcount_table; - int ret; - - ret = bdrv_create_file(filename, options); - if (ret < 0) { - return ret; - } - - ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR); - if (ret < 0) { - return ret; - } - - /* Write the header */ - memset(&header, 0, sizeof(header)); - header.magic = cpu_to_be32(QCOW_MAGIC); - header.version = cpu_to_be32(version); - header.cluster_bits = cpu_to_be32(cluster_bits); - header.size = cpu_to_be64(0); - header.l1_table_offset = cpu_to_be64(0); - header.l1_size = cpu_to_be32(0); - header.refcount_table_offset = cpu_to_be64(cluster_size); - header.refcount_table_clusters = cpu_to_be32(1); - header.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT); - header.header_length = cpu_to_be32(sizeof(header)); - - if (flags & BLOCK_FLAG_ENCRYPT) { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); - } else { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); - } - - if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) { - header.compatible_features |= - cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS); - } - - ret = bdrv_pwrite(bs, 0, &header, sizeof(header)); - if (ret < 0) { - goto out; - } - - /* Write an empty refcount table */ - refcount_table = g_malloc0(cluster_size); - ret = bdrv_pwrite(bs, cluster_size, refcount_table, cluster_size); - g_free(refcount_table); - - if (ret < 0) { - goto out; - } - - bdrv_close(bs); - - /* - * And now open the image and make it consistent first (i.e. increase the - * refcount of the cluster that is occupied by the header and the refcount - * table) - */ - BlockDriver* drv = bdrv_find_format("qcow2"); - assert(drv != NULL); - ret = bdrv_open(bs, filename, NULL, - BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv); - if (ret < 0) { - goto out; - } - - ret = qcow2_alloc_clusters(bs, 2 * cluster_size); - if (ret < 0) { - goto out; - - } else if (ret != 0) { - error_report("Huh, first cluster in empty image is already in use?"); - abort(); - } - - /* Okay, now that we have a valid image, let's give it the right size */ - ret = bdrv_truncate(bs, total_size * BDRV_SECTOR_SIZE); - if (ret < 0) { - goto out; - } - - /* Want a backing file? There you go.*/ - if (backing_file) { - ret = bdrv_change_backing_file(bs, backing_file, backing_format); - if (ret < 0) { - goto out; - } - } - - /* And if we're supposed to preallocate metadata, do that now */ - if (prealloc) { - BDRVQcowState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = preallocate(bs); - qemu_co_mutex_unlock(&s->lock); - if (ret < 0) { - goto out; - } - } - - ret = 0; -out: - bdrv_delete(bs); - return ret; -} - -static int qcow2_create(const char *filename, QEMUOptionParameter *options) -{ - const char *backing_file = NULL; - const char *backing_fmt = NULL; - uint64_t sectors = 0; - int flags = 0; - size_t cluster_size = DEFAULT_CLUSTER_SIZE; - int prealloc = 0; - int version = 2; - - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - sectors = options->value.n / 512; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { - backing_fmt = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { - flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - cluster_size = options->value.n; - } - } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { - if (!options->value.s || !strcmp(options->value.s, "off")) { - prealloc = 0; - } else if (!strcmp(options->value.s, "metadata")) { - prealloc = 1; - } else { - fprintf(stderr, "Invalid preallocation mode: '%s'\n", - options->value.s); - return -EINVAL; - } - } else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) { - if (!options->value.s || !strcmp(options->value.s, "0.10")) { - version = 2; - } else if (!strcmp(options->value.s, "1.1")) { - version = 3; - } else { - fprintf(stderr, "Invalid compatibility level: '%s'\n", - options->value.s); - return -EINVAL; - } - } else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) { - flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0; - } - options++; - } - - if (backing_file && prealloc) { - fprintf(stderr, "Backing file and preallocation cannot be used at " - "the same time\n"); - return -EINVAL; - } - - if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) { - fprintf(stderr, "Lazy refcounts only supported with compatibility " - "level 1.1 and above (use compat=1.1 or greater)\n"); - return -EINVAL; - } - - return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, - cluster_size, prealloc, options, version); -} - -static int qcow2_make_empty(BlockDriverState *bs) -{ -#if 0 - /* XXX: not correct */ - BDRVQcowState *s = bs->opaque; - uint32_t l1_length = s->l1_size * sizeof(uint64_t); - int ret; - - memset(s->l1_table, 0, l1_length); - if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0) - return -1; - ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length); - if (ret < 0) - return ret; - - l2_cache_reset(bs); -#endif - return 0; -} - -static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ - int ret; - BDRVQcowState *s = bs->opaque; - - /* Emulate misaligned zero writes */ - if (sector_num % s->cluster_sectors || nb_sectors % s->cluster_sectors) { - return -ENOTSUP; - } - - /* Whatever is left can use real zero clusters */ - qemu_co_mutex_lock(&s->lock); - ret = qcow2_zero_clusters(bs, sector_num << BDRV_SECTOR_BITS, - nb_sectors); - qemu_co_mutex_unlock(&s->lock); - - return ret; -} - -static coroutine_fn int qcow2_co_discard(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ - int ret; - BDRVQcowState *s = bs->opaque; - - qemu_co_mutex_lock(&s->lock); - ret = qcow2_discard_clusters(bs, sector_num << BDRV_SECTOR_BITS, - nb_sectors); - qemu_co_mutex_unlock(&s->lock); - return ret; -} - -static int qcow2_truncate(BlockDriverState *bs, int64_t offset) -{ - BDRVQcowState *s = bs->opaque; - int64_t new_l1_size; - int ret; - - if (offset & 511) { - error_report("The new size must be a multiple of 512"); - return -EINVAL; - } - - /* cannot proceed if image has snapshots */ - if (s->nb_snapshots) { - error_report("Can't resize an image which has snapshots"); - return -ENOTSUP; - } - - /* shrinking is currently not supported */ - if (offset < bs->total_sectors * 512) { - error_report("qcow2 doesn't support shrinking images yet"); - return -ENOTSUP; - } - - new_l1_size = size_to_l1(s, offset); - ret = qcow2_grow_l1_table(bs, new_l1_size, true); - if (ret < 0) { - return ret; - } - - /* write updated header.size */ - offset = cpu_to_be64(offset); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), - &offset, sizeof(uint64_t)); - if (ret < 0) { - return ret; - } - - s->l1_vm_state_index = new_l1_size; - return 0; -} - -/* XXX: put compressed sectors first, then all the cluster aligned - tables to avoid losing bytes in alignment */ -static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - BDRVQcowState *s = bs->opaque; - z_stream strm; - int ret, out_len; - uint8_t *out_buf; - uint64_t cluster_offset; - - if (nb_sectors == 0) { - /* align end of file to a sector boundary to ease reading with - sector based I/Os */ - cluster_offset = bdrv_getlength(bs->file); - cluster_offset = (cluster_offset + 511) & ~511; - bdrv_truncate(bs->file, cluster_offset); - return 0; - } - - if (nb_sectors != s->cluster_sectors) { - ret = -EINVAL; - - /* Zero-pad last write if image size is not cluster aligned */ - if (sector_num + nb_sectors == bs->total_sectors && - nb_sectors < s->cluster_sectors) { - uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size); - memset(pad_buf, 0, s->cluster_size); - memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE); - ret = qcow2_write_compressed(bs, sector_num, - pad_buf, s->cluster_sectors); - qemu_vfree(pad_buf); - } - return ret; - } - - out_buf = g_malloc(s->cluster_size + (s->cluster_size / 1000) + 128); - - /* best compression, small window, no zlib header */ - memset(&strm, 0, sizeof(strm)); - ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, -12, - 9, Z_DEFAULT_STRATEGY); - if (ret != 0) { - ret = -EINVAL; - goto fail; - } - - strm.avail_in = s->cluster_size; - strm.next_in = (uint8_t *)buf; - strm.avail_out = s->cluster_size; - strm.next_out = out_buf; - - ret = deflate(&strm, Z_FINISH); - if (ret != Z_STREAM_END && ret != Z_OK) { - deflateEnd(&strm); - ret = -EINVAL; - goto fail; - } - out_len = strm.next_out - out_buf; - - deflateEnd(&strm); - - if (ret != Z_STREAM_END || out_len >= s->cluster_size) { - /* could not compress: write normal cluster */ - ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors); - if (ret < 0) { - goto fail; - } - } else { - cluster_offset = qcow2_alloc_compressed_cluster_offset(bs, - sector_num << 9, out_len); - if (!cluster_offset) { - ret = -EIO; - goto fail; - } - cluster_offset &= s->cluster_offset_mask; - BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED); - ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len); - if (ret < 0) { - goto fail; - } - } - - ret = 0; -fail: - g_free(out_buf); - return ret; -} - -static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - int ret; - - qemu_co_mutex_lock(&s->lock); - ret = qcow2_cache_flush(bs, s->l2_table_cache); - if (ret < 0) { - qemu_co_mutex_unlock(&s->lock); - return ret; - } - - if (qcow2_need_accurate_refcounts(s)) { - ret = qcow2_cache_flush(bs, s->refcount_block_cache); - if (ret < 0) { - qemu_co_mutex_unlock(&s->lock); - return ret; - } - } - qemu_co_mutex_unlock(&s->lock); - - return 0; -} - -static int64_t qcow2_vm_state_offset(BDRVQcowState *s) -{ - return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); -} - -static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) -{ - BDRVQcowState *s = bs->opaque; - bdi->cluster_size = s->cluster_size; - bdi->vm_state_offset = qcow2_vm_state_offset(s); - return 0; -} - -#if 0 -static void dump_refcounts(BlockDriverState *bs) -{ - BDRVQcowState *s = bs->opaque; - int64_t nb_clusters, k, k1, size; - int refcount; - - size = bdrv_getlength(bs->file); - nb_clusters = size_to_clusters(s, size); - for(k = 0; k < nb_clusters;) { - k1 = k; - refcount = get_refcount(bs, k); - k++; - while (k < nb_clusters && get_refcount(bs, k) == refcount) - k++; - printf("%" PRId64 ": refcount=%d nb=%" PRId64 "\n", k, refcount, - k - k1); - } -} -#endif - -static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t pos) -{ - BDRVQcowState *s = bs->opaque; - int growable = bs->growable; - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE); - bs->growable = 1; - ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov); - bs->growable = growable; - - return ret; -} - -static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, - int64_t pos, int size) -{ - BDRVQcowState *s = bs->opaque; - int growable = bs->growable; - int ret; - - BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD); - bs->growable = 1; - ret = bdrv_pread(bs, qcow2_vm_state_offset(s) + pos, buf, size); - bs->growable = growable; - - return ret; -} - -static QEMUOptionParameter qcow2_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_COMPAT_LEVEL, - .type = OPT_STRING, - .help = "Compatibility level (0.10 or 1.1)" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_BACKING_FMT, - .type = OPT_STRING, - .help = "Image format of the base image" - }, - { - .name = BLOCK_OPT_ENCRYPT, - .type = OPT_FLAG, - .help = "Encrypt the image" - }, - { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "qcow2 cluster size", - .value = { .n = DEFAULT_CLUSTER_SIZE }, - }, - { - .name = BLOCK_OPT_PREALLOC, - .type = OPT_STRING, - .help = "Preallocation mode (allowed values: off, metadata)" - }, - { - .name = BLOCK_OPT_LAZY_REFCOUNTS, - .type = OPT_FLAG, - .help = "Postpone refcount updates", - }, - { NULL } -}; - -static BlockDriver bdrv_qcow2 = { - .format_name = "qcow2", - .instance_size = sizeof(BDRVQcowState), - .bdrv_probe = qcow2_probe, - .bdrv_open = qcow2_open, - .bdrv_close = qcow2_close, - .bdrv_reopen_prepare = qcow2_reopen_prepare, - .bdrv_create = qcow2_create, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_co_is_allocated = qcow2_co_is_allocated, - .bdrv_set_key = qcow2_set_key, - .bdrv_make_empty = qcow2_make_empty, - - .bdrv_co_readv = qcow2_co_readv, - .bdrv_co_writev = qcow2_co_writev, - .bdrv_co_flush_to_os = qcow2_co_flush_to_os, - - .bdrv_co_write_zeroes = qcow2_co_write_zeroes, - .bdrv_co_discard = qcow2_co_discard, - .bdrv_truncate = qcow2_truncate, - .bdrv_write_compressed = qcow2_write_compressed, - - .bdrv_snapshot_create = qcow2_snapshot_create, - .bdrv_snapshot_goto = qcow2_snapshot_goto, - .bdrv_snapshot_delete = qcow2_snapshot_delete, - .bdrv_snapshot_list = qcow2_snapshot_list, - .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, - .bdrv_get_info = qcow2_get_info, - - .bdrv_save_vmstate = qcow2_save_vmstate, - .bdrv_load_vmstate = qcow2_load_vmstate, - - .bdrv_change_backing_file = qcow2_change_backing_file, - - .bdrv_invalidate_cache = qcow2_invalidate_cache, - - .create_options = qcow2_create_options, - .bdrv_check = qcow2_check, -}; - -static void bdrv_qcow2_init(void) -{ - bdrv_register(&bdrv_qcow2); -} - -block_init(bdrv_qcow2_init); diff --git a/contrib/qemu/block/qcow2.h b/contrib/qemu/block/qcow2.h deleted file mode 100644 index 3b2d5cda71f..00000000000 --- a/contrib/qemu/block/qcow2.h +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-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. - */ - -#ifndef BLOCK_QCOW2_H -#define BLOCK_QCOW2_H - -#include "qemu/aes.h" -#include "block/coroutine.h" - -//#define DEBUG_ALLOC -//#define DEBUG_ALLOC2 -//#define DEBUG_EXT - -#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) - -#define QCOW_CRYPT_NONE 0 -#define QCOW_CRYPT_AES 1 - -#define QCOW_MAX_CRYPT_CLUSTERS 32 - -/* indicate that the refcount of the referenced cluster is exactly one. */ -#define QCOW_OFLAG_COPIED (1LL << 63) -/* indicate that the cluster is compressed (they never have the copied flag) */ -#define QCOW_OFLAG_COMPRESSED (1LL << 62) -/* The cluster reads as all zeros */ -#define QCOW_OFLAG_ZERO (1LL << 0) - -#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ - -#define MIN_CLUSTER_BITS 9 -#define MAX_CLUSTER_BITS 21 - -#define L2_CACHE_SIZE 16 - -/* Must be at least 4 to cover all cases of refcount table growth */ -#define REFCOUNT_CACHE_SIZE 4 - -#define DEFAULT_CLUSTER_SIZE 65536 - - -#define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts" -#define QCOW2_OPT_DISCARD_REQUEST "pass_discard_request" -#define QCOW2_OPT_DISCARD_SNAPSHOT "pass_discard_snapshot" -#define QCOW2_OPT_DISCARD_OTHER "pass_discard_other" - -typedef struct QCowHeader { - uint32_t magic; - uint32_t version; - uint64_t backing_file_offset; - uint32_t backing_file_size; - uint32_t cluster_bits; - uint64_t size; /* in bytes */ - uint32_t crypt_method; - uint32_t l1_size; /* XXX: save number of clusters instead ? */ - uint64_t l1_table_offset; - uint64_t refcount_table_offset; - uint32_t refcount_table_clusters; - uint32_t nb_snapshots; - uint64_t snapshots_offset; - - /* The following fields are only valid for version >= 3 */ - uint64_t incompatible_features; - uint64_t compatible_features; - uint64_t autoclear_features; - - uint32_t refcount_order; - uint32_t header_length; -} QCowHeader; - -typedef struct QCowSnapshot { - uint64_t l1_table_offset; - uint32_t l1_size; - char *id_str; - char *name; - uint64_t disk_size; - uint64_t vm_state_size; - uint32_t date_sec; - uint32_t date_nsec; - uint64_t vm_clock_nsec; -} QCowSnapshot; - -struct Qcow2Cache; -typedef struct Qcow2Cache Qcow2Cache; - -typedef struct Qcow2UnknownHeaderExtension { - uint32_t magic; - uint32_t len; - QLIST_ENTRY(Qcow2UnknownHeaderExtension) next; - uint8_t data[]; -} Qcow2UnknownHeaderExtension; - -enum { - QCOW2_FEAT_TYPE_INCOMPATIBLE = 0, - QCOW2_FEAT_TYPE_COMPATIBLE = 1, - QCOW2_FEAT_TYPE_AUTOCLEAR = 2, -}; - -/* Incompatible feature bits */ -enum { - QCOW2_INCOMPAT_DIRTY_BITNR = 0, - QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR, - - QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY, -}; - -/* Compatible feature bits */ -enum { - QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR = 0, - QCOW2_COMPAT_LAZY_REFCOUNTS = 1 << QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, - - QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS, -}; - -enum qcow2_discard_type { - QCOW2_DISCARD_NEVER = 0, - QCOW2_DISCARD_ALWAYS, - QCOW2_DISCARD_REQUEST, - QCOW2_DISCARD_SNAPSHOT, - QCOW2_DISCARD_OTHER, - QCOW2_DISCARD_MAX -}; - -typedef struct Qcow2Feature { - uint8_t type; - uint8_t bit; - char name[46]; -} QEMU_PACKED Qcow2Feature; - -typedef struct Qcow2DiscardRegion { - BlockDriverState *bs; - uint64_t offset; - uint64_t bytes; - QTAILQ_ENTRY(Qcow2DiscardRegion) next; -} Qcow2DiscardRegion; - -typedef struct BDRVQcowState { - int cluster_bits; - int cluster_size; - int cluster_sectors; - int l2_bits; - int l2_size; - int l1_size; - int l1_vm_state_index; - int csize_shift; - int csize_mask; - uint64_t cluster_offset_mask; - uint64_t l1_table_offset; - uint64_t *l1_table; - - Qcow2Cache* l2_table_cache; - Qcow2Cache* refcount_block_cache; - - uint8_t *cluster_cache; - uint8_t *cluster_data; - uint64_t cluster_cache_offset; - QLIST_HEAD(QCowClusterAlloc, QCowL2Meta) cluster_allocs; - - uint64_t *refcount_table; - uint64_t refcount_table_offset; - uint32_t refcount_table_size; - int64_t free_cluster_index; - int64_t free_byte_offset; - - CoMutex lock; - - uint32_t crypt_method; /* current crypt method, 0 if no key yet */ - uint32_t crypt_method_header; - AES_KEY aes_encrypt_key; - AES_KEY aes_decrypt_key; - uint64_t snapshots_offset; - int snapshots_size; - int nb_snapshots; - QCowSnapshot *snapshots; - - int flags; - int qcow_version; - bool use_lazy_refcounts; - - bool discard_passthrough[QCOW2_DISCARD_MAX]; - - uint64_t incompatible_features; - uint64_t compatible_features; - uint64_t autoclear_features; - - size_t unknown_header_fields_size; - void* unknown_header_fields; - QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext; - QTAILQ_HEAD (, Qcow2DiscardRegion) discards; - bool cache_discards; -} BDRVQcowState; - -/* XXX: use std qcow open function ? */ -typedef struct QCowCreateState { - int cluster_size; - int cluster_bits; - uint16_t *refcount_block; - uint64_t *refcount_table; - int64_t l1_table_offset; - int64_t refcount_table_offset; - int64_t refcount_block_offset; -} QCowCreateState; - -struct QCowAIOCB; - -typedef struct Qcow2COWRegion { - /** - * Offset of the COW region in bytes from the start of the first cluster - * touched by the request. - */ - uint64_t offset; - - /** Number of sectors to copy */ - int nb_sectors; -} Qcow2COWRegion; - -/** - * Describes an in-flight (part of a) write request that writes to clusters - * that are not referenced in their L2 table yet. - */ -typedef struct QCowL2Meta -{ - /** Guest offset of the first newly allocated cluster */ - uint64_t offset; - - /** Host offset of the first newly allocated cluster */ - uint64_t alloc_offset; - - /** - * Number of sectors from the start of the first allocated cluster to - * the end of the (possibly shortened) request - */ - int nb_available; - - /** Number of newly allocated clusters */ - int nb_clusters; - - /** - * Requests that overlap with this allocation and wait to be restarted - * when the allocating request has completed. - */ - CoQueue dependent_requests; - - /** - * The COW Region between the start of the first allocated cluster and the - * area the guest actually writes to. - */ - Qcow2COWRegion cow_start; - - /** - * The COW Region between the area the guest actually writes to and the - * end of the last allocated cluster. - */ - Qcow2COWRegion cow_end; - - /** Pointer to next L2Meta of the same write request */ - struct QCowL2Meta *next; - - QLIST_ENTRY(QCowL2Meta) next_in_flight; -} QCowL2Meta; - -enum { - QCOW2_CLUSTER_UNALLOCATED, - QCOW2_CLUSTER_NORMAL, - QCOW2_CLUSTER_COMPRESSED, - QCOW2_CLUSTER_ZERO -}; - -#define L1E_OFFSET_MASK 0x00ffffffffffff00ULL -#define L2E_OFFSET_MASK 0x00ffffffffffff00ULL -#define L2E_COMPRESSED_OFFSET_SIZE_MASK 0x3fffffffffffffffULL - -#define REFT_OFFSET_MASK 0xffffffffffffff00ULL - -static inline int64_t start_of_cluster(BDRVQcowState *s, int64_t offset) -{ - return offset & ~(s->cluster_size - 1); -} - -static inline int64_t offset_into_cluster(BDRVQcowState *s, int64_t offset) -{ - return offset & (s->cluster_size - 1); -} - -static inline int size_to_clusters(BDRVQcowState *s, int64_t size) -{ - return (size + (s->cluster_size - 1)) >> s->cluster_bits; -} - -static inline int64_t size_to_l1(BDRVQcowState *s, int64_t size) -{ - int shift = s->cluster_bits + s->l2_bits; - return (size + (1ULL << shift) - 1) >> shift; -} - -static inline int offset_to_l2_index(BDRVQcowState *s, int64_t offset) -{ - return (offset >> s->cluster_bits) & (s->l2_size - 1); -} - -static inline int64_t align_offset(int64_t offset, int n) -{ - offset = (offset + n - 1) & ~(n - 1); - return offset; -} - -static inline int qcow2_get_cluster_type(uint64_t l2_entry) -{ - if (l2_entry & QCOW_OFLAG_COMPRESSED) { - return QCOW2_CLUSTER_COMPRESSED; - } else if (l2_entry & QCOW_OFLAG_ZERO) { - return QCOW2_CLUSTER_ZERO; - } else if (!(l2_entry & L2E_OFFSET_MASK)) { - return QCOW2_CLUSTER_UNALLOCATED; - } else { - return QCOW2_CLUSTER_NORMAL; - } -} - -/* Check whether refcounts are eager or lazy */ -static inline bool qcow2_need_accurate_refcounts(BDRVQcowState *s) -{ - return !(s->incompatible_features & QCOW2_INCOMPAT_DIRTY); -} - -static inline uint64_t l2meta_cow_start(QCowL2Meta *m) -{ - return m->offset + m->cow_start.offset; -} - -static inline uint64_t l2meta_cow_end(QCowL2Meta *m) -{ - return m->offset + m->cow_end.offset - + (m->cow_end.nb_sectors << BDRV_SECTOR_BITS); -} - -// FIXME Need qcow2_ prefix to global functions - -/* qcow2.c functions */ -int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t sector_num, int nb_sectors); - -int qcow2_mark_dirty(BlockDriverState *bs); -int qcow2_update_header(BlockDriverState *bs); - -/* qcow2-refcount.c functions */ -int qcow2_refcount_init(BlockDriverState *bs); -void qcow2_refcount_close(BlockDriverState *bs); - -int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size); -int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, - int nb_clusters); -int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size); -void qcow2_free_clusters(BlockDriverState *bs, - int64_t offset, int64_t size, - enum qcow2_discard_type type); -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, - int nb_clusters, enum qcow2_discard_type type); - -int qcow2_update_snapshot_refcount(BlockDriverState *bs, - int64_t l1_table_offset, int l1_size, int addend); - -int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, - BdrvCheckMode fix); - -void qcow2_process_discards(BlockDriverState *bs, int ret); - -/* qcow2-cluster.c functions */ -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, - bool exact_size); -void qcow2_l2_cache_reset(BlockDriverState *bs); -int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); -void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, int enc, - const AES_KEY *key); - -int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, - int *num, uint64_t *cluster_offset); -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m); -uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, - uint64_t offset, - int compressed_size); - -int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); -int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, - int nb_sectors); -int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors); - -/* qcow2-snapshot.c functions */ -int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); -int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id); -int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); -int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab); -int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name); - -void qcow2_free_snapshots(BlockDriverState *bs); -int qcow2_read_snapshots(BlockDriverState *bs); - -/* qcow2-cache.c functions */ -Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables); -int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c); - -void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table); -int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c); -int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c, - Qcow2Cache *dependency); -void qcow2_cache_depends_on_flush(Qcow2Cache *c); - -int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table); -int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table); -int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); - -#endif diff --git a/contrib/qemu/block/qed-check.c b/contrib/qemu/block/qed-check.c deleted file mode 100644 index b473dcd61f6..00000000000 --- a/contrib/qemu/block/qed-check.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * QEMU Enhanced Disk Format Consistency Check - * - * Copyright IBM, Corp. 2010 - * - * 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 "qed.h" - -typedef struct { - BDRVQEDState *s; - BdrvCheckResult *result; - bool fix; /* whether to fix invalid offsets */ - - uint64_t nclusters; - uint32_t *used_clusters; /* referenced cluster bitmap */ - - QEDRequest request; -} QEDCheck; - -static bool qed_test_bit(uint32_t *bitmap, uint64_t n) { - return !!(bitmap[n / 32] & (1 << (n % 32))); -} - -static void qed_set_bit(uint32_t *bitmap, uint64_t n) { - bitmap[n / 32] |= 1 << (n % 32); -} - -/** - * Set bitmap bits for clusters - * - * @check: Check structure - * @offset: Starting offset in bytes - * @n: Number of clusters - */ -static bool qed_set_used_clusters(QEDCheck *check, uint64_t offset, - unsigned int n) -{ - uint64_t cluster = qed_bytes_to_clusters(check->s, offset); - unsigned int corruptions = 0; - - while (n-- != 0) { - /* Clusters should only be referenced once */ - if (qed_test_bit(check->used_clusters, cluster)) { - corruptions++; - } - - qed_set_bit(check->used_clusters, cluster); - cluster++; - } - - check->result->corruptions += corruptions; - return corruptions == 0; -} - -/** - * Check an L2 table - * - * @ret: Number of invalid cluster offsets - */ -static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table) -{ - BDRVQEDState *s = check->s; - unsigned int i, num_invalid = 0; - uint64_t last_offset = 0; - - for (i = 0; i < s->table_nelems; i++) { - uint64_t offset = table->offsets[i]; - - if (qed_offset_is_unalloc_cluster(offset) || - qed_offset_is_zero_cluster(offset)) { - continue; - } - check->result->bfi.allocated_clusters++; - if (last_offset && (last_offset + s->header.cluster_size != offset)) { - check->result->bfi.fragmented_clusters++; - } - last_offset = offset; - - /* Detect invalid cluster offset */ - if (!qed_check_cluster_offset(s, offset)) { - if (check->fix) { - table->offsets[i] = 0; - check->result->corruptions_fixed++; - } else { - check->result->corruptions++; - } - - num_invalid++; - continue; - } - - qed_set_used_clusters(check, offset, 1); - } - - return num_invalid; -} - -/** - * Descend tables and check each cluster is referenced once only - */ -static int qed_check_l1_table(QEDCheck *check, QEDTable *table) -{ - BDRVQEDState *s = check->s; - unsigned int i, num_invalid_l1 = 0; - int ret, last_error = 0; - - /* Mark L1 table clusters used */ - qed_set_used_clusters(check, s->header.l1_table_offset, - s->header.table_size); - - for (i = 0; i < s->table_nelems; i++) { - unsigned int num_invalid_l2; - uint64_t offset = table->offsets[i]; - - if (qed_offset_is_unalloc_cluster(offset)) { - continue; - } - - /* Detect invalid L2 offset */ - if (!qed_check_table_offset(s, offset)) { - /* Clear invalid offset */ - if (check->fix) { - table->offsets[i] = 0; - check->result->corruptions_fixed++; - } else { - check->result->corruptions++; - } - - num_invalid_l1++; - continue; - } - - if (!qed_set_used_clusters(check, offset, s->header.table_size)) { - continue; /* skip an invalid table */ - } - - ret = qed_read_l2_table_sync(s, &check->request, offset); - if (ret) { - check->result->check_errors++; - last_error = ret; - continue; - } - - num_invalid_l2 = qed_check_l2_table(check, - check->request.l2_table->table); - - /* Write out fixed L2 table */ - if (num_invalid_l2 > 0 && check->fix) { - ret = qed_write_l2_table_sync(s, &check->request, 0, - s->table_nelems, false); - if (ret) { - check->result->check_errors++; - last_error = ret; - continue; - } - } - } - - /* Drop reference to final table */ - qed_unref_l2_cache_entry(check->request.l2_table); - check->request.l2_table = NULL; - - /* Write out fixed L1 table */ - if (num_invalid_l1 > 0 && check->fix) { - ret = qed_write_l1_table_sync(s, 0, s->table_nelems); - if (ret) { - check->result->check_errors++; - last_error = ret; - } - } - - return last_error; -} - -/** - * Check for unreferenced (leaked) clusters - */ -static void qed_check_for_leaks(QEDCheck *check) -{ - BDRVQEDState *s = check->s; - uint64_t i; - - for (i = s->header.header_size; i < check->nclusters; i++) { - if (!qed_test_bit(check->used_clusters, i)) { - check->result->leaks++; - } - } -} - -/** - * Mark an image clean once it passes check or has been repaired - */ -static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result) -{ - /* Skip if there were unfixable corruptions or I/O errors */ - if (result->corruptions > 0 || result->check_errors > 0) { - return; - } - - /* Skip if image is already marked clean */ - if (!(s->header.features & QED_F_NEED_CHECK)) { - return; - } - - /* Ensure fixes reach storage before clearing check bit */ - bdrv_flush(s->bs); - - s->header.features &= ~QED_F_NEED_CHECK; - qed_write_header_sync(s); -} - -int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix) -{ - QEDCheck check = { - .s = s, - .result = result, - .nclusters = qed_bytes_to_clusters(s, s->file_size), - .request = { .l2_table = NULL }, - .fix = fix, - }; - int ret; - - check.used_clusters = g_malloc0(((check.nclusters + 31) / 32) * - sizeof(check.used_clusters[0])); - - check.result->bfi.total_clusters = - (s->header.image_size + s->header.cluster_size - 1) / - s->header.cluster_size; - ret = qed_check_l1_table(&check, s->l1_table); - if (ret == 0) { - /* Only check for leaks if entire image was scanned successfully */ - qed_check_for_leaks(&check); - - if (fix) { - qed_check_mark_clean(s, result); - } - } - - g_free(check.used_clusters); - return ret; -} diff --git a/contrib/qemu/block/qed-cluster.c b/contrib/qemu/block/qed-cluster.c deleted file mode 100644 index f64b2af8f7e..00000000000 --- a/contrib/qemu/block/qed-cluster.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * QEMU Enhanced Disk Format Cluster functions - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> - * Anthony Liguori <aliguori@us.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 "qed.h" - -/** - * Count the number of contiguous data clusters - * - * @s: QED state - * @table: L2 table - * @index: First cluster index - * @n: Maximum number of clusters - * @offset: Set to first cluster offset - * - * This function scans tables for contiguous clusters. A contiguous run of - * clusters may be allocated, unallocated, or zero. - */ -static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s, - QEDTable *table, - unsigned int index, - unsigned int n, - uint64_t *offset) -{ - unsigned int end = MIN(index + n, s->table_nelems); - uint64_t last = table->offsets[index]; - unsigned int i; - - *offset = last; - - for (i = index + 1; i < end; i++) { - if (qed_offset_is_unalloc_cluster(last)) { - /* Counting unallocated clusters */ - if (!qed_offset_is_unalloc_cluster(table->offsets[i])) { - break; - } - } else if (qed_offset_is_zero_cluster(last)) { - /* Counting zero clusters */ - if (!qed_offset_is_zero_cluster(table->offsets[i])) { - break; - } - } else { - /* Counting allocated clusters */ - if (table->offsets[i] != last + s->header.cluster_size) { - break; - } - last = table->offsets[i]; - } - } - return i - index; -} - -typedef struct { - BDRVQEDState *s; - uint64_t pos; - size_t len; - - QEDRequest *request; - - /* User callback */ - QEDFindClusterFunc *cb; - void *opaque; -} QEDFindClusterCB; - -static void qed_find_cluster_cb(void *opaque, int ret) -{ - QEDFindClusterCB *find_cluster_cb = opaque; - BDRVQEDState *s = find_cluster_cb->s; - QEDRequest *request = find_cluster_cb->request; - uint64_t offset = 0; - size_t len = 0; - unsigned int index; - unsigned int n; - - if (ret) { - goto out; - } - - index = qed_l2_index(s, find_cluster_cb->pos); - n = qed_bytes_to_clusters(s, - qed_offset_into_cluster(s, find_cluster_cb->pos) + - find_cluster_cb->len); - n = qed_count_contiguous_clusters(s, request->l2_table->table, - index, n, &offset); - - if (qed_offset_is_unalloc_cluster(offset)) { - ret = QED_CLUSTER_L2; - } else if (qed_offset_is_zero_cluster(offset)) { - ret = QED_CLUSTER_ZERO; - } else if (qed_check_cluster_offset(s, offset)) { - ret = QED_CLUSTER_FOUND; - } else { - ret = -EINVAL; - } - - len = MIN(find_cluster_cb->len, n * s->header.cluster_size - - qed_offset_into_cluster(s, find_cluster_cb->pos)); - -out: - find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len); - g_free(find_cluster_cb); -} - -/** - * Find the offset of a data cluster - * - * @s: QED state - * @request: L2 cache entry - * @pos: Byte position in device - * @len: Number of bytes - * @cb: Completion function - * @opaque: User data for completion function - * - * This function translates a position in the block device to an offset in the - * image file. It invokes the cb completion callback to report back the - * translated offset or unallocated range in the image file. - * - * If the L2 table exists, request->l2_table points to the L2 table cache entry - * and the caller must free the reference when they are finished. The cache - * entry is exposed in this way to avoid callers having to read the L2 table - * again later during request processing. If request->l2_table is non-NULL it - * will be unreferenced before taking on the new cache entry. - */ -void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos, - size_t len, QEDFindClusterFunc *cb, void *opaque) -{ - QEDFindClusterCB *find_cluster_cb; - uint64_t l2_offset; - - /* Limit length to L2 boundary. Requests are broken up at the L2 boundary - * so that a request acts on one L2 table at a time. - */ - len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos); - - l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)]; - if (qed_offset_is_unalloc_cluster(l2_offset)) { - cb(opaque, QED_CLUSTER_L1, 0, len); - return; - } - if (!qed_check_table_offset(s, l2_offset)) { - cb(opaque, -EINVAL, 0, 0); - return; - } - - find_cluster_cb = g_malloc(sizeof(*find_cluster_cb)); - find_cluster_cb->s = s; - find_cluster_cb->pos = pos; - find_cluster_cb->len = len; - find_cluster_cb->cb = cb; - find_cluster_cb->opaque = opaque; - find_cluster_cb->request = request; - - qed_read_l2_table(s, request, l2_offset, - qed_find_cluster_cb, find_cluster_cb); -} diff --git a/contrib/qemu/block/qed-gencb.c b/contrib/qemu/block/qed-gencb.c deleted file mode 100644 index 7d7ac1ffc8e..00000000000 --- a/contrib/qemu/block/qed-gencb.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * QEMU Enhanced Disk Format - * - * Copyright IBM, Corp. 2010 - * - * 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 "qed.h" - -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque) -{ - GenericCB *gencb = g_malloc(len); - gencb->cb = cb; - gencb->opaque = opaque; - return gencb; -} - -void gencb_complete(void *opaque, int ret) -{ - GenericCB *gencb = opaque; - BlockDriverCompletionFunc *cb = gencb->cb; - void *user_opaque = gencb->opaque; - - g_free(gencb); - cb(user_opaque, ret); -} diff --git a/contrib/qemu/block/qed-l2-cache.c b/contrib/qemu/block/qed-l2-cache.c deleted file mode 100644 index e9b2aae44d9..00000000000 --- a/contrib/qemu/block/qed-l2-cache.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * QEMU Enhanced Disk Format L2 Cache - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Anthony Liguori <aliguori@us.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. - * - */ - -/* - * L2 table cache usage is as follows: - * - * An open image has one L2 table cache that is used to avoid accessing the - * image file for recently referenced L2 tables. - * - * Cluster offset lookup translates the logical offset within the block device - * to a cluster offset within the image file. This is done by indexing into - * the L1 and L2 tables which store cluster offsets. It is here where the L2 - * table cache serves up recently referenced L2 tables. - * - * If there is a cache miss, that L2 table is read from the image file and - * committed to the cache. Subsequent accesses to that L2 table will be served - * from the cache until the table is evicted from the cache. - * - * L2 tables are also committed to the cache when new L2 tables are allocated - * in the image file. Since the L2 table cache is write-through, the new L2 - * table is first written out to the image file and then committed to the - * cache. - * - * Multiple I/O requests may be using an L2 table cache entry at any given - * time. That means an entry may be in use across several requests and - * reference counting is needed to free the entry at the correct time. In - * particular, an entry evicted from the cache will only be freed once all - * references are dropped. - * - * An in-flight I/O request will hold a reference to a L2 table cache entry for - * the period during which it needs to access the L2 table. This includes - * cluster offset lookup, L2 table allocation, and L2 table update when a new - * data cluster has been allocated. - * - * An interesting case occurs when two requests need to access an L2 table that - * is not in the cache. Since the operation to read the table from the image - * file takes some time to complete, both requests may see a cache miss and - * start reading the L2 table from the image file. The first to finish will - * commit its L2 table into the cache. When the second tries to commit its - * table will be deleted in favor of the existing cache entry. - */ - -#include "trace.h" -#include "qed.h" - -/* Each L2 holds 2GB so this let's us fully cache a 100GB disk */ -#define MAX_L2_CACHE_SIZE 50 - -/** - * Initialize the L2 cache - */ -void qed_init_l2_cache(L2TableCache *l2_cache) -{ - QTAILQ_INIT(&l2_cache->entries); - l2_cache->n_entries = 0; -} - -/** - * Free the L2 cache - */ -void qed_free_l2_cache(L2TableCache *l2_cache) -{ - CachedL2Table *entry, *next_entry; - - QTAILQ_FOREACH_SAFE(entry, &l2_cache->entries, node, next_entry) { - qemu_vfree(entry->table); - g_free(entry); - } -} - -/** - * Allocate an uninitialized entry from the cache - * - * The returned entry has a reference count of 1 and is owned by the caller. - * The caller must allocate the actual table field for this entry and it must - * be freeable using qemu_vfree(). - */ -CachedL2Table *qed_alloc_l2_cache_entry(L2TableCache *l2_cache) -{ - CachedL2Table *entry; - - entry = g_malloc0(sizeof(*entry)); - entry->ref++; - - trace_qed_alloc_l2_cache_entry(l2_cache, entry); - - return entry; -} - -/** - * Decrease an entry's reference count and free if necessary when the reference - * count drops to zero. - */ -void qed_unref_l2_cache_entry(CachedL2Table *entry) -{ - if (!entry) { - return; - } - - entry->ref--; - trace_qed_unref_l2_cache_entry(entry, entry->ref); - if (entry->ref == 0) { - qemu_vfree(entry->table); - g_free(entry); - } -} - -/** - * Find an entry in the L2 cache. This may return NULL and it's up to the - * caller to satisfy the cache miss. - * - * For a cached entry, this function increases the reference count and returns - * the entry. - */ -CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2_cache, uint64_t offset) -{ - CachedL2Table *entry; - - QTAILQ_FOREACH(entry, &l2_cache->entries, node) { - if (entry->offset == offset) { - trace_qed_find_l2_cache_entry(l2_cache, entry, offset, entry->ref); - entry->ref++; - return entry; - } - } - return NULL; -} - -/** - * Commit an L2 cache entry into the cache. This is meant to be used as part of - * the process to satisfy a cache miss. A caller would allocate an entry which - * is not actually in the L2 cache and then once the entry was valid and - * present on disk, the entry can be committed into the cache. - * - * Since the cache is write-through, it's important that this function is not - * called until the entry is present on disk and the L1 has been updated to - * point to the entry. - * - * N.B. This function steals a reference to the l2_table from the caller so the - * caller must obtain a new reference by issuing a call to - * qed_find_l2_cache_entry(). - */ -void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table) -{ - CachedL2Table *entry; - - entry = qed_find_l2_cache_entry(l2_cache, l2_table->offset); - if (entry) { - qed_unref_l2_cache_entry(entry); - qed_unref_l2_cache_entry(l2_table); - return; - } - - /* Evict an unused cache entry so we have space. If all entries are in use - * we can grow the cache temporarily and we try to shrink back down later. - */ - if (l2_cache->n_entries >= MAX_L2_CACHE_SIZE) { - CachedL2Table *next; - QTAILQ_FOREACH_SAFE(entry, &l2_cache->entries, node, next) { - if (entry->ref > 1) { - continue; - } - - QTAILQ_REMOVE(&l2_cache->entries, entry, node); - l2_cache->n_entries--; - qed_unref_l2_cache_entry(entry); - - /* Stop evicting when we've shrunk back to max size */ - if (l2_cache->n_entries < MAX_L2_CACHE_SIZE) { - break; - } - } - } - - l2_cache->n_entries++; - QTAILQ_INSERT_TAIL(&l2_cache->entries, l2_table, node); -} diff --git a/contrib/qemu/block/qed-table.c b/contrib/qemu/block/qed-table.c deleted file mode 100644 index 76d2dcccf81..00000000000 --- a/contrib/qemu/block/qed-table.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * QEMU Enhanced Disk Format Table I/O - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> - * Anthony Liguori <aliguori@us.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 "trace.h" -#include "qemu/sockets.h" /* for EINPROGRESS on Windows */ -#include "qed.h" - -typedef struct { - GenericCB gencb; - BDRVQEDState *s; - QEDTable *table; - - struct iovec iov; - QEMUIOVector qiov; -} QEDReadTableCB; - -static void qed_read_table_cb(void *opaque, int ret) -{ - QEDReadTableCB *read_table_cb = opaque; - QEDTable *table = read_table_cb->table; - int noffsets = read_table_cb->qiov.size / sizeof(uint64_t); - int i; - - /* Handle I/O error */ - if (ret) { - goto out; - } - - /* Byteswap offsets */ - for (i = 0; i < noffsets; i++) { - table->offsets[i] = le64_to_cpu(table->offsets[i]); - } - -out: - /* Completion */ - trace_qed_read_table_cb(read_table_cb->s, read_table_cb->table, ret); - gencb_complete(&read_table_cb->gencb, ret); -} - -static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, - BlockDriverCompletionFunc *cb, void *opaque) -{ - QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb), - cb, opaque); - QEMUIOVector *qiov = &read_table_cb->qiov; - - trace_qed_read_table(s, offset, table); - - read_table_cb->s = s; - read_table_cb->table = table; - read_table_cb->iov.iov_base = table->offsets, - read_table_cb->iov.iov_len = s->header.cluster_size * s->header.table_size, - - qemu_iovec_init_external(qiov, &read_table_cb->iov, 1); - bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov, - qiov->size / BDRV_SECTOR_SIZE, - qed_read_table_cb, read_table_cb); -} - -typedef struct { - GenericCB gencb; - BDRVQEDState *s; - QEDTable *orig_table; - QEDTable *table; - bool flush; /* flush after write? */ - - struct iovec iov; - QEMUIOVector qiov; -} QEDWriteTableCB; - -static void qed_write_table_cb(void *opaque, int ret) -{ - QEDWriteTableCB *write_table_cb = opaque; - - trace_qed_write_table_cb(write_table_cb->s, - write_table_cb->orig_table, - write_table_cb->flush, - ret); - - if (ret) { - goto out; - } - - if (write_table_cb->flush) { - /* We still need to flush first */ - write_table_cb->flush = false; - bdrv_aio_flush(write_table_cb->s->bs, qed_write_table_cb, - write_table_cb); - return; - } - -out: - qemu_vfree(write_table_cb->table); - gencb_complete(&write_table_cb->gencb, ret); -} - -/** - * Write out an updated part or all of a table - * - * @s: QED state - * @offset: Offset of table in image file, in bytes - * @table: Table - * @index: Index of first element - * @n: Number of elements - * @flush: Whether or not to sync to disk - * @cb: Completion function - * @opaque: Argument for completion function - */ -static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, - unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque) -{ - QEDWriteTableCB *write_table_cb; - unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1; - unsigned int start, end, i; - size_t len_bytes; - - trace_qed_write_table(s, offset, table, index, n); - - /* Calculate indices of the first and one after last elements */ - start = index & ~sector_mask; - end = (index + n + sector_mask) & ~sector_mask; - - len_bytes = (end - start) * sizeof(uint64_t); - - write_table_cb = gencb_alloc(sizeof(*write_table_cb), cb, opaque); - write_table_cb->s = s; - write_table_cb->orig_table = table; - write_table_cb->flush = flush; - write_table_cb->table = qemu_blockalign(s->bs, len_bytes); - write_table_cb->iov.iov_base = write_table_cb->table->offsets; - write_table_cb->iov.iov_len = len_bytes; - qemu_iovec_init_external(&write_table_cb->qiov, &write_table_cb->iov, 1); - - /* Byteswap table */ - for (i = start; i < end; i++) { - uint64_t le_offset = cpu_to_le64(table->offsets[i]); - write_table_cb->table->offsets[i - start] = le_offset; - } - - /* Adjust for offset into table */ - offset += start * sizeof(uint64_t); - - bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE, - &write_table_cb->qiov, - write_table_cb->qiov.size / BDRV_SECTOR_SIZE, - qed_write_table_cb, write_table_cb); -} - -/** - * Propagate return value from async callback - */ -static void qed_sync_cb(void *opaque, int ret) -{ - *(int *)opaque = ret; -} - -int qed_read_l1_table_sync(BDRVQEDState *s) -{ - int ret = -EINPROGRESS; - - qed_read_table(s, s->header.l1_table_offset, - s->l1_table, qed_sync_cb, &ret); - while (ret == -EINPROGRESS) { - qemu_aio_wait(); - } - - return ret; -} - -void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n, - BlockDriverCompletionFunc *cb, void *opaque) -{ - BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE); - qed_write_table(s, s->header.l1_table_offset, - s->l1_table, index, n, false, cb, opaque); -} - -int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, - unsigned int n) -{ - int ret = -EINPROGRESS; - - qed_write_l1_table(s, index, n, qed_sync_cb, &ret); - while (ret == -EINPROGRESS) { - qemu_aio_wait(); - } - - return ret; -} - -typedef struct { - GenericCB gencb; - BDRVQEDState *s; - uint64_t l2_offset; - QEDRequest *request; -} QEDReadL2TableCB; - -static void qed_read_l2_table_cb(void *opaque, int ret) -{ - QEDReadL2TableCB *read_l2_table_cb = opaque; - QEDRequest *request = read_l2_table_cb->request; - BDRVQEDState *s = read_l2_table_cb->s; - CachedL2Table *l2_table = request->l2_table; - uint64_t l2_offset = read_l2_table_cb->l2_offset; - - if (ret) { - /* can't trust loaded L2 table anymore */ - qed_unref_l2_cache_entry(l2_table); - request->l2_table = NULL; - } else { - l2_table->offset = l2_offset; - - qed_commit_l2_cache_entry(&s->l2_cache, l2_table); - - /* This is guaranteed to succeed because we just committed the entry - * to the cache. - */ - request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset); - assert(request->l2_table != NULL); - } - - gencb_complete(&read_l2_table_cb->gencb, ret); -} - -void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset, - BlockDriverCompletionFunc *cb, void *opaque) -{ - QEDReadL2TableCB *read_l2_table_cb; - - qed_unref_l2_cache_entry(request->l2_table); - - /* Check for cached L2 entry */ - request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, offset); - if (request->l2_table) { - cb(opaque, 0); - return; - } - - request->l2_table = qed_alloc_l2_cache_entry(&s->l2_cache); - request->l2_table->table = qed_alloc_table(s); - - read_l2_table_cb = gencb_alloc(sizeof(*read_l2_table_cb), cb, opaque); - read_l2_table_cb->s = s; - read_l2_table_cb->l2_offset = offset; - read_l2_table_cb->request = request; - - BLKDBG_EVENT(s->bs->file, BLKDBG_L2_LOAD); - qed_read_table(s, offset, request->l2_table->table, - qed_read_l2_table_cb, read_l2_table_cb); -} - -int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset) -{ - int ret = -EINPROGRESS; - - qed_read_l2_table(s, request, offset, qed_sync_cb, &ret); - while (ret == -EINPROGRESS) { - qemu_aio_wait(); - } - - return ret; -} - -void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque) -{ - BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE); - qed_write_table(s, request->l2_table->offset, - request->l2_table->table, index, n, flush, cb, opaque); -} - -int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush) -{ - int ret = -EINPROGRESS; - - qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret); - while (ret == -EINPROGRESS) { - qemu_aio_wait(); - } - - return ret; -} diff --git a/contrib/qemu/block/qed.c b/contrib/qemu/block/qed.c deleted file mode 100644 index f767b0528ce..00000000000 --- a/contrib/qemu/block/qed.c +++ /dev/null @@ -1,1596 +0,0 @@ -/* - * QEMU Enhanced Disk Format - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> - * Anthony Liguori <aliguori@us.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/timer.h" -#include "trace.h" -#include "qed.h" -#include "qapi/qmp/qerror.h" -#include "migration/migration.h" - -static void qed_aio_cancel(BlockDriverAIOCB *blockacb) -{ - QEDAIOCB *acb = (QEDAIOCB *)blockacb; - bool finished = false; - - /* Wait for the request to finish */ - acb->finished = &finished; - while (!finished) { - qemu_aio_wait(); - } -} - -static const AIOCBInfo qed_aiocb_info = { - .aiocb_size = sizeof(QEDAIOCB), - .cancel = qed_aio_cancel, -}; - -static int bdrv_qed_probe(const uint8_t *buf, int buf_size, - const char *filename) -{ - const QEDHeader *header = (const QEDHeader *)buf; - - if (buf_size < sizeof(*header)) { - return 0; - } - if (le32_to_cpu(header->magic) != QED_MAGIC) { - return 0; - } - return 100; -} - -/** - * Check whether an image format is raw - * - * @fmt: Backing file format, may be NULL - */ -static bool qed_fmt_is_raw(const char *fmt) -{ - return fmt && strcmp(fmt, "raw") == 0; -} - -static void qed_header_le_to_cpu(const QEDHeader *le, QEDHeader *cpu) -{ - cpu->magic = le32_to_cpu(le->magic); - cpu->cluster_size = le32_to_cpu(le->cluster_size); - cpu->table_size = le32_to_cpu(le->table_size); - cpu->header_size = le32_to_cpu(le->header_size); - cpu->features = le64_to_cpu(le->features); - cpu->compat_features = le64_to_cpu(le->compat_features); - cpu->autoclear_features = le64_to_cpu(le->autoclear_features); - cpu->l1_table_offset = le64_to_cpu(le->l1_table_offset); - cpu->image_size = le64_to_cpu(le->image_size); - cpu->backing_filename_offset = le32_to_cpu(le->backing_filename_offset); - cpu->backing_filename_size = le32_to_cpu(le->backing_filename_size); -} - -static void qed_header_cpu_to_le(const QEDHeader *cpu, QEDHeader *le) -{ - le->magic = cpu_to_le32(cpu->magic); - le->cluster_size = cpu_to_le32(cpu->cluster_size); - le->table_size = cpu_to_le32(cpu->table_size); - le->header_size = cpu_to_le32(cpu->header_size); - le->features = cpu_to_le64(cpu->features); - le->compat_features = cpu_to_le64(cpu->compat_features); - le->autoclear_features = cpu_to_le64(cpu->autoclear_features); - le->l1_table_offset = cpu_to_le64(cpu->l1_table_offset); - le->image_size = cpu_to_le64(cpu->image_size); - le->backing_filename_offset = cpu_to_le32(cpu->backing_filename_offset); - le->backing_filename_size = cpu_to_le32(cpu->backing_filename_size); -} - -int qed_write_header_sync(BDRVQEDState *s) -{ - QEDHeader le; - int ret; - - qed_header_cpu_to_le(&s->header, &le); - ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le)); - if (ret != sizeof(le)) { - return ret; - } - return 0; -} - -typedef struct { - GenericCB gencb; - BDRVQEDState *s; - struct iovec iov; - QEMUIOVector qiov; - int nsectors; - uint8_t *buf; -} QEDWriteHeaderCB; - -static void qed_write_header_cb(void *opaque, int ret) -{ - QEDWriteHeaderCB *write_header_cb = opaque; - - qemu_vfree(write_header_cb->buf); - gencb_complete(write_header_cb, ret); -} - -static void qed_write_header_read_cb(void *opaque, int ret) -{ - QEDWriteHeaderCB *write_header_cb = opaque; - BDRVQEDState *s = write_header_cb->s; - - if (ret) { - qed_write_header_cb(write_header_cb, ret); - return; - } - - /* Update header */ - qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf); - - bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov, - write_header_cb->nsectors, qed_write_header_cb, - write_header_cb); -} - -/** - * Update header in-place (does not rewrite backing filename or other strings) - * - * This function only updates known header fields in-place and does not affect - * extra data after the QED header. - */ -static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb, - void *opaque) -{ - /* We must write full sectors for O_DIRECT but cannot necessarily generate - * the data following the header if an unrecognized compat feature is - * active. Therefore, first read the sectors containing the header, update - * them, and write back. - */ - - int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) / - BDRV_SECTOR_SIZE; - size_t len = nsectors * BDRV_SECTOR_SIZE; - QEDWriteHeaderCB *write_header_cb = gencb_alloc(sizeof(*write_header_cb), - cb, opaque); - - write_header_cb->s = s; - write_header_cb->nsectors = nsectors; - write_header_cb->buf = qemu_blockalign(s->bs, len); - write_header_cb->iov.iov_base = write_header_cb->buf; - write_header_cb->iov.iov_len = len; - qemu_iovec_init_external(&write_header_cb->qiov, &write_header_cb->iov, 1); - - bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors, - qed_write_header_read_cb, write_header_cb); -} - -static uint64_t qed_max_image_size(uint32_t cluster_size, uint32_t table_size) -{ - uint64_t table_entries; - uint64_t l2_size; - - table_entries = (table_size * cluster_size) / sizeof(uint64_t); - l2_size = table_entries * cluster_size; - - return l2_size * table_entries; -} - -static bool qed_is_cluster_size_valid(uint32_t cluster_size) -{ - if (cluster_size < QED_MIN_CLUSTER_SIZE || - cluster_size > QED_MAX_CLUSTER_SIZE) { - return false; - } - if (cluster_size & (cluster_size - 1)) { - return false; /* not power of 2 */ - } - return true; -} - -static bool qed_is_table_size_valid(uint32_t table_size) -{ - if (table_size < QED_MIN_TABLE_SIZE || - table_size > QED_MAX_TABLE_SIZE) { - return false; - } - if (table_size & (table_size - 1)) { - return false; /* not power of 2 */ - } - return true; -} - -static bool qed_is_image_size_valid(uint64_t image_size, uint32_t cluster_size, - uint32_t table_size) -{ - if (image_size % BDRV_SECTOR_SIZE != 0) { - return false; /* not multiple of sector size */ - } - if (image_size > qed_max_image_size(cluster_size, table_size)) { - return false; /* image is too large */ - } - return true; -} - -/** - * Read a string of known length from the image file - * - * @file: Image file - * @offset: File offset to start of string, in bytes - * @n: String length in bytes - * @buf: Destination buffer - * @buflen: Destination buffer length in bytes - * @ret: 0 on success, -errno on failure - * - * The string is NUL-terminated. - */ -static int qed_read_string(BlockDriverState *file, uint64_t offset, size_t n, - char *buf, size_t buflen) -{ - int ret; - if (n >= buflen) { - return -EINVAL; - } - ret = bdrv_pread(file, offset, buf, n); - if (ret < 0) { - return ret; - } - buf[n] = '\0'; - return 0; -} - -/** - * Allocate new clusters - * - * @s: QED state - * @n: Number of contiguous clusters to allocate - * @ret: Offset of first allocated cluster - * - * This function only produces the offset where the new clusters should be - * written. It updates BDRVQEDState but does not make any changes to the image - * file. - */ -static uint64_t qed_alloc_clusters(BDRVQEDState *s, unsigned int n) -{ - uint64_t offset = s->file_size; - s->file_size += n * s->header.cluster_size; - return offset; -} - -QEDTable *qed_alloc_table(BDRVQEDState *s) -{ - /* Honor O_DIRECT memory alignment requirements */ - return qemu_blockalign(s->bs, - s->header.cluster_size * s->header.table_size); -} - -/** - * Allocate a new zeroed L2 table - */ -static CachedL2Table *qed_new_l2_table(BDRVQEDState *s) -{ - CachedL2Table *l2_table = qed_alloc_l2_cache_entry(&s->l2_cache); - - l2_table->table = qed_alloc_table(s); - l2_table->offset = qed_alloc_clusters(s, s->header.table_size); - - memset(l2_table->table->offsets, 0, - s->header.cluster_size * s->header.table_size); - return l2_table; -} - -static void qed_aio_next_io(void *opaque, int ret); - -static void qed_plug_allocating_write_reqs(BDRVQEDState *s) -{ - assert(!s->allocating_write_reqs_plugged); - - s->allocating_write_reqs_plugged = true; -} - -static void qed_unplug_allocating_write_reqs(BDRVQEDState *s) -{ - QEDAIOCB *acb; - - assert(s->allocating_write_reqs_plugged); - - s->allocating_write_reqs_plugged = false; - - acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs); - if (acb) { - qed_aio_next_io(acb, 0); - } -} - -static void qed_finish_clear_need_check(void *opaque, int ret) -{ - /* Do nothing */ -} - -static void qed_flush_after_clear_need_check(void *opaque, int ret) -{ - BDRVQEDState *s = opaque; - - bdrv_aio_flush(s->bs, qed_finish_clear_need_check, s); - - /* No need to wait until flush completes */ - qed_unplug_allocating_write_reqs(s); -} - -static void qed_clear_need_check(void *opaque, int ret) -{ - BDRVQEDState *s = opaque; - - if (ret) { - qed_unplug_allocating_write_reqs(s); - return; - } - - s->header.features &= ~QED_F_NEED_CHECK; - qed_write_header(s, qed_flush_after_clear_need_check, s); -} - -static void qed_need_check_timer_cb(void *opaque) -{ - BDRVQEDState *s = opaque; - - /* The timer should only fire when allocating writes have drained */ - assert(!QSIMPLEQ_FIRST(&s->allocating_write_reqs)); - - trace_qed_need_check_timer_cb(s); - - qed_plug_allocating_write_reqs(s); - - /* Ensure writes are on disk before clearing flag */ - bdrv_aio_flush(s->bs, qed_clear_need_check, s); -} - -static void qed_start_need_check_timer(BDRVQEDState *s) -{ - trace_qed_start_need_check_timer(s); - - /* Use vm_clock so we don't alter the image file while suspended for - * migration. - */ - qemu_mod_timer(s->need_check_timer, qemu_get_clock_ns(vm_clock) + - get_ticks_per_sec() * QED_NEED_CHECK_TIMEOUT); -} - -/* It's okay to call this multiple times or when no timer is started */ -static void qed_cancel_need_check_timer(BDRVQEDState *s) -{ - trace_qed_cancel_need_check_timer(s); - qemu_del_timer(s->need_check_timer); -} - -static void bdrv_qed_rebind(BlockDriverState *bs) -{ - BDRVQEDState *s = bs->opaque; - s->bs = bs; -} - -static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags) -{ - BDRVQEDState *s = bs->opaque; - QEDHeader le_header; - int64_t file_size; - int ret; - - s->bs = bs; - QSIMPLEQ_INIT(&s->allocating_write_reqs); - - ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header)); - if (ret < 0) { - return ret; - } - qed_header_le_to_cpu(&le_header, &s->header); - - if (s->header.magic != QED_MAGIC) { - return -EMEDIUMTYPE; - } - if (s->header.features & ~QED_FEATURE_MASK) { - /* image uses unsupported feature bits */ - char buf[64]; - snprintf(buf, sizeof(buf), "%" PRIx64, - s->header.features & ~QED_FEATURE_MASK); - qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "QED", buf); - return -ENOTSUP; - } - if (!qed_is_cluster_size_valid(s->header.cluster_size)) { - return -EINVAL; - } - - /* Round down file size to the last cluster */ - file_size = bdrv_getlength(bs->file); - if (file_size < 0) { - return file_size; - } - s->file_size = qed_start_of_cluster(s, file_size); - - if (!qed_is_table_size_valid(s->header.table_size)) { - return -EINVAL; - } - if (!qed_is_image_size_valid(s->header.image_size, - s->header.cluster_size, - s->header.table_size)) { - return -EINVAL; - } - if (!qed_check_table_offset(s, s->header.l1_table_offset)) { - return -EINVAL; - } - - s->table_nelems = (s->header.cluster_size * s->header.table_size) / - sizeof(uint64_t); - s->l2_shift = ffs(s->header.cluster_size) - 1; - s->l2_mask = s->table_nelems - 1; - s->l1_shift = s->l2_shift + ffs(s->table_nelems) - 1; - - if ((s->header.features & QED_F_BACKING_FILE)) { - if ((uint64_t)s->header.backing_filename_offset + - s->header.backing_filename_size > - s->header.cluster_size * s->header.header_size) { - return -EINVAL; - } - - ret = qed_read_string(bs->file, s->header.backing_filename_offset, - s->header.backing_filename_size, bs->backing_file, - sizeof(bs->backing_file)); - if (ret < 0) { - return ret; - } - - if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) { - pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw"); - } - } - - /* Reset unknown autoclear feature bits. This is a backwards - * compatibility mechanism that allows images to be opened by older - * programs, which "knock out" unknown feature bits. When an image is - * opened by a newer program again it can detect that the autoclear - * feature is no longer valid. - */ - if ((s->header.autoclear_features & ~QED_AUTOCLEAR_FEATURE_MASK) != 0 && - !bdrv_is_read_only(bs->file) && !(flags & BDRV_O_INCOMING)) { - s->header.autoclear_features &= QED_AUTOCLEAR_FEATURE_MASK; - - ret = qed_write_header_sync(s); - if (ret) { - return ret; - } - - /* From here on only known autoclear feature bits are valid */ - bdrv_flush(bs->file); - } - - s->l1_table = qed_alloc_table(s); - qed_init_l2_cache(&s->l2_cache); - - ret = qed_read_l1_table_sync(s); - if (ret) { - goto out; - } - - /* If image was not closed cleanly, check consistency */ - if (!(flags & BDRV_O_CHECK) && (s->header.features & QED_F_NEED_CHECK)) { - /* Read-only images cannot be fixed. There is no risk of corruption - * since write operations are not possible. Therefore, allow - * potentially inconsistent images to be opened read-only. This can - * aid data recovery from an otherwise inconsistent image. - */ - if (!bdrv_is_read_only(bs->file) && - !(flags & BDRV_O_INCOMING)) { - BdrvCheckResult result = {0}; - - ret = qed_check(s, &result, true); - if (ret) { - goto out; - } - } - } - - s->need_check_timer = qemu_new_timer_ns(vm_clock, - qed_need_check_timer_cb, s); - -out: - if (ret) { - qed_free_l2_cache(&s->l2_cache); - qemu_vfree(s->l1_table); - } - return ret; -} - -/* We have nothing to do for QED reopen, stubs just return - * success */ -static int bdrv_qed_reopen_prepare(BDRVReopenState *state, - BlockReopenQueue *queue, Error **errp) -{ - return 0; -} - -static void bdrv_qed_close(BlockDriverState *bs) -{ - BDRVQEDState *s = bs->opaque; - - qed_cancel_need_check_timer(s); - qemu_free_timer(s->need_check_timer); - - /* Ensure writes reach stable storage */ - bdrv_flush(bs->file); - - /* Clean shutdown, no check required on next open */ - if (s->header.features & QED_F_NEED_CHECK) { - s->header.features &= ~QED_F_NEED_CHECK; - qed_write_header_sync(s); - } - - qed_free_l2_cache(&s->l2_cache); - qemu_vfree(s->l1_table); -} - -static int qed_create(const char *filename, uint32_t cluster_size, - uint64_t image_size, uint32_t table_size, - const char *backing_file, const char *backing_fmt) -{ - QEDHeader header = { - .magic = QED_MAGIC, - .cluster_size = cluster_size, - .table_size = table_size, - .header_size = 1, - .features = 0, - .compat_features = 0, - .l1_table_offset = cluster_size, - .image_size = image_size, - }; - QEDHeader le_header; - uint8_t *l1_table = NULL; - size_t l1_size = header.cluster_size * header.table_size; - int ret = 0; - BlockDriverState *bs = NULL; - - ret = bdrv_create_file(filename, NULL); - if (ret < 0) { - return ret; - } - - ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB); - if (ret < 0) { - return ret; - } - - /* File must start empty and grow, check truncate is supported */ - ret = bdrv_truncate(bs, 0); - if (ret < 0) { - goto out; - } - - if (backing_file) { - header.features |= QED_F_BACKING_FILE; - header.backing_filename_offset = sizeof(le_header); - header.backing_filename_size = strlen(backing_file); - - if (qed_fmt_is_raw(backing_fmt)) { - header.features |= QED_F_BACKING_FORMAT_NO_PROBE; - } - } - - qed_header_cpu_to_le(&header, &le_header); - ret = bdrv_pwrite(bs, 0, &le_header, sizeof(le_header)); - if (ret < 0) { - goto out; - } - ret = bdrv_pwrite(bs, sizeof(le_header), backing_file, - header.backing_filename_size); - if (ret < 0) { - goto out; - } - - l1_table = g_malloc0(l1_size); - ret = bdrv_pwrite(bs, header.l1_table_offset, l1_table, l1_size); - if (ret < 0) { - goto out; - } - - ret = 0; /* success */ -out: - g_free(l1_table); - bdrv_delete(bs); - return ret; -} - -static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options) -{ - uint64_t image_size = 0; - uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE; - uint32_t table_size = QED_DEFAULT_TABLE_SIZE; - const char *backing_file = NULL; - const char *backing_fmt = NULL; - - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - image_size = options->value.n; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { - backing_fmt = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - cluster_size = options->value.n; - } - } else if (!strcmp(options->name, BLOCK_OPT_TABLE_SIZE)) { - if (options->value.n) { - table_size = options->value.n; - } - } - options++; - } - - if (!qed_is_cluster_size_valid(cluster_size)) { - fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n", - QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE); - return -EINVAL; - } - if (!qed_is_table_size_valid(table_size)) { - fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n", - QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE); - return -EINVAL; - } - if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) { - fprintf(stderr, "QED image size must be a non-zero multiple of " - "cluster size and less than %" PRIu64 " bytes\n", - qed_max_image_size(cluster_size, table_size)); - return -EINVAL; - } - - return qed_create(filename, cluster_size, image_size, table_size, - backing_file, backing_fmt); -} - -typedef struct { - Coroutine *co; - int is_allocated; - int *pnum; -} QEDIsAllocatedCB; - -static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len) -{ - QEDIsAllocatedCB *cb = opaque; - *cb->pnum = len / BDRV_SECTOR_SIZE; - cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO); - if (cb->co) { - qemu_coroutine_enter(cb->co, NULL); - } -} - -static int coroutine_fn bdrv_qed_co_is_allocated(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, int *pnum) -{ - BDRVQEDState *s = bs->opaque; - uint64_t pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE; - size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE; - QEDIsAllocatedCB cb = { - .is_allocated = -1, - .pnum = pnum, - }; - QEDRequest request = { .l2_table = NULL }; - - qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb); - - /* Now sleep if the callback wasn't invoked immediately */ - while (cb.is_allocated == -1) { - cb.co = qemu_coroutine_self(); - qemu_coroutine_yield(); - } - - qed_unref_l2_cache_entry(request.l2_table); - - return cb.is_allocated; -} - -static int bdrv_qed_make_empty(BlockDriverState *bs) -{ - return -ENOTSUP; -} - -static BDRVQEDState *acb_to_s(QEDAIOCB *acb) -{ - return acb->common.bs->opaque; -} - -/** - * Read from the backing file or zero-fill if no backing file - * - * @s: QED state - * @pos: Byte position in device - * @qiov: Destination I/O vector - * @cb: Completion function - * @opaque: User data for completion function - * - * This function reads qiov->size bytes starting at pos from the backing file. - * If there is no backing file then zeroes are read. - */ -static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos, - QEMUIOVector *qiov, - BlockDriverCompletionFunc *cb, void *opaque) -{ - uint64_t backing_length = 0; - size_t size; - - /* If there is a backing file, get its length. Treat the absence of a - * backing file like a zero length backing file. - */ - if (s->bs->backing_hd) { - int64_t l = bdrv_getlength(s->bs->backing_hd); - if (l < 0) { - cb(opaque, l); - return; - } - backing_length = l; - } - - /* Zero all sectors if reading beyond the end of the backing file */ - if (pos >= backing_length || - pos + qiov->size > backing_length) { - qemu_iovec_memset(qiov, 0, 0, qiov->size); - } - - /* Complete now if there are no backing file sectors to read */ - if (pos >= backing_length) { - cb(opaque, 0); - return; - } - - /* If the read straddles the end of the backing file, shorten it */ - size = MIN((uint64_t)backing_length - pos, qiov->size); - - BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); - bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE, - qiov, size / BDRV_SECTOR_SIZE, cb, opaque); -} - -typedef struct { - GenericCB gencb; - BDRVQEDState *s; - QEMUIOVector qiov; - struct iovec iov; - uint64_t offset; -} CopyFromBackingFileCB; - -static void qed_copy_from_backing_file_cb(void *opaque, int ret) -{ - CopyFromBackingFileCB *copy_cb = opaque; - qemu_vfree(copy_cb->iov.iov_base); - gencb_complete(©_cb->gencb, ret); -} - -static void qed_copy_from_backing_file_write(void *opaque, int ret) -{ - CopyFromBackingFileCB *copy_cb = opaque; - BDRVQEDState *s = copy_cb->s; - - if (ret) { - qed_copy_from_backing_file_cb(copy_cb, ret); - return; - } - - BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE); - bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE, - ©_cb->qiov, copy_cb->qiov.size / BDRV_SECTOR_SIZE, - qed_copy_from_backing_file_cb, copy_cb); -} - -/** - * Copy data from backing file into the image - * - * @s: QED state - * @pos: Byte position in device - * @len: Number of bytes - * @offset: Byte offset in image file - * @cb: Completion function - * @opaque: User data for completion function - */ -static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, - uint64_t len, uint64_t offset, - BlockDriverCompletionFunc *cb, - void *opaque) -{ - CopyFromBackingFileCB *copy_cb; - - /* Skip copy entirely if there is no work to do */ - if (len == 0) { - cb(opaque, 0); - return; - } - - copy_cb = gencb_alloc(sizeof(*copy_cb), cb, opaque); - copy_cb->s = s; - copy_cb->offset = offset; - copy_cb->iov.iov_base = qemu_blockalign(s->bs, len); - copy_cb->iov.iov_len = len; - qemu_iovec_init_external(©_cb->qiov, ©_cb->iov, 1); - - qed_read_backing_file(s, pos, ©_cb->qiov, - qed_copy_from_backing_file_write, copy_cb); -} - -/** - * Link one or more contiguous clusters into a table - * - * @s: QED state - * @table: L2 table - * @index: First cluster index - * @n: Number of contiguous clusters - * @cluster: First cluster offset - * - * The cluster offset may be an allocated byte offset in the image file, the - * zero cluster marker, or the unallocated cluster marker. - */ -static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index, - unsigned int n, uint64_t cluster) -{ - int i; - for (i = index; i < index + n; i++) { - table->offsets[i] = cluster; - if (!qed_offset_is_unalloc_cluster(cluster) && - !qed_offset_is_zero_cluster(cluster)) { - cluster += s->header.cluster_size; - } - } -} - -static void qed_aio_complete_bh(void *opaque) -{ - QEDAIOCB *acb = opaque; - BlockDriverCompletionFunc *cb = acb->common.cb; - void *user_opaque = acb->common.opaque; - int ret = acb->bh_ret; - bool *finished = acb->finished; - - qemu_bh_delete(acb->bh); - qemu_aio_release(acb); - - /* Invoke callback */ - cb(user_opaque, ret); - - /* Signal cancel completion */ - if (finished) { - *finished = true; - } -} - -static void qed_aio_complete(QEDAIOCB *acb, int ret) -{ - BDRVQEDState *s = acb_to_s(acb); - - trace_qed_aio_complete(s, acb, ret); - - /* Free resources */ - qemu_iovec_destroy(&acb->cur_qiov); - qed_unref_l2_cache_entry(acb->request.l2_table); - - /* Free the buffer we may have allocated for zero writes */ - if (acb->flags & QED_AIOCB_ZERO) { - qemu_vfree(acb->qiov->iov[0].iov_base); - acb->qiov->iov[0].iov_base = NULL; - } - - /* Arrange for a bh to invoke the completion function */ - acb->bh_ret = ret; - acb->bh = qemu_bh_new(qed_aio_complete_bh, acb); - qemu_bh_schedule(acb->bh); - - /* Start next allocating write request waiting behind this one. Note that - * requests enqueue themselves when they first hit an unallocated cluster - * but they wait until the entire request is finished before waking up the - * next request in the queue. This ensures that we don't cycle through - * requests multiple times but rather finish one at a time completely. - */ - if (acb == QSIMPLEQ_FIRST(&s->allocating_write_reqs)) { - QSIMPLEQ_REMOVE_HEAD(&s->allocating_write_reqs, next); - acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs); - if (acb) { - qed_aio_next_io(acb, 0); - } else if (s->header.features & QED_F_NEED_CHECK) { - qed_start_need_check_timer(s); - } - } -} - -/** - * Commit the current L2 table to the cache - */ -static void qed_commit_l2_update(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - CachedL2Table *l2_table = acb->request.l2_table; - uint64_t l2_offset = l2_table->offset; - - qed_commit_l2_cache_entry(&s->l2_cache, l2_table); - - /* This is guaranteed to succeed because we just committed the entry to the - * cache. - */ - acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset); - assert(acb->request.l2_table != NULL); - - qed_aio_next_io(opaque, ret); -} - -/** - * Update L1 table with new L2 table offset and write it out - */ -static void qed_aio_write_l1_update(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - int index; - - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - index = qed_l1_index(s, acb->cur_pos); - s->l1_table->offsets[index] = acb->request.l2_table->offset; - - qed_write_l1_table(s, index, 1, qed_commit_l2_update, acb); -} - -/** - * Update L2 table with new cluster offsets and write them out - */ -static void qed_aio_write_l2_update(QEDAIOCB *acb, int ret, uint64_t offset) -{ - BDRVQEDState *s = acb_to_s(acb); - bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1; - int index; - - if (ret) { - goto err; - } - - if (need_alloc) { - qed_unref_l2_cache_entry(acb->request.l2_table); - acb->request.l2_table = qed_new_l2_table(s); - } - - index = qed_l2_index(s, acb->cur_pos); - qed_update_l2_table(s, acb->request.l2_table->table, index, acb->cur_nclusters, - offset); - - if (need_alloc) { - /* Write out the whole new L2 table */ - qed_write_l2_table(s, &acb->request, 0, s->table_nelems, true, - qed_aio_write_l1_update, acb); - } else { - /* Write out only the updated part of the L2 table */ - qed_write_l2_table(s, &acb->request, index, acb->cur_nclusters, false, - qed_aio_next_io, acb); - } - return; - -err: - qed_aio_complete(acb, ret); -} - -static void qed_aio_write_l2_update_cb(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - qed_aio_write_l2_update(acb, ret, acb->cur_cluster); -} - -/** - * Flush new data clusters before updating the L2 table - * - * This flush is necessary when a backing file is in use. A crash during an - * allocating write could result in empty clusters in the image. If the write - * only touched a subregion of the cluster, then backing image sectors have - * been lost in the untouched region. The solution is to flush after writing a - * new data cluster and before updating the L2 table. - */ -static void qed_aio_write_flush_before_l2_update(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - - if (!bdrv_aio_flush(s->bs->file, qed_aio_write_l2_update_cb, opaque)) { - qed_aio_complete(acb, -EIO); - } -} - -/** - * Write data to the image file - */ -static void qed_aio_write_main(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - uint64_t offset = acb->cur_cluster + - qed_offset_into_cluster(s, acb->cur_pos); - BlockDriverCompletionFunc *next_fn; - - trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size); - - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - if (acb->find_cluster_ret == QED_CLUSTER_FOUND) { - next_fn = qed_aio_next_io; - } else { - if (s->bs->backing_hd) { - next_fn = qed_aio_write_flush_before_l2_update; - } else { - next_fn = qed_aio_write_l2_update_cb; - } - } - - BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO); - bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE, - &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE, - next_fn, acb); -} - -/** - * Populate back untouched region of new data cluster - */ -static void qed_aio_write_postfill(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - uint64_t start = acb->cur_pos + acb->cur_qiov.size; - uint64_t len = - qed_start_of_cluster(s, start + s->header.cluster_size - 1) - start; - uint64_t offset = acb->cur_cluster + - qed_offset_into_cluster(s, acb->cur_pos) + - acb->cur_qiov.size; - - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - trace_qed_aio_write_postfill(s, acb, start, len, offset); - qed_copy_from_backing_file(s, start, len, offset, - qed_aio_write_main, acb); -} - -/** - * Populate front untouched region of new data cluster - */ -static void qed_aio_write_prefill(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - uint64_t start = qed_start_of_cluster(s, acb->cur_pos); - uint64_t len = qed_offset_into_cluster(s, acb->cur_pos); - - trace_qed_aio_write_prefill(s, acb, start, len, acb->cur_cluster); - qed_copy_from_backing_file(s, start, len, acb->cur_cluster, - qed_aio_write_postfill, acb); -} - -/** - * Check if the QED_F_NEED_CHECK bit should be set during allocating write - */ -static bool qed_should_set_need_check(BDRVQEDState *s) -{ - /* The flush before L2 update path ensures consistency */ - if (s->bs->backing_hd) { - return false; - } - - return !(s->header.features & QED_F_NEED_CHECK); -} - -static void qed_aio_write_zero_cluster(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - qed_aio_write_l2_update(acb, 0, 1); -} - -/** - * Write new data cluster - * - * @acb: Write request - * @len: Length in bytes - * - * This path is taken when writing to previously unallocated clusters. - */ -static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len) -{ - BDRVQEDState *s = acb_to_s(acb); - BlockDriverCompletionFunc *cb; - - /* Cancel timer when the first allocating request comes in */ - if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) { - qed_cancel_need_check_timer(s); - } - - /* Freeze this request if another allocating write is in progress */ - if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) { - QSIMPLEQ_INSERT_TAIL(&s->allocating_write_reqs, acb, next); - } - if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs) || - s->allocating_write_reqs_plugged) { - return; /* wait for existing request to finish */ - } - - acb->cur_nclusters = qed_bytes_to_clusters(s, - qed_offset_into_cluster(s, acb->cur_pos) + len); - qemu_iovec_concat(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len); - - if (acb->flags & QED_AIOCB_ZERO) { - /* Skip ahead if the clusters are already zero */ - if (acb->find_cluster_ret == QED_CLUSTER_ZERO) { - qed_aio_next_io(acb, 0); - return; - } - - cb = qed_aio_write_zero_cluster; - } else { - cb = qed_aio_write_prefill; - acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters); - } - - if (qed_should_set_need_check(s)) { - s->header.features |= QED_F_NEED_CHECK; - qed_write_header(s, cb, acb); - } else { - cb(acb, 0); - } -} - -/** - * Write data cluster in place - * - * @acb: Write request - * @offset: Cluster offset in bytes - * @len: Length in bytes - * - * This path is taken when writing to already allocated clusters. - */ -static void qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len) -{ - /* Allocate buffer for zero writes */ - if (acb->flags & QED_AIOCB_ZERO) { - struct iovec *iov = acb->qiov->iov; - - if (!iov->iov_base) { - iov->iov_base = qemu_blockalign(acb->common.bs, iov->iov_len); - memset(iov->iov_base, 0, iov->iov_len); - } - } - - /* Calculate the I/O vector */ - acb->cur_cluster = offset; - qemu_iovec_concat(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len); - - /* Do the actual write */ - qed_aio_write_main(acb, 0); -} - -/** - * Write data cluster - * - * @opaque: Write request - * @ret: QED_CLUSTER_FOUND, QED_CLUSTER_L2, QED_CLUSTER_L1, - * or -errno - * @offset: Cluster offset in bytes - * @len: Length in bytes - * - * Callback from qed_find_cluster(). - */ -static void qed_aio_write_data(void *opaque, int ret, - uint64_t offset, size_t len) -{ - QEDAIOCB *acb = opaque; - - trace_qed_aio_write_data(acb_to_s(acb), acb, ret, offset, len); - - acb->find_cluster_ret = ret; - - switch (ret) { - case QED_CLUSTER_FOUND: - qed_aio_write_inplace(acb, offset, len); - break; - - case QED_CLUSTER_L2: - case QED_CLUSTER_L1: - case QED_CLUSTER_ZERO: - qed_aio_write_alloc(acb, len); - break; - - default: - qed_aio_complete(acb, ret); - break; - } -} - -/** - * Read data cluster - * - * @opaque: Read request - * @ret: QED_CLUSTER_FOUND, QED_CLUSTER_L2, QED_CLUSTER_L1, - * or -errno - * @offset: Cluster offset in bytes - * @len: Length in bytes - * - * Callback from qed_find_cluster(). - */ -static void qed_aio_read_data(void *opaque, int ret, - uint64_t offset, size_t len) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - BlockDriverState *bs = acb->common.bs; - - /* Adjust offset into cluster */ - offset += qed_offset_into_cluster(s, acb->cur_pos); - - trace_qed_aio_read_data(s, acb, ret, offset, len); - - if (ret < 0) { - goto err; - } - - qemu_iovec_concat(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len); - - /* Handle zero cluster and backing file reads */ - if (ret == QED_CLUSTER_ZERO) { - qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size); - qed_aio_next_io(acb, 0); - return; - } else if (ret != QED_CLUSTER_FOUND) { - qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov, - qed_aio_next_io, acb); - return; - } - - BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE, - &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE, - qed_aio_next_io, acb); - return; - -err: - qed_aio_complete(acb, ret); -} - -/** - * Begin next I/O or complete the request - */ -static void qed_aio_next_io(void *opaque, int ret) -{ - QEDAIOCB *acb = opaque; - BDRVQEDState *s = acb_to_s(acb); - QEDFindClusterFunc *io_fn = (acb->flags & QED_AIOCB_WRITE) ? - qed_aio_write_data : qed_aio_read_data; - - trace_qed_aio_next_io(s, acb, ret, acb->cur_pos + acb->cur_qiov.size); - - /* Handle I/O error */ - if (ret) { - qed_aio_complete(acb, ret); - return; - } - - acb->qiov_offset += acb->cur_qiov.size; - acb->cur_pos += acb->cur_qiov.size; - qemu_iovec_reset(&acb->cur_qiov); - - /* Complete request */ - if (acb->cur_pos >= acb->end_pos) { - qed_aio_complete(acb, 0); - return; - } - - /* Find next cluster and start I/O */ - qed_find_cluster(s, &acb->request, - acb->cur_pos, acb->end_pos - acb->cur_pos, - io_fn, acb); -} - -static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, int flags) -{ - QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque); - - trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors, - opaque, flags); - - acb->flags = flags; - acb->finished = NULL; - acb->qiov = qiov; - acb->qiov_offset = 0; - acb->cur_pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE; - acb->end_pos = acb->cur_pos + nb_sectors * BDRV_SECTOR_SIZE; - acb->request.l2_table = NULL; - qemu_iovec_init(&acb->cur_qiov, qiov->niov); - - /* Start request */ - qed_aio_next_io(acb, 0); - return &acb->common; -} - -static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) -{ - return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); -} - -static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) -{ - return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, - opaque, QED_AIOCB_WRITE); -} - -typedef struct { - Coroutine *co; - int ret; - bool done; -} QEDWriteZeroesCB; - -static void coroutine_fn qed_co_write_zeroes_cb(void *opaque, int ret) -{ - QEDWriteZeroesCB *cb = opaque; - - cb->done = true; - cb->ret = ret; - if (cb->co) { - qemu_coroutine_enter(cb->co, NULL); - } -} - -static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors) -{ - BlockDriverAIOCB *blockacb; - BDRVQEDState *s = bs->opaque; - QEDWriteZeroesCB cb = { .done = false }; - QEMUIOVector qiov; - struct iovec iov; - - /* Refuse if there are untouched backing file sectors */ - if (bs->backing_hd) { - if (qed_offset_into_cluster(s, sector_num * BDRV_SECTOR_SIZE) != 0) { - return -ENOTSUP; - } - if (qed_offset_into_cluster(s, nb_sectors * BDRV_SECTOR_SIZE) != 0) { - return -ENOTSUP; - } - } - - /* Zero writes start without an I/O buffer. If a buffer becomes necessary - * then it will be allocated during request processing. - */ - iov.iov_base = NULL, - iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE, - - qemu_iovec_init_external(&qiov, &iov, 1); - blockacb = qed_aio_setup(bs, sector_num, &qiov, nb_sectors, - qed_co_write_zeroes_cb, &cb, - QED_AIOCB_WRITE | QED_AIOCB_ZERO); - if (!blockacb) { - return -EIO; - } - if (!cb.done) { - cb.co = qemu_coroutine_self(); - qemu_coroutine_yield(); - } - assert(cb.done); - return cb.ret; -} - -static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset) -{ - BDRVQEDState *s = bs->opaque; - uint64_t old_image_size; - int ret; - - if (!qed_is_image_size_valid(offset, s->header.cluster_size, - s->header.table_size)) { - return -EINVAL; - } - - /* Shrinking is currently not supported */ - if ((uint64_t)offset < s->header.image_size) { - return -ENOTSUP; - } - - old_image_size = s->header.image_size; - s->header.image_size = offset; - ret = qed_write_header_sync(s); - if (ret < 0) { - s->header.image_size = old_image_size; - } - return ret; -} - -static int64_t bdrv_qed_getlength(BlockDriverState *bs) -{ - BDRVQEDState *s = bs->opaque; - return s->header.image_size; -} - -static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) -{ - BDRVQEDState *s = bs->opaque; - - memset(bdi, 0, sizeof(*bdi)); - bdi->cluster_size = s->header.cluster_size; - bdi->is_dirty = s->header.features & QED_F_NEED_CHECK; - return 0; -} - -static int bdrv_qed_change_backing_file(BlockDriverState *bs, - const char *backing_file, - const char *backing_fmt) -{ - BDRVQEDState *s = bs->opaque; - QEDHeader new_header, le_header; - void *buffer; - size_t buffer_len, backing_file_len; - int ret; - - /* Refuse to set backing filename if unknown compat feature bits are - * active. If the image uses an unknown compat feature then we may not - * know the layout of data following the header structure and cannot safely - * add a new string. - */ - if (backing_file && (s->header.compat_features & - ~QED_COMPAT_FEATURE_MASK)) { - return -ENOTSUP; - } - - memcpy(&new_header, &s->header, sizeof(new_header)); - - new_header.features &= ~(QED_F_BACKING_FILE | - QED_F_BACKING_FORMAT_NO_PROBE); - - /* Adjust feature flags */ - if (backing_file) { - new_header.features |= QED_F_BACKING_FILE; - - if (qed_fmt_is_raw(backing_fmt)) { - new_header.features |= QED_F_BACKING_FORMAT_NO_PROBE; - } - } - - /* Calculate new header size */ - backing_file_len = 0; - - if (backing_file) { - backing_file_len = strlen(backing_file); - } - - buffer_len = sizeof(new_header); - new_header.backing_filename_offset = buffer_len; - new_header.backing_filename_size = backing_file_len; - buffer_len += backing_file_len; - - /* Make sure we can rewrite header without failing */ - if (buffer_len > new_header.header_size * new_header.cluster_size) { - return -ENOSPC; - } - - /* Prepare new header */ - buffer = g_malloc(buffer_len); - - qed_header_cpu_to_le(&new_header, &le_header); - memcpy(buffer, &le_header, sizeof(le_header)); - buffer_len = sizeof(le_header); - - if (backing_file) { - memcpy(buffer + buffer_len, backing_file, backing_file_len); - buffer_len += backing_file_len; - } - - /* Write new header */ - ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len); - g_free(buffer); - if (ret == 0) { - memcpy(&s->header, &new_header, sizeof(new_header)); - } - return ret; -} - -static void bdrv_qed_invalidate_cache(BlockDriverState *bs) -{ - BDRVQEDState *s = bs->opaque; - - bdrv_qed_close(bs); - memset(s, 0, sizeof(BDRVQEDState)); - bdrv_qed_open(bs, NULL, bs->open_flags); -} - -static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, - BdrvCheckMode fix) -{ - BDRVQEDState *s = bs->opaque; - - return qed_check(s, result, !!fix); -} - -static QEMUOptionParameter qed_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size (in bytes)" - }, { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, { - .name = BLOCK_OPT_BACKING_FMT, - .type = OPT_STRING, - .help = "Image format of the base image" - }, { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "Cluster size (in bytes)", - .value = { .n = QED_DEFAULT_CLUSTER_SIZE }, - }, { - .name = BLOCK_OPT_TABLE_SIZE, - .type = OPT_SIZE, - .help = "L1/L2 table size (in clusters)" - }, - { /* end of list */ } -}; - -static BlockDriver bdrv_qed = { - .format_name = "qed", - .instance_size = sizeof(BDRVQEDState), - .create_options = qed_create_options, - - .bdrv_probe = bdrv_qed_probe, - .bdrv_rebind = bdrv_qed_rebind, - .bdrv_open = bdrv_qed_open, - .bdrv_close = bdrv_qed_close, - .bdrv_reopen_prepare = bdrv_qed_reopen_prepare, - .bdrv_create = bdrv_qed_create, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_co_is_allocated = bdrv_qed_co_is_allocated, - .bdrv_make_empty = bdrv_qed_make_empty, - .bdrv_aio_readv = bdrv_qed_aio_readv, - .bdrv_aio_writev = bdrv_qed_aio_writev, - .bdrv_co_write_zeroes = bdrv_qed_co_write_zeroes, - .bdrv_truncate = bdrv_qed_truncate, - .bdrv_getlength = bdrv_qed_getlength, - .bdrv_get_info = bdrv_qed_get_info, - .bdrv_change_backing_file = bdrv_qed_change_backing_file, - .bdrv_invalidate_cache = bdrv_qed_invalidate_cache, - .bdrv_check = bdrv_qed_check, -}; - -static void bdrv_qed_init(void) -{ - bdrv_register(&bdrv_qed); -} - -block_init(bdrv_qed_init); diff --git a/contrib/qemu/block/qed.h b/contrib/qemu/block/qed.h deleted file mode 100644 index 2b4ddedf313..00000000000 --- a/contrib/qemu/block/qed.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * QEMU Enhanced Disk Format - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> - * Anthony Liguori <aliguori@us.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. - * - */ - -#ifndef BLOCK_QED_H -#define BLOCK_QED_H - -#include "block/block_int.h" - -/* The layout of a QED file is as follows: - * - * +--------+----------+----------+----------+-----+ - * | header | L1 table | cluster0 | cluster1 | ... | - * +--------+----------+----------+----------+-----+ - * - * There is a 2-level pagetable for cluster allocation: - * - * +----------+ - * | L1 table | - * +----------+ - * ,------' | '------. - * +----------+ | +----------+ - * | L2 table | ... | L2 table | - * +----------+ +----------+ - * ,------' | '------. - * +----------+ | +----------+ - * | Data | ... | Data | - * +----------+ +----------+ - * - * The L1 table is fixed size and always present. L2 tables are allocated on - * demand. The L1 table size determines the maximum possible image size; it - * can be influenced using the cluster_size and table_size values. - * - * All fields are little-endian on disk. - */ - -enum { - QED_MAGIC = 'Q' | 'E' << 8 | 'D' << 16 | '\0' << 24, - - /* The image supports a backing file */ - QED_F_BACKING_FILE = 0x01, - - /* The image needs a consistency check before use */ - QED_F_NEED_CHECK = 0x02, - - /* The backing file format must not be probed, treat as raw image */ - QED_F_BACKING_FORMAT_NO_PROBE = 0x04, - - /* Feature bits must be used when the on-disk format changes */ - QED_FEATURE_MASK = QED_F_BACKING_FILE | /* supported feature bits */ - QED_F_NEED_CHECK | - QED_F_BACKING_FORMAT_NO_PROBE, - QED_COMPAT_FEATURE_MASK = 0, /* supported compat feature bits */ - QED_AUTOCLEAR_FEATURE_MASK = 0, /* supported autoclear feature bits */ - - /* Data is stored in groups of sectors called clusters. Cluster size must - * be large to avoid keeping too much metadata. I/O requests that have - * sub-cluster size will require read-modify-write. - */ - QED_MIN_CLUSTER_SIZE = 4 * 1024, /* in bytes */ - QED_MAX_CLUSTER_SIZE = 64 * 1024 * 1024, - QED_DEFAULT_CLUSTER_SIZE = 64 * 1024, - - /* Allocated clusters are tracked using a 2-level pagetable. Table size is - * a multiple of clusters so large maximum image sizes can be supported - * without jacking up the cluster size too much. - */ - QED_MIN_TABLE_SIZE = 1, /* in clusters */ - QED_MAX_TABLE_SIZE = 16, - QED_DEFAULT_TABLE_SIZE = 4, - - /* Delay to flush and clean image after last allocating write completes */ - QED_NEED_CHECK_TIMEOUT = 5, /* in seconds */ -}; - -typedef struct { - uint32_t magic; /* QED\0 */ - - uint32_t cluster_size; /* in bytes */ - uint32_t table_size; /* for L1 and L2 tables, in clusters */ - uint32_t header_size; /* in clusters */ - - uint64_t features; /* format feature bits */ - uint64_t compat_features; /* compatible feature bits */ - uint64_t autoclear_features; /* self-resetting feature bits */ - - uint64_t l1_table_offset; /* in bytes */ - uint64_t image_size; /* total logical image size, in bytes */ - - /* if (features & QED_F_BACKING_FILE) */ - uint32_t backing_filename_offset; /* in bytes from start of header */ - uint32_t backing_filename_size; /* in bytes */ -} QEDHeader; - -typedef struct { - uint64_t offsets[0]; /* in bytes */ -} QEDTable; - -/* The L2 cache is a simple write-through cache for L2 structures */ -typedef struct CachedL2Table { - QEDTable *table; - uint64_t offset; /* offset=0 indicates an invalidate entry */ - QTAILQ_ENTRY(CachedL2Table) node; - int ref; -} CachedL2Table; - -typedef struct { - QTAILQ_HEAD(, CachedL2Table) entries; - unsigned int n_entries; -} L2TableCache; - -typedef struct QEDRequest { - CachedL2Table *l2_table; -} QEDRequest; - -enum { - QED_AIOCB_WRITE = 0x0001, /* read or write? */ - QED_AIOCB_ZERO = 0x0002, /* zero write, used with QED_AIOCB_WRITE */ -}; - -typedef struct QEDAIOCB { - BlockDriverAIOCB common; - QEMUBH *bh; - int bh_ret; /* final return status for completion bh */ - QSIMPLEQ_ENTRY(QEDAIOCB) next; /* next request */ - int flags; /* QED_AIOCB_* bits ORed together */ - bool *finished; /* signal for cancel completion */ - uint64_t end_pos; /* request end on block device, in bytes */ - - /* User scatter-gather list */ - QEMUIOVector *qiov; - size_t qiov_offset; /* byte count already processed */ - - /* Current cluster scatter-gather list */ - QEMUIOVector cur_qiov; - uint64_t cur_pos; /* position on block device, in bytes */ - uint64_t cur_cluster; /* cluster offset in image file */ - unsigned int cur_nclusters; /* number of clusters being accessed */ - int find_cluster_ret; /* used for L1/L2 update */ - - QEDRequest request; -} QEDAIOCB; - -typedef struct { - BlockDriverState *bs; /* device */ - uint64_t file_size; /* length of image file, in bytes */ - - QEDHeader header; /* always cpu-endian */ - QEDTable *l1_table; - L2TableCache l2_cache; /* l2 table cache */ - uint32_t table_nelems; - uint32_t l1_shift; - uint32_t l2_shift; - uint32_t l2_mask; - - /* Allocating write request queue */ - QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs; - bool allocating_write_reqs_plugged; - - /* Periodic flush and clear need check flag */ - QEMUTimer *need_check_timer; -} BDRVQEDState; - -enum { - QED_CLUSTER_FOUND, /* cluster found */ - QED_CLUSTER_ZERO, /* zero cluster found */ - QED_CLUSTER_L2, /* cluster missing in L2 */ - QED_CLUSTER_L1, /* cluster missing in L1 */ -}; - -/** - * qed_find_cluster() completion callback - * - * @opaque: User data for completion callback - * @ret: QED_CLUSTER_FOUND Success - * QED_CLUSTER_L2 Data cluster unallocated in L2 - * QED_CLUSTER_L1 L2 unallocated in L1 - * -errno POSIX error occurred - * @offset: Data cluster offset - * @len: Contiguous bytes starting from cluster offset - * - * This function is invoked when qed_find_cluster() completes. - * - * On success ret is QED_CLUSTER_FOUND and offset/len are a contiguous range - * in the image file. - * - * On failure ret is QED_CLUSTER_L2 or QED_CLUSTER_L1 for missing L2 or L1 - * table offset, respectively. len is number of contiguous unallocated bytes. - */ -typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t len); - -/** - * Generic callback for chaining async callbacks - */ -typedef struct { - BlockDriverCompletionFunc *cb; - void *opaque; -} GenericCB; - -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque); -void gencb_complete(void *opaque, int ret); - -/** - * Header functions - */ -int qed_write_header_sync(BDRVQEDState *s); - -/** - * L2 cache functions - */ -void qed_init_l2_cache(L2TableCache *l2_cache); -void qed_free_l2_cache(L2TableCache *l2_cache); -CachedL2Table *qed_alloc_l2_cache_entry(L2TableCache *l2_cache); -void qed_unref_l2_cache_entry(CachedL2Table *entry); -CachedL2Table *qed_find_l2_cache_entry(L2TableCache *l2_cache, uint64_t offset); -void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table); - -/** - * Table I/O functions - */ -int qed_read_l1_table_sync(BDRVQEDState *s); -void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n, - BlockDriverCompletionFunc *cb, void *opaque); -int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, - unsigned int n); -int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - uint64_t offset); -void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset, - BlockDriverCompletionFunc *cb, void *opaque); -void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque); -int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, bool flush); - -/** - * Cluster functions - */ -void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos, - size_t len, QEDFindClusterFunc *cb, void *opaque); - -/** - * Consistency check - */ -int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); - -QEDTable *qed_alloc_table(BDRVQEDState *s); - -/** - * Round down to the start of a cluster - */ -static inline uint64_t qed_start_of_cluster(BDRVQEDState *s, uint64_t offset) -{ - return offset & ~(uint64_t)(s->header.cluster_size - 1); -} - -static inline uint64_t qed_offset_into_cluster(BDRVQEDState *s, uint64_t offset) -{ - return offset & (s->header.cluster_size - 1); -} - -static inline uint64_t qed_bytes_to_clusters(BDRVQEDState *s, uint64_t bytes) -{ - return qed_start_of_cluster(s, bytes + (s->header.cluster_size - 1)) / - (s->header.cluster_size - 1); -} - -static inline unsigned int qed_l1_index(BDRVQEDState *s, uint64_t pos) -{ - return pos >> s->l1_shift; -} - -static inline unsigned int qed_l2_index(BDRVQEDState *s, uint64_t pos) -{ - return (pos >> s->l2_shift) & s->l2_mask; -} - -/** - * Test if a cluster offset is valid - */ -static inline bool qed_check_cluster_offset(BDRVQEDState *s, uint64_t offset) -{ - uint64_t header_size = (uint64_t)s->header.header_size * - s->header.cluster_size; - - if (offset & (s->header.cluster_size - 1)) { - return false; - } - return offset >= header_size && offset < s->file_size; -} - -/** - * Test if a table offset is valid - */ -static inline bool qed_check_table_offset(BDRVQEDState *s, uint64_t offset) -{ - uint64_t end_offset = offset + (s->header.table_size - 1) * - s->header.cluster_size; - - /* Overflow check */ - if (end_offset <= offset) { - return false; - } - - return qed_check_cluster_offset(s, offset) && - qed_check_cluster_offset(s, end_offset); -} - -static inline bool qed_offset_is_cluster_aligned(BDRVQEDState *s, - uint64_t offset) -{ - if (qed_offset_into_cluster(s, offset)) { - return false; - } - return true; -} - -static inline bool qed_offset_is_unalloc_cluster(uint64_t offset) -{ - if (offset == 0) { - return true; - } - return false; -} - -static inline bool qed_offset_is_zero_cluster(uint64_t offset) -{ - if (offset == 1) { - return true; - } - return false; -} - -#endif /* BLOCK_QED_H */ diff --git a/contrib/qemu/block/snapshot.c b/contrib/qemu/block/snapshot.c deleted file mode 100644 index 6c6d9deea1f..00000000000 --- a/contrib/qemu/block/snapshot.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Block layer snapshot related functions - * - * 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 "block/snapshot.h" -#include "block/block_int.h" - -int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, - const char *name) -{ - QEMUSnapshotInfo *sn_tab, *sn; - int nb_sns, i, ret; - - ret = -ENOENT; - nb_sns = bdrv_snapshot_list(bs, &sn_tab); - if (nb_sns < 0) { - return ret; - } - for (i = 0; i < nb_sns; i++) { - sn = &sn_tab[i]; - if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) { - *sn_info = *sn; - ret = 0; - break; - } - } - g_free(sn_tab); - return ret; -} - -int bdrv_can_snapshot(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { - return 0; - } - - if (!drv->bdrv_snapshot_create) { - if (bs->file != NULL) { - return bdrv_can_snapshot(bs->file); - } - return 0; - } - - return 1; -} - -int bdrv_snapshot_create(BlockDriverState *bs, - QEMUSnapshotInfo *sn_info) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (drv->bdrv_snapshot_create) { - return drv->bdrv_snapshot_create(bs, sn_info); - } - if (bs->file) { - return bdrv_snapshot_create(bs->file, sn_info); - } - return -ENOTSUP; -} - -int bdrv_snapshot_goto(BlockDriverState *bs, - const char *snapshot_id) -{ - BlockDriver *drv = bs->drv; - int ret, open_ret; - - if (!drv) { - return -ENOMEDIUM; - } - if (drv->bdrv_snapshot_goto) { - return drv->bdrv_snapshot_goto(bs, snapshot_id); - } - - if (bs->file) { - drv->bdrv_close(bs); - ret = bdrv_snapshot_goto(bs->file, snapshot_id); - open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); - if (open_ret < 0) { - bdrv_delete(bs->file); - bs->drv = NULL; - return open_ret; - } - return ret; - } - - return -ENOTSUP; -} - -int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (drv->bdrv_snapshot_delete) { - return drv->bdrv_snapshot_delete(bs, snapshot_id); - } - if (bs->file) { - return bdrv_snapshot_delete(bs->file, snapshot_id); - } - return -ENOTSUP; -} - -int bdrv_snapshot_list(BlockDriverState *bs, - QEMUSnapshotInfo **psn_info) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (drv->bdrv_snapshot_list) { - return drv->bdrv_snapshot_list(bs, psn_info); - } - if (bs->file) { - return bdrv_snapshot_list(bs->file, psn_info); - } - return -ENOTSUP; -} - -int bdrv_snapshot_load_tmp(BlockDriverState *bs, - const char *snapshot_name) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (!bs->read_only) { - return -EINVAL; - } - if (drv->bdrv_snapshot_load_tmp) { - return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); - } - return -ENOTSUP; -} diff --git a/contrib/qemu/config-host.h b/contrib/qemu/config-host.h deleted file mode 100644 index 6b5c8da1243..00000000000 --- a/contrib/qemu/config-host.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Automatically generated by create_config - do not modify */ -#define CONFIG_QEMU_CONFDIR "/usr/local/etc/qemu" -#define CONFIG_QEMU_DATADIR "/usr/local/share/qemu" -#define CONFIG_QEMU_DOCDIR "/usr/local/share/doc/qemu" -#define CONFIG_QEMU_LOCALSTATEDIR "/usr/local/var" -#define CONFIG_QEMU_HELPERDIR "/usr/local/libexec" -#define CONFIG_QEMU_LOCALEDIR "/usr/local/share/locale" -#define HOST_X86_64 1 -#define CONFIG_QEMU_LDST_OPTIMIZATION 1 -#define CONFIG_POSIX 1 -#define CONFIG_LINUX 1 -#define CONFIG_SLIRP 1 -#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd" -#define CONFIG_AUDIO_DRIVERS \ - &oss_audio_driver,\ - -#define CONFIG_OSS 1 -#define CONFIG_BDRV_RW_WHITELIST\ - NULL -#define CONFIG_BDRV_RO_WHITELIST\ - NULL -#define CONFIG_VNC 1 -#define CONFIG_VNC_TLS 1 -#define CONFIG_VNC_SASL 1 -#define CONFIG_VNC_WS 1 -#define CONFIG_FNMATCH 1 -#define CONFIG_UUID 1 -#define CONFIG_XFS 1 -#define QEMU_VERSION "1.5.50" -#define QEMU_PKGVERSION "" -#define CONFIG_CURSES 1 -#define CONFIG_UTIMENSAT 1 -#define CONFIG_PIPE2 1 -#define CONFIG_ACCEPT4 1 -#define CONFIG_SPLICE 1 -#define CONFIG_EVENTFD 1 -#define CONFIG_FALLOCATE 1 -#define CONFIG_FALLOCATE_PUNCH_HOLE 1 -#define CONFIG_SYNC_FILE_RANGE 1 -#define CONFIG_FIEMAP 1 -#define CONFIG_DUP3 1 -#define CONFIG_EPOLL 1 -#define CONFIG_EPOLL_CREATE1 1 -#define CONFIG_EPOLL_PWAIT 1 -#define CONFIG_SENDFILE 1 -#define CONFIG_INOTIFY 1 -#define CONFIG_INOTIFY1 1 -#define CONFIG_BYTESWAP_H 1 -#define CONFIG_CURL 1 -#define CONFIG_LINUX_AIO 1 -#define CONFIG_ATTR 1 -#define CONFIG_VHOST_SCSI 1 -#define CONFIG_IOVEC 1 -#define CONFIG_PREADV 1 -#define CONFIG_FDT 1 -#define CONFIG_SIGNALFD 1 -#define CONFIG_FDATASYNC 1 -#define CONFIG_MADVISE 1 -#define CONFIG_POSIX_MADVISE 1 -#define CONFIG_SIGEV_THREAD_ID 1 -#define CONFIG_UNAME_RELEASE "" -#define CONFIG_QOM_CAST_DEBUG 1 -#define CONFIG_COROUTINE_BACKEND ucontext -#define CONFIG_OPEN_BY_HANDLE 1 -#define CONFIG_LINUX_MAGIC_H 1 -#define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1 -#define CONFIG_HAS_ENVIRON 1 -#define CONFIG_CPUID_H 1 -#define CONFIG_VIRTIO_BLK_DATA_PLANE $(CONFIG_VIRTIO) -#define CONFIG_TRACE_NOP 1 -#define CONFIG_TRACE_FILE trace -#define CONFIG_TRACE_DEFAULT 1 diff --git a/contrib/qemu/coroutine-ucontext.c b/contrib/qemu/coroutine-ucontext.c deleted file mode 100644 index 4bf2cde279b..00000000000 --- a/contrib/qemu/coroutine-ucontext.c +++ /dev/null @@ -1,225 +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 <stdlib.h> -#include <setjmp.h> -#include <stdint.h> -#include <pthread.h> -#include <ucontext.h> -#include "qemu-common.h" -#include "block/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 - */ -typedef struct { - /** Currently executing coroutine */ - Coroutine *current; - - /** The default coroutine */ - CoroutineUContext leader; -} CoroutineThreadState; - -static pthread_key_t thread_state_key; - -/* - * 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 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(); - } -} - -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); -} - -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/contrib/qemu/include/block/aio.h b/contrib/qemu/include/block/aio.h deleted file mode 100644 index 183679374fa..00000000000 --- a/contrib/qemu/include/block/aio.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * QEMU aio implementation - * - * 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. - * - */ - -#ifndef QEMU_AIO_H -#define QEMU_AIO_H - -#include "qemu-common.h" -#include "qemu/queue.h" -#include "qemu/event_notifier.h" - -typedef struct BlockDriverAIOCB BlockDriverAIOCB; -typedef void BlockDriverCompletionFunc(void *opaque, int ret); - -typedef struct AIOCBInfo { - void (*cancel)(BlockDriverAIOCB *acb); - size_t aiocb_size; -} AIOCBInfo; - -struct BlockDriverAIOCB { - const AIOCBInfo *aiocb_info; - BlockDriverState *bs; - BlockDriverCompletionFunc *cb; - void *opaque; -}; - -void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); -void qemu_aio_release(void *p); - -typedef struct AioHandler AioHandler; -typedef void QEMUBHFunc(void *opaque); -typedef void IOHandler(void *opaque); - -typedef struct AioContext { - GSource source; - - /* The list of registered AIO handlers */ - QLIST_HEAD(, AioHandler) aio_handlers; - - /* This is a simple lock used to protect the aio_handlers list. - * Specifically, it's used to ensure that no callbacks are removed while - * we're walking and dispatching callbacks. - */ - int walking_handlers; - - /* Anchor of the list of Bottom Halves belonging to the context */ - struct QEMUBH *first_bh; - - /* A simple lock used to protect the first_bh list, and ensure that - * no callbacks are removed while we're walking and dispatching callbacks. - */ - int walking_bh; - - /* Used for aio_notify. */ - EventNotifier notifier; - - /* GPollFDs for aio_poll() */ - GArray *pollfds; - - /* Thread pool for performing work and receiving completion callbacks */ - struct ThreadPool *thread_pool; -} AioContext; - -/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ -typedef int (AioFlushEventNotifierHandler)(EventNotifier *e); - -/** - * aio_context_new: Allocate a new AioContext. - * - * AioContext provide a mini event-loop that can be waited on synchronously. - * They also provide bottom halves, a service to execute a piece of code - * as soon as possible. - */ -AioContext *aio_context_new(void); - -/** - * aio_context_ref: - * @ctx: The AioContext to operate on. - * - * Add a reference to an AioContext. - */ -void aio_context_ref(AioContext *ctx); - -/** - * aio_context_unref: - * @ctx: The AioContext to operate on. - * - * Drop a reference to an AioContext. - */ -void aio_context_unref(AioContext *ctx); - -/** - * aio_bh_new: Allocate a new bottom half structure. - * - * Bottom halves are lightweight callbacks whose invocation is guaranteed - * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure - * is opaque and must be allocated prior to its use. - */ -QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); - -/** - * aio_notify: Force processing of pending events. - * - * Similar to signaling a condition variable, aio_notify forces - * aio_wait to exit, so that the next call will re-examine pending events. - * The caller of aio_notify will usually call aio_wait again very soon, - * or go through another iteration of the GLib main loop. Hence, aio_notify - * also has the side effect of recalculating the sets of file descriptors - * that the main loop waits for. - * - * Calling aio_notify is rarely necessary, because for example scheduling - * a bottom half calls it already. - */ -void aio_notify(AioContext *ctx); - -/** - * aio_bh_poll: Poll bottom halves for an AioContext. - * - * These are internal functions used by the QEMU main loop. - */ -int aio_bh_poll(AioContext *ctx); - -/** - * qemu_bh_schedule: Schedule a bottom half. - * - * Scheduling a bottom half interrupts the main loop and causes the - * execution of the callback that was passed to qemu_bh_new. - * - * Bottom halves that are scheduled from a bottom half handler are instantly - * invoked. This can create an infinite loop if a bottom half handler - * schedules itself. - * - * @bh: The bottom half to be scheduled. - */ -void qemu_bh_schedule(QEMUBH *bh); - -/** - * qemu_bh_cancel: Cancel execution of a bottom half. - * - * Canceling execution of a bottom half undoes the effect of calls to - * qemu_bh_schedule without freeing its resources yet. While cancellation - * itself is also wait-free and thread-safe, it can of course race with the - * loop that executes bottom halves unless you are holding the iothread - * mutex. This makes it mostly useless if you are not holding the mutex. - * - * @bh: The bottom half to be canceled. - */ -void qemu_bh_cancel(QEMUBH *bh); - -/** - *qemu_bh_delete: Cancel execution of a bottom half and free its resources. - * - * Deleting a bottom half frees the memory that was allocated for it by - * qemu_bh_new. It also implies canceling the bottom half if it was - * scheduled. - * - * @bh: The bottom half to be deleted. - */ -void qemu_bh_delete(QEMUBH *bh); - -/* Return whether there are any pending callbacks from the GSource - * attached to the AioContext. - * - * This is used internally in the implementation of the GSource. - */ -bool aio_pending(AioContext *ctx); - -/* Progress in completing AIO work to occur. This can issue new pending - * aio as a result of executing I/O completion or bh callbacks. - * - * If there is no pending AIO operation or completion (bottom half), - * return false. If there are pending AIO operations of bottom halves, - * return true. - * - * If there are no pending bottom halves, but there are pending AIO - * operations, it may not be possible to make any progress without - * blocking. If @blocking is true, this function will wait until one - * or more AIO events have completed, to ensure something has moved - * before returning. - */ -bool aio_poll(AioContext *ctx, bool blocking); - -#ifdef CONFIG_POSIX -/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ -typedef int (AioFlushHandler)(void *opaque); - -/* Register a file descriptor and associated callbacks. Behaves very similarly - * to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will - * be invoked when using qemu_aio_wait(). - * - * Code that invokes AIO completion functions should rely on this function - * instead of qemu_set_fd_handler[2]. - */ -void aio_set_fd_handler(AioContext *ctx, - int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque); -#endif - -/* Register an event notifier and associated callbacks. Behaves very similarly - * to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks - * will be invoked when using qemu_aio_wait(). - * - * Code that invokes AIO completion functions should rely on this function - * instead of event_notifier_set_handler. - */ -void aio_set_event_notifier(AioContext *ctx, - EventNotifier *notifier, - EventNotifierHandler *io_read, - AioFlushEventNotifierHandler *io_flush); - -/* Return a GSource that lets the main loop poll the file descriptors attached - * to this AioContext. - */ -GSource *aio_get_g_source(AioContext *ctx); - -/* Return the ThreadPool bound to this AioContext */ -struct ThreadPool *aio_get_thread_pool(AioContext *ctx); - -/* Functions to operate on the main QEMU AioContext. */ - -bool qemu_aio_wait(void); -void qemu_aio_set_event_notifier(EventNotifier *notifier, - EventNotifierHandler *io_read, - AioFlushEventNotifierHandler *io_flush); - -#ifdef CONFIG_POSIX -void qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque); -#endif - -#endif diff --git a/contrib/qemu/include/block/block.h b/contrib/qemu/include/block/block.h deleted file mode 100644 index b6b9014a9ce..00000000000 --- a/contrib/qemu/include/block/block.h +++ /dev/null @@ -1,443 +0,0 @@ -#ifndef BLOCK_H -#define BLOCK_H - -#include "block/aio.h" -#include "qemu-common.h" -#include "qemu/option.h" -#include "block/coroutine.h" -#include "qapi/qmp/qobject.h" -#include "qapi-types.h" - -/* block.c */ -typedef struct BlockDriver BlockDriver; -typedef struct BlockJob BlockJob; - -typedef struct BlockDriverInfo { - /* in bytes, 0 if irrelevant */ - int cluster_size; - /* offset at which the VM state can be saved (0 if not possible) */ - int64_t vm_state_offset; - bool is_dirty; -} BlockDriverInfo; - -typedef struct BlockFragInfo { - uint64_t allocated_clusters; - uint64_t total_clusters; - uint64_t fragmented_clusters; - uint64_t compressed_clusters; -} BlockFragInfo; - -/* Callbacks for block device models */ -typedef struct BlockDevOps { - /* - * Runs when virtual media changed (monitor commands eject, change) - * Argument load is true on load and false on eject. - * Beware: doesn't run when a host device's physical media - * changes. Sure would be useful if it did. - * Device models with removable media must implement this callback. - */ - void (*change_media_cb)(void *opaque, bool load); - /* - * Runs when an eject request is issued from the monitor, the tray - * is closed, and the medium is locked. - * Device models that do not implement is_medium_locked will not need - * this callback. Device models that can lock the medium or tray might - * want to implement the callback and unlock the tray when "force" is - * true, even if they do not support eject requests. - */ - void (*eject_request_cb)(void *opaque, bool force); - /* - * Is the virtual tray open? - * Device models implement this only when the device has a tray. - */ - bool (*is_tray_open)(void *opaque); - /* - * Is the virtual medium locked into the device? - * Device models implement this only when device has such a lock. - */ - bool (*is_medium_locked)(void *opaque); - /* - * Runs when the size changed (e.g. monitor command block_resize) - */ - void (*resize_cb)(void *opaque); -} BlockDevOps; - -#define BDRV_O_RDWR 0x0002 -#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */ -#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */ -#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */ -#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */ -#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */ -#define BDRV_O_NO_FLUSH 0x0200 /* disable flushing on this disk */ -#define BDRV_O_COPY_ON_READ 0x0400 /* copy read backing sectors into image */ -#define BDRV_O_INCOMING 0x0800 /* consistency hint for incoming migration */ -#define BDRV_O_CHECK 0x1000 /* open solely for consistency check */ -#define BDRV_O_ALLOW_RDWR 0x2000 /* allow reopen to change from r/o to r/w */ -#define BDRV_O_UNMAP 0x4000 /* execute guest UNMAP/TRIM operations */ - -#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH) - -#define BDRV_SECTOR_BITS 9 -#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) -#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1) - -typedef enum { - BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP -} BlockErrorAction; - -typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; - -typedef struct BDRVReopenState { - BlockDriverState *bs; - int flags; - void *opaque; -} BDRVReopenState; - - -void bdrv_iostatus_enable(BlockDriverState *bs); -void bdrv_iostatus_reset(BlockDriverState *bs); -void bdrv_iostatus_disable(BlockDriverState *bs); -bool bdrv_iostatus_is_enabled(const BlockDriverState *bs); -void bdrv_iostatus_set_err(BlockDriverState *bs, int error); -void bdrv_info_print(Monitor *mon, const QObject *data); -void bdrv_info(Monitor *mon, QObject **ret_data); -void bdrv_stats_print(Monitor *mon, const QObject *data); -void bdrv_info_stats(Monitor *mon, QObject **ret_data); - -/* disk I/O throttling */ -void bdrv_io_limits_enable(BlockDriverState *bs); -void bdrv_io_limits_disable(BlockDriverState *bs); -bool bdrv_io_limits_enabled(BlockDriverState *bs); - -void bdrv_init(void); -void bdrv_init_with_whitelist(void); -BlockDriver *bdrv_find_protocol(const char *filename, - bool allow_protocol_prefix); -BlockDriver *bdrv_find_format(const char *format_name); -BlockDriver *bdrv_find_whitelisted_format(const char *format_name, - bool readonly); -int bdrv_create(BlockDriver *drv, const char* filename, - QEMUOptionParameter *options); -int bdrv_create_file(const char* filename, QEMUOptionParameter *options); -BlockDriverState *bdrv_new(const char *device_name); -void bdrv_make_anon(BlockDriverState *bs); -void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); -void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top); -void bdrv_delete(BlockDriverState *bs); -int bdrv_parse_cache_flags(const char *mode, int *flags); -int bdrv_parse_discard_flags(const char *mode, int *flags); -int bdrv_file_open(BlockDriverState **pbs, const char *filename, - QDict *options, int flags); -int bdrv_open_backing_file(BlockDriverState *bs, QDict *options); -int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, - int flags, BlockDriver *drv); -BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, - BlockDriverState *bs, int flags); -int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); -int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp); -int bdrv_reopen_prepare(BDRVReopenState *reopen_state, - BlockReopenQueue *queue, Error **errp); -void bdrv_reopen_commit(BDRVReopenState *reopen_state); -void bdrv_reopen_abort(BDRVReopenState *reopen_state); -void bdrv_close(BlockDriverState *bs); -void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); -int bdrv_attach_dev(BlockDriverState *bs, void *dev); -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); -void bdrv_detach_dev(BlockDriverState *bs, void *dev); -void *bdrv_get_attached_dev(BlockDriverState *bs); -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, - void *opaque); -void bdrv_dev_eject_request(BlockDriverState *bs, bool force); -bool bdrv_dev_has_removable_media(BlockDriverState *bs); -bool bdrv_dev_is_tray_open(BlockDriverState *bs); -bool bdrv_dev_is_medium_locked(BlockDriverState *bs); -int bdrv_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors); -int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors); -int bdrv_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors); -int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov); -int bdrv_pread(BlockDriverState *bs, int64_t offset, - void *buf, int count); -int bdrv_pwrite(BlockDriverState *bs, int64_t offset, - const void *buf, int count); -int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov); -int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, - const void *buf, int count); -int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov); -int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); -int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov); -/* - * Efficiently zero a region of the disk image. Note that this is a regular - * I/O request like read or write and should have a reasonable size. This - * function is not suitable for zeroing the entire image in a single request - * because it may allocate memory for the entire region. - */ -int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, - int nb_sectors); -int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum); -int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, int *pnum); -BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, - const char *backing_file); -int bdrv_get_backing_file_depth(BlockDriverState *bs); -int bdrv_truncate(BlockDriverState *bs, int64_t offset); -int64_t bdrv_getlength(BlockDriverState *bs); -int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); -void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); -int bdrv_commit(BlockDriverState *bs); -int bdrv_commit_all(void); -int bdrv_change_backing_file(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt); -void bdrv_register(BlockDriver *bdrv); -int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, - BlockDriverState *base); -BlockDriverState *bdrv_find_overlay(BlockDriverState *active, - BlockDriverState *bs); -BlockDriverState *bdrv_find_base(BlockDriverState *bs); - - -typedef struct BdrvCheckResult { - int corruptions; - int leaks; - int check_errors; - int corruptions_fixed; - int leaks_fixed; - int64_t image_end_offset; - BlockFragInfo bfi; -} BdrvCheckResult; - -typedef enum { - BDRV_FIX_LEAKS = 1, - BDRV_FIX_ERRORS = 2, -} BdrvCheckMode; - -int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); - -/* async block I/O */ -typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, - int sector_num); -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -void bdrv_aio_cancel(BlockDriverAIOCB *acb); - -typedef struct BlockRequest { - /* Fields to be filled by multiwrite caller */ - int64_t sector; - int nb_sectors; - QEMUIOVector *qiov; - BlockDriverCompletionFunc *cb; - void *opaque; - - /* Filled by multiwrite implementation */ - int error; -} BlockRequest; - -int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, - int num_reqs); - -/* sg packet commands */ -int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque); - -/* Invalidate any cached metadata used by image formats */ -void bdrv_invalidate_cache(BlockDriverState *bs); -void bdrv_invalidate_cache_all(void); - -void bdrv_clear_incoming_migration_all(void); - -/* Ensure contents are flushed to disk. */ -int bdrv_flush(BlockDriverState *bs); -int coroutine_fn bdrv_co_flush(BlockDriverState *bs); -int bdrv_flush_all(void); -void bdrv_close_all(void); -void bdrv_drain_all(void); - -int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); -int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); -int bdrv_has_zero_init_1(BlockDriverState *bs); -int bdrv_has_zero_init(BlockDriverState *bs); -int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - int *pnum); -int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, - int64_t sector_num, int nb_sectors, int *pnum); - -void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, - BlockdevOnError on_write_error); -BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read); -BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error); -void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, - bool is_read, int error); -int bdrv_is_read_only(BlockDriverState *bs); -int bdrv_is_sg(BlockDriverState *bs); -int bdrv_enable_write_cache(BlockDriverState *bs); -void bdrv_set_enable_write_cache(BlockDriverState *bs, bool wce); -int bdrv_is_inserted(BlockDriverState *bs); -int bdrv_media_changed(BlockDriverState *bs); -void bdrv_lock_medium(BlockDriverState *bs, bool locked); -void bdrv_eject(BlockDriverState *bs, bool eject_flag); -const char *bdrv_get_format_name(BlockDriverState *bs); -BlockDriverState *bdrv_find(const char *name); -BlockDriverState *bdrv_next(BlockDriverState *bs); -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), - void *opaque); -int bdrv_is_encrypted(BlockDriverState *bs); -int bdrv_key_required(BlockDriverState *bs); -int bdrv_set_key(BlockDriverState *bs, const char *key); -int bdrv_query_missing_keys(void); -void bdrv_iterate_format(void (*it)(void *opaque, const char *name), - void *opaque); -const char *bdrv_get_device_name(BlockDriverState *bs); -int bdrv_get_flags(BlockDriverState *bs); -int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors); -int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); -void bdrv_round_to_clusters(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - int64_t *cluster_sector_num, - int *cluster_nb_sectors); - -const char *bdrv_get_encrypted_filename(BlockDriverState *bs); -void bdrv_get_backing_filename(BlockDriverState *bs, - char *filename, int filename_size); -void bdrv_get_full_backing_filename(BlockDriverState *bs, - char *dest, size_t sz); -int bdrv_is_snapshot(BlockDriverState *bs); - -int path_is_absolute(const char *path); -void path_combine(char *dest, int dest_size, - const char *base_path, - const char *filename); - -int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); -int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, - int64_t pos, int size); - -int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, - int64_t pos, int size); - -void bdrv_img_create(const char *filename, const char *fmt, - const char *base_filename, const char *base_fmt, - char *options, uint64_t img_size, int flags, - Error **errp, bool quiet); - -void bdrv_set_buffer_alignment(BlockDriverState *bs, int align); -void *qemu_blockalign(BlockDriverState *bs, size_t size); -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); - -struct HBitmapIter; -void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity); -int bdrv_get_dirty(BlockDriverState *bs, int64_t sector); -void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); -void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); -void bdrv_dirty_iter_init(BlockDriverState *bs, struct HBitmapIter *hbi); -int64_t bdrv_get_dirty_count(BlockDriverState *bs); - -void bdrv_enable_copy_on_read(BlockDriverState *bs); -void bdrv_disable_copy_on_read(BlockDriverState *bs); - -void bdrv_set_in_use(BlockDriverState *bs, int in_use); -int bdrv_in_use(BlockDriverState *bs); - -#ifdef CONFIG_LINUX_AIO -int raw_get_aio_fd(BlockDriverState *bs); -#else -static inline int raw_get_aio_fd(BlockDriverState *bs) -{ - return -ENOTSUP; -} -#endif - -enum BlockAcctType { - BDRV_ACCT_READ, - BDRV_ACCT_WRITE, - BDRV_ACCT_FLUSH, - BDRV_MAX_IOTYPE, -}; - -typedef struct BlockAcctCookie { - int64_t bytes; - int64_t start_time_ns; - enum BlockAcctType type; -} BlockAcctCookie; - -void bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, - int64_t bytes, enum BlockAcctType type); -void bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie); - -typedef enum { - BLKDBG_L1_UPDATE, - - BLKDBG_L1_GROW_ALLOC_TABLE, - BLKDBG_L1_GROW_WRITE_TABLE, - BLKDBG_L1_GROW_ACTIVATE_TABLE, - - BLKDBG_L2_LOAD, - BLKDBG_L2_UPDATE, - BLKDBG_L2_UPDATE_COMPRESSED, - BLKDBG_L2_ALLOC_COW_READ, - BLKDBG_L2_ALLOC_WRITE, - - BLKDBG_READ_AIO, - BLKDBG_READ_BACKING_AIO, - BLKDBG_READ_COMPRESSED, - - BLKDBG_WRITE_AIO, - BLKDBG_WRITE_COMPRESSED, - - BLKDBG_VMSTATE_LOAD, - BLKDBG_VMSTATE_SAVE, - - BLKDBG_COW_READ, - BLKDBG_COW_WRITE, - - BLKDBG_REFTABLE_LOAD, - BLKDBG_REFTABLE_GROW, - - BLKDBG_REFBLOCK_LOAD, - BLKDBG_REFBLOCK_UPDATE, - BLKDBG_REFBLOCK_UPDATE_PART, - BLKDBG_REFBLOCK_ALLOC, - BLKDBG_REFBLOCK_ALLOC_HOOKUP, - BLKDBG_REFBLOCK_ALLOC_WRITE, - BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS, - BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE, - BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE, - - BLKDBG_CLUSTER_ALLOC, - BLKDBG_CLUSTER_ALLOC_BYTES, - BLKDBG_CLUSTER_FREE, - - BLKDBG_FLUSH_TO_OS, - BLKDBG_FLUSH_TO_DISK, - - BLKDBG_EVENT_MAX, -} BlkDebugEvent; - -#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt) -void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event); - -int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event, - const char *tag); -int bdrv_debug_resume(BlockDriverState *bs, const char *tag); -bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag); - -#endif diff --git a/contrib/qemu/include/block/block_int.h b/contrib/qemu/include/block/block_int.h deleted file mode 100644 index c6ac871e210..00000000000 --- a/contrib/qemu/include/block/block_int.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * QEMU System Emulator block driver - * - * 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. - */ -#ifndef BLOCK_INT_H -#define BLOCK_INT_H - -#include "block/block.h" -#include "qemu/option.h" -#include "qemu/queue.h" -#include "block/coroutine.h" -#include "qemu/timer.h" -#include "qapi-types.h" -#include "qapi/qmp/qerror.h" -#include "monitor/monitor.h" -#include "qemu/hbitmap.h" -#include "block/snapshot.h" - -#define BLOCK_FLAG_ENCRYPT 1 -#define BLOCK_FLAG_COMPAT6 4 -#define BLOCK_FLAG_LAZY_REFCOUNTS 8 - -#define BLOCK_IO_LIMIT_READ 0 -#define BLOCK_IO_LIMIT_WRITE 1 -#define BLOCK_IO_LIMIT_TOTAL 2 - -#define BLOCK_IO_SLICE_TIME 100000000 -#define NANOSECONDS_PER_SECOND 1000000000.0 - -#define BLOCK_OPT_SIZE "size" -#define BLOCK_OPT_ENCRYPT "encryption" -#define BLOCK_OPT_COMPAT6 "compat6" -#define BLOCK_OPT_BACKING_FILE "backing_file" -#define BLOCK_OPT_BACKING_FMT "backing_fmt" -#define BLOCK_OPT_CLUSTER_SIZE "cluster_size" -#define BLOCK_OPT_TABLE_SIZE "table_size" -#define BLOCK_OPT_PREALLOC "preallocation" -#define BLOCK_OPT_SUBFMT "subformat" -#define BLOCK_OPT_COMPAT_LEVEL "compat" -#define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts" -#define BLOCK_OPT_ADAPTER_TYPE "adapter_type" - -typedef struct BdrvTrackedRequest { - BlockDriverState *bs; - int64_t sector_num; - int nb_sectors; - bool is_write; - QLIST_ENTRY(BdrvTrackedRequest) list; - Coroutine *co; /* owner, used for deadlock detection */ - CoQueue wait_queue; /* coroutines blocked on this request */ -} BdrvTrackedRequest; - - -typedef struct BlockIOLimit { - int64_t bps[3]; - int64_t iops[3]; -} BlockIOLimit; - -typedef struct BlockIOBaseValue { - uint64_t bytes[2]; - uint64_t ios[2]; -} BlockIOBaseValue; - -struct BlockDriver { - const char *format_name; - int instance_size; - int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); - int (*bdrv_probe_device)(const char *filename); - - /* Any driver implementing this callback is expected to be able to handle - * NULL file names in its .bdrv_open() implementation */ - void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp); - - /* For handling image reopen for split or non-split files */ - int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state, - BlockReopenQueue *queue, Error **errp); - void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); - void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); - - int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags); - int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags); - int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors); - int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors); - void (*bdrv_close)(BlockDriverState *bs); - void (*bdrv_rebind)(BlockDriverState *bs); - int (*bdrv_create)(const char *filename, QEMUOptionParameter *options); - int (*bdrv_set_key)(BlockDriverState *bs, const char *key); - int (*bdrv_make_empty)(BlockDriverState *bs); - /* aio */ - BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - - int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); - int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); - /* - * Efficiently zero a region of the disk image. Typically an image format - * would use a compact metadata representation to implement this. This - * function pointer may be NULL and .bdrv_co_writev() will be called - * instead. - */ - int coroutine_fn (*bdrv_co_write_zeroes)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors); - int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors); - int coroutine_fn (*bdrv_co_is_allocated)(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, int *pnum); - - /* - * Invalidate any cached meta-data. - */ - void (*bdrv_invalidate_cache)(BlockDriverState *bs); - - /* - * Flushes all data that was already written to the OS all the way down to - * the disk (for example raw-posix calls fsync()). - */ - int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs); - - /* - * Flushes all internal caches to the OS. The data may still sit in a - * writeback cache of the host OS, but it will survive a crash of the qemu - * process. - */ - int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs); - - const char *protocol_name; - int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset); - int64_t (*bdrv_getlength)(BlockDriverState *bs); - int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); - int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors); - - int (*bdrv_snapshot_create)(BlockDriverState *bs, - QEMUSnapshotInfo *sn_info); - int (*bdrv_snapshot_goto)(BlockDriverState *bs, - const char *snapshot_id); - int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id); - int (*bdrv_snapshot_list)(BlockDriverState *bs, - QEMUSnapshotInfo **psn_info); - int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs, - const char *snapshot_name); - int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); - - int (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t pos); - int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf, - int64_t pos, int size); - - int (*bdrv_change_backing_file)(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt); - - /* removable device specific */ - int (*bdrv_is_inserted)(BlockDriverState *bs); - int (*bdrv_media_changed)(BlockDriverState *bs); - void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); - void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); - - /* to control generic scsi devices */ - int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); - BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque); - - /* List of options for creating images, terminated by name == NULL */ - QEMUOptionParameter *create_options; - - - /* - * Returns 0 for completed check, -errno for internal errors. - * The check results are stored in result. - */ - int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result, - BdrvCheckMode fix); - - void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event); - - /* TODO Better pass a option string/QDict/QemuOpts to add any rule? */ - int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event, - const char *tag); - int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag); - bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag); - - /* - * Returns 1 if newly created images are guaranteed to contain only - * zeros, 0 otherwise. - */ - int (*bdrv_has_zero_init)(BlockDriverState *bs); - - QLIST_ENTRY(BlockDriver) list; -}; - -/* - * Note: the function bdrv_append() copies and swaps contents of - * BlockDriverStates, so if you add new fields to this struct, please - * inspect bdrv_append() to determine if the new fields need to be - * copied as well. - */ -struct BlockDriverState { - int64_t total_sectors; /* if we are reading a disk image, give its - size in sectors */ - int read_only; /* if true, the media is read only */ - int open_flags; /* flags used to open the file, re-used for re-open */ - int encrypted; /* if true, the media is encrypted */ - int valid_key; /* if true, a valid encryption key has been set */ - int sg; /* if true, the device is a /dev/sg* */ - int copy_on_read; /* if true, copy read backing sectors into image - note this is a reference count */ - - BlockDriver *drv; /* NULL means no media */ - void *opaque; - - void *dev; /* attached device model, if any */ - /* TODO change to DeviceState when all users are qdevified */ - const BlockDevOps *dev_ops; - void *dev_opaque; - - char filename[1024]; - char backing_file[1024]; /* if non zero, the image is a diff of - this file image */ - char backing_format[16]; /* if non-zero and backing_file exists */ - int is_temporary; - - BlockDriverState *backing_hd; - BlockDriverState *file; - - NotifierList close_notifiers; - - /* Callback before write request is processed */ - NotifierWithReturnList before_write_notifiers; - - /* number of in-flight copy-on-read requests */ - unsigned int copy_on_read_in_flight; - - /* the time for latest disk I/O */ - int64_t slice_start; - int64_t slice_end; - BlockIOLimit io_limits; - BlockIOBaseValue slice_submitted; - CoQueue throttled_reqs; - QEMUTimer *block_timer; - bool io_limits_enabled; - - /* I/O stats (display with "info blockstats"). */ - uint64_t nr_bytes[BDRV_MAX_IOTYPE]; - uint64_t nr_ops[BDRV_MAX_IOTYPE]; - uint64_t total_time_ns[BDRV_MAX_IOTYPE]; - uint64_t wr_highest_sector; - - /* Whether the disk can expand beyond total_sectors */ - int growable; - - /* the memory alignment required for the buffers handled by this driver */ - int buffer_alignment; - - /* do we need to tell the quest if we have a volatile write cache? */ - int enable_write_cache; - - /* NOTE: the following infos are only hints for real hardware - drivers. They are not used by the block driver */ - BlockdevOnError on_read_error, on_write_error; - bool iostatus_enabled; - BlockDeviceIoStatus iostatus; - char device_name[32]; - HBitmap *dirty_bitmap; - int in_use; /* users other than guest access, eg. block migration */ - QTAILQ_ENTRY(BlockDriverState) list; - - QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; - - /* long-running background operation */ - BlockJob *job; - - QDict *options; -}; - -int get_tmp_filename(char *filename, int size); - -void bdrv_set_io_limits(BlockDriverState *bs, - BlockIOLimit *io_limits); - -/** - * bdrv_add_before_write_notifier: - * - * Register a callback that is invoked before write requests are processed but - * after any throttling or waiting for overlapping requests. - */ -void bdrv_add_before_write_notifier(BlockDriverState *bs, - NotifierWithReturn *notifier); - -/** - * bdrv_get_aio_context: - * - * Returns: the currently bound #AioContext - */ -AioContext *bdrv_get_aio_context(BlockDriverState *bs); - -#ifdef _WIN32 -int is_windows_drive(const char *filename); -#endif -void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - enum MonitorEvent ev, - BlockErrorAction action, bool is_read); - -/** - * stream_start: - * @bs: Block device to operate on. - * @base: Block device that will become the new base, or %NULL to - * flatten the whole backing file chain onto @bs. - * @base_id: The file name that will be written to @bs as the new - * backing file if the job completes. Ignored if @base is %NULL. - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @on_error: The action to take upon error. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * @errp: Error object. - * - * Start a streaming operation on @bs. Clusters that are unallocated - * in @bs, but allocated in any image between @base and @bs (both - * exclusive) will be written to @bs. At the end of a successful - * streaming job, the backing file of @bs will be changed to - * @base_id in the written image and to @base in the live BlockDriverState. - */ -void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, int64_t speed, BlockdevOnError on_error, - BlockDriverCompletionFunc *cb, - void *opaque, Error **errp); - -/** - * commit_start: - * @bs: Top Block device - * @base: Block device that will be written into, and become the new top - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @on_error: The action to take upon error. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * @errp: Error object. - * - */ -void commit_start(BlockDriverState *bs, BlockDriverState *base, - BlockDriverState *top, int64_t speed, - BlockdevOnError on_error, BlockDriverCompletionFunc *cb, - void *opaque, Error **errp); - -/* - * mirror_start: - * @bs: Block device to operate on. - * @target: Block device to write to. - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @granularity: The chosen granularity for the dirty bitmap. - * @buf_size: The amount of data that can be in flight at one time. - * @mode: Whether to collapse all images in the chain to the target. - * @on_source_error: The action to take upon error reading from the source. - * @on_target_error: The action to take upon error writing to the target. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * @errp: Error object. - * - * Start a mirroring operation on @bs. Clusters that are allocated - * in @bs will be written to @bs until the job is cancelled or - * manually completed. At the end of a successful mirroring job, - * @bs will be switched to read from @target. - */ -void mirror_start(BlockDriverState *bs, BlockDriverState *target, - int64_t speed, int64_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockdevOnError on_source_error, - BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, - void *opaque, Error **errp); - -/* - * backup_start: - * @bs: Block device to operate on. - * @target: Block device to write to. - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @on_source_error: The action to take upon error reading from the source. - * @on_target_error: The action to take upon error writing to the target. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * - * Start a backup operation on @bs. Clusters in @bs are written to @target - * until the job is cancelled or manually completed. - */ -void backup_start(BlockDriverState *bs, BlockDriverState *target, - int64_t speed, BlockdevOnError on_source_error, - BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, void *opaque, - Error **errp); - -#endif /* BLOCK_INT_H */ diff --git a/contrib/qemu/include/block/blockjob.h b/contrib/qemu/include/block/blockjob.h deleted file mode 100644 index c290d07bba0..00000000000 --- a/contrib/qemu/include/block/blockjob.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Declarations for long-running block device operations - * - * Copyright (c) 2011 IBM Corp. - * Copyright (c) 2012 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. - */ -#ifndef BLOCKJOB_H -#define BLOCKJOB_H 1 - -#include "block/block.h" - -/** - * BlockJobType: - * - * A class type for block job objects. - */ -typedef struct BlockJobType { - /** Derived BlockJob struct size */ - size_t instance_size; - - /** String describing the operation, part of query-block-jobs QMP API */ - const char *job_type; - - /** Optional callback for job types that support setting a speed limit */ - void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); - - /** Optional callback for job types that need to forward I/O status reset */ - void (*iostatus_reset)(BlockJob *job); - - /** - * Optional callback for job types whose completion must be triggered - * manually. - */ - void (*complete)(BlockJob *job, Error **errp); -} BlockJobType; - -/** - * BlockJob: - * - * Long-running operation on a BlockDriverState. - */ -struct BlockJob { - /** The job type, including the job vtable. */ - const BlockJobType *job_type; - - /** The block device on which the job is operating. */ - BlockDriverState *bs; - - /** - * The coroutine that executes the job. If not NULL, it is - * reentered when busy is false and the job is cancelled. - */ - Coroutine *co; - - /** - * Set to true if the job should cancel itself. The flag must - * always be tested just before toggling the busy flag from false - * to true. After a job has been cancelled, it should only yield - * if #qemu_aio_wait will ("sooner or later") reenter the coroutine. - */ - bool cancelled; - - /** - * Set to true if the job is either paused, or will pause itself - * as soon as possible (if busy == true). - */ - bool paused; - - /** - * Set to false by the job while it is in a quiescent state, where - * no I/O is pending and the job has yielded on any condition - * that is not detected by #qemu_aio_wait, such as a timer. - */ - bool busy; - - /** Status that is published by the query-block-jobs QMP API */ - BlockDeviceIoStatus iostatus; - - /** Offset that is published by the query-block-jobs QMP API */ - int64_t offset; - - /** Length that is published by the query-block-jobs QMP API */ - int64_t len; - - /** Speed that was set with @block_job_set_speed. */ - int64_t speed; - - /** The completion function that will be called when the job completes. */ - BlockDriverCompletionFunc *cb; - - /** The opaque value that is passed to the completion function. */ - void *opaque; -}; - -/** - * block_job_create: - * @job_type: The class object for the newly-created job. - * @bs: The block - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * @errp: Error object. - * - * Create a new long-running block device job and return it. The job - * will call @cb asynchronously when the job completes. Note that - * @bs may have been closed at the time the @cb it is called. If - * this is the case, the job may be reported as either cancelled or - * completed. - * - * This function is not part of the public job interface; it should be - * called from a wrapper that is specific to the job type. - */ -void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, - int64_t speed, BlockDriverCompletionFunc *cb, - void *opaque, Error **errp); - -/** - * block_job_sleep_ns: - * @job: The job that calls the function. - * @clock: The clock to sleep on. - * @ns: How many nanoseconds to stop for. - * - * Put the job to sleep (assuming that it wasn't canceled) for @ns - * nanoseconds. Canceling the job will interrupt the wait immediately. - */ -void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); - -/** - * block_job_completed: - * @job: The job being completed. - * @ret: The status code. - * - * Call the completion function that was registered at creation time, and - * free @job. - */ -void block_job_completed(BlockJob *job, int ret); - -/** - * block_job_set_speed: - * @job: The job to set the speed for. - * @speed: The new value - * @errp: Error object. - * - * Set a rate-limiting parameter for the job; the actual meaning may - * vary depending on the job type. - */ -void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); - -/** - * block_job_cancel: - * @job: The job to be canceled. - * - * Asynchronously cancel the specified job. - */ -void block_job_cancel(BlockJob *job); - -/** - * block_job_complete: - * @job: The job to be completed. - * @errp: Error object. - * - * Asynchronously complete the specified job. - */ -void block_job_complete(BlockJob *job, Error **errp); - -/** - * block_job_is_cancelled: - * @job: The job being queried. - * - * Returns whether the job is scheduled for cancellation. - */ -bool block_job_is_cancelled(BlockJob *job); - -/** - * block_job_query: - * @job: The job to get information about. - * - * Return information about a job. - */ -BlockJobInfo *block_job_query(BlockJob *job); - -/** - * block_job_pause: - * @job: The job to be paused. - * - * Asynchronously pause the specified job. - */ -void block_job_pause(BlockJob *job); - -/** - * block_job_resume: - * @job: The job to be resumed. - * - * Resume the specified job. - */ -void block_job_resume(BlockJob *job); - -/** - * qobject_from_block_job: - * @job: The job whose information is requested. - * - * Return a QDict corresponding to @job's query-block-jobs entry. - */ -QObject *qobject_from_block_job(BlockJob *job); - -/** - * block_job_ready: - * @job: The job which is now ready to complete. - * - * Send a BLOCK_JOB_READY event for the specified job. - */ -void block_job_ready(BlockJob *job); - -/** - * block_job_is_paused: - * @job: The job being queried. - * - * Returns whether the job is currently paused, or will pause - * as soon as it reaches a sleeping point. - */ -bool block_job_is_paused(BlockJob *job); - -/** - * block_job_cancel_sync: - * @job: The job to be canceled. - * - * Synchronously cancel the job. The completion callback is called - * before the function returns. The job may actually complete - * instead of canceling itself; the circumstances under which this - * happens depend on the kind of job that is active. - * - * Returns the return value from the job if the job actually completed - * during the call, or -ECANCELED if it was canceled. - */ -int block_job_cancel_sync(BlockJob *job); - -/** - * block_job_iostatus_reset: - * @job: The job whose I/O status should be reset. - * - * Reset I/O status on @job and on BlockDriverState objects it uses, - * other than job->bs. - */ -void block_job_iostatus_reset(BlockJob *job); - -/** - * block_job_error_action: - * @job: The job to signal an error for. - * @bs: The block device on which to set an I/O error. - * @on_err: The error action setting. - * @is_read: Whether the operation was a read. - * @error: The error that was reported. - * - * Report an I/O error for a block job and possibly stop the VM. Return the - * action that was selected based on @on_err and @error. - */ -BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, - BlockdevOnError on_err, - int is_read, int error); -#endif diff --git a/contrib/qemu/include/block/coroutine.h b/contrib/qemu/include/block/coroutine.h deleted file mode 100644 index 377805a3b08..00000000000 --- a/contrib/qemu/include/block/coroutine.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * QEMU coroutine implementation - * - * 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. - * - */ - -#ifndef QEMU_COROUTINE_H -#define QEMU_COROUTINE_H - -#include <stdbool.h> -#include "qemu/queue.h" -#include "qemu/timer.h" - -/** - * Coroutines are a mechanism for stack switching and can be used for - * cooperative userspace threading. These functions provide a simple but - * useful flavor of coroutines that is suitable for writing sequential code, - * rather than callbacks, for operations that need to give up control while - * waiting for events to complete. - * - * These functions are re-entrant and may be used outside the global mutex. - */ - -/** - * Mark a function that executes in coroutine context - * - * Functions that execute in coroutine context cannot be called directly from - * normal functions. In the future it would be nice to enable compiler or - * static checker support for catching such errors. This annotation might make - * it possible and in the meantime it serves as documentation. - * - * For example: - * - * static void coroutine_fn foo(void) { - * .... - * } - */ -#define coroutine_fn - -typedef struct Coroutine Coroutine; - -/** - * Coroutine entry point - * - * When the coroutine is entered for the first time, opaque is passed in as an - * argument. - * - * When this function returns, the coroutine is destroyed automatically and - * execution continues in the caller who last entered the coroutine. - */ -typedef void coroutine_fn CoroutineEntry(void *opaque); - -/** - * Create a new coroutine - * - * Use qemu_coroutine_enter() to actually transfer control to the coroutine. - */ -Coroutine *qemu_coroutine_create(CoroutineEntry *entry); - -/** - * Transfer control to a coroutine - * - * The opaque argument is passed as the argument to the entry point when - * entering the coroutine for the first time. It is subsequently ignored. - */ -void qemu_coroutine_enter(Coroutine *coroutine, void *opaque); - -/** - * Transfer control back to a coroutine's caller - * - * This function does not return until the coroutine is re-entered using - * qemu_coroutine_enter(). - */ -void coroutine_fn qemu_coroutine_yield(void); - -/** - * Get the currently executing coroutine - */ -Coroutine *coroutine_fn qemu_coroutine_self(void); - -/** - * Return whether or not currently inside a coroutine - * - * This can be used to write functions that work both when in coroutine context - * and when not in coroutine context. Note that such functions cannot use the - * coroutine_fn annotation since they work outside coroutine context. - */ -bool qemu_in_coroutine(void); - - - -/** - * CoQueues are a mechanism to queue coroutines in order to continue executing - * them later. They provide the fundamental primitives on which coroutine locks - * are built. - */ -typedef struct CoQueue { - QTAILQ_HEAD(, Coroutine) entries; - AioContext *ctx; -} CoQueue; - -/** - * Initialise a CoQueue. This must be called before any other operation is used - * on the CoQueue. - */ -void qemu_co_queue_init(CoQueue *queue); - -/** - * Adds the current coroutine to the CoQueue and transfers control to the - * caller of the coroutine. - */ -void coroutine_fn qemu_co_queue_wait(CoQueue *queue); - -/** - * Adds the current coroutine to the head of the CoQueue and transfers control to the - * caller of the coroutine. - */ -void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue); - -/** - * Restarts the next coroutine in the CoQueue and removes it from the queue. - * - * Returns true if a coroutine was restarted, false if the queue is empty. - */ -bool qemu_co_queue_next(CoQueue *queue); - -/** - * Restarts all coroutines in the CoQueue and leaves the queue empty. - */ -void qemu_co_queue_restart_all(CoQueue *queue); - -/** - * Checks if the CoQueue is empty. - */ -bool qemu_co_queue_empty(CoQueue *queue); - - -/** - * Provides a mutex that can be used to synchronise coroutines - */ -typedef struct CoMutex { - bool locked; - CoQueue queue; -} CoMutex; - -/** - * Initialises a CoMutex. This must be called before any other operation is used - * on the CoMutex. - */ -void qemu_co_mutex_init(CoMutex *mutex); - -/** - * Locks the mutex. If the lock cannot be taken immediately, control is - * transferred to the caller of the current coroutine. - */ -void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); - -/** - * Unlocks the mutex and schedules the next coroutine that was waiting for this - * lock to be run. - */ -void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); - -typedef struct CoRwlock { - bool writer; - int reader; - CoQueue queue; -} CoRwlock; - -/** - * Initialises a CoRwlock. This must be called before any other operation - * is used on the CoRwlock - */ -void qemu_co_rwlock_init(CoRwlock *lock); - -/** - * Read locks the CoRwlock. If the lock cannot be taken immediately because - * of a parallel writer, control is transferred to the caller of the current - * coroutine. - */ -void qemu_co_rwlock_rdlock(CoRwlock *lock); - -/** - * Write Locks the mutex. If the lock cannot be taken immediately because - * of a parallel reader, control is transferred to the caller of the current - * coroutine. - */ -void qemu_co_rwlock_wrlock(CoRwlock *lock); - -/** - * Unlocks the read/write lock and schedules the next coroutine that was - * waiting for this lock to be run. - */ -void qemu_co_rwlock_unlock(CoRwlock *lock); - -/** - * Yield the coroutine for a given duration - * - * Note this function uses timers and hence only works when a main loop is in - * use. See main-loop.h and do not use from qemu-tool programs. - */ -void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns); - -/** - * Yield until a file descriptor becomes readable - * - * Note that this function clobbers the handlers for the file descriptor. - */ -void coroutine_fn yield_until_fd_readable(int fd); -#endif /* QEMU_COROUTINE_H */ diff --git a/contrib/qemu/include/block/coroutine_int.h b/contrib/qemu/include/block/coroutine_int.h deleted file mode 100644 index f133d65af86..00000000000 --- a/contrib/qemu/include/block/coroutine_int.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Coroutine internals - * - * 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. - */ - -#ifndef QEMU_COROUTINE_INT_H -#define QEMU_COROUTINE_INT_H - -#include "qemu/queue.h" -#include "block/coroutine.h" - -typedef enum { - COROUTINE_YIELD = 1, - COROUTINE_TERMINATE = 2, -} CoroutineAction; - -struct Coroutine { - CoroutineEntry *entry; - void *entry_arg; - Coroutine *caller; - QSLIST_ENTRY(Coroutine) pool_next; - - /* Coroutines that should be woken up when we yield or terminate */ - QTAILQ_HEAD(, Coroutine) co_queue_wakeup; - QTAILQ_ENTRY(Coroutine) co_queue_next; -}; - -Coroutine *qemu_coroutine_new(void); -void qemu_coroutine_delete(Coroutine *co); -CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to, - CoroutineAction action); -void coroutine_fn qemu_co_queue_run_restart(Coroutine *co); - -#endif diff --git a/contrib/qemu/include/block/snapshot.h b/contrib/qemu/include/block/snapshot.h deleted file mode 100644 index eaf61f0326e..00000000000 --- a/contrib/qemu/include/block/snapshot.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Block layer snapshot related functions - * - * 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. - */ - -#ifndef SNAPSHOT_H -#define SNAPSHOT_H - -#include "qemu-common.h" - -typedef struct QEMUSnapshotInfo { - char id_str[128]; /* unique snapshot id */ - /* the following fields are informative. They are not needed for - the consistency of the snapshot */ - char name[256]; /* user chosen name */ - uint64_t vm_state_size; /* VM state info size */ - uint32_t date_sec; /* UTC date of the snapshot */ - uint32_t date_nsec; - uint64_t vm_clock_nsec; /* VM clock relative to boot */ -} QEMUSnapshotInfo; - -int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, - const char *name); -int bdrv_can_snapshot(BlockDriverState *bs); -int bdrv_snapshot_create(BlockDriverState *bs, - QEMUSnapshotInfo *sn_info); -int bdrv_snapshot_goto(BlockDriverState *bs, - const char *snapshot_id); -int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); -int bdrv_snapshot_list(BlockDriverState *bs, - QEMUSnapshotInfo **psn_info); -int bdrv_snapshot_load_tmp(BlockDriverState *bs, - const char *snapshot_name); -#endif diff --git a/contrib/qemu/include/config.h b/contrib/qemu/include/config.h deleted file mode 100644 index e20f78696a1..00000000000 --- a/contrib/qemu/include/config.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "config-host.h" -#include "config-target.h" diff --git a/contrib/qemu/include/exec/cpu-common.h b/contrib/qemu/include/exec/cpu-common.h deleted file mode 100644 index e4996e19c32..00000000000 --- a/contrib/qemu/include/exec/cpu-common.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef CPU_COMMON_H -#define CPU_COMMON_H 1 - -/* CPU interfaces that are target independent. */ - -#ifndef CONFIG_USER_ONLY -#include "exec/hwaddr.h" -#endif - -#ifndef NEED_CPU_H -#include "exec/poison.h" -#endif - -#include "qemu/bswap.h" -#include "qemu/queue.h" - -/** - * CPUListState: - * @cpu_fprintf: Print function. - * @file: File to print to using @cpu_fprint. - * - * State commonly used for iterating over CPU models. - */ -typedef struct CPUListState { - fprintf_function cpu_fprintf; - FILE *file; -} CPUListState; - -#if !defined(CONFIG_USER_ONLY) - -enum device_endian { - DEVICE_NATIVE_ENDIAN, - DEVICE_BIG_ENDIAN, - DEVICE_LITTLE_ENDIAN, -}; - -/* address in the RAM (different from a physical address) */ -#if defined(CONFIG_XEN_BACKEND) -typedef uint64_t ram_addr_t; -# define RAM_ADDR_MAX UINT64_MAX -# define RAM_ADDR_FMT "%" PRIx64 -#else -typedef uintptr_t ram_addr_t; -# define RAM_ADDR_MAX UINTPTR_MAX -# define RAM_ADDR_FMT "%" PRIxPTR -#endif - -/* memory API */ - -typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value); -typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); - -void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); -/* This should not be used by devices. */ -MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); -void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); - -void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, - int len, int is_write); -static inline void cpu_physical_memory_read(hwaddr addr, - void *buf, int len) -{ - cpu_physical_memory_rw(addr, buf, len, 0); -} -static inline void cpu_physical_memory_write(hwaddr addr, - const void *buf, int len) -{ - cpu_physical_memory_rw(addr, (void *)buf, len, 1); -} -void *cpu_physical_memory_map(hwaddr addr, - hwaddr *plen, - int is_write); -void cpu_physical_memory_unmap(void *buffer, hwaddr len, - int is_write, hwaddr access_len); -void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); - -bool cpu_physical_memory_is_io(hwaddr phys_addr); - -/* Coalesced MMIO regions are areas where write operations can be reordered. - * This usually implies that write operations are side-effect free. This allows - * batching which can make a major impact on performance when using - * virtualization. - */ -void qemu_flush_coalesced_mmio_buffer(void); - -uint32_t ldub_phys(hwaddr addr); -uint32_t lduw_le_phys(hwaddr addr); -uint32_t lduw_be_phys(hwaddr addr); -uint32_t ldl_le_phys(hwaddr addr); -uint32_t ldl_be_phys(hwaddr addr); -uint64_t ldq_le_phys(hwaddr addr); -uint64_t ldq_be_phys(hwaddr addr); -void stb_phys(hwaddr addr, uint32_t val); -void stw_le_phys(hwaddr addr, uint32_t val); -void stw_be_phys(hwaddr addr, uint32_t val); -void stl_le_phys(hwaddr addr, uint32_t val); -void stl_be_phys(hwaddr addr, uint32_t val); -void stq_le_phys(hwaddr addr, uint64_t val); -void stq_be_phys(hwaddr addr, uint64_t val); - -#ifdef NEED_CPU_H -uint32_t lduw_phys(hwaddr addr); -uint32_t ldl_phys(hwaddr addr); -uint64_t ldq_phys(hwaddr addr); -void stl_phys_notdirty(hwaddr addr, uint32_t val); -void stw_phys(hwaddr addr, uint32_t val); -void stl_phys(hwaddr addr, uint32_t val); -void stq_phys(hwaddr addr, uint64_t val); -#endif - -void cpu_physical_memory_write_rom(hwaddr addr, - const uint8_t *buf, int len); - -extern struct MemoryRegion io_mem_rom; -extern struct MemoryRegion io_mem_notdirty; - -typedef void (RAMBlockIterFunc)(void *host_addr, - ram_addr_t offset, ram_addr_t length, void *opaque); - -void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque); - -#endif - -#endif /* !CPU_COMMON_H */ diff --git a/contrib/qemu/include/exec/hwaddr.h b/contrib/qemu/include/exec/hwaddr.h deleted file mode 100644 index c9eb78fba18..00000000000 --- a/contrib/qemu/include/exec/hwaddr.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Define hwaddr if it exists. */ - -#ifndef HWADDR_H -#define HWADDR_H - -#define HWADDR_BITS 64 -/* hwaddr is the type of a physical address (its size can - be different from 'target_ulong'). */ - -typedef uint64_t hwaddr; -#define HWADDR_MAX UINT64_MAX -#define TARGET_FMT_plx "%016" PRIx64 -#define HWADDR_PRId PRId64 -#define HWADDR_PRIi PRIi64 -#define HWADDR_PRIo PRIo64 -#define HWADDR_PRIu PRIu64 -#define HWADDR_PRIx PRIx64 -#define HWADDR_PRIX PRIX64 - -#endif diff --git a/contrib/qemu/include/exec/poison.h b/contrib/qemu/include/exec/poison.h deleted file mode 100644 index 2341a750413..00000000000 --- a/contrib/qemu/include/exec/poison.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Poison identifiers that should not be used when building - target independent device code. */ - -#ifndef HW_POISON_H -#define HW_POISON_H -#ifdef __GNUC__ - -#pragma GCC poison TARGET_I386 -#pragma GCC poison TARGET_X86_64 -#pragma GCC poison TARGET_ALPHA -#pragma GCC poison TARGET_ARM -#pragma GCC poison TARGET_CRIS -#pragma GCC poison TARGET_LM32 -#pragma GCC poison TARGET_M68K -#pragma GCC poison TARGET_MIPS -#pragma GCC poison TARGET_MIPS64 -#pragma GCC poison TARGET_OPENRISC -#pragma GCC poison TARGET_PPC -#pragma GCC poison TARGET_PPCEMB -#pragma GCC poison TARGET_PPC64 -#pragma GCC poison TARGET_ABI32 -#pragma GCC poison TARGET_SH4 -#pragma GCC poison TARGET_SPARC -#pragma GCC poison TARGET_SPARC64 - -#pragma GCC poison TARGET_WORDS_BIGENDIAN -#pragma GCC poison BSWAP_NEEDED - -#pragma GCC poison TARGET_LONG_BITS -#pragma GCC poison TARGET_FMT_lx -#pragma GCC poison TARGET_FMT_ld - -#pragma GCC poison TARGET_PAGE_SIZE -#pragma GCC poison TARGET_PAGE_MASK -#pragma GCC poison TARGET_PAGE_BITS -#pragma GCC poison TARGET_PAGE_ALIGN - -#pragma GCC poison CPUArchState -#pragma GCC poison env - -#pragma GCC poison lduw_phys -#pragma GCC poison ldl_phys -#pragma GCC poison ldq_phys -#pragma GCC poison stl_phys_notdirty -#pragma GCC poison stw_phys -#pragma GCC poison stl_phys -#pragma GCC poison stq_phys - -#pragma GCC poison CPU_INTERRUPT_HARD -#pragma GCC poison CPU_INTERRUPT_EXITTB -#pragma GCC poison CPU_INTERRUPT_HALT -#pragma GCC poison CPU_INTERRUPT_DEBUG -#pragma GCC poison CPU_INTERRUPT_TGT_EXT_0 -#pragma GCC poison CPU_INTERRUPT_TGT_EXT_1 -#pragma GCC poison CPU_INTERRUPT_TGT_EXT_2 -#pragma GCC poison CPU_INTERRUPT_TGT_EXT_3 -#pragma GCC poison CPU_INTERRUPT_TGT_EXT_4 -#pragma GCC poison CPU_INTERRUPT_TGT_INT_0 -#pragma GCC poison CPU_INTERRUPT_TGT_INT_1 -#pragma GCC poison CPU_INTERRUPT_TGT_INT_2 - -#endif -#endif diff --git a/contrib/qemu/include/fpu/softfloat.h b/contrib/qemu/include/fpu/softfloat.h deleted file mode 100644 index f3927e2419f..00000000000 --- a/contrib/qemu/include/fpu/softfloat.h +++ /dev/null @@ -1,641 +0,0 @@ -/* - * QEMU float support - * - * Derived from SoftFloat. - */ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#ifndef SOFTFLOAT_H -#define SOFTFLOAT_H - -#if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH) -#include <sunmath.h> -#endif - -#include <inttypes.h> -#include "config-host.h" -#include "qemu/osdep.h" - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ -typedef uint8_t flag; -typedef uint8_t uint8; -typedef int8_t int8; -typedef unsigned int uint32; -typedef signed int int32; -typedef uint64_t uint64; -typedef int64_t int64; - -#define LIT64( a ) a##LL -#define INLINE static inline - -#define STATUS_PARAM , float_status *status -#define STATUS(field) status->field -#define STATUS_VAR , status - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point ordering relations -*----------------------------------------------------------------------------*/ -enum { - float_relation_less = -1, - float_relation_equal = 0, - float_relation_greater = 1, - float_relation_unordered = 2 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -/* Use structures for soft-float types. This prevents accidentally mixing - them with native int/float types. A sufficiently clever compiler and - sane ABI should be able to see though these structs. However - x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */ -//#define USE_SOFTFLOAT_STRUCT_TYPES -#ifdef USE_SOFTFLOAT_STRUCT_TYPES -typedef struct { - uint16_t v; -} float16; -#define float16_val(x) (((float16)(x)).v) -#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; }) -#define const_float16(x) { x } -typedef struct { - uint32_t v; -} float32; -/* The cast ensures an error if the wrong type is passed. */ -#define float32_val(x) (((float32)(x)).v) -#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; }) -#define const_float32(x) { x } -typedef struct { - uint64_t v; -} float64; -#define float64_val(x) (((float64)(x)).v) -#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; }) -#define const_float64(x) { x } -#else -typedef uint16_t float16; -typedef uint32_t float32; -typedef uint64_t float64; -#define float16_val(x) (x) -#define float32_val(x) (x) -#define float64_val(x) (x) -#define make_float16(x) (x) -#define make_float32(x) (x) -#define make_float64(x) (x) -#define const_float16(x) (x) -#define const_float32(x) (x) -#define const_float64(x) (x) -#endif -typedef struct { - uint64_t low; - uint16_t high; -} floatx80; -#define make_floatx80(exp, mant) ((floatx80) { mant, exp }) -#define make_floatx80_init(exp, mant) { .low = mant, .high = exp } -typedef struct { -#ifdef HOST_WORDS_BIGENDIAN - uint64_t high, low; -#else - uint64_t low, high; -#endif -} float128; -#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ }) -#define make_float128_init(high_, low_) { .high = high_, .low = low_ } - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -enum { - float_flag_invalid = 1, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32, - float_flag_input_denormal = 64, - float_flag_output_denormal = 128 -}; - -typedef struct float_status { - signed char float_detect_tininess; - signed char float_rounding_mode; - signed char float_exception_flags; - signed char floatx80_rounding_precision; - /* should denormalised results go to zero and set the inexact flag? */ - flag flush_to_zero; - /* should denormalised inputs go to zero and set the input_denormal flag? */ - flag flush_inputs_to_zero; - flag default_nan_mode; -} float_status; - -void set_float_rounding_mode(int val STATUS_PARAM); -void set_float_exception_flags(int val STATUS_PARAM); -INLINE void set_float_detect_tininess(int val STATUS_PARAM) -{ - STATUS(float_detect_tininess) = val; -} -INLINE void set_flush_to_zero(flag val STATUS_PARAM) -{ - STATUS(flush_to_zero) = val; -} -INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM) -{ - STATUS(flush_inputs_to_zero) = val; -} -INLINE void set_default_nan_mode(flag val STATUS_PARAM) -{ - STATUS(default_nan_mode) = val; -} -INLINE int get_float_exception_flags(float_status *status) -{ - return STATUS(float_exception_flags); -} -void set_floatx80_rounding_precision(int val STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int8 flags STATUS_PARAM); - -/*---------------------------------------------------------------------------- -| Options to indicate which negations to perform in float*_muladd() -| Using these differs from negating an input or output before calling -| the muladd function in that this means that a NaN doesn't have its -| sign bit inverted before it is propagated. -*----------------------------------------------------------------------------*/ -enum { - float_muladd_negate_c = 1, - float_muladd_negate_product = 2, - float_muladd_negate_result = 4, -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int32 STATUS_PARAM ); -float64 int32_to_float64( int32 STATUS_PARAM ); -float32 uint32_to_float32( uint32 STATUS_PARAM ); -float64 uint32_to_float64( uint32 STATUS_PARAM ); -floatx80 int32_to_floatx80( int32 STATUS_PARAM ); -float128 int32_to_float128( int32 STATUS_PARAM ); -float32 int64_to_float32( int64 STATUS_PARAM ); -float32 uint64_to_float32( uint64 STATUS_PARAM ); -float64 int64_to_float64( int64 STATUS_PARAM ); -float64 uint64_to_float64( uint64 STATUS_PARAM ); -floatx80 int64_to_floatx80( int64 STATUS_PARAM ); -float128 int64_to_float128( int64 STATUS_PARAM ); -float128 uint64_to_float128( uint64 STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software half-precision conversion routines. -*----------------------------------------------------------------------------*/ -float16 float32_to_float16( float32, flag STATUS_PARAM ); -float32 float16_to_float32( float16, flag STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software half-precision operations. -*----------------------------------------------------------------------------*/ -int float16_is_quiet_nan( float16 ); -int float16_is_signaling_nan( float16 ); -float16 float16_maybe_silence_nan( float16 ); - -INLINE int float16_is_any_nan(float16 a) -{ - return ((float16_val(a) & ~0x8000) > 0x7c00); -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated half-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float16 float16_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int_fast16_t float32_to_int16_round_to_zero(float32 STATUS_PARAM); -uint_fast16_t float32_to_uint16_round_to_zero(float32 STATUS_PARAM); -int32 float32_to_int32( float32 STATUS_PARAM ); -int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM ); -uint32 float32_to_uint32( float32 STATUS_PARAM ); -uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM ); -int64 float32_to_int64( float32 STATUS_PARAM ); -int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM ); -float64 float32_to_float64( float32 STATUS_PARAM ); -floatx80 float32_to_floatx80( float32 STATUS_PARAM ); -float128 float32_to_float128( float32 STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 STATUS_PARAM ); -float32 float32_add( float32, float32 STATUS_PARAM ); -float32 float32_sub( float32, float32 STATUS_PARAM ); -float32 float32_mul( float32, float32 STATUS_PARAM ); -float32 float32_div( float32, float32 STATUS_PARAM ); -float32 float32_rem( float32, float32 STATUS_PARAM ); -float32 float32_muladd(float32, float32, float32, int STATUS_PARAM); -float32 float32_sqrt( float32 STATUS_PARAM ); -float32 float32_exp2( float32 STATUS_PARAM ); -float32 float32_log2( float32 STATUS_PARAM ); -int float32_eq( float32, float32 STATUS_PARAM ); -int float32_le( float32, float32 STATUS_PARAM ); -int float32_lt( float32, float32 STATUS_PARAM ); -int float32_unordered( float32, float32 STATUS_PARAM ); -int float32_eq_quiet( float32, float32 STATUS_PARAM ); -int float32_le_quiet( float32, float32 STATUS_PARAM ); -int float32_lt_quiet( float32, float32 STATUS_PARAM ); -int float32_unordered_quiet( float32, float32 STATUS_PARAM ); -int float32_compare( float32, float32 STATUS_PARAM ); -int float32_compare_quiet( float32, float32 STATUS_PARAM ); -float32 float32_min(float32, float32 STATUS_PARAM); -float32 float32_max(float32, float32 STATUS_PARAM); -int float32_is_quiet_nan( float32 ); -int float32_is_signaling_nan( float32 ); -float32 float32_maybe_silence_nan( float32 ); -float32 float32_scalbn( float32, int STATUS_PARAM ); - -INLINE float32 float32_abs(float32 a) -{ - /* Note that abs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float32(float32_val(a) & 0x7fffffff); -} - -INLINE float32 float32_chs(float32 a) -{ - /* Note that chs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float32(float32_val(a) ^ 0x80000000); -} - -INLINE int float32_is_infinity(float32 a) -{ - return (float32_val(a) & 0x7fffffff) == 0x7f800000; -} - -INLINE int float32_is_neg(float32 a) -{ - return float32_val(a) >> 31; -} - -INLINE int float32_is_zero(float32 a) -{ - return (float32_val(a) & 0x7fffffff) == 0; -} - -INLINE int float32_is_any_nan(float32 a) -{ - return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL); -} - -INLINE int float32_is_zero_or_denormal(float32 a) -{ - return (float32_val(a) & 0x7f800000) == 0; -} - -INLINE float32 float32_set_sign(float32 a, int sign) -{ - return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31)); -} - -#define float32_zero make_float32(0) -#define float32_one make_float32(0x3f800000) -#define float32_ln2 make_float32(0x3f317218) -#define float32_pi make_float32(0x40490fdb) -#define float32_half make_float32(0x3f000000) -#define float32_infinity make_float32(0x7f800000) - - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float32 float32_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int_fast16_t float64_to_int16_round_to_zero(float64 STATUS_PARAM); -uint_fast16_t float64_to_uint16_round_to_zero(float64 STATUS_PARAM); -int32 float64_to_int32( float64 STATUS_PARAM ); -int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM ); -uint32 float64_to_uint32( float64 STATUS_PARAM ); -uint32 float64_to_uint32_round_to_zero( float64 STATUS_PARAM ); -int64 float64_to_int64( float64 STATUS_PARAM ); -int64 float64_to_int64_round_to_zero( float64 STATUS_PARAM ); -uint64 float64_to_uint64 (float64 a STATUS_PARAM); -uint64 float64_to_uint64_round_to_zero (float64 a STATUS_PARAM); -float32 float64_to_float32( float64 STATUS_PARAM ); -floatx80 float64_to_floatx80( float64 STATUS_PARAM ); -float128 float64_to_float128( float64 STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 STATUS_PARAM ); -float64 float64_trunc_to_int( float64 STATUS_PARAM ); -float64 float64_add( float64, float64 STATUS_PARAM ); -float64 float64_sub( float64, float64 STATUS_PARAM ); -float64 float64_mul( float64, float64 STATUS_PARAM ); -float64 float64_div( float64, float64 STATUS_PARAM ); -float64 float64_rem( float64, float64 STATUS_PARAM ); -float64 float64_muladd(float64, float64, float64, int STATUS_PARAM); -float64 float64_sqrt( float64 STATUS_PARAM ); -float64 float64_log2( float64 STATUS_PARAM ); -int float64_eq( float64, float64 STATUS_PARAM ); -int float64_le( float64, float64 STATUS_PARAM ); -int float64_lt( float64, float64 STATUS_PARAM ); -int float64_unordered( float64, float64 STATUS_PARAM ); -int float64_eq_quiet( float64, float64 STATUS_PARAM ); -int float64_le_quiet( float64, float64 STATUS_PARAM ); -int float64_lt_quiet( float64, float64 STATUS_PARAM ); -int float64_unordered_quiet( float64, float64 STATUS_PARAM ); -int float64_compare( float64, float64 STATUS_PARAM ); -int float64_compare_quiet( float64, float64 STATUS_PARAM ); -float64 float64_min(float64, float64 STATUS_PARAM); -float64 float64_max(float64, float64 STATUS_PARAM); -int float64_is_quiet_nan( float64 a ); -int float64_is_signaling_nan( float64 ); -float64 float64_maybe_silence_nan( float64 ); -float64 float64_scalbn( float64, int STATUS_PARAM ); - -INLINE float64 float64_abs(float64 a) -{ - /* Note that abs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float64(float64_val(a) & 0x7fffffffffffffffLL); -} - -INLINE float64 float64_chs(float64 a) -{ - /* Note that chs does *not* handle NaN specially, nor does - * it flush denormal inputs to zero. - */ - return make_float64(float64_val(a) ^ 0x8000000000000000LL); -} - -INLINE int float64_is_infinity(float64 a) -{ - return (float64_val(a) & 0x7fffffffffffffffLL ) == 0x7ff0000000000000LL; -} - -INLINE int float64_is_neg(float64 a) -{ - return float64_val(a) >> 63; -} - -INLINE int float64_is_zero(float64 a) -{ - return (float64_val(a) & 0x7fffffffffffffffLL) == 0; -} - -INLINE int float64_is_any_nan(float64 a) -{ - return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL); -} - -INLINE int float64_is_zero_or_denormal(float64 a) -{ - return (float64_val(a) & 0x7ff0000000000000LL) == 0; -} - -INLINE float64 float64_set_sign(float64 a, int sign) -{ - return make_float64((float64_val(a) & 0x7fffffffffffffffULL) - | ((int64_t)sign << 63)); -} - -#define float64_zero make_float64(0) -#define float64_one make_float64(0x3ff0000000000000LL) -#define float64_ln2 make_float64(0x3fe62e42fefa39efLL) -#define float64_pi make_float64(0x400921fb54442d18LL) -#define float64_half make_float64(0x3fe0000000000000LL) -#define float64_infinity make_float64(0x7ff0000000000000LL) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float64 float64_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 floatx80_to_int32( floatx80 STATUS_PARAM ); -int32 floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM ); -int64 floatx80_to_int64( floatx80 STATUS_PARAM ); -int64 floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM ); -float32 floatx80_to_float32( floatx80 STATUS_PARAM ); -float64 floatx80_to_float64( floatx80 STATUS_PARAM ); -float128 floatx80_to_float128( floatx80 STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM ); -floatx80 floatx80_add( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_sub( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_sqrt( floatx80 STATUS_PARAM ); -int floatx80_eq( floatx80, floatx80 STATUS_PARAM ); -int floatx80_le( floatx80, floatx80 STATUS_PARAM ); -int floatx80_lt( floatx80, floatx80 STATUS_PARAM ); -int floatx80_unordered( floatx80, floatx80 STATUS_PARAM ); -int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_compare( floatx80, floatx80 STATUS_PARAM ); -int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_is_quiet_nan( floatx80 ); -int floatx80_is_signaling_nan( floatx80 ); -floatx80 floatx80_maybe_silence_nan( floatx80 ); -floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM ); - -INLINE floatx80 floatx80_abs(floatx80 a) -{ - a.high &= 0x7fff; - return a; -} - -INLINE floatx80 floatx80_chs(floatx80 a) -{ - a.high ^= 0x8000; - return a; -} - -INLINE int floatx80_is_infinity(floatx80 a) -{ - return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL; -} - -INLINE int floatx80_is_neg(floatx80 a) -{ - return a.high >> 15; -} - -INLINE int floatx80_is_zero(floatx80 a) -{ - return (a.high & 0x7fff) == 0 && a.low == 0; -} - -INLINE int floatx80_is_zero_or_denormal(floatx80 a) -{ - return (a.high & 0x7fff) == 0; -} - -INLINE int floatx80_is_any_nan(floatx80 a) -{ - return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1); -} - -#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL) -#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL) -#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL) -#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL) -#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL) -#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const floatx80 floatx80_default_nan; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float128_to_int32( float128 STATUS_PARAM ); -int32 float128_to_int32_round_to_zero( float128 STATUS_PARAM ); -int64 float128_to_int64( float128 STATUS_PARAM ); -int64 float128_to_int64_round_to_zero( float128 STATUS_PARAM ); -float32 float128_to_float32( float128 STATUS_PARAM ); -float64 float128_to_float64( float128 STATUS_PARAM ); -floatx80 float128_to_floatx80( float128 STATUS_PARAM ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 STATUS_PARAM ); -float128 float128_add( float128, float128 STATUS_PARAM ); -float128 float128_sub( float128, float128 STATUS_PARAM ); -float128 float128_mul( float128, float128 STATUS_PARAM ); -float128 float128_div( float128, float128 STATUS_PARAM ); -float128 float128_rem( float128, float128 STATUS_PARAM ); -float128 float128_sqrt( float128 STATUS_PARAM ); -int float128_eq( float128, float128 STATUS_PARAM ); -int float128_le( float128, float128 STATUS_PARAM ); -int float128_lt( float128, float128 STATUS_PARAM ); -int float128_unordered( float128, float128 STATUS_PARAM ); -int float128_eq_quiet( float128, float128 STATUS_PARAM ); -int float128_le_quiet( float128, float128 STATUS_PARAM ); -int float128_lt_quiet( float128, float128 STATUS_PARAM ); -int float128_unordered_quiet( float128, float128 STATUS_PARAM ); -int float128_compare( float128, float128 STATUS_PARAM ); -int float128_compare_quiet( float128, float128 STATUS_PARAM ); -int float128_is_quiet_nan( float128 ); -int float128_is_signaling_nan( float128 ); -float128 float128_maybe_silence_nan( float128 ); -float128 float128_scalbn( float128, int STATUS_PARAM ); - -INLINE float128 float128_abs(float128 a) -{ - a.high &= 0x7fffffffffffffffLL; - return a; -} - -INLINE float128 float128_chs(float128 a) -{ - a.high ^= 0x8000000000000000LL; - return a; -} - -INLINE int float128_is_infinity(float128 a) -{ - return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0; -} - -INLINE int float128_is_neg(float128 a) -{ - return a.high >> 63; -} - -INLINE int float128_is_zero(float128 a) -{ - return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0; -} - -INLINE int float128_is_zero_or_denormal(float128 a) -{ - return (a.high & 0x7fff000000000000LL) == 0; -} - -INLINE int float128_is_any_nan(float128 a) -{ - return ((a.high >> 48) & 0x7fff) == 0x7fff && - ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0)); -} - -#define float128_zero make_float128(0, 0) - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float128 float128_default_nan; - -#endif /* !SOFTFLOAT_H */ diff --git a/contrib/qemu/include/glib-compat.h b/contrib/qemu/include/glib-compat.h deleted file mode 100644 index 8aa77afd626..00000000000 --- a/contrib/qemu/include/glib-compat.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * GLIB Compatibility Functions - * - * Copyright IBM, Corp. 2013 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QEMU_GLIB_COMPAT_H -#define QEMU_GLIB_COMPAT_H - -#include <glib.h> - -#if !GLIB_CHECK_VERSION(2, 14, 0) -static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, - gpointer data) -{ - return g_timeout_add(interval * 1000, function, data); -} -#endif - -#endif diff --git a/contrib/qemu/include/migration/migration.h b/contrib/qemu/include/migration/migration.h deleted file mode 100644 index bc9fde0b2ab..00000000000 --- a/contrib/qemu/include/migration/migration.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * QEMU live migration - * - * 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. - * - */ - -#ifndef QEMU_MIGRATION_H -#define QEMU_MIGRATION_H - -#include "qapi/qmp/qdict.h" -#include "qemu-common.h" -#include "qemu/thread.h" -#include "qemu/notify.h" -#include "qapi/error.h" -#include "migration/vmstate.h" -#include "qapi-types.h" -#include "exec/cpu-common.h" - -struct MigrationParams { - bool blk; - bool shared; -}; - -typedef struct MigrationState MigrationState; - -struct MigrationState -{ - int64_t bandwidth_limit; - size_t bytes_xfer; - size_t xfer_limit; - QemuThread thread; - QEMUBH *cleanup_bh; - QEMUFile *file; - - int state; - MigrationParams params; - double mbps; - int64_t total_time; - int64_t downtime; - int64_t expected_downtime; - int64_t dirty_pages_rate; - int64_t dirty_bytes_rate; - bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; - int64_t xbzrle_cache_size; -}; - -void process_incoming_migration(QEMUFile *f); - -void qemu_start_incoming_migration(const char *uri, Error **errp); - -uint64_t migrate_max_downtime(void); - -void do_info_migrate_print(Monitor *mon, const QObject *data); - -void do_info_migrate(Monitor *mon, QObject **ret_data); - -void exec_start_incoming_migration(const char *host_port, Error **errp); - -void exec_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); - -void tcp_start_incoming_migration(const char *host_port, Error **errp); - -void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); - -void unix_start_incoming_migration(const char *path, Error **errp); - -void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp); - -void fd_start_incoming_migration(const char *path, Error **errp); - -void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp); - -void migrate_fd_error(MigrationState *s); - -void migrate_fd_connect(MigrationState *s); - -int migrate_fd_close(MigrationState *s); - -void add_migration_state_change_notifier(Notifier *notify); -void remove_migration_state_change_notifier(Notifier *notify); -bool migration_is_active(MigrationState *); -bool migration_has_finished(MigrationState *); -bool migration_has_failed(MigrationState *); -MigrationState *migrate_get_current(void); - -uint64_t ram_bytes_remaining(void); -uint64_t ram_bytes_transferred(void); -uint64_t ram_bytes_total(void); - -void acct_update_position(QEMUFile *f, size_t size, bool zero); - -extern SaveVMHandlers savevm_ram_handlers; - -uint64_t dup_mig_bytes_transferred(void); -uint64_t dup_mig_pages_transferred(void); -uint64_t skipped_mig_bytes_transferred(void); -uint64_t skipped_mig_pages_transferred(void); -uint64_t norm_mig_bytes_transferred(void); -uint64_t norm_mig_pages_transferred(void); -uint64_t xbzrle_mig_bytes_transferred(void); -uint64_t xbzrle_mig_pages_transferred(void); -uint64_t xbzrle_mig_pages_overflow(void); -uint64_t xbzrle_mig_pages_cache_miss(void); - -/** - * @migrate_add_blocker - prevent migration from proceeding - * - * @reason - an error to be returned whenever migration is attempted - */ -void migrate_add_blocker(Error *reason); - -/** - * @migrate_del_blocker - remove a blocking error from migration - * - * @reason - the error blocking migration - */ -void migrate_del_blocker(Error *reason); - -bool migrate_rdma_pin_all(void); - -bool migrate_auto_converge(void); - -int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, - uint8_t *dst, int dlen); -int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen); - -int migrate_use_xbzrle(void); -int64_t migrate_xbzrle_cache_size(void); - -int64_t xbzrle_cache_resize(int64_t new_size); - -void ram_control_before_iterate(QEMUFile *f, uint64_t flags); -void ram_control_after_iterate(QEMUFile *f, uint64_t flags); -void ram_control_load_hook(QEMUFile *f, uint64_t flags); - -/* Whenever this is found in the data stream, the flags - * will be passed to ram_control_load_hook in the incoming-migration - * side. This lets before_ram_iterate/after_ram_iterate add - * transport-specific sections to the RAM migration data. - */ -#define RAM_SAVE_FLAG_HOOK 0x80 - -#define RAM_SAVE_CONTROL_NOT_SUPP -1000 -#define RAM_SAVE_CONTROL_DELAYED -2000 - -size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, - ram_addr_t offset, size_t size, - int *bytes_sent); - -#endif diff --git a/contrib/qemu/include/migration/qemu-file.h b/contrib/qemu/include/migration/qemu-file.h deleted file mode 100644 index 0f757fbeb63..00000000000 --- a/contrib/qemu/include/migration/qemu-file.h +++ /dev/null @@ -1,266 +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. - */ -#ifndef QEMU_FILE_H -#define QEMU_FILE_H 1 -#include "exec/cpu-common.h" - -/* This function writes a chunk of data to a file at the given position. - * The pos argument can be ignored if the file is only being used for - * streaming. The handler should try to write all of the data it can. - */ -typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf, - int64_t pos, int size); - -/* Read a chunk of data from a file at the given position. The pos argument - * can be ignored if the file is only be used for streaming. The number of - * bytes actually read should be returned. - */ -typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf, - int64_t pos, int size); - -/* Close a file - * - * Return negative error number on error, 0 or positive value on success. - * - * The meaning of return value on success depends on the specific back-end being - * used. - */ -typedef int (QEMUFileCloseFunc)(void *opaque); - -/* Called to return the OS file descriptor associated to the QEMUFile. - */ -typedef int (QEMUFileGetFD)(void *opaque); - -/* - * This function writes an iovec to file. - */ -typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov, - int iovcnt, int64_t pos); - -/* - * This function provides hooks around different - * stages of RAM migration. - */ -typedef int (QEMURamHookFunc)(QEMUFile *f, void *opaque, uint64_t flags); - -/* - * Constants used by ram_control_* hooks - */ -#define RAM_CONTROL_SETUP 0 -#define RAM_CONTROL_ROUND 1 -#define RAM_CONTROL_HOOK 2 -#define RAM_CONTROL_FINISH 3 - -/* - * This function allows override of where the RAM page - * is saved (such as RDMA, for example.) - */ -typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque, - ram_addr_t block_offset, - ram_addr_t offset, - size_t size, - int *bytes_sent); - -typedef struct QEMUFileOps { - QEMUFilePutBufferFunc *put_buffer; - QEMUFileGetBufferFunc *get_buffer; - QEMUFileCloseFunc *close; - QEMUFileGetFD *get_fd; - QEMUFileWritevBufferFunc *writev_buffer; - QEMURamHookFunc *before_ram_iterate; - QEMURamHookFunc *after_ram_iterate; - QEMURamHookFunc *hook_ram_load; - QEMURamSaveFunc *save_page; -} QEMUFileOps; - -QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops); -QEMUFile *qemu_fopen(const char *filename, const char *mode); -QEMUFile *qemu_fdopen(int fd, const char *mode); -QEMUFile *qemu_fopen_socket(int fd, const char *mode); -QEMUFile *qemu_popen_cmd(const char *command, const char *mode); -int qemu_get_fd(QEMUFile *f); -int qemu_fclose(QEMUFile *f); -int64_t qemu_ftell(QEMUFile *f); -void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); -void qemu_put_byte(QEMUFile *f, int v); -/* - * put_buffer without copying the buffer. - * The buffer should be available till it is sent asynchronously. - */ -void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size); -bool qemu_file_mode_is_not_valid(const char *mode); - -static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v) -{ - qemu_put_byte(f, (int)v); -} - -#define qemu_put_sbyte qemu_put_byte - -void qemu_put_be16(QEMUFile *f, unsigned int v); -void qemu_put_be32(QEMUFile *f, unsigned int v); -void qemu_put_be64(QEMUFile *f, uint64_t v); -int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); -int qemu_get_byte(QEMUFile *f); -void qemu_update_position(QEMUFile *f, size_t size); - -static inline unsigned int qemu_get_ubyte(QEMUFile *f) -{ - return (unsigned int)qemu_get_byte(f); -} - -#define qemu_get_sbyte qemu_get_byte - -unsigned int qemu_get_be16(QEMUFile *f); -unsigned int qemu_get_be32(QEMUFile *f); -uint64_t qemu_get_be64(QEMUFile *f); - -int qemu_file_rate_limit(QEMUFile *f); -void qemu_file_reset_rate_limit(QEMUFile *f); -void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); -int64_t qemu_file_get_rate_limit(QEMUFile *f); -int qemu_file_get_error(QEMUFile *f); -void qemu_fflush(QEMUFile *f); - -static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) -{ - qemu_put_be64(f, *pv); -} - -static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv) -{ - qemu_put_be32(f, *pv); -} - -static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv) -{ - qemu_put_be16(f, *pv); -} - -static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv) -{ - qemu_put_byte(f, *pv); -} - -static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv) -{ - *pv = qemu_get_be64(f); -} - -static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv) -{ - *pv = qemu_get_be32(f); -} - -static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv) -{ - *pv = qemu_get_be16(f); -} - -static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv) -{ - *pv = qemu_get_byte(f); -} - -// Signed versions for type safety -static inline void qemu_put_sbuffer(QEMUFile *f, const int8_t *buf, int size) -{ - qemu_put_buffer(f, (const uint8_t *)buf, size); -} - -static inline void qemu_put_sbe16(QEMUFile *f, int v) -{ - qemu_put_be16(f, (unsigned int)v); -} - -static inline void qemu_put_sbe32(QEMUFile *f, int v) -{ - qemu_put_be32(f, (unsigned int)v); -} - -static inline void qemu_put_sbe64(QEMUFile *f, int64_t v) -{ - qemu_put_be64(f, (uint64_t)v); -} - -static inline size_t qemu_get_sbuffer(QEMUFile *f, int8_t *buf, int size) -{ - return qemu_get_buffer(f, (uint8_t *)buf, size); -} - -static inline int qemu_get_sbe16(QEMUFile *f) -{ - return (int)qemu_get_be16(f); -} - -static inline int qemu_get_sbe32(QEMUFile *f) -{ - return (int)qemu_get_be32(f); -} - -static inline int64_t qemu_get_sbe64(QEMUFile *f) -{ - return (int64_t)qemu_get_be64(f); -} - -static inline void qemu_put_s8s(QEMUFile *f, const int8_t *pv) -{ - qemu_put_8s(f, (const uint8_t *)pv); -} - -static inline void qemu_put_sbe16s(QEMUFile *f, const int16_t *pv) -{ - qemu_put_be16s(f, (const uint16_t *)pv); -} - -static inline void qemu_put_sbe32s(QEMUFile *f, const int32_t *pv) -{ - qemu_put_be32s(f, (const uint32_t *)pv); -} - -static inline void qemu_put_sbe64s(QEMUFile *f, const int64_t *pv) -{ - qemu_put_be64s(f, (const uint64_t *)pv); -} - -static inline void qemu_get_s8s(QEMUFile *f, int8_t *pv) -{ - qemu_get_8s(f, (uint8_t *)pv); -} - -static inline void qemu_get_sbe16s(QEMUFile *f, int16_t *pv) -{ - qemu_get_be16s(f, (uint16_t *)pv); -} - -static inline void qemu_get_sbe32s(QEMUFile *f, int32_t *pv) -{ - qemu_get_be32s(f, (uint32_t *)pv); -} - -static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv) -{ - qemu_get_be64s(f, (uint64_t *)pv); -} -#endif diff --git a/contrib/qemu/include/migration/vmstate.h b/contrib/qemu/include/migration/vmstate.h deleted file mode 100644 index 1c31b5d6fb5..00000000000 --- a/contrib/qemu/include/migration/vmstate.h +++ /dev/null @@ -1,740 +0,0 @@ -/* - * QEMU migration/snapshot declarations - * - * Copyright (c) 2009-2011 Red Hat, Inc. - * - * Original author: Juan Quintela <quintela@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. - */ -#ifndef QEMU_VMSTATE_H -#define QEMU_VMSTATE_H 1 - -#ifndef CONFIG_USER_ONLY -#include <migration/qemu-file.h> -#endif - -typedef void SaveStateHandler(QEMUFile *f, void *opaque); -typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); - -typedef struct SaveVMHandlers { - /* This runs inside the iothread lock. */ - void (*set_params)(const MigrationParams *params, void * opaque); - SaveStateHandler *save_state; - - void (*cancel)(void *opaque); - int (*save_live_complete)(QEMUFile *f, void *opaque); - - /* This runs both outside and inside the iothread lock. */ - bool (*is_active)(void *opaque); - - /* This runs outside the iothread lock in the migration case, and - * within the lock in the savevm case. The callback had better only - * use data that is local to the migration thread or protected - * by other locks. - */ - int (*save_live_iterate)(QEMUFile *f, void *opaque); - - /* This runs outside the iothread lock! */ - int (*save_live_setup)(QEMUFile *f, void *opaque); - uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size); - - LoadStateHandler *load_state; -} SaveVMHandlers; - -int register_savevm(DeviceState *dev, - const char *idstr, - int instance_id, - int version_id, - SaveStateHandler *save_state, - LoadStateHandler *load_state, - void *opaque); - -int register_savevm_live(DeviceState *dev, - const char *idstr, - int instance_id, - int version_id, - SaveVMHandlers *ops, - void *opaque); - -void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); -void register_device_unmigratable(DeviceState *dev, const char *idstr, - void *opaque); - - -typedef struct VMStateInfo VMStateInfo; -typedef struct VMStateDescription VMStateDescription; - -struct VMStateInfo { - const char *name; - int (*get)(QEMUFile *f, void *pv, size_t size); - void (*put)(QEMUFile *f, void *pv, size_t size); -}; - -enum VMStateFlags { - VMS_SINGLE = 0x001, - VMS_POINTER = 0x002, - VMS_ARRAY = 0x004, - VMS_STRUCT = 0x008, - VMS_VARRAY_INT32 = 0x010, /* Array with size in int32_t field*/ - VMS_BUFFER = 0x020, /* static sized buffer */ - VMS_ARRAY_OF_POINTER = 0x040, - VMS_VARRAY_UINT16 = 0x080, /* Array with size in uint16_t field */ - VMS_VBUFFER = 0x100, /* Buffer with size in int32_t field */ - VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */ - VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/ - VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/ -}; - -typedef struct { - const char *name; - size_t offset; - size_t size; - size_t start; - int num; - size_t num_offset; - size_t size_offset; - const VMStateInfo *info; - enum VMStateFlags flags; - const VMStateDescription *vmsd; - int version_id; - bool (*field_exists)(void *opaque, int version_id); -} VMStateField; - -typedef struct VMStateSubsection { - const VMStateDescription *vmsd; - bool (*needed)(void *opaque); -} VMStateSubsection; - -struct VMStateDescription { - const char *name; - int unmigratable; - int version_id; - int minimum_version_id; - int minimum_version_id_old; - LoadStateHandler *load_state_old; - int (*pre_load)(void *opaque); - int (*post_load)(void *opaque, int version_id); - void (*pre_save)(void *opaque); - VMStateField *fields; - const VMStateSubsection *subsections; -}; - -#ifdef CONFIG_USER_ONLY -extern const VMStateDescription vmstate_dummy; -#endif - -extern const VMStateInfo vmstate_info_bool; - -extern const VMStateInfo vmstate_info_int8; -extern const VMStateInfo vmstate_info_int16; -extern const VMStateInfo vmstate_info_int32; -extern const VMStateInfo vmstate_info_int64; - -extern const VMStateInfo vmstate_info_uint8_equal; -extern const VMStateInfo vmstate_info_uint16_equal; -extern const VMStateInfo vmstate_info_int32_equal; -extern const VMStateInfo vmstate_info_uint32_equal; -extern const VMStateInfo vmstate_info_uint64_equal; -extern const VMStateInfo vmstate_info_int32_le; - -extern const VMStateInfo vmstate_info_uint8; -extern const VMStateInfo vmstate_info_uint16; -extern const VMStateInfo vmstate_info_uint32; -extern const VMStateInfo vmstate_info_uint64; - -extern const VMStateInfo vmstate_info_float64; - -extern const VMStateInfo vmstate_info_timer; -extern const VMStateInfo vmstate_info_buffer; -extern const VMStateInfo vmstate_info_unused_buffer; -extern const VMStateInfo vmstate_info_bitmap; - -#define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0) -#define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0) -#define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0) - -#define vmstate_offset_value(_state, _field, _type) \ - (offsetof(_state, _field) + \ - type_check(_type, typeof_field(_state, _field))) - -#define vmstate_offset_pointer(_state, _field, _type) \ - (offsetof(_state, _field) + \ - type_check_pointer(_type, typeof_field(_state, _field))) - -#define vmstate_offset_array(_state, _field, _type, _num) \ - (offsetof(_state, _field) + \ - type_check_array(_type, typeof_field(_state, _field), _num)) - -#define vmstate_offset_2darray(_state, _field, _type, _n1, _n2) \ - (offsetof(_state, _field) + \ - type_check_2darray(_type, typeof_field(_state, _field), _n1, _n2)) - -#define vmstate_offset_sub_array(_state, _field, _type, _start) \ - (offsetof(_state, _field[_start])) - -#define vmstate_offset_buffer(_state, _field) \ - vmstate_offset_array(_state, _field, uint8_t, \ - sizeof(typeof_field(_state, _field))) - -#define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .size = sizeof(_type), \ - .info = &(_info), \ - .flags = VMS_SINGLE, \ - .offset = vmstate_offset_value(_state, _field, _type), \ -} - -#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_SINGLE|VMS_POINTER, \ - .offset = vmstate_offset_value(_state, _field, _type), \ -} - -#define VMSTATE_POINTER_TEST(_field, _state, _test, _info, _type) { \ - .name = (stringify(_field)), \ - .info = &(_info), \ - .field_exists = (_test), \ - .size = sizeof(_type), \ - .flags = VMS_SINGLE|VMS_POINTER, \ - .offset = vmstate_offset_value(_state, _field, _type), \ -} - -#define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) {\ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num = (_num), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_ARRAY, \ - .offset = vmstate_offset_array(_state, _field, _type, _num), \ -} - -#define VMSTATE_2DARRAY(_field, _state, _n1, _n2, _version, _info, _type) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num = (_n1) * (_n2), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_ARRAY, \ - .offset = vmstate_offset_2darray(_state, _field, _type, _n1, _n2), \ -} - -#define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\ - .name = (stringify(_field)), \ - .field_exists = (_test), \ - .num = (_num), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_ARRAY, \ - .offset = vmstate_offset_array(_state, _field, _type, _num),\ -} - -#define VMSTATE_SUB_ARRAY(_field, _state, _start, _num, _version, _info, _type) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num = (_num), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_ARRAY, \ - .offset = vmstate_offset_sub_array(_state, _field, _type, _start), \ -} - -#define VMSTATE_ARRAY_INT32_UNSAFE(_field, _state, _field_num, _info, _type) {\ - .name = (stringify(_field)), \ - .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_VARRAY_INT32, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_VARRAY_INT32(_field, _state, _field_num, _version, _info, _type) {\ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_VARRAY_INT32|VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ -} - -#define VMSTATE_VARRAY_UINT32(_field, _state, _field_num, _version, _info, _type) {\ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_VARRAY_UINT32|VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ -} - -#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_VARRAY_UINT16, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, _type), \ -} - -#define VMSTATE_STRUCT_POINTER_TEST(_field, _state, _test, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .field_exists = (_test), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT|VMS_POINTER, \ - .offset = vmstate_offset_value(_state, _field, _type), \ -} - -#define VMSTATE_ARRAY_OF_POINTER(_field, _state, _num, _version, _info, _type) {\ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .num = (_num), \ - .info = &(_info), \ - .size = sizeof(_type), \ - .flags = VMS_ARRAY|VMS_ARRAY_OF_POINTER, \ - .offset = vmstate_offset_array(_state, _field, _type, _num), \ -} - -#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .num = (_num), \ - .field_exists = (_test), \ - .version_id = (_version), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT|VMS_ARRAY, \ - .offset = vmstate_offset_array(_state, _field, _type, _num),\ -} - -#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \ - .version_id = (_version), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT|VMS_VARRAY_UINT8, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_STRUCT_VARRAY_POINTER_INT32(_field, _state, _field_num, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .version_id = 0, \ - .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ - .size = sizeof(_type), \ - .vmsd = &(_vmsd), \ - .flags = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ -} - -#define VMSTATE_STRUCT_VARRAY_POINTER_UINT32(_field, _state, _field_num, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .version_id = 0, \ - .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\ - .size = sizeof(_type), \ - .vmsd = &(_vmsd), \ - .flags = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ -} - -#define VMSTATE_STRUCT_VARRAY_POINTER_UINT16(_field, _state, _field_num, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .version_id = 0, \ - .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\ - .size = sizeof(_type), \ - .vmsd = &(_vmsd), \ - .flags = VMS_POINTER | VMS_VARRAY_UINT16 | VMS_STRUCT, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ -} - -#define VMSTATE_STRUCT_VARRAY_INT32(_field, _state, _field_num, _version, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \ - .version_id = (_version), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT|VMS_VARRAY_INT32, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_STRUCT_VARRAY_UINT32(_field, _state, _field_num, _version, _vmsd, _type) { \ - .name = (stringify(_field)), \ - .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \ - .version_id = (_version), \ - .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ - .flags = VMS_STRUCT|VMS_VARRAY_UINT32, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .size = (_size - _start), \ - .info = &vmstate_info_buffer, \ - .flags = VMS_BUFFER, \ - .offset = vmstate_offset_buffer(_state, _field) + _start, \ -} - -#define VMSTATE_VBUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\ - .size = (_multiply), \ - .info = &vmstate_info_buffer, \ - .flags = VMS_VBUFFER|VMS_POINTER|VMS_MULTIPLY, \ - .offset = offsetof(_state, _field), \ - .start = (_start), \ -} - -#define VMSTATE_VBUFFER(_field, _state, _version, _test, _start, _field_size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\ - .info = &vmstate_info_buffer, \ - .flags = VMS_VBUFFER|VMS_POINTER, \ - .offset = offsetof(_state, _field), \ - .start = (_start), \ -} - -#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _start, _field_size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .field_exists = (_test), \ - .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\ - .info = &vmstate_info_buffer, \ - .flags = VMS_VBUFFER|VMS_POINTER, \ - .offset = offsetof(_state, _field), \ - .start = (_start), \ -} - -#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .size = (_size), \ - .info = &(_info), \ - .flags = VMS_BUFFER, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_BUFFER_POINTER_UNSAFE(_field, _state, _version, _size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .size = (_size), \ - .info = &vmstate_info_buffer, \ - .flags = VMS_BUFFER|VMS_POINTER, \ - .offset = offsetof(_state, _field), \ -} - -#define VMSTATE_UNUSED_BUFFER(_test, _version, _size) { \ - .name = "unused", \ - .field_exists = (_test), \ - .version_id = (_version), \ - .size = (_size), \ - .info = &vmstate_info_unused_buffer, \ - .flags = VMS_BUFFER, \ -} - -/* _field_size should be a int32_t field in the _state struct giving the - * size of the bitmap _field in bits. - */ -#define VMSTATE_BITMAP(_field, _state, _version, _field_size) { \ - .name = (stringify(_field)), \ - .version_id = (_version), \ - .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\ - .info = &vmstate_info_bitmap, \ - .flags = VMS_VBUFFER|VMS_POINTER, \ - .offset = offsetof(_state, _field), \ -} - -/* _f : field name - _f_n : num of elements field_name - _n : num of elements - _s : struct state name - _v : version -*/ - -#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \ - VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type) - -#define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \ - VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type) - -#define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \ - VMSTATE_STRUCT_POINTER_TEST(_field, _state, NULL, _vmsd, _type) - -#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \ - VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, \ - _vmsd, _type) - -#define VMSTATE_BOOL_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_bool, bool) - -#define VMSTATE_INT8_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int8, int8_t) -#define VMSTATE_INT16_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int16, int16_t) -#define VMSTATE_INT32_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int32, int32_t) -#define VMSTATE_INT64_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int64, int64_t) - -#define VMSTATE_UINT8_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, uint8_t) -#define VMSTATE_UINT16_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, uint16_t) -#define VMSTATE_UINT32_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, uint32_t) -#define VMSTATE_UINT64_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t) - -#define VMSTATE_BOOL(_f, _s) \ - VMSTATE_BOOL_V(_f, _s, 0) - -#define VMSTATE_INT8(_f, _s) \ - VMSTATE_INT8_V(_f, _s, 0) -#define VMSTATE_INT16(_f, _s) \ - VMSTATE_INT16_V(_f, _s, 0) -#define VMSTATE_INT32(_f, _s) \ - VMSTATE_INT32_V(_f, _s, 0) -#define VMSTATE_INT64(_f, _s) \ - VMSTATE_INT64_V(_f, _s, 0) - -#define VMSTATE_UINT8(_f, _s) \ - VMSTATE_UINT8_V(_f, _s, 0) -#define VMSTATE_UINT16(_f, _s) \ - VMSTATE_UINT16_V(_f, _s, 0) -#define VMSTATE_UINT32(_f, _s) \ - VMSTATE_UINT32_V(_f, _s, 0) -#define VMSTATE_UINT64(_f, _s) \ - VMSTATE_UINT64_V(_f, _s, 0) - -#define VMSTATE_UINT8_EQUAL(_f, _s) \ - VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint8_equal, uint8_t) - -#define VMSTATE_UINT16_EQUAL(_f, _s) \ - VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint16_equal, uint16_t) - -#define VMSTATE_UINT16_EQUAL_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16_equal, uint16_t) - -#define VMSTATE_INT32_EQUAL(_f, _s) \ - VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_equal, int32_t) - -#define VMSTATE_UINT32_EQUAL_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32_equal, uint32_t) - -#define VMSTATE_UINT32_EQUAL(_f, _s) \ - VMSTATE_UINT32_EQUAL_V(_f, _s, 0) - -#define VMSTATE_UINT64_EQUAL_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64_equal, uint64_t) - -#define VMSTATE_UINT64_EQUAL(_f, _s) \ - VMSTATE_UINT64_EQUAL_V(_f, _s, 0) - -#define VMSTATE_INT32_LE(_f, _s) \ - VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t) - -#define VMSTATE_UINT8_TEST(_f, _s, _t) \ - VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint8, uint8_t) - -#define VMSTATE_UINT16_TEST(_f, _s, _t) \ - VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint16, uint16_t) - -#define VMSTATE_UINT32_TEST(_f, _s, _t) \ - VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t) - - -#define VMSTATE_FLOAT64_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64) - -#define VMSTATE_FLOAT64(_f, _s) \ - VMSTATE_FLOAT64_V(_f, _s, 0) - -#define VMSTATE_TIMER_TEST(_f, _s, _test) \ - VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *) - -#define VMSTATE_TIMER_V(_f, _s, _v) \ - VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *) - -#define VMSTATE_TIMER(_f, _s) \ - VMSTATE_TIMER_V(_f, _s, 0) - -#define VMSTATE_TIMER_ARRAY(_f, _s, _n) \ - VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *) - -#define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool) - -#define VMSTATE_BOOL_ARRAY(_f, _s, _n) \ - VMSTATE_BOOL_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_UINT16_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint16, uint16_t) - -#define VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, _v) \ - VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint16, uint16_t) - -#define VMSTATE_UINT16_ARRAY(_f, _s, _n) \ - VMSTATE_UINT16_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_UINT16_2DARRAY(_f, _s, _n1, _n2) \ - VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, 0) - -#define VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, _v) \ - VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint8, uint8_t) - -#define VMSTATE_UINT8_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint8, uint8_t) - -#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \ - VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2) \ - VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0) - -#define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t) - -#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \ - VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint64, uint64_t) - -#define VMSTATE_UINT64_ARRAY(_f, _s, _n) \ - VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int16, int16_t) - -#define VMSTATE_INT16_ARRAY(_f, _s, _n) \ - VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_INT32_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int32, int32_t) - -#define VMSTATE_INT32_ARRAY(_f, _s, _n) \ - VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \ - VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t) - -#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \ - VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t) - -#define VMSTATE_INT64_ARRAY(_f, _s, _n) \ - VMSTATE_INT64_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_float64, float64) - -#define VMSTATE_FLOAT64_ARRAY(_f, _s, _n) \ - VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_BUFFER_V(_f, _s, _v) \ - VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f))) - -#define VMSTATE_BUFFER(_f, _s) \ - VMSTATE_BUFFER_V(_f, _s, 0) - -#define VMSTATE_PARTIAL_BUFFER(_f, _s, _size) \ - VMSTATE_STATIC_BUFFER(_f, _s, 0, NULL, 0, _size) - -#define VMSTATE_BUFFER_START_MIDDLE(_f, _s, _start) \ - VMSTATE_STATIC_BUFFER(_f, _s, 0, NULL, _start, sizeof(typeof_field(_s, _f))) - -#define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \ - VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size) - -#define VMSTATE_PARTIAL_VBUFFER_UINT32(_f, _s, _size) \ - VMSTATE_VBUFFER_UINT32(_f, _s, 0, NULL, 0, _size) - -#define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \ - VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size) - -#define VMSTATE_BUFFER_TEST(_f, _s, _test) \ - VMSTATE_STATIC_BUFFER(_f, _s, 0, _test, 0, sizeof(typeof_field(_s, _f))) - -#define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size) \ - VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, vmstate_info_buffer, _size) - -#define VMSTATE_UNUSED_V(_v, _size) \ - VMSTATE_UNUSED_BUFFER(NULL, _v, _size) - -#define VMSTATE_UNUSED(_size) \ - VMSTATE_UNUSED_V(0, _size) - -#define VMSTATE_UNUSED_TEST(_test, _size) \ - VMSTATE_UNUSED_BUFFER(_test, 0, _size) - -#define VMSTATE_END_OF_LIST() \ - {} - -int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque, int version_id); -void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque); - -int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, - const VMStateDescription *vmsd, - void *base, int alias_id, - int required_for_version); - -static inline int vmstate_register(DeviceState *dev, int instance_id, - const VMStateDescription *vmsd, - void *opaque) -{ - return vmstate_register_with_alias_id(dev, instance_id, vmsd, - opaque, -1, 0); -} - -void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd, - void *opaque); - -struct MemoryRegion; -void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev); -void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev); -void vmstate_register_ram_global(struct MemoryRegion *memory); - -#endif diff --git a/contrib/qemu/include/monitor/monitor.h b/contrib/qemu/include/monitor/monitor.h deleted file mode 100644 index 1942cc42fe2..00000000000 --- a/contrib/qemu/include/monitor/monitor.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef MONITOR_H -#define MONITOR_H - -#include "qemu-common.h" -#include "qapi/qmp/qerror.h" -#include "qapi/qmp/qdict.h" -#include "block/block.h" -#include "monitor/readline.h" - -extern Monitor *cur_mon; -extern Monitor *default_mon; - -/* flags for monitor_init */ -#define MONITOR_IS_DEFAULT 0x01 -#define MONITOR_USE_READLINE 0x02 -#define MONITOR_USE_CONTROL 0x04 -#define MONITOR_USE_PRETTY 0x08 - -/* flags for monitor commands */ -#define MONITOR_CMD_ASYNC 0x0001 - -/* QMP events */ -typedef enum MonitorEvent { - QEVENT_SHUTDOWN, - QEVENT_RESET, - QEVENT_POWERDOWN, - QEVENT_STOP, - QEVENT_RESUME, - QEVENT_VNC_CONNECTED, - QEVENT_VNC_INITIALIZED, - QEVENT_VNC_DISCONNECTED, - QEVENT_BLOCK_IO_ERROR, - QEVENT_RTC_CHANGE, - QEVENT_WATCHDOG, - QEVENT_SPICE_CONNECTED, - QEVENT_SPICE_INITIALIZED, - QEVENT_SPICE_DISCONNECTED, - QEVENT_BLOCK_JOB_COMPLETED, - QEVENT_BLOCK_JOB_CANCELLED, - QEVENT_BLOCK_JOB_ERROR, - QEVENT_BLOCK_JOB_READY, - QEVENT_DEVICE_DELETED, - QEVENT_DEVICE_TRAY_MOVED, - QEVENT_NIC_RX_FILTER_CHANGED, - QEVENT_SUSPEND, - QEVENT_SUSPEND_DISK, - QEVENT_WAKEUP, - QEVENT_BALLOON_CHANGE, - QEVENT_SPICE_MIGRATE_COMPLETED, - QEVENT_GUEST_PANICKED, - - /* Add to 'monitor_event_names' array in monitor.c when - * defining new events here */ - - QEVENT_MAX, -} MonitorEvent; - -int monitor_cur_is_qmp(void); - -void monitor_protocol_event(MonitorEvent event, QObject *data); -void monitor_init(CharDriverState *chr, int flags); - -int monitor_suspend(Monitor *mon); -void monitor_resume(Monitor *mon); - -int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, - BlockDriverCompletionFunc *completion_cb, - void *opaque); -int monitor_read_block_device_key(Monitor *mon, const char *device, - BlockDriverCompletionFunc *completion_cb, - void *opaque); - -int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp); -int monitor_handle_fd_param(Monitor *mon, const char *fdname); - -void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) - GCC_FMT_ATTR(2, 0); -void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); -void monitor_print_filename(Monitor *mon, const char *filename); -void monitor_flush(Monitor *mon); -int monitor_set_cpu(int cpu_index); -int monitor_get_cpu_index(void); - -typedef void (MonitorCompletion)(void *opaque, QObject *ret_data); - -void monitor_set_error(Monitor *mon, QError *qerror); -void monitor_read_command(Monitor *mon, int show_prompt); -ReadLineState *monitor_get_rs(Monitor *mon); -int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, - void *opaque); - -int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); - -int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); - -AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, - bool has_opaque, const char *opaque, - Error **errp); -int monitor_fdset_get_fd(int64_t fdset_id, int flags); -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd); -int monitor_fdset_dup_fd_remove(int dup_fd); -int monitor_fdset_dup_fd_find(int dup_fd); - -#endif /* !MONITOR_H */ diff --git a/contrib/qemu/include/monitor/readline.h b/contrib/qemu/include/monitor/readline.h deleted file mode 100644 index fc9806ecf1a..00000000000 --- a/contrib/qemu/include/monitor/readline.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef READLINE_H -#define READLINE_H - -#include "qemu-common.h" - -#define READLINE_CMD_BUF_SIZE 4095 -#define READLINE_MAX_CMDS 64 -#define READLINE_MAX_COMPLETIONS 256 - -typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque); -typedef void ReadLineCompletionFunc(const char *cmdline); - -typedef struct ReadLineState { - char cmd_buf[READLINE_CMD_BUF_SIZE + 1]; - int cmd_buf_index; - int cmd_buf_size; - - char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1]; - int last_cmd_buf_index; - int last_cmd_buf_size; - - int esc_state; - int esc_param; - - char *history[READLINE_MAX_CMDS]; - int hist_entry; - - ReadLineCompletionFunc *completion_finder; - char *completions[READLINE_MAX_COMPLETIONS]; - int nb_completions; - int completion_index; - - ReadLineFunc *readline_func; - void *readline_opaque; - int read_password; - char prompt[256]; - Monitor *mon; -} ReadLineState; - -void readline_add_completion(ReadLineState *rs, const char *str); -void readline_set_completion_index(ReadLineState *rs, int completion_index); - -const char *readline_get_history(ReadLineState *rs, unsigned int index); - -void readline_handle_byte(ReadLineState *rs, int ch); - -void readline_start(ReadLineState *rs, const char *prompt, int read_password, - ReadLineFunc *readline_func, void *opaque); -void readline_restart(ReadLineState *rs); -void readline_show_prompt(ReadLineState *rs); - -ReadLineState *readline_init(Monitor *mon, - ReadLineCompletionFunc *completion_finder); - -#endif /* !READLINE_H */ diff --git a/contrib/qemu/include/qapi/error.h b/contrib/qemu/include/qapi/error.h deleted file mode 100644 index ffd1cea4772..00000000000 --- a/contrib/qemu/include/qapi/error.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * QEMU Error Objects - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.com> - * - * This work is licensed under the terms of the GNU LGPL, version 2. See - * the COPYING.LIB file in the top-level directory. - */ -#ifndef ERROR_H -#define ERROR_H - -#include "qemu/compiler.h" -#include "qapi-types.h" -#include <stdbool.h> - -/** - * A class representing internal errors within QEMU. An error has a ErrorClass - * code and a human message. - */ -typedef struct Error Error; - -/** - * Set an indirect pointer to an error given a ErrorClass value and a - * printf-style human message. This function is not meant to be used outside - * of QEMU. - */ -void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4); - -/** - * Set an indirect pointer to an error given a ErrorClass value and a - * printf-style human message, followed by a strerror() string if - * @os_error is not zero. - */ -void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); - -/** - * Same as error_set(), but sets a generic error - */ -#define error_setg(err, fmt, ...) \ - error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) -#define error_setg_errno(err, os_error, fmt, ...) \ - error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) - -/** - * Helper for open() errors - */ -void error_setg_file_open(Error **errp, int os_errno, const char *filename); - -/** - * Returns true if an indirect pointer to an error is pointing to a valid - * error object. - */ -bool error_is_set(Error **err); - -/* - * Get the error class of an error object. - */ -ErrorClass error_get_class(const Error *err); - -/** - * Returns an exact copy of the error passed as an argument. - */ -Error *error_copy(const Error *err); - -/** - * Get a human readable representation of an error object. - */ -const char *error_get_pretty(Error *err); - -/** - * Propagate an error to an indirect pointer to an error. This function will - * always transfer ownership of the error reference and handles the case where - * dst_err is NULL correctly. Errors after the first are discarded. - */ -void error_propagate(Error **dst_err, Error *local_err); - -/** - * Free an error object. - */ -void error_free(Error *err); - -#endif diff --git a/contrib/qemu/include/qapi/qmp/json-lexer.h b/contrib/qemu/include/qapi/qmp/json-lexer.h deleted file mode 100644 index cdff0460a83..00000000000 --- a/contrib/qemu/include/qapi/qmp/json-lexer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * JSON lexer - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QEMU_JSON_LEXER_H -#define QEMU_JSON_LEXER_H - -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qlist.h" - -typedef enum json_token_type { - JSON_OPERATOR = 100, - JSON_INTEGER, - JSON_FLOAT, - JSON_KEYWORD, - JSON_STRING, - JSON_ESCAPE, - JSON_SKIP, - JSON_ERROR, -} JSONTokenType; - -typedef struct JSONLexer JSONLexer; - -typedef void (JSONLexerEmitter)(JSONLexer *, QString *, JSONTokenType, int x, int y); - -struct JSONLexer -{ - JSONLexerEmitter *emit; - int state; - QString *token; - int x, y; -}; - -void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func); - -int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size); - -int json_lexer_flush(JSONLexer *lexer); - -void json_lexer_destroy(JSONLexer *lexer); - -#endif diff --git a/contrib/qemu/include/qapi/qmp/json-parser.h b/contrib/qemu/include/qapi/qmp/json-parser.h deleted file mode 100644 index 44d88f34685..00000000000 --- a/contrib/qemu/include/qapi/qmp/json-parser.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * JSON Parser - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QEMU_JSON_PARSER_H -#define QEMU_JSON_PARSER_H - -#include "qemu-common.h" -#include "qapi/qmp/qlist.h" -#include "qapi/error.h" - -QObject *json_parser_parse(QList *tokens, va_list *ap); -QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp); - -#endif diff --git a/contrib/qemu/include/qapi/qmp/json-streamer.h b/contrib/qemu/include/qapi/qmp/json-streamer.h deleted file mode 100644 index 823f7d7fa42..00000000000 --- a/contrib/qemu/include/qapi/qmp/json-streamer.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * JSON streaming support - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QEMU_JSON_STREAMER_H -#define QEMU_JSON_STREAMER_H - -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/json-lexer.h" - -typedef struct JSONMessageParser -{ - void (*emit)(struct JSONMessageParser *parser, QList *tokens); - JSONLexer lexer; - int brace_count; - int bracket_count; - QList *tokens; - uint64_t token_size; -} JSONMessageParser; - -void json_message_parser_init(JSONMessageParser *parser, - void (*func)(JSONMessageParser *, QList *)); - -int json_message_parser_feed(JSONMessageParser *parser, - const char *buffer, size_t size); - -int json_message_parser_flush(JSONMessageParser *parser); - -void json_message_parser_destroy(JSONMessageParser *parser); - -#endif diff --git a/contrib/qemu/include/qapi/qmp/qbool.h b/contrib/qemu/include/qapi/qmp/qbool.h deleted file mode 100644 index c4eaab9bb9f..00000000000 --- a/contrib/qemu/include/qapi/qmp/qbool.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QBool Module - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QBOOL_H -#define QBOOL_H - -#include <stdint.h> -#include "qapi/qmp/qobject.h" - -typedef struct QBool { - QObject_HEAD; - int value; -} QBool; - -QBool *qbool_from_int(int value); -int qbool_get_int(const QBool *qb); -QBool *qobject_to_qbool(const QObject *obj); - -#endif /* QBOOL_H */ diff --git a/contrib/qemu/include/qapi/qmp/qdict.h b/contrib/qemu/include/qapi/qmp/qdict.h deleted file mode 100644 index 685b2e3fcbb..00000000000 --- a/contrib/qemu/include/qapi/qmp/qdict.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * QDict Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ - -#ifndef QDICT_H -#define QDICT_H - -#include "qapi/qmp/qobject.h" -#include "qapi/qmp/qlist.h" -#include "qemu/queue.h" -#include <stdint.h> - -#define QDICT_BUCKET_MAX 512 - -typedef struct QDictEntry { - char *key; - QObject *value; - QLIST_ENTRY(QDictEntry) next; -} QDictEntry; - -typedef struct QDict { - QObject_HEAD; - size_t size; - QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX]; -} QDict; - -/* Object API */ -QDict *qdict_new(void); -const char *qdict_entry_key(const QDictEntry *entry); -QObject *qdict_entry_value(const QDictEntry *entry); -size_t qdict_size(const QDict *qdict); -void qdict_put_obj(QDict *qdict, const char *key, QObject *value); -void qdict_del(QDict *qdict, const char *key); -int qdict_haskey(const QDict *qdict, const char *key); -QObject *qdict_get(const QDict *qdict, const char *key); -QDict *qobject_to_qdict(const QObject *obj); -void qdict_iter(const QDict *qdict, - void (*iter)(const char *key, QObject *obj, void *opaque), - void *opaque); -const QDictEntry *qdict_first(const QDict *qdict); -const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry); - -/* Helper to qdict_put_obj(), accepts any object */ -#define qdict_put(qdict, key, obj) \ - qdict_put_obj(qdict, key, QOBJECT(obj)) - -/* High level helpers */ -double qdict_get_double(const QDict *qdict, const char *key); -int64_t qdict_get_int(const QDict *qdict, const char *key); -int qdict_get_bool(const QDict *qdict, const char *key); -QList *qdict_get_qlist(const QDict *qdict, const char *key); -QDict *qdict_get_qdict(const QDict *qdict, const char *key); -const char *qdict_get_str(const QDict *qdict, const char *key); -int64_t qdict_get_try_int(const QDict *qdict, const char *key, - int64_t def_value); -int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value); -const char *qdict_get_try_str(const QDict *qdict, const char *key); - -QDict *qdict_clone_shallow(const QDict *src); - -#endif /* QDICT_H */ diff --git a/contrib/qemu/include/qapi/qmp/qerror.h b/contrib/qemu/include/qapi/qmp/qerror.h deleted file mode 100644 index c30c2f6d7a3..00000000000 --- a/contrib/qemu/include/qapi/qmp/qerror.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * QError Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ -#ifndef QERROR_H -#define QERROR_H - -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "qemu/error-report.h" -#include "qapi/error.h" -#include "qapi-types.h" -#include <stdarg.h> - -typedef struct QError { - QObject_HEAD; - Location loc; - char *err_msg; - ErrorClass err_class; -} QError; - -QString *qerror_human(const QError *qerror); -void qerror_report(ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(2, 3); -void qerror_report_err(Error *err); -void assert_no_error(Error *err); - -/* - * QError class list - * Please keep the definitions in alphabetical order. - * Use scripts/check-qerror.sh to check. - */ -#define QERR_ADD_CLIENT_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Could not add client" - -#define QERR_AMBIGUOUS_PATH \ - ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object" - -#define QERR_BAD_BUS_FOR_DEVICE \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus" - -#define QERR_BASE_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found" - -#define QERR_BLOCK_JOB_NOT_ACTIVE \ - ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'" - -#define QERR_BLOCK_JOB_PAUSED \ - ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused" - -#define QERR_BLOCK_JOB_NOT_READY \ - ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed" - -#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" - -#define QERR_BUFFER_OVERRUN \ - ERROR_CLASS_GENERIC_ERROR, "An internal buffer overran" - -#define QERR_BUS_NO_HOTPLUG \ - ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging" - -#define QERR_BUS_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found" - -#define QERR_COMMAND_DISABLED \ - ERROR_CLASS_GENERIC_ERROR, "The command %s has been disabled for this instance" - -#define QERR_COMMAND_NOT_FOUND \ - ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found" - -#define QERR_DEVICE_ENCRYPTED \ - ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted" - -#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \ - ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when using feature '%s' in device '%s'" - -#define QERR_DEVICE_HAS_NO_MEDIUM \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium" - -#define QERR_DEVICE_INIT_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' could not be initialized" - -#define QERR_DEVICE_IN_USE \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is in use" - -#define QERR_DEVICE_IS_READ_ONLY \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only" - -#define QERR_DEVICE_LOCKED \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is locked" - -#define QERR_DEVICE_MULTIPLE_BUSSES \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' has multiple child busses" - -#define QERR_DEVICE_NO_BUS \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no child bus" - -#define QERR_DEVICE_NO_HOTPLUG \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging" - -#define QERR_DEVICE_NOT_ACTIVE \ - ERROR_CLASS_DEVICE_NOT_ACTIVE, "Device '%s' has not been activated" - -#define QERR_DEVICE_NOT_ENCRYPTED \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not encrypted" - -#define QERR_DEVICE_NOT_FOUND \ - ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found" - -#define QERR_DEVICE_NOT_REMOVABLE \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not removable" - -#define QERR_DUPLICATE_ID \ - ERROR_CLASS_GENERIC_ERROR, "Duplicate ID '%s' for %s" - -#define QERR_FD_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found" - -#define QERR_FD_NOT_SUPPLIED \ - ERROR_CLASS_GENERIC_ERROR, "No file descriptor supplied via SCM_RIGHTS" - -#define QERR_FEATURE_DISABLED \ - ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled" - -#define QERR_INVALID_BLOCK_FORMAT \ - ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'" - -#define QERR_INVALID_OPTION_GROUP \ - ERROR_CLASS_GENERIC_ERROR, "There is no option group '%s'" - -#define QERR_INVALID_PARAMETER \ - ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'" - -#define QERR_INVALID_PARAMETER_COMBINATION \ - ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination" - -#define QERR_INVALID_PARAMETER_TYPE \ - ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s" - -#define QERR_INVALID_PARAMETER_VALUE \ - ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' expects %s" - -#define QERR_INVALID_PASSWORD \ - ERROR_CLASS_GENERIC_ERROR, "Password incorrect" - -#define QERR_IO_ERROR \ - ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred" - -#define QERR_JSON_PARSE_ERROR \ - ERROR_CLASS_GENERIC_ERROR, "JSON parse error, %s" - -#define QERR_JSON_PARSING \ - ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" - -#define QERR_KVM_MISSING_CAP \ - ERROR_CLASS_K_V_M_MISSING_CAP, "Using KVM without %s, %s unavailable" - -#define QERR_MIGRATION_ACTIVE \ - ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" - -#define QERR_MIGRATION_NOT_SUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'" - -#define QERR_MISSING_PARAMETER \ - ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing" - -#define QERR_NO_BUS_FOR_DEVICE \ - ERROR_CLASS_GENERIC_ERROR, "No '%s' bus found for device '%s'" - -#define QERR_NOT_SUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "Not supported" - -#define QERR_PERMISSION_DENIED \ - ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation" - -#define QERR_PROPERTY_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' not found" - -#define QERR_PROPERTY_VALUE_BAD \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'" - -#define QERR_PROPERTY_VALUE_IN_USE \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't take value '%s', it's in use" - -#define QERR_PROPERTY_VALUE_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't find value '%s'" - -#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \ - ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2" - -#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ - ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" - -#define QERR_QGA_COMMAND_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'" - -#define QERR_QGA_LOGGING_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Guest agent failed to log non-optional log statement" - -#define QERR_QMP_BAD_INPUT_OBJECT \ - ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input" - -#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \ - ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' expects '%s'" - -#define QERR_QMP_EXTRA_MEMBER \ - ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected" - -#define QERR_RESET_REQUIRED \ - ERROR_CLASS_GENERIC_ERROR, "Resetting the Virtual Machine is required" - -#define QERR_SET_PASSWD_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Could not set password" - -#define QERR_TOO_MANY_FILES \ - ERROR_CLASS_GENERIC_ERROR, "Too many open files" - -#define QERR_UNDEFINED_ERROR \ - ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred" - -#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ - ERROR_CLASS_GENERIC_ERROR, "'%s' uses a %s feature which is not supported by this qemu version: %s" - -#define QERR_UNSUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported" - -#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \ - ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'" - -#define QERR_SOCKET_CONNECT_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket" - -#define QERR_SOCKET_LISTEN_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Failed to set socket to listening mode" - -#define QERR_SOCKET_BIND_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Failed to bind socket" - -#define QERR_SOCKET_CREATE_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Failed to create socket" - -#endif /* QERROR_H */ diff --git a/contrib/qemu/include/qapi/qmp/qfloat.h b/contrib/qemu/include/qapi/qmp/qfloat.h deleted file mode 100644 index a8658443dc2..00000000000 --- a/contrib/qemu/include/qapi/qmp/qfloat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QFloat Module - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QFLOAT_H -#define QFLOAT_H - -#include <stdint.h> -#include "qapi/qmp/qobject.h" - -typedef struct QFloat { - QObject_HEAD; - double value; -} QFloat; - -QFloat *qfloat_from_double(double value); -double qfloat_get_double(const QFloat *qi); -QFloat *qobject_to_qfloat(const QObject *obj); - -#endif /* QFLOAT_H */ diff --git a/contrib/qemu/include/qapi/qmp/qint.h b/contrib/qemu/include/qapi/qmp/qint.h deleted file mode 100644 index 48a41b0f2ae..00000000000 --- a/contrib/qemu/include/qapi/qmp/qint.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * QInt Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ - -#ifndef QINT_H -#define QINT_H - -#include <stdint.h> -#include "qapi/qmp/qobject.h" - -typedef struct QInt { - QObject_HEAD; - int64_t value; -} QInt; - -QInt *qint_from_int(int64_t value); -int64_t qint_get_int(const QInt *qi); -QInt *qobject_to_qint(const QObject *obj); - -#endif /* QINT_H */ diff --git a/contrib/qemu/include/qapi/qmp/qjson.h b/contrib/qemu/include/qapi/qmp/qjson.h deleted file mode 100644 index 73351ed6d68..00000000000 --- a/contrib/qemu/include/qapi/qmp/qjson.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QObject JSON integration - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QJSON_H -#define QJSON_H - -#include <stdarg.h> -#include "qemu/compiler.h" -#include "qapi/qmp/qobject.h" -#include "qapi/qmp/qstring.h" - -QObject *qobject_from_json(const char *string) GCC_FMT_ATTR(1, 0); -QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); -QObject *qobject_from_jsonv(const char *string, va_list *ap) GCC_FMT_ATTR(1, 0); - -QString *qobject_to_json(const QObject *obj); -QString *qobject_to_json_pretty(const QObject *obj); - -#endif /* QJSON_H */ diff --git a/contrib/qemu/include/qapi/qmp/qlist.h b/contrib/qemu/include/qapi/qmp/qlist.h deleted file mode 100644 index 6cc4831df3e..00000000000 --- a/contrib/qemu/include/qapi/qmp/qlist.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * QList Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ - -#ifndef QLIST_H -#define QLIST_H - -#include "qapi/qmp/qobject.h" -#include "qemu/queue.h" - -typedef struct QListEntry { - QObject *value; - QTAILQ_ENTRY(QListEntry) next; -} QListEntry; - -typedef struct QList { - QObject_HEAD; - QTAILQ_HEAD(,QListEntry) head; -} QList; - -#define qlist_append(qlist, obj) \ - qlist_append_obj(qlist, QOBJECT(obj)) - -#define QLIST_FOREACH_ENTRY(qlist, var) \ - for ((var) = ((qlist)->head.tqh_first); \ - (var); \ - (var) = ((var)->next.tqe_next)) - -static inline QObject *qlist_entry_obj(const QListEntry *entry) -{ - return entry->value; -} - -QList *qlist_new(void); -QList *qlist_copy(QList *src); -void qlist_append_obj(QList *qlist, QObject *obj); -void qlist_iter(const QList *qlist, - void (*iter)(QObject *obj, void *opaque), void *opaque); -QObject *qlist_pop(QList *qlist); -QObject *qlist_peek(QList *qlist); -int qlist_empty(const QList *qlist); -size_t qlist_size(const QList *qlist); -QList *qobject_to_qlist(const QObject *obj); - -static inline const QListEntry *qlist_first(const QList *qlist) -{ - return QTAILQ_FIRST(&qlist->head); -} - -static inline const QListEntry *qlist_next(const QListEntry *entry) -{ - return QTAILQ_NEXT(entry, next); -} - -#endif /* QLIST_H */ diff --git a/contrib/qemu/include/qapi/qmp/qobject.h b/contrib/qemu/include/qapi/qmp/qobject.h deleted file mode 100644 index 9124649ed20..00000000000 --- a/contrib/qemu/include/qapi/qmp/qobject.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * QEMU Object Model. - * - * Based on ideas by Avi Kivity <avi@redhat.com> - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - * - * QObject Reference Counts Terminology - * ------------------------------------ - * - * - Returning references: A function that returns an object may - * return it as either a weak or a strong reference. If the reference - * is strong, you are responsible for calling QDECREF() on the reference - * when you are done. - * - * If the reference is weak, the owner of the reference may free it at - * any time in the future. Before storing the reference anywhere, you - * should call QINCREF() to make the reference strong. - * - * - Transferring ownership: when you transfer ownership of a reference - * by calling a function, you are no longer responsible for calling - * QDECREF() when the reference is no longer needed. In other words, - * when the function returns you must behave as if the reference to the - * passed object was weak. - */ -#ifndef QOBJECT_H -#define QOBJECT_H - -#include <stddef.h> -#include <assert.h> - -typedef enum { - QTYPE_NONE, - QTYPE_QINT, - QTYPE_QSTRING, - QTYPE_QDICT, - QTYPE_QLIST, - QTYPE_QFLOAT, - QTYPE_QBOOL, - QTYPE_QERROR, -} qtype_code; - -struct QObject; - -typedef struct QType { - qtype_code code; - void (*destroy)(struct QObject *); -} QType; - -typedef struct QObject { - const QType *type; - size_t refcnt; -} QObject; - -/* Objects definitions must include this */ -#define QObject_HEAD \ - QObject base - -/* Get the 'base' part of an object */ -#define QOBJECT(obj) (&(obj)->base) - -/* High-level interface for qobject_incref() */ -#define QINCREF(obj) \ - qobject_incref(QOBJECT(obj)) - -/* High-level interface for qobject_decref() */ -#define QDECREF(obj) \ - qobject_decref(obj ? QOBJECT(obj) : NULL) - -/* Initialize an object to default values */ -#define QOBJECT_INIT(obj, qtype_type) \ - obj->base.refcnt = 1; \ - obj->base.type = qtype_type - -/** - * qobject_incref(): Increment QObject's reference count - */ -static inline void qobject_incref(QObject *obj) -{ - if (obj) - obj->refcnt++; -} - -/** - * qobject_decref(): Decrement QObject's reference count, deallocate - * when it reaches zero - */ -static inline void qobject_decref(QObject *obj) -{ - if (obj && --obj->refcnt == 0) { - assert(obj->type != NULL); - assert(obj->type->destroy != NULL); - obj->type->destroy(obj); - } -} - -/** - * qobject_type(): Return the QObject's type - */ -static inline qtype_code qobject_type(const QObject *obj) -{ - assert(obj->type != NULL); - return obj->type->code; -} - -#endif /* QOBJECT_H */ diff --git a/contrib/qemu/include/qapi/qmp/qstring.h b/contrib/qemu/include/qapi/qmp/qstring.h deleted file mode 100644 index 1bc3666107c..00000000000 --- a/contrib/qemu/include/qapi/qmp/qstring.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * QString Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ - -#ifndef QSTRING_H -#define QSTRING_H - -#include <stdint.h> -#include "qapi/qmp/qobject.h" - -typedef struct QString { - QObject_HEAD; - char *string; - size_t length; - size_t capacity; -} QString; - -QString *qstring_new(void); -QString *qstring_from_str(const char *str); -QString *qstring_from_substr(const char *str, int start, int end); -size_t qstring_get_length(const QString *qstring); -const char *qstring_get_str(const QString *qstring); -void qstring_append_int(QString *qstring, int64_t value); -void qstring_append(QString *qstring, const char *str); -void qstring_append_chr(QString *qstring, int c); -QString *qobject_to_qstring(const QObject *obj); - -#endif /* QSTRING_H */ diff --git a/contrib/qemu/include/qapi/qmp/types.h b/contrib/qemu/include/qapi/qmp/types.h deleted file mode 100644 index 7782ec5a602..00000000000 --- a/contrib/qemu/include/qapi/qmp/types.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Include all QEMU objects. - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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. - */ - -#ifndef QEMU_OBJECTS_H -#define QEMU_OBJECTS_H - -#include "qapi/qmp/qobject.h" -#include "qapi/qmp/qint.h" -#include "qapi/qmp/qfloat.h" -#include "qapi/qmp/qbool.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qjson.h" - -#endif /* QEMU_OBJECTS_H */ diff --git a/contrib/qemu/include/qemu-common.h b/contrib/qemu/include/qemu-common.h deleted file mode 100644 index 6948bb91774..00000000000 --- a/contrib/qemu/include/qemu-common.h +++ /dev/null @@ -1,478 +0,0 @@ - -/* Common header file that is included by all of QEMU. - * - * This file is supposed to be included only by .c files. No header file should - * depend on qemu-common.h, as this would easily lead to circular header - * dependencies. - * - * If a header file uses a definition from qemu-common.h, that definition - * must be moved to a separate header file, and the header that uses it - * must include that header. - */ -#ifndef QEMU_COMMON_H -#define QEMU_COMMON_H - -#include "qemu/compiler.h" -#include "config-host.h" -#include "qemu/typedefs.h" - -#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__) -#define WORDS_ALIGNED -#endif - -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) - -/* we put basic includes here to avoid repeating them in device drivers */ -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <stdbool.h> -#include <string.h> -#include <strings.h> -#include <inttypes.h> -#include <limits.h> -#include <time.h> -#include <ctype.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <assert.h> -#include <signal.h> -#include "glib-compat.h" - -#ifdef _WIN32 -#include "sysemu/os-win32.h" -#endif - -#ifdef CONFIG_POSIX -#include "sysemu/os-posix.h" -#endif - -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif -#ifndef O_BINARY -#define O_BINARY 0 -#endif -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -#ifndef ENOMEDIUM -#define ENOMEDIUM ENODEV -#endif -#if !defined(ENOTSUP) -#define ENOTSUP 4096 -#endif -#if !defined(ECANCELED) -#define ECANCELED 4097 -#endif -#if !defined(EMEDIUMTYPE) -#define EMEDIUMTYPE 4098 -#endif -#ifndef TIME_MAX -#define TIME_MAX LONG_MAX -#endif - -/* HOST_LONG_BITS is the size of a native pointer in bits. */ -#if UINTPTR_MAX == UINT32_MAX -# define HOST_LONG_BITS 32 -#elif UINTPTR_MAX == UINT64_MAX -# define HOST_LONG_BITS 64 -#else -# error Unknown pointer size -#endif - -typedef int (*fprintf_function)(FILE *f, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - -#ifdef _WIN32 -#define fsync _commit -#if !defined(lseek) -# define lseek _lseeki64 -#endif -int qemu_ftruncate64(int, int64_t); -#if !defined(ftruncate) -# define ftruncate qemu_ftruncate64 -#endif - -static inline char *realpath(const char *path, char *resolved_path) -{ - _fullpath(resolved_path, path, _MAX_PATH); - return resolved_path; -} -#endif - -/* icount */ -void configure_icount(const char *option); -extern int use_icount; - -#include "qemu/osdep.h" -#include "qemu/bswap.h" - -/* FIXME: Remove NEED_CPU_H. */ -#ifdef NEED_CPU_H -#include "cpu.h" -#endif /* !defined(NEED_CPU_H) */ - -/* main function, renamed */ -#if defined(CONFIG_COCOA) -int qemu_main(int argc, char **argv, char **envp); -#endif - -void qemu_get_timedate(struct tm *tm, int offset); -int qemu_timedate_diff(struct tm *tm); - -#if !GLIB_CHECK_VERSION(2, 20, 0) -/* - * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly - * on older systems. - */ -static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) -{ - GMainContext *ctx = g_main_context_default(); - return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); -} -#endif - -/** - * is_help_option: - * @s: string to test - * - * Check whether @s is one of the standard strings which indicate - * that the user is asking for a list of the valid values for a - * command option like -cpu or -M. The current accepted strings - * are 'help' and '?'. '?' is deprecated (it is a shell wildcard - * which makes it annoying to use in a reliable way) but provided - * for backwards compatibility. - * - * Returns: true if @s is a request for a list. - */ -static inline bool is_help_option(const char *s) -{ - return !strcmp(s, "?") || !strcmp(s, "help"); -} - -/* cutils.c */ -void pstrcpy(char *buf, int buf_size, const char *str); -void strpadcpy(char *buf, int buf_size, const char *str, char pad); -char *pstrcat(char *buf, int buf_size, const char *s); -int strstart(const char *str, const char *val, const char **ptr); -int stristart(const char *str, const char *val, const char **ptr); -int qemu_strnlen(const char *s, int max_len); -char *qemu_strsep(char **input, const char *delim); -time_t mktimegm(struct tm *tm); -int qemu_fls(int i); -int qemu_fdatasync(int fd); -int fcntl_setfl(int fd, int flag); -int qemu_parse_fd(const char *param); - -int parse_uint(const char *s, unsigned long long *value, char **endptr, - int base); -int parse_uint_full(const char *s, unsigned long long *value, int base); - -/* - * strtosz() suffixes used to specify the default treatment of an - * argument passed to strtosz() without an explicit suffix. - * These should be defined using upper case characters in the range - * A-Z, as strtosz() will use qemu_toupper() on the given argument - * prior to comparison. - */ -#define STRTOSZ_DEFSUFFIX_EB 'E' -#define STRTOSZ_DEFSUFFIX_PB 'P' -#define STRTOSZ_DEFSUFFIX_TB 'T' -#define STRTOSZ_DEFSUFFIX_GB 'G' -#define STRTOSZ_DEFSUFFIX_MB 'M' -#define STRTOSZ_DEFSUFFIX_KB 'K' -#define STRTOSZ_DEFSUFFIX_B 'B' -int64_t strtosz(const char *nptr, char **end); -int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix); -int64_t strtosz_suffix_unit(const char *nptr, char **end, - const char default_suffix, int64_t unit); - -/* path.c */ -void init_paths(const char *prefix); -const char *path(const char *pathname); - -#define qemu_isalnum(c) isalnum((unsigned char)(c)) -#define qemu_isalpha(c) isalpha((unsigned char)(c)) -#define qemu_iscntrl(c) iscntrl((unsigned char)(c)) -#define qemu_isdigit(c) isdigit((unsigned char)(c)) -#define qemu_isgraph(c) isgraph((unsigned char)(c)) -#define qemu_islower(c) islower((unsigned char)(c)) -#define qemu_isprint(c) isprint((unsigned char)(c)) -#define qemu_ispunct(c) ispunct((unsigned char)(c)) -#define qemu_isspace(c) isspace((unsigned char)(c)) -#define qemu_isupper(c) isupper((unsigned char)(c)) -#define qemu_isxdigit(c) isxdigit((unsigned char)(c)) -#define qemu_tolower(c) tolower((unsigned char)(c)) -#define qemu_toupper(c) toupper((unsigned char)(c)) -#define qemu_isascii(c) isascii((unsigned char)(c)) -#define qemu_toascii(c) toascii((unsigned char)(c)) - -void *qemu_oom_check(void *ptr); - -ssize_t qemu_write_full(int fd, const void *buf, size_t count) - QEMU_WARN_UNUSED_RESULT; -ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags) - QEMU_WARN_UNUSED_RESULT; -ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags) - QEMU_WARN_UNUSED_RESULT; - -#ifndef _WIN32 -int qemu_pipe(int pipefd[2]); -/* like openpty() but also makes it raw; return master fd */ -int qemu_openpty_raw(int *aslave, char *pty_name); -#endif - -#ifdef _WIN32 -/* MinGW needs type casts for the 'buf' and 'optval' arguments. */ -#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \ - getsockopt(sockfd, level, optname, (void *)optval, optlen) -#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ - setsockopt(sockfd, level, optname, (const void *)optval, optlen) -#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) -#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ - sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen) -#else -#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \ - getsockopt(sockfd, level, optname, optval, optlen) -#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ - setsockopt(sockfd, level, optname, optval, optlen) -#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) -#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ - sendto(sockfd, buf, len, flags, destaddr, addrlen) -#endif - -/* Error handling. */ - -void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2); - -struct ParallelIOArg { - void *buffer; - int count; -}; - -typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size); - -typedef uint64_t pcibus_t; - -typedef enum LostTickPolicy { - LOST_TICK_DISCARD, - LOST_TICK_DELAY, - LOST_TICK_MERGE, - LOST_TICK_SLEW, - LOST_TICK_MAX -} LostTickPolicy; - -typedef struct PCIHostDeviceAddress { - unsigned int domain; - unsigned int bus; - unsigned int slot; - unsigned int function; -} PCIHostDeviceAddress; - -void tcg_exec_init(unsigned long tb_size); -bool tcg_enabled(void); - -void cpu_exec_init_all(void); - -/* CPU save/load. */ -#ifdef CPU_SAVE_VERSION -void cpu_save(QEMUFile *f, void *opaque); -int cpu_load(QEMUFile *f, void *opaque, int version_id); -#endif - -/* Unblock cpu */ -void qemu_cpu_kick_self(void); - -/* work queue */ -struct qemu_work_item { - struct qemu_work_item *next; - void (*func)(void *data); - void *data; - int done; - bool free; -}; - - -/** - * Sends a (part of) iovec down a socket, yielding when the socket is full, or - * Receives data into a (part of) iovec from a socket, - * yielding when there is no data in the socket. - * The same interface as qemu_sendv_recvv(), with added yielding. - * XXX should mark these as coroutine_fn - */ -ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt, - size_t offset, size_t bytes, bool do_send); -#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \ - qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false) -#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \ - qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, true) - -/** - * The same as above, but with just a single buffer - */ -ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send); -#define qemu_co_recv(sockfd, buf, bytes) \ - qemu_co_send_recv(sockfd, buf, bytes, false) -#define qemu_co_send(sockfd, buf, bytes) \ - qemu_co_send_recv(sockfd, buf, bytes, true) - -typedef struct QEMUIOVector { - struct iovec *iov; - int niov; - int nalloc; - size_t size; -} QEMUIOVector; - -void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); -void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); -void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); -void qemu_iovec_concat(QEMUIOVector *dst, - QEMUIOVector *src, size_t soffset, size_t sbytes); -void qemu_iovec_concat_iov(QEMUIOVector *dst, - struct iovec *src_iov, unsigned int src_cnt, - size_t soffset, size_t sbytes); -void qemu_iovec_destroy(QEMUIOVector *qiov); -void qemu_iovec_reset(QEMUIOVector *qiov); -size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, - void *buf, size_t bytes); -size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, - const void *buf, size_t bytes); -size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, - int fillc, size_t bytes); - -bool buffer_is_zero(const void *buf, size_t len); - -void qemu_progress_init(int enabled, float min_skip); -void qemu_progress_end(void); -void qemu_progress_print(float delta, int max); -const char *qemu_get_vm_name(void); - -#define QEMU_FILE_TYPE_BIOS 0 -#define QEMU_FILE_TYPE_KEYMAP 1 -char *qemu_find_file(int type, const char *name); - -/* OS specific functions */ -void os_setup_early_signal_handling(void); -char *os_find_datadir(const char *argv0); -void os_parse_cmd_args(int index, const char *optarg); -void os_pidfile_error(void); - -/* Convert a byte between binary and BCD. */ -static inline uint8_t to_bcd(uint8_t val) -{ - return ((val / 10) << 4) | (val % 10); -} - -static inline uint8_t from_bcd(uint8_t val) -{ - return ((val >> 4) * 10) + (val & 0x0f); -} - -/* compute with 96 bit intermediate result: (a*b)/c */ -static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) -{ - union { - uint64_t ll; - struct { -#ifdef HOST_WORDS_BIGENDIAN - uint32_t high, low; -#else - uint32_t low, high; -#endif - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} - -/* Round number down to multiple */ -#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m)) - -/* Round number up to multiple */ -#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m)) - -static inline bool is_power_of_2(uint64_t value) -{ - if (!value) { - return 0; - } - - return !(value & (value - 1)); -} - -/* round down to the nearest power of 2*/ -int64_t pow2floor(int64_t value); - -#include "qemu/module.h" - -/* - * 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); -int uleb128_decode_small(const uint8_t *in, uint32_t *n); - -/* unicode.c */ -int mod_utf8_codepoint(const char *s, size_t n, char **end); - -/* - * Hexdump a buffer to a file. An optional string prefix is added to every line - */ - -void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size); - -/* 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) -/* 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) -#else -#define VECTYPE unsigned long -#define SPLAT(p) (*(p) * (~0UL / 255)) -#define ALL_EQ(v1, v2) ((v1) == (v2)) -#endif - -#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8 -static inline bool -can_use_buffer_find_nonzero_offset(const void *buf, size_t len) -{ - return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR - * sizeof(VECTYPE)) == 0 - && ((uintptr_t) buf) % sizeof(VECTYPE) == 0); -} -size_t buffer_find_nonzero_offset(const void *buf, size_t len); - -/* - * helper to parse debug environment variables - */ -int parse_debug_env(const char *name, int max, int initial); - -#endif diff --git a/contrib/qemu/include/qemu/aes.h b/contrib/qemu/include/qemu/aes.h deleted file mode 100644 index e79c707436f..00000000000 --- a/contrib/qemu/include/qemu/aes.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QEMU_AES_H -#define QEMU_AES_H - -#define AES_MAXNR 14 -#define AES_BLOCK_SIZE 16 - -struct aes_key_st { - uint32_t rd_key[4 *(AES_MAXNR + 1)]; - int rounds; -}; -typedef struct aes_key_st AES_KEY; - -int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key); -int AES_set_decrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key); - -void AES_encrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key); -void AES_decrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key); -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc); - -/* -AES_Te0[x] = S [x].[02, 01, 01, 03]; -AES_Te1[x] = S [x].[03, 02, 01, 01]; -AES_Te2[x] = S [x].[01, 03, 02, 01]; -AES_Te3[x] = S [x].[01, 01, 03, 02]; -AES_Te4[x] = S [x].[01, 01, 01, 01]; - -AES_Td0[x] = Si[x].[0e, 09, 0d, 0b]; -AES_Td1[x] = Si[x].[0b, 0e, 09, 0d]; -AES_Td2[x] = Si[x].[0d, 0b, 0e, 09]; -AES_Td3[x] = Si[x].[09, 0d, 0b, 0e]; -AES_Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -extern const uint32_t AES_Te0[256], AES_Te1[256], AES_Te2[256], - AES_Te3[256], AES_Te4[256]; -extern const uint32_t AES_Td0[256], AES_Td1[256], AES_Td2[256], - AES_Td3[256], AES_Td4[256]; - -#endif diff --git a/contrib/qemu/include/qemu/atomic.h b/contrib/qemu/include/qemu/atomic.h deleted file mode 100644 index 0aa89133018..00000000000 --- a/contrib/qemu/include/qemu/atomic.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Simple interface for atomic operations. - * - * Copyright (C) 2013 Red Hat, Inc. - * - * 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. - * - */ - -#ifndef __QEMU_ATOMIC_H -#define __QEMU_ATOMIC_H 1 - -#include "qemu/compiler.h" - -/* For C11 atomic ops */ - -/* Compiler barrier */ -#define barrier() ({ asm volatile("" ::: "memory"); (void)0; }) - -#ifndef __ATOMIC_RELAXED - -/* - * We use GCC builtin if it's available, as that can use mfence on - * 32-bit as well, e.g. if built with -march=pentium-m. However, on - * i386 the spec is buggy, and the implementation followed it until - * 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793). - */ -#if defined(__i386__) || defined(__x86_64__) -#if !QEMU_GNUC_PREREQ(4, 4) -#if defined __x86_64__ -#define smp_mb() ({ asm volatile("mfence" ::: "memory"); (void)0; }) -#else -#define smp_mb() ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; }) -#endif -#endif -#endif - - -#ifdef __alpha__ -#define smp_read_barrier_depends() asm volatile("mb":::"memory") -#endif - -#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) - -/* - * Because of the strongly ordered storage model, wmb() and rmb() are nops - * here (a compiler barrier only). QEMU doesn't do accesses to write-combining - * qemu memory or non-temporal load/stores from C code. - */ -#define smp_wmb() barrier() -#define smp_rmb() barrier() - -/* - * __sync_lock_test_and_set() is documented to be an acquire barrier only, - * but it is a full barrier at the hardware level. Add a compiler barrier - * to make it a full barrier also at the compiler level. - */ -#define atomic_xchg(ptr, i) (barrier(), __sync_lock_test_and_set(ptr, i)) - -/* - * Load/store with Java volatile semantics. - */ -#define atomic_mb_set(ptr, i) ((void)atomic_xchg(ptr, i)) - -#elif defined(_ARCH_PPC) - -/* - * We use an eieio() for wmb() on powerpc. This assumes we don't - * need to order cacheable and non-cacheable stores with respect to - * each other. - * - * smp_mb has the same problem as on x86 for not-very-new GCC - * (http://patchwork.ozlabs.org/patch/126184/, Nov 2011). - */ -#define smp_wmb() ({ asm volatile("eieio" ::: "memory"); (void)0; }) -#if defined(__powerpc64__) -#define smp_rmb() ({ asm volatile("lwsync" ::: "memory"); (void)0; }) -#else -#define smp_rmb() ({ asm volatile("sync" ::: "memory"); (void)0; }) -#endif -#define smp_mb() ({ asm volatile("sync" ::: "memory"); (void)0; }) - -#endif /* _ARCH_PPC */ - -#endif /* C11 atomics */ - -/* - * For (host) platforms we don't have explicit barrier definitions - * for, we use the gcc __sync_synchronize() primitive to generate a - * full barrier. This should be safe on all platforms, though it may - * be overkill for smp_wmb() and smp_rmb(). - */ -#ifndef smp_mb -#define smp_mb() __sync_synchronize() -#endif - -#ifndef smp_wmb -#ifdef __ATOMIC_RELEASE -#define smp_wmb() __atomic_thread_fence(__ATOMIC_RELEASE) -#else -#define smp_wmb() __sync_synchronize() -#endif -#endif - -#ifndef smp_rmb -#ifdef __ATOMIC_ACQUIRE -#define smp_rmb() __atomic_thread_fence(__ATOMIC_ACQUIRE) -#else -#define smp_rmb() __sync_synchronize() -#endif -#endif - -#ifndef smp_read_barrier_depends -#ifdef __ATOMIC_CONSUME -#define smp_read_barrier_depends() __atomic_thread_fence(__ATOMIC_CONSUME) -#else -#define smp_read_barrier_depends() barrier() -#endif -#endif - -#ifndef atomic_read -#define atomic_read(ptr) (*(__typeof__(*ptr) *volatile) (ptr)) -#endif - -#ifndef atomic_set -#define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i)) -#endif - -/* These have the same semantics as Java volatile variables. - * See http://gee.cs.oswego.edu/dl/jmm/cookbook.html: - * "1. Issue a StoreStore barrier (wmb) before each volatile store." - * 2. Issue a StoreLoad barrier after each volatile store. - * Note that you could instead issue one before each volatile load, but - * this would be slower for typical programs using volatiles in which - * reads greatly outnumber writes. Alternatively, if available, you - * can implement volatile store as an atomic instruction (for example - * XCHG on x86) and omit the barrier. This may be more efficient if - * atomic instructions are cheaper than StoreLoad barriers. - * 3. Issue LoadLoad and LoadStore barriers after each volatile load." - * - * If you prefer to think in terms of "pairing" of memory barriers, - * an atomic_mb_read pairs with an atomic_mb_set. - * - * And for the few ia64 lovers that exist, an atomic_mb_read is a ld.acq, - * while an atomic_mb_set is a st.rel followed by a memory barrier. - * - * These are a bit weaker than __atomic_load/store with __ATOMIC_SEQ_CST - * (see docs/atomics.txt), and I'm not sure that __ATOMIC_ACQ_REL is enough. - * Just always use the barriers manually by the rules above. - */ -#ifndef atomic_mb_read -#define atomic_mb_read(ptr) ({ \ - typeof(*ptr) _val = atomic_read(ptr); \ - smp_rmb(); \ - _val; \ -}) -#endif - -#ifndef atomic_mb_set -#define atomic_mb_set(ptr, i) do { \ - smp_wmb(); \ - atomic_set(ptr, i); \ - smp_mb(); \ -} while (0) -#endif - -#ifndef atomic_xchg -#ifdef __ATOMIC_SEQ_CST -#define atomic_xchg(ptr, i) ({ \ - typeof(*ptr) _new = (i), _old; \ - __atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \ - _old; \ -}) -#elif defined __clang__ -#define atomic_xchg(ptr, i) __sync_exchange(ptr, i) -#else -/* __sync_lock_test_and_set() is documented to be an acquire barrier only. */ -#define atomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i)) -#endif -#endif - -/* Provide shorter names for GCC atomic builtins. */ -#define atomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1) -#define atomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1) -#define atomic_fetch_add __sync_fetch_and_add -#define atomic_fetch_sub __sync_fetch_and_sub -#define atomic_fetch_and __sync_fetch_and_and -#define atomic_fetch_or __sync_fetch_and_or -#define atomic_cmpxchg __sync_val_compare_and_swap - -/* And even shorter names that return void. */ -#define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1)) -#define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1)) -#define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n)) -#define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n)) -#define atomic_and(ptr, n) ((void) __sync_fetch_and_and(ptr, n)) -#define atomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n)) - -#endif diff --git a/contrib/qemu/include/qemu/bitmap.h b/contrib/qemu/include/qemu/bitmap.h deleted file mode 100644 index 308bbb71e9b..00000000000 --- a/contrib/qemu/include/qemu/bitmap.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Bitmap Module - * - * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com> - * - * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h - * - * 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. - */ - -#ifndef BITMAP_H -#define BITMAP_H - -#include "qemu-common.h" -#include "qemu/bitops.h" - -/* - * The available bitmap operations and their rough meaning in the - * case that the bitmap is a single unsigned long are thus: - * - * Note that nbits should be always a compile time evaluable constant. - * Otherwise many inlines will generate horrible code. - * - * bitmap_zero(dst, nbits) *dst = 0UL - * bitmap_fill(dst, nbits) *dst = ~0UL - * bitmap_copy(dst, src, nbits) *dst = *src - * bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2 - * bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2 - * bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2 - * bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2) - * bitmap_complement(dst, src, nbits) *dst = ~(*src) - * bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal? - * bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap? - * bitmap_empty(src, nbits) Are all bits zero in *src? - * bitmap_full(src, nbits) Are all bits set in *src? - * bitmap_set(dst, pos, nbits) Set specified bit area - * bitmap_clear(dst, pos, nbits) Clear specified bit area - * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area - */ - -/* - * Also the following operations apply to bitmaps. - * - * set_bit(bit, addr) *addr |= bit - * clear_bit(bit, addr) *addr &= ~bit - * change_bit(bit, addr) *addr ^= bit - * test_bit(bit, addr) Is bit set in *addr? - * test_and_set_bit(bit, addr) Set bit and return old value - * test_and_clear_bit(bit, addr) Clear bit and return old value - * test_and_change_bit(bit, addr) Change bit and return old value - * find_first_zero_bit(addr, nbits) Position first zero bit in *addr - * find_first_bit(addr, nbits) Position first set bit in *addr - * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit - * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit - */ - -#define BITMAP_LAST_WORD_MASK(nbits) \ - ( \ - ((nbits) % BITS_PER_LONG) ? \ - (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ - ) - -#define DECLARE_BITMAP(name,bits) \ - unsigned long name[BITS_TO_LONGS(bits)] - -#define small_nbits(nbits) \ - ((nbits) <= BITS_PER_LONG) - -int slow_bitmap_empty(const unsigned long *bitmap, int bits); -int slow_bitmap_full(const unsigned long *bitmap, int bits); -int slow_bitmap_equal(const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); -void slow_bitmap_complement(unsigned long *dst, const unsigned long *src, - int bits); -void slow_bitmap_shift_right(unsigned long *dst, - const unsigned long *src, int shift, int bits); -void slow_bitmap_shift_left(unsigned long *dst, - const unsigned long *src, int shift, int bits); -int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); -void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); -void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); -int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); -int slow_bitmap_intersects(const unsigned long *bitmap1, - const unsigned long *bitmap2, int bits); - -static inline unsigned long *bitmap_new(int nbits) -{ - int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); - return g_malloc0(len); -} - -static inline void bitmap_zero(unsigned long *dst, int nbits) -{ - if (small_nbits(nbits)) { - *dst = 0UL; - } else { - int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); - memset(dst, 0, len); - } -} - -static inline void bitmap_fill(unsigned long *dst, int nbits) -{ - size_t nlongs = BITS_TO_LONGS(nbits); - if (!small_nbits(nbits)) { - int len = (nlongs - 1) * sizeof(unsigned long); - memset(dst, 0xff, len); - } - dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); -} - -static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, - int nbits) -{ - if (small_nbits(nbits)) { - *dst = *src; - } else { - int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); - memcpy(dst, src, len); - } -} - -static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - return (*dst = *src1 & *src2) != 0; - } - return slow_bitmap_and(dst, src1, src2, nbits); -} - -static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - *dst = *src1 | *src2; - } else { - slow_bitmap_or(dst, src1, src2, nbits); - } -} - -static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - *dst = *src1 ^ *src2; - } else { - slow_bitmap_xor(dst, src1, src2, nbits); - } -} - -static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - return (*dst = *src1 & ~(*src2)) != 0; - } - return slow_bitmap_andnot(dst, src1, src2, nbits); -} - -static inline void bitmap_complement(unsigned long *dst, const unsigned long *src, - int nbits) -{ - if (small_nbits(nbits)) { - *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits); - } else { - slow_bitmap_complement(dst, src, nbits); - } -} - -static inline int bitmap_equal(const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); - } else { - return slow_bitmap_equal(src1, src2, nbits); - } -} - -static inline int bitmap_empty(const unsigned long *src, int nbits) -{ - if (small_nbits(nbits)) { - return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); - } else { - return slow_bitmap_empty(src, nbits); - } -} - -static inline int bitmap_full(const unsigned long *src, int nbits) -{ - if (small_nbits(nbits)) { - return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); - } else { - return slow_bitmap_full(src, nbits); - } -} - -static inline int bitmap_intersects(const unsigned long *src1, - const unsigned long *src2, int nbits) -{ - if (small_nbits(nbits)) { - return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; - } else { - return slow_bitmap_intersects(src1, src2, nbits); - } -} - -void bitmap_set(unsigned long *map, int i, int len); -void bitmap_clear(unsigned long *map, int start, int nr); -unsigned long bitmap_find_next_zero_area(unsigned long *map, - unsigned long size, - unsigned long start, - unsigned int nr, - unsigned long align_mask); - -#endif /* BITMAP_H */ diff --git a/contrib/qemu/include/qemu/bitops.h b/contrib/qemu/include/qemu/bitops.h deleted file mode 100644 index affcc969dcf..00000000000 --- a/contrib/qemu/include/qemu/bitops.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Bitops Module - * - * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com> - * - * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h - * - * 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. - */ - -#ifndef BITOPS_H -#define BITOPS_H - -#include "qemu-common.h" -#include "host-utils.h" - -#define BITS_PER_BYTE CHAR_BIT -#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE) - -#define BIT(nr) (1UL << (nr)) -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) - -/** - * set_bit - Set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - */ -static inline void set_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - - *p |= mask; -} - -/** - * clear_bit - Clears a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - */ -static inline void clear_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - - *p &= ~mask; -} - -/** - * change_bit - Toggle a bit in memory - * @nr: Bit to change - * @addr: Address to start counting from - */ -static inline void change_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - - *p ^= mask; -} - -/** - * test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - */ -static inline int test_and_set_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -/** - * test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to clear - * @addr: Address to count from - */ -static inline int test_and_clear_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -/** - * test_and_change_bit - Change a bit and return its old value - * @nr: Bit to change - * @addr: Address to count from - */ -static inline int test_and_change_bit(int nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = addr + BIT_WORD(nr); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -/** - * test_bit - Determine whether a bit is set - * @nr: bit number to test - * @addr: Address to start counting from - */ -static inline int test_bit(int nr, const unsigned long *addr) -{ - return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); -} - -/** - * find_last_bit - find the last set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit number of the first set bit, or size. - */ -unsigned long find_last_bit(const unsigned long *addr, - unsigned long size); - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The bitmap size in bits - */ -unsigned long find_next_bit(const unsigned long *addr, - unsigned long size, unsigned long offset); - -/** - * find_next_zero_bit - find the next cleared bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The bitmap size in bits - */ - -unsigned long find_next_zero_bit(const unsigned long *addr, - unsigned long size, - unsigned long offset); - -/** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit number of the first set bit. - */ -static inline unsigned long find_first_bit(const unsigned long *addr, - unsigned long size) -{ - return find_next_bit(addr, size, 0); -} - -/** - * find_first_zero_bit - find the first cleared bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit number of the first cleared bit. - */ -static inline unsigned long find_first_zero_bit(const unsigned long *addr, - unsigned long size) -{ - return find_next_zero_bit(addr, size, 0); -} - -static inline unsigned long hweight_long(unsigned long w) -{ - unsigned long count; - - for (count = 0; w; w >>= 1) { - count += w & 1; - } - return count; -} - -/** - * extract32: - * @value: the value to extract the bit field from - * @start: the lowest bit in the bit field (numbered from 0) - * @length: the length of the bit field - * - * Extract from the 32 bit input @value the bit field specified by the - * @start and @length parameters, and return it. The bit field must - * lie entirely within the 32 bit word. It is valid to request that - * all 32 bits are returned (ie @length 32 and @start 0). - * - * Returns: the value of the bit field extracted from the input value. - */ -static inline uint32_t extract32(uint32_t value, int start, int length) -{ - assert(start >= 0 && length > 0 && length <= 32 - start); - return (value >> start) & (~0U >> (32 - length)); -} - -/** - * extract64: - * @value: the value to extract the bit field from - * @start: the lowest bit in the bit field (numbered from 0) - * @length: the length of the bit field - * - * Extract from the 64 bit input @value the bit field specified by the - * @start and @length parameters, and return it. The bit field must - * lie entirely within the 64 bit word. It is valid to request that - * all 64 bits are returned (ie @length 64 and @start 0). - * - * Returns: the value of the bit field extracted from the input value. - */ -static inline uint64_t extract64(uint64_t value, int start, int length) -{ - assert(start >= 0 && length > 0 && length <= 64 - start); - return (value >> start) & (~0ULL >> (64 - length)); -} - -/** - * deposit32: - * @value: initial value to insert bit field into - * @start: the lowest bit in the bit field (numbered from 0) - * @length: the length of the bit field - * @fieldval: the value to insert into the bit field - * - * Deposit @fieldval into the 32 bit @value at the bit field specified - * by the @start and @length parameters, and return the modified - * @value. Bits of @value outside the bit field are not modified. - * Bits of @fieldval above the least significant @length bits are - * ignored. The bit field must lie entirely within the 32 bit word. - * It is valid to request that all 32 bits are modified (ie @length - * 32 and @start 0). - * - * Returns: the modified @value. - */ -static inline uint32_t deposit32(uint32_t value, int start, int length, - uint32_t fieldval) -{ - uint32_t mask; - assert(start >= 0 && length > 0 && length <= 32 - start); - mask = (~0U >> (32 - length)) << start; - return (value & ~mask) | ((fieldval << start) & mask); -} - -/** - * deposit64: - * @value: initial value to insert bit field into - * @start: the lowest bit in the bit field (numbered from 0) - * @length: the length of the bit field - * @fieldval: the value to insert into the bit field - * - * Deposit @fieldval into the 64 bit @value at the bit field specified - * by the @start and @length parameters, and return the modified - * @value. Bits of @value outside the bit field are not modified. - * Bits of @fieldval above the least significant @length bits are - * ignored. The bit field must lie entirely within the 64 bit word. - * It is valid to request that all 64 bits are modified (ie @length - * 64 and @start 0). - * - * Returns: the modified @value. - */ -static inline uint64_t deposit64(uint64_t value, int start, int length, - uint64_t fieldval) -{ - uint64_t mask; - assert(start >= 0 && length > 0 && length <= 64 - start); - mask = (~0ULL >> (64 - length)) << start; - return (value & ~mask) | ((fieldval << start) & mask); -} - -#endif diff --git a/contrib/qemu/include/qemu/bswap.h b/contrib/qemu/include/qemu/bswap.h deleted file mode 100644 index bf6457b8c46..00000000000 --- a/contrib/qemu/include/qemu/bswap.h +++ /dev/null @@ -1,487 +0,0 @@ -#ifndef BSWAP_H -#define BSWAP_H - -#include "config-host.h" -#include <inttypes.h> -#include <limits.h> -#include <string.h> -#include "fpu/softfloat.h" - -#ifdef CONFIG_MACHINE_BSWAP_H -# include <sys/endian.h> -# include <sys/types.h> -# include <machine/bswap.h> -#elif defined(__FreeBSD__) -# include <sys/endian.h> -#elif defined(CONFIG_BYTESWAP_H) -#ifdef GF_DARWIN_HOST_OS -# include <libkern/OSByteOrder.h> -#define bswap_16(x) OSSwapInt16(x) -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) -#else -# include <byteswap.h> -#endif - -static inline uint16_t bswap16(uint16_t x) -{ - return bswap_16(x); -} - -static inline uint32_t bswap32(uint32_t x) -{ - return bswap_32(x); -} - -static inline uint64_t bswap64(uint64_t x) -{ - return bswap_64(x); -} -# else -static inline uint16_t bswap16(uint16_t x) -{ - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); -} - -static inline uint32_t bswap32(uint32_t x) -{ - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); -} - -static inline uint64_t bswap64(uint64_t x) -{ - return (((x & 0x00000000000000ffULL) << 56) | - ((x & 0x000000000000ff00ULL) << 40) | - ((x & 0x0000000000ff0000ULL) << 24) | - ((x & 0x00000000ff000000ULL) << 8) | - ((x & 0x000000ff00000000ULL) >> 8) | - ((x & 0x0000ff0000000000ULL) >> 24) | - ((x & 0x00ff000000000000ULL) >> 40) | - ((x & 0xff00000000000000ULL) >> 56)); -} -#endif /* ! CONFIG_MACHINE_BSWAP_H */ - -static inline void bswap16s(uint16_t *s) -{ - *s = bswap16(*s); -} - -static inline void bswap32s(uint32_t *s) -{ - *s = bswap32(*s); -} - -static inline void bswap64s(uint64_t *s) -{ - *s = bswap64(*s); -} - -#if defined(HOST_WORDS_BIGENDIAN) -#define be_bswap(v, size) (v) -#define le_bswap(v, size) glue(bswap, size)(v) -#define be_bswaps(v, size) -#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0) -#else -#define le_bswap(v, size) (v) -#define be_bswap(v, size) glue(bswap, size)(v) -#define le_bswaps(v, size) -#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0) -#endif - -#define CPU_CONVERT(endian, size, type)\ -static inline type endian ## size ## _to_cpu(type v)\ -{\ - return glue(endian, _bswap)(v, size);\ -}\ -\ -static inline type cpu_to_ ## endian ## size(type v)\ -{\ - return glue(endian, _bswap)(v, size);\ -}\ -\ -static inline void endian ## size ## _to_cpus(type *p)\ -{\ - glue(endian, _bswaps)(p, size);\ -}\ -\ -static inline void cpu_to_ ## endian ## size ## s(type *p)\ -{\ - glue(endian, _bswaps)(p, size);\ -}\ -\ -static inline type endian ## size ## _to_cpup(const type *p)\ -{\ - return glue(glue(endian, size), _to_cpu)(*p);\ -}\ -\ -static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\ -{\ - *p = glue(glue(cpu_to_, endian), size)(v);\ -} - -CPU_CONVERT(be, 16, uint16_t) -CPU_CONVERT(be, 32, uint32_t) -CPU_CONVERT(be, 64, uint64_t) - -CPU_CONVERT(le, 16, uint16_t) -CPU_CONVERT(le, 32, uint32_t) -CPU_CONVERT(le, 64, uint64_t) - -/* len must be one of 1, 2, 4 */ -static inline uint32_t qemu_bswap_len(uint32_t value, int len) -{ - return bswap32(value) >> (32 - 8 * len); -} - -/* Unions for reinterpreting between floats and integers. */ - -typedef union { - float32 f; - uint32_t l; -} CPU_FloatU; - -typedef union { - float64 d; -#if defined(HOST_WORDS_BIGENDIAN) - struct { - uint32_t upper; - uint32_t lower; - } l; -#else - struct { - uint32_t lower; - uint32_t upper; - } l; -#endif - uint64_t ll; -} CPU_DoubleU; - -typedef union { - floatx80 d; - struct { - uint64_t lower; - uint16_t upper; - } l; -} CPU_LDoubleU; - -typedef union { - float128 q; -#if defined(HOST_WORDS_BIGENDIAN) - struct { - uint32_t upmost; - uint32_t upper; - uint32_t lower; - uint32_t lowest; - } l; - struct { - uint64_t upper; - uint64_t lower; - } ll; -#else - struct { - uint32_t lowest; - uint32_t lower; - uint32_t upper; - uint32_t upmost; - } l; - struct { - uint64_t lower; - uint64_t upper; - } ll; -#endif -} CPU_QuadU; - -/* unaligned/endian-independent pointer access */ - -/* - * the generic syntax is: - * - * load: ld{type}{sign}{size}{endian}_p(ptr) - * - * store: st{type}{size}{endian}_p(ptr, val) - * - * Note there are small differences with the softmmu access API! - * - * type is: - * (empty): integer access - * f : float access - * - * sign is: - * (empty): for floats or 32 bit size - * u : unsigned - * s : signed - * - * size is: - * b: 8 bits - * w: 16 bits - * l: 32 bits - * q: 64 bits - * - * endian is: - * (empty): host endian - * be : big endian - * le : little endian - */ - -static inline int ldub_p(const void *ptr) -{ - return *(uint8_t *)ptr; -} - -static inline int ldsb_p(const void *ptr) -{ - return *(int8_t *)ptr; -} - -static inline void stb_p(void *ptr, int v) -{ - *(uint8_t *)ptr = v; -} - -/* Any compiler worth its salt will turn these memcpy into native unaligned - operations. Thus we don't need to play games with packed attributes, or - inline byte-by-byte stores. */ - -static inline int lduw_p(const void *ptr) -{ - uint16_t r; - memcpy(&r, ptr, sizeof(r)); - return r; -} - -static inline int ldsw_p(const void *ptr) -{ - int16_t r; - memcpy(&r, ptr, sizeof(r)); - return r; -} - -static inline void stw_p(void *ptr, uint16_t v) -{ - memcpy(ptr, &v, sizeof(v)); -} - -static inline int ldl_p(const void *ptr) -{ - int32_t r; - memcpy(&r, ptr, sizeof(r)); - return r; -} - -static inline void stl_p(void *ptr, uint32_t v) -{ - memcpy(ptr, &v, sizeof(v)); -} - -static inline uint64_t ldq_p(const void *ptr) -{ - uint64_t r; - memcpy(&r, ptr, sizeof(r)); - return r; -} - -static inline void stq_p(void *ptr, uint64_t v) -{ - memcpy(ptr, &v, sizeof(v)); -} - -static inline int lduw_le_p(const void *ptr) -{ - return (uint16_t)le_bswap(lduw_p(ptr), 16); -} - -static inline int ldsw_le_p(const void *ptr) -{ - return (int16_t)le_bswap(lduw_p(ptr), 16); -} - -static inline int ldl_le_p(const void *ptr) -{ - return le_bswap(ldl_p(ptr), 32); -} - -static inline uint64_t ldq_le_p(const void *ptr) -{ - return le_bswap(ldq_p(ptr), 64); -} - -static inline void stw_le_p(void *ptr, int v) -{ - stw_p(ptr, le_bswap(v, 16)); -} - -static inline void stl_le_p(void *ptr, int v) -{ - stl_p(ptr, le_bswap(v, 32)); -} - -static inline void stq_le_p(void *ptr, uint64_t v) -{ - stq_p(ptr, le_bswap(v, 64)); -} - -/* float access */ - -static inline float32 ldfl_le_p(const void *ptr) -{ - CPU_FloatU u; - u.l = ldl_le_p(ptr); - return u.f; -} - -static inline void stfl_le_p(void *ptr, float32 v) -{ - CPU_FloatU u; - u.f = v; - stl_le_p(ptr, u.l); -} - -static inline float64 ldfq_le_p(const void *ptr) -{ - CPU_DoubleU u; - u.ll = ldq_le_p(ptr); - return u.d; -} - -static inline void stfq_le_p(void *ptr, float64 v) -{ - CPU_DoubleU u; - u.d = v; - stq_le_p(ptr, u.ll); -} - -static inline int lduw_be_p(const void *ptr) -{ - return (uint16_t)be_bswap(lduw_p(ptr), 16); -} - -static inline int ldsw_be_p(const void *ptr) -{ - return (int16_t)be_bswap(lduw_p(ptr), 16); -} - -static inline int ldl_be_p(const void *ptr) -{ - return be_bswap(ldl_p(ptr), 32); -} - -static inline uint64_t ldq_be_p(const void *ptr) -{ - return be_bswap(ldq_p(ptr), 64); -} - -static inline void stw_be_p(void *ptr, int v) -{ - stw_p(ptr, be_bswap(v, 16)); -} - -static inline void stl_be_p(void *ptr, int v) -{ - stl_p(ptr, be_bswap(v, 32)); -} - -static inline void stq_be_p(void *ptr, uint64_t v) -{ - stq_p(ptr, be_bswap(v, 64)); -} - -/* float access */ - -static inline float32 ldfl_be_p(const void *ptr) -{ - CPU_FloatU u; - u.l = ldl_be_p(ptr); - return u.f; -} - -static inline void stfl_be_p(void *ptr, float32 v) -{ - CPU_FloatU u; - u.f = v; - stl_be_p(ptr, u.l); -} - -static inline float64 ldfq_be_p(const void *ptr) -{ - CPU_DoubleU u; - u.ll = ldq_be_p(ptr); - return u.d; -} - -static inline void stfq_be_p(void *ptr, float64 v) -{ - CPU_DoubleU u; - u.d = v; - stq_be_p(ptr, u.ll); -} - -/* Legacy unaligned versions. Note that we never had a complete set. */ - -static inline void cpu_to_le16wu(uint16_t *p, uint16_t v) -{ - stw_le_p(p, v); -} - -static inline void cpu_to_le32wu(uint32_t *p, uint32_t v) -{ - stl_le_p(p, v); -} - -static inline uint16_t le16_to_cpupu(const uint16_t *p) -{ - return lduw_le_p(p); -} - -static inline uint32_t le32_to_cpupu(const uint32_t *p) -{ - return ldl_le_p(p); -} - -static inline uint32_t be32_to_cpupu(const uint32_t *p) -{ - return ldl_be_p(p); -} - -static inline void cpu_to_be16wu(uint16_t *p, uint16_t v) -{ - stw_be_p(p, v); -} - -static inline void cpu_to_be32wu(uint32_t *p, uint32_t v) -{ - stl_be_p(p, v); -} - -static inline void cpu_to_be64wu(uint64_t *p, uint64_t v) -{ - stq_be_p(p, v); -} - -static inline void cpu_to_32wu(uint32_t *p, uint32_t v) -{ - stl_p(p, v); -} - -static inline unsigned long leul_to_cpu(unsigned long v) -{ - /* In order to break an include loop between here and - qemu-common.h, don't rely on HOST_LONG_BITS. */ -#if ULONG_MAX == UINT32_MAX - return le_bswap(v, 32); -#elif ULONG_MAX == UINT64_MAX - return le_bswap(v, 64); -#else -# error Unknown sizeof long -#endif -} - -#undef le_bswap -#undef be_bswap -#undef le_bswaps -#undef be_bswaps - -#endif /* BSWAP_H */ diff --git a/contrib/qemu/include/qemu/compiler.h b/contrib/qemu/include/qemu/compiler.h deleted file mode 100644 index 155b358964a..00000000000 --- a/contrib/qemu/include/qemu/compiler.h +++ /dev/null @@ -1,55 +0,0 @@ -/* public domain */ - -#ifndef COMPILER_H -#define COMPILER_H - -#include "config-host.h" - -/*---------------------------------------------------------------------------- -| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler. -| The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h. -*----------------------------------------------------------------------------*/ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define QEMU_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -# define QEMU_GNUC_PREREQ(maj, min) 0 -#endif - -#define QEMU_NORETURN __attribute__ ((__noreturn__)) - -#if QEMU_GNUC_PREREQ(3, 4) -#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define QEMU_WARN_UNUSED_RESULT -#endif - -#if defined(_WIN32) -# define QEMU_PACKED __attribute__((gcc_struct, packed)) -#else -# define QEMU_PACKED __attribute__((packed)) -#endif - -#define cat(x,y) x ## y -#define cat2(x,y) cat(x,y) -#define QEMU_BUILD_BUG_ON(x) \ - typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused)); - -#if defined __GNUC__ -# if !QEMU_GNUC_PREREQ(4, 4) - /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */ -# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) -# else - /* Use gnu_printf when supported (qemu uses standard format strings). */ -# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) -# if defined(_WIN32) - /* Map __printf__ to __gnu_printf__ because we want standard format strings - * even when MinGW or GLib include files use __printf__. */ -# define __printf__ __gnu_printf__ -# endif -# endif -#else -#define GCC_FMT_ATTR(n, m) -#endif - -#endif /* COMPILER_H */ diff --git a/contrib/qemu/include/qemu/error-report.h b/contrib/qemu/include/qemu/error-report.h deleted file mode 100644 index 3b098a91730..00000000000 --- a/contrib/qemu/include/qemu/error-report.h +++ /dev/null @@ -1,46 +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. - */ - -#ifndef QEMU_ERROR_H -#define QEMU_ERROR_H - -#include <stdarg.h> -#include <stdbool.h> -#include "qemu/compiler.h" - -typedef struct Location { - /* all members are private to qemu-error.c */ - enum { LOC_NONE, LOC_CMDLINE, LOC_FILE } kind; - int num; - const void *ptr; - struct Location *prev; -} Location; - -Location *loc_push_restore(Location *loc); -Location *loc_push_none(Location *loc); -Location *loc_pop(Location *loc); -Location *loc_save(Location *loc); -void loc_restore(Location *loc); -void loc_set_none(void); -void loc_set_cmdline(char **argv, int idx, int cnt); -void loc_set_file(const char *fname, int lno); - -void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0); -void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -void error_print_loc(void); -void error_set_progname(const char *argv0); -void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -const char *error_get_progname(void); -extern bool enable_timestamp_msg; - -#endif diff --git a/contrib/qemu/include/qemu/event_notifier.h b/contrib/qemu/include/qemu/event_notifier.h deleted file mode 100644 index 88b57af7ce8..00000000000 --- a/contrib/qemu/include/qemu/event_notifier.h +++ /dev/null @@ -1,46 +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. - */ - -#ifndef QEMU_EVENT_NOTIFIER_H -#define QEMU_EVENT_NOTIFIER_H - -#include "qemu-common.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -struct EventNotifier { -#ifdef _WIN32 - HANDLE event; -#else - int rfd; - int wfd; -#endif -}; - -typedef void EventNotifierHandler(EventNotifier *); - -int event_notifier_init(EventNotifier *, int active); -void event_notifier_cleanup(EventNotifier *); -int event_notifier_set(EventNotifier *); -int event_notifier_test_and_clear(EventNotifier *); -int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *); - -#ifdef CONFIG_POSIX -void event_notifier_init_fd(EventNotifier *, int fd); -int event_notifier_get_fd(EventNotifier *); -#else -HANDLE event_notifier_get_handle(EventNotifier *); -#endif - -#endif diff --git a/contrib/qemu/include/qemu/hbitmap.h b/contrib/qemu/include/qemu/hbitmap.h deleted file mode 100644 index 550d7ce2c39..00000000000 --- a/contrib/qemu/include/qemu/hbitmap.h +++ /dev/null @@ -1,209 +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. - */ - -#ifndef HBITMAP_H -#define HBITMAP_H 1 - -#include <limits.h> -#include <stdint.h> -#include <stdbool.h> -#include "bitops.h" -#include "host-utils.h" - -typedef struct HBitmap HBitmap; -typedef struct HBitmapIter HBitmapIter; - -#define BITS_PER_LEVEL (BITS_PER_LONG == 32 ? 5 : 6) - -/* For 32-bit, the largest that fits in a 4 GiB address space. - * For 64-bit, the number of sectors in 1 PiB. Good luck, in - * either case... :) - */ -#define HBITMAP_LOG_MAX_SIZE (BITS_PER_LONG == 32 ? 34 : 41) - -/* We need to place a sentinel in level 0 to speed up iteration. Thus, - * we do this instead of HBITMAP_LOG_MAX_SIZE / BITS_PER_LEVEL. The - * difference is that it allocates an extra level when HBITMAP_LOG_MAX_SIZE - * is an exact multiple of BITS_PER_LEVEL. - */ -#define HBITMAP_LEVELS ((HBITMAP_LOG_MAX_SIZE / BITS_PER_LEVEL) + 1) - -struct HBitmapIter { - const HBitmap *hb; - - /* Copied from hb for access in the inline functions (hb is opaque). */ - int granularity; - - /* Entry offset into the last-level array of longs. */ - size_t pos; - - /* The currently-active path in the tree. Each item of cur[i] stores - * the bits (i.e. the subtrees) yet to be processed under that node. - */ - unsigned long cur[HBITMAP_LEVELS]; -}; - -/** - * hbitmap_alloc: - * @size: Number of bits in the bitmap. - * @granularity: Granularity of the bitmap. Aligned groups of 2^@granularity - * bits will be represented by a single bit. Each operation on a - * range of bits first rounds the bits to determine which group they land - * in, and then affect the entire set; iteration will only visit the first - * bit of each group. - * - * Allocate a new HBitmap. - */ -HBitmap *hbitmap_alloc(uint64_t size, int granularity); - -/** - * hbitmap_empty: - * @hb: HBitmap to operate on. - * - * Return whether the bitmap is empty. - */ -bool hbitmap_empty(const HBitmap *hb); - -/** - * hbitmap_granularity: - * @hb: HBitmap to operate on. - * - * Return the granularity of the HBitmap. - */ -int hbitmap_granularity(const HBitmap *hb); - -/** - * hbitmap_count: - * @hb: HBitmap to operate on. - * - * Return the number of bits set in the HBitmap. - */ -uint64_t hbitmap_count(const HBitmap *hb); - -/** - * hbitmap_set: - * @hb: HBitmap to operate on. - * @start: First bit to set (0-based). - * @count: Number of bits to set. - * - * Set a consecutive range of bits in an HBitmap. - */ -void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count); - -/** - * hbitmap_reset: - * @hb: HBitmap to operate on. - * @start: First bit to reset (0-based). - * @count: Number of bits to reset. - * - * Reset a consecutive range of bits in an HBitmap. - */ -void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count); - -/** - * hbitmap_get: - * @hb: HBitmap to operate on. - * @item: Bit to query (0-based). - * - * Return whether the @item-th bit in an HBitmap is set. - */ -bool hbitmap_get(const HBitmap *hb, uint64_t item); - -/** - * hbitmap_free: - * @hb: HBitmap to operate on. - * - * Free an HBitmap and all of its associated memory. - */ -void hbitmap_free(HBitmap *hb); - -/** - * hbitmap_iter_init: - * @hbi: HBitmapIter to initialize. - * @hb: HBitmap to iterate on. - * @first: First bit to visit (0-based, must be strictly less than the - * size of the bitmap). - * - * Set up @hbi to iterate on the HBitmap @hb. hbitmap_iter_next will return - * the lowest-numbered bit that is set in @hb, starting at @first. - * - * Concurrent setting of bits is acceptable, and will at worst cause the - * iteration to miss some of those bits. Resetting bits before the current - * position of the iterator is also okay. However, concurrent resetting of - * bits can lead to unexpected behavior if the iterator has not yet reached - * those bits. - */ -void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first); - -/* hbitmap_iter_skip_words: - * @hbi: HBitmapIter to operate on. - * - * Internal function used by hbitmap_iter_next and hbitmap_iter_next_word. - */ -unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi); - -/** - * hbitmap_iter_next: - * @hbi: HBitmapIter to operate on. - * - * Return the next bit that is set in @hbi's associated HBitmap, - * or -1 if all remaining bits are zero. - */ -static inline int64_t hbitmap_iter_next(HBitmapIter *hbi) -{ - unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1]; - int64_t item; - - if (cur == 0) { - cur = hbitmap_iter_skip_words(hbi); - if (cur == 0) { - return -1; - } - } - - /* The next call will resume work from the next bit. */ - hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); - item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); - - return item << hbi->granularity; -} - -/** - * hbitmap_iter_next_word: - * @hbi: HBitmapIter to operate on. - * @p_cur: Location where to store the next non-zero word. - * - * Return the index of the next nonzero word that is set in @hbi's - * associated HBitmap, and set *p_cur to the content of that word - * (bits before the index that was passed to hbitmap_iter_init are - * trimmed on the first call). Return -1, and set *p_cur to zero, - * if all remaining words are zero. - */ -static inline size_t hbitmap_iter_next_word(HBitmapIter *hbi, unsigned long *p_cur) -{ - unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1]; - - if (cur == 0) { - cur = hbitmap_iter_skip_words(hbi); - if (cur == 0) { - *p_cur = 0; - return -1; - } - } - - /* The next call will resume work from the next word. */ - hbi->cur[HBITMAP_LEVELS - 1] = 0; - *p_cur = cur; - return hbi->pos; -} - - -#endif diff --git a/contrib/qemu/include/qemu/host-utils.h b/contrib/qemu/include/qemu/host-utils.h deleted file mode 100644 index 0f688c1c00a..00000000000 --- a/contrib/qemu/include/qemu/host-utils.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Utility compute operations used by translated code. - * - * Copyright (c) 2007 Thiemo Seufer - * Copyright (c) 2007 Jocelyn Mayer - * - * 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. - */ -#ifndef HOST_UTILS_H -#define HOST_UTILS_H 1 - -#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */ -#include <limits.h> - -#ifdef CONFIG_INT128 -static inline void mulu64(uint64_t *plow, uint64_t *phigh, - uint64_t a, uint64_t b) -{ - __uint128_t r = (__uint128_t)a * b; - *plow = r; - *phigh = r >> 64; -} - -static inline void muls64(uint64_t *plow, uint64_t *phigh, - int64_t a, int64_t b) -{ - __int128_t r = (__int128_t)a * b; - *plow = r; - *phigh = r >> 64; -} -#else -void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); -void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); -#endif - -/** - * clz32 - count leading zeros in a 32-bit value. - * @val: The value to search - * - * Returns 32 if the value is zero. Note that the GCC builtin is - * undefined if the value is zero. - */ -static inline int clz32(uint32_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return val ? __builtin_clz(val) : 32; -#else - /* Binary search for the leading one bit. */ - int cnt = 0; - - if (!(val & 0xFFFF0000U)) { - cnt += 16; - val <<= 16; - } - if (!(val & 0xFF000000U)) { - cnt += 8; - val <<= 8; - } - if (!(val & 0xF0000000U)) { - cnt += 4; - val <<= 4; - } - if (!(val & 0xC0000000U)) { - cnt += 2; - val <<= 2; - } - if (!(val & 0x80000000U)) { - cnt++; - val <<= 1; - } - if (!(val & 0x80000000U)) { - cnt++; - } - return cnt; -#endif -} - -/** - * clo32 - count leading ones in a 32-bit value. - * @val: The value to search - * - * Returns 32 if the value is -1. - */ -static inline int clo32(uint32_t val) -{ - return clz32(~val); -} - -/** - * clz64 - count leading zeros in a 64-bit value. - * @val: The value to search - * - * Returns 64 if the value is zero. Note that the GCC builtin is - * undefined if the value is zero. - */ -static inline int clz64(uint64_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return val ? __builtin_clzll(val) : 64; -#else - int cnt = 0; - - if (!(val >> 32)) { - cnt += 32; - } else { - val >>= 32; - } - - return cnt + clz32(val); -#endif -} - -/** - * clo64 - count leading ones in a 64-bit value. - * @val: The value to search - * - * Returns 64 if the value is -1. - */ -static inline int clo64(uint64_t val) -{ - return clz64(~val); -} - -/** - * ctz32 - count trailing zeros in a 32-bit value. - * @val: The value to search - * - * Returns 32 if the value is zero. Note that the GCC builtin is - * undefined if the value is zero. - */ -static inline int ctz32(uint32_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return val ? __builtin_ctz(val) : 32; -#else - /* Binary search for the trailing one bit. */ - int cnt; - - cnt = 0; - if (!(val & 0x0000FFFFUL)) { - cnt += 16; - val >>= 16; - } - if (!(val & 0x000000FFUL)) { - cnt += 8; - val >>= 8; - } - if (!(val & 0x0000000FUL)) { - cnt += 4; - val >>= 4; - } - if (!(val & 0x00000003UL)) { - cnt += 2; - val >>= 2; - } - if (!(val & 0x00000001UL)) { - cnt++; - val >>= 1; - } - if (!(val & 0x00000001UL)) { - cnt++; - } - - return cnt; -#endif -} - -/** - * cto32 - count trailing ones in a 32-bit value. - * @val: The value to search - * - * Returns 32 if the value is -1. - */ -static inline int cto32(uint32_t val) -{ - return ctz32(~val); -} - -/** - * ctz64 - count trailing zeros in a 64-bit value. - * @val: The value to search - * - * Returns 64 if the value is zero. Note that the GCC builtin is - * undefined if the value is zero. - */ -static inline int ctz64(uint64_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return val ? __builtin_ctzll(val) : 64; -#else - int cnt; - - cnt = 0; - if (!((uint32_t)val)) { - cnt += 32; - val >>= 32; - } - - return cnt + ctz32(val); -#endif -} - -/** - * ctz64 - count trailing ones in a 64-bit value. - * @val: The value to search - * - * Returns 64 if the value is -1. - */ -static inline int cto64(uint64_t val) -{ - return ctz64(~val); -} - -/** - * ctpop8 - count the population of one bits in an 8-bit value. - * @val: The value to search - */ -static inline int ctpop8(uint8_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return __builtin_popcount(val); -#else - val = (val & 0x55) + ((val >> 1) & 0x55); - val = (val & 0x33) + ((val >> 2) & 0x33); - val = (val & 0x0f) + ((val >> 4) & 0x0f); - - return val; -#endif -} - -/** - * ctpop16 - count the population of one bits in a 16-bit value. - * @val: The value to search - */ -static inline int ctpop16(uint16_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return __builtin_popcount(val); -#else - val = (val & 0x5555) + ((val >> 1) & 0x5555); - val = (val & 0x3333) + ((val >> 2) & 0x3333); - val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f); - val = (val & 0x00ff) + ((val >> 8) & 0x00ff); - - return val; -#endif -} - -/** - * ctpop32 - count the population of one bits in a 32-bit value. - * @val: The value to search - */ -static inline int ctpop32(uint32_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return __builtin_popcount(val); -#else - val = (val & 0x55555555) + ((val >> 1) & 0x55555555); - val = (val & 0x33333333) + ((val >> 2) & 0x33333333); - val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f); - val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff); - val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff); - - return val; -#endif -} - -/** - * ctpop64 - count the population of one bits in a 64-bit value. - * @val: The value to search - */ -static inline int ctpop64(uint64_t val) -{ -#if QEMU_GNUC_PREREQ(3, 4) - return __builtin_popcountll(val); -#else - val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL); - val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL); - val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL); - val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL); - val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL); - val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL); - - return val; -#endif -} - -/* Host type specific sizes of these routines. */ - -#if ULONG_MAX == UINT32_MAX -# define clzl clz32 -# define ctzl ctz32 -# define clol clo32 -# define ctol cto32 -# define ctpopl ctpop32 -#elif ULONG_MAX == UINT64_MAX -# define clzl clz64 -# define ctzl ctz64 -# define clol clo64 -# define ctol cto64 -# define ctpopl ctpop64 -#else -# error Unknown sizeof long -#endif - -#endif diff --git a/contrib/qemu/include/qemu/iov.h b/contrib/qemu/include/qemu/iov.h deleted file mode 100644 index 68d25f29b76..00000000000 --- a/contrib/qemu/include/qemu/iov.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Helpers for using (partial) iovecs. - * - * Copyright (C) 2010 Red Hat, Inc. - * - * Author(s): - * 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. - */ - -#ifndef IOV_H -#define IOV_H - -#include "qemu-common.h" - -/** - * count and return data size, in bytes, of an iovec - * starting at `iov' of `iov_cnt' number of elements. - */ -size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt); - -/** - * Copy from single continuous buffer to scatter-gather vector of buffers - * (iovec) and back like memcpy() between two continuous memory regions. - * Data in single continuous buffer starting at address `buf' and - * `bytes' bytes long will be copied to/from an iovec `iov' with - * `iov_cnt' number of elements, starting at byte position `offset' - * within the iovec. If the iovec does not contain enough space, - * only part of data will be copied, up to the end of the iovec. - * Number of bytes actually copied will be returned, which is - * min(bytes, iov_size(iov)-offset) - * `Offset' must point to the inside of iovec. - * It is okay to use very large value for `bytes' since we're - * limited by the size of the iovec anyway, provided that the - * buffer pointed to by buf has enough space. One possible - * such "large" value is -1 (sinice size_t is unsigned), - * so specifying `-1' as `bytes' means 'up to the end of iovec'. - */ -size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, - size_t offset, const void *buf, size_t bytes); -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, void *buf, size_t bytes); - -/** - * Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements, - * starting at byte offset `start', to value `fillc', repeating it - * `bytes' number of times. `Offset' must point to the inside of iovec. - * If `bytes' is large enough, only last bytes portion of iovec, - * up to the end of it, will be filled with the specified value. - * Function return actual number of bytes processed, which is - * min(size, iov_size(iov) - offset). - * Again, it is okay to use large value for `bytes' to mean "up to the end". - */ -size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, int fillc, size_t bytes); - -/* - * Send/recv data from/to iovec buffers directly - * - * `offset' bytes in the beginning of iovec buffer are skipped and - * next `bytes' bytes are used, which must be within data of iovec. - * - * r = iov_send_recv(sockfd, iov, iovcnt, offset, bytes, true); - * - * is logically equivalent to - * - * char *buf = malloc(bytes); - * iov_to_buf(iov, iovcnt, offset, buf, bytes); - * r = send(sockfd, buf, bytes, 0); - * free(buf); - * - * For iov_send_recv() _whole_ area being sent or received - * should be within the iovec, not only beginning of it. - */ -ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, - size_t offset, size_t bytes, bool do_send); -#define iov_recv(sockfd, iov, iov_cnt, offset, bytes) \ - iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false) -#define iov_send(sockfd, iov, iov_cnt, offset, bytes) \ - iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, true) - -/** - * Produce a text hexdump of iovec `iov' with `iov_cnt' number of elements - * in file `fp', prefixing each line with `prefix' and processing not more - * than `limit' data bytes. - */ -void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, - FILE *fp, const char *prefix, size_t limit); - -/* - * Partial copy of vector from iov to dst_iov (data is not copied). - * dst_iov overlaps iov at a specified offset. - * size of dst_iov is at most bytes. dst vector count is returned. - */ -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); - -/* - * Remove a given number of bytes from the front or back of a vector. - * This may update iov and/or iov_cnt to exclude iovec elements that are - * no longer required. - * - * The number of bytes actually discarded is returned. This number may be - * smaller than requested if the vector is too small. - */ -size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, - size_t bytes); -size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, - size_t bytes); - -#endif diff --git a/contrib/qemu/include/qemu/main-loop.h b/contrib/qemu/include/qemu/main-loop.h deleted file mode 100644 index 6f0200a7acc..00000000000 --- a/contrib/qemu/include/qemu/main-loop.h +++ /dev/null @@ -1,311 +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. - */ - -#ifndef QEMU_MAIN_LOOP_H -#define QEMU_MAIN_LOOP_H 1 - -#include "block/aio.h" - -#define SIG_IPI SIGUSR1 - -/** - * qemu_init_main_loop: Set up the process so that it can run the main loop. - * - * This includes setting up signal handlers. It should be called before - * any other threads are created. In addition, threads other than the - * main one should block signals that are trapped by the main loop. - * For simplicity, you can consider these signals to be safe: SIGUSR1, - * SIGUSR2, thread signals (SIGFPE, SIGILL, SIGSEGV, SIGBUS) and real-time - * signals if available. Remember that Windows in practice does not have - * signals, though. - * - * In the case of QEMU tools, this will also start/initialize timers. - */ -int qemu_init_main_loop(void); - -/** - * main_loop_wait: Run one iteration of the main loop. - * - * If @nonblocking is true, poll for events, otherwise suspend until - * one actually occurs. The main loop usually consists of a loop that - * repeatedly calls main_loop_wait(false). - * - * Main loop services include file descriptor callbacks, bottom halves - * and timers (defined in qemu-timer.h). Bottom halves are similar to timers - * that execute immediately, but have a lower overhead and scheduling them - * is wait-free, thread-safe and signal-safe. - * - * It is sometimes useful to put a whole program in a coroutine. In this - * case, the coroutine actually should be started from within the main loop, - * so that the main loop can run whenever the coroutine yields. To do this, - * you can use a bottom half to enter the coroutine as soon as the main loop - * starts: - * - * void enter_co_bh(void *opaque) { - * QEMUCoroutine *co = opaque; - * qemu_coroutine_enter(co, NULL); - * } - * - * ... - * QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry); - * QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co); - * qemu_bh_schedule(start_bh); - * while (...) { - * main_loop_wait(false); - * } - * - * (In the future we may provide a wrapper for this). - * - * @nonblocking: Whether the caller should block until an event occurs. - */ -int main_loop_wait(int nonblocking); - -/** - * qemu_get_aio_context: Return the main loop's AioContext - */ -AioContext *qemu_get_aio_context(void); - -/** - * qemu_notify_event: Force processing of pending events. - * - * Similar to signaling a condition variable, qemu_notify_event forces - * main_loop_wait to look at pending events and exit. The caller of - * main_loop_wait will usually call it again very soon, so qemu_notify_event - * also has the side effect of recalculating the sets of file descriptors - * that the main loop waits for. - * - * Calling qemu_notify_event is rarely necessary, because main loop - * services (bottom halves and timers) call it themselves. One notable - * exception occurs when using qemu_set_fd_handler2 (see below). - */ -void qemu_notify_event(void); - -#ifdef _WIN32 -/* return TRUE if no sleep should be done afterwards */ -typedef int PollingFunc(void *opaque); - -/** - * qemu_add_polling_cb: Register a Windows-specific polling callback - * - * Currently, under Windows some events are polled rather than waited for. - * Polling callbacks do not ensure that @func is called timely, because - * the main loop might wait for an arbitrarily long time. If possible, - * you should instead create a separate thread that does a blocking poll - * and set a Win32 event object. The event can then be passed to - * qemu_add_wait_object. - * - * Polling callbacks really have nothing Windows specific in them, but - * as they are a hack and are currently not necessary under POSIX systems, - * they are only available when QEMU is running under Windows. - * - * @func: The function that does the polling, and returns 1 to force - * immediate completion of main_loop_wait. - * @opaque: A pointer-size value that is passed to @func. - */ -int qemu_add_polling_cb(PollingFunc *func, void *opaque); - -/** - * qemu_del_polling_cb: Unregister a Windows-specific polling callback - * - * This function removes a callback that was registered with - * qemu_add_polling_cb. - * - * @func: The function that was passed to qemu_add_polling_cb. - * @opaque: A pointer-size value that was passed to qemu_add_polling_cb. - */ -void qemu_del_polling_cb(PollingFunc *func, void *opaque); - -/* Wait objects handling */ -typedef void WaitObjectFunc(void *opaque); - -/** - * qemu_add_wait_object: Register a callback for a Windows handle - * - * Under Windows, the iohandler mechanism can only be used with sockets. - * QEMU must use the WaitForMultipleObjects API to wait on other handles. - * This function registers a #HANDLE with QEMU, so that it will be included - * in the main loop's calls to WaitForMultipleObjects. When the handle - * is in a signaled state, QEMU will call @func. - * - * @handle: The Windows handle to be observed. - * @func: A function to be called when @handle is in a signaled state. - * @opaque: A pointer-size value that is passed to @func. - */ -int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); - -/** - * qemu_del_wait_object: Unregister a callback for a Windows handle - * - * This function removes a callback that was registered with - * qemu_add_wait_object. - * - * @func: The function that was passed to qemu_add_wait_object. - * @opaque: A pointer-size value that was passed to qemu_add_wait_object. - */ -void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); -#endif - -/* async I/O support */ - -typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); -typedef int IOCanReadHandler(void *opaque); - -/** - * qemu_set_fd_handler2: Register a file descriptor with the main loop - * - * This function tells the main loop to wake up whenever one of the - * following conditions is true: - * - * 1) if @fd_write is not %NULL, when the file descriptor is writable; - * - * 2) if @fd_read is not %NULL, when the file descriptor is readable. - * - * @fd_read_poll can be used to disable the @fd_read callback temporarily. - * This is useful to avoid calling qemu_set_fd_handler2 every time the - * client becomes interested in reading (or dually, stops being interested). - * A typical example is when @fd is a listening socket and you want to bound - * the number of active clients. Remember to call qemu_notify_event whenever - * the condition may change from %false to %true. - * - * The callbacks that are set up by qemu_set_fd_handler2 are level-triggered. - * If @fd_read does not read from @fd, or @fd_write does not write to @fd - * until its buffers are full, they will be called again on the next - * iteration. - * - * @fd: The file descriptor to be observed. Under Windows it must be - * a #SOCKET. - * - * @fd_read_poll: A function that returns 1 if the @fd_read callback - * should be fired. If the function returns 0, the main loop will not - * end its iteration even if @fd becomes readable. - * - * @fd_read: A level-triggered callback that is fired if @fd is readable - * at the beginning of a main loop iteration, or if it becomes readable - * during one. - * - * @fd_write: A level-triggered callback that is fired when @fd is writable - * at the beginning of a main loop iteration, or if it becomes writable - * during one. - * - * @opaque: A pointer-sized value that is passed to @fd_read_poll, - * @fd_read and @fd_write. - */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); - -/** - * qemu_set_fd_handler: Register a file descriptor with the main loop - * - * This function tells the main loop to wake up whenever one of the - * following conditions is true: - * - * 1) if @fd_write is not %NULL, when the file descriptor is writable; - * - * 2) if @fd_read is not %NULL, when the file descriptor is readable. - * - * The callbacks that are set up by qemu_set_fd_handler are level-triggered. - * If @fd_read does not read from @fd, or @fd_write does not write to @fd - * until its buffers are full, they will be called again on the next - * iteration. - * - * @fd: The file descriptor to be observed. Under Windows it must be - * a #SOCKET. - * - * @fd_read: A level-triggered callback that is fired if @fd is readable - * at the beginning of a main loop iteration, or if it becomes readable - * during one. - * - * @fd_write: A level-triggered callback that is fired when @fd is writable - * at the beginning of a main loop iteration, or if it becomes writable - * during one. - * - * @opaque: A pointer-sized value that is passed to @fd_read and @fd_write. - */ -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); - -#ifdef CONFIG_POSIX -/** - * qemu_add_child_watch: Register a child process for reaping. - * - * Under POSIX systems, a parent process must read the exit status of - * its child processes using waitpid, or the operating system will not - * free some of the resources attached to that process. - * - * This function directs the QEMU main loop to observe a child process - * and call waitpid as soon as it exits; the watch is then removed - * automatically. It is useful whenever QEMU forks a child process - * but will find out about its termination by other means such as a - * "broken pipe". - * - * @pid: The pid that QEMU should observe. - */ -int qemu_add_child_watch(pid_t pid); -#endif - -/** - * qemu_mutex_lock_iothread: Lock the main loop mutex. - * - * This function locks the main loop mutex. The mutex is taken by - * qemu_init_main_loop and always taken except while waiting on - * external events (such as with select). The mutex should be taken - * by threads other than the main loop thread when calling - * qemu_bh_new(), qemu_set_fd_handler() and basically all other - * functions documented in this file. - * - * NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread - * is a no-op there. - */ -void qemu_mutex_lock_iothread(void); - -/** - * qemu_mutex_unlock_iothread: Unlock the main loop mutex. - * - * This function unlocks the main loop mutex. The mutex is taken by - * qemu_init_main_loop and always taken except while waiting on - * external events (such as with select). The mutex should be unlocked - * as soon as possible by threads other than the main loop thread, - * because it prevents the main loop from processing callbacks, - * including timers and bottom halves. - * - * NOTE: tools currently are single-threaded and qemu_mutex_unlock_iothread - * is a no-op there. - */ -void qemu_mutex_unlock_iothread(void); - -/* internal interfaces */ - -void qemu_fd_register(int fd); -void qemu_iohandler_fill(GArray *pollfds); -void qemu_iohandler_poll(GArray *pollfds, int rc); - -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); -void qemu_bh_schedule_idle(QEMUBH *bh); - -#endif diff --git a/contrib/qemu/include/qemu/module.h b/contrib/qemu/include/qemu/module.h deleted file mode 100644 index c4ccd571664..00000000000 --- a/contrib/qemu/include/qemu/module.h +++ /dev/null @@ -1,40 +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. - * - */ - -#ifndef QEMU_MODULE_H -#define QEMU_MODULE_H - -/* This should not be used directly. Use block_init etc. instead. */ -#define module_init(function, type) \ -static void __attribute__((constructor)) do_qemu_init_ ## function(void) { \ - register_module_init(function, type); \ -} - -typedef enum { - MODULE_INIT_BLOCK, - MODULE_INIT_MACHINE, - MODULE_INIT_QAPI, - MODULE_INIT_QOM, - MODULE_INIT_MAX -} module_init_type; - -#define block_init(function) module_init(function, MODULE_INIT_BLOCK) -#define machine_init(function) module_init(function, MODULE_INIT_MACHINE) -#define qapi_init(function) module_init(function, MODULE_INIT_QAPI) -#define type_init(function) module_init(function, MODULE_INIT_QOM) - -void register_module_init(void (*fn)(void), module_init_type type); - -void module_call_init(module_init_type type); - -#endif diff --git a/contrib/qemu/include/qemu/notify.h b/contrib/qemu/include/qemu/notify.h deleted file mode 100644 index a3d73e4bc76..00000000000 --- a/contrib/qemu/include/qemu/notify.h +++ /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. - * - */ - -#ifndef QEMU_NOTIFY_H -#define QEMU_NOTIFY_H - -#include "qemu/queue.h" - -typedef struct Notifier Notifier; - -struct Notifier -{ - void (*notify)(Notifier *notifier, void *data); - QLIST_ENTRY(Notifier) node; -}; - -typedef struct NotifierList -{ - QLIST_HEAD(, Notifier) notifiers; -} NotifierList; - -#define NOTIFIER_LIST_INITIALIZER(head) \ - { QLIST_HEAD_INITIALIZER((head).notifiers) } - -void notifier_list_init(NotifierList *list); - -void notifier_list_add(NotifierList *list, Notifier *notifier); - -void notifier_remove(Notifier *notifier); - -void notifier_list_notify(NotifierList *list, void *data); - -/* Same as Notifier but allows .notify() to return errors */ -typedef struct NotifierWithReturn NotifierWithReturn; - -struct NotifierWithReturn { - /** - * Return 0 on success (next notifier will be invoked), otherwise - * notifier_with_return_list_notify() will stop and return the value. - */ - int (*notify)(NotifierWithReturn *notifier, void *data); - QLIST_ENTRY(NotifierWithReturn) node; -}; - -typedef struct NotifierWithReturnList { - QLIST_HEAD(, NotifierWithReturn) notifiers; -} NotifierWithReturnList; - -#define NOTIFIER_WITH_RETURN_LIST_INITIALIZER(head) \ - { QLIST_HEAD_INITIALIZER((head).notifiers) } - -void notifier_with_return_list_init(NotifierWithReturnList *list); - -void notifier_with_return_list_add(NotifierWithReturnList *list, - NotifierWithReturn *notifier); - -void notifier_with_return_remove(NotifierWithReturn *notifier); - -int notifier_with_return_list_notify(NotifierWithReturnList *list, - void *data); - -#endif diff --git a/contrib/qemu/include/qemu/option.h b/contrib/qemu/include/qemu/option.h deleted file mode 100644 index a83c700323e..00000000000 --- a/contrib/qemu/include/qemu/option.h +++ /dev/null @@ -1,157 +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. - */ - -#ifndef QEMU_OPTIONS_H -#define QEMU_OPTIONS_H - -#include <stdint.h> -#include "qemu/queue.h" -#include "qapi/error.h" -#include "qapi/qmp/qdict.h" - -enum QEMUOptionParType { - OPT_FLAG, - OPT_NUMBER, - OPT_SIZE, - OPT_STRING, -}; - -typedef struct QEMUOptionParameter { - const char *name; - enum QEMUOptionParType type; - union { - uint64_t n; - char* s; - } value; - const char *help; -} QEMUOptionParameter; - - -const char *get_opt_name(char *buf, int buf_size, const char *p, char delim); -const char *get_opt_value(char *buf, int buf_size, const char *p); -int get_next_param_value(char *buf, int buf_size, - const char *tag, const char **pstr); -int get_param_value(char *buf, int buf_size, - const char *tag, const char *str); - - -/* - * The following functions take a parameter list as input. This is a pointer to - * the first element of a QEMUOptionParameter array which is terminated by an - * entry with entry->name == NULL. - */ - -QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list, - const char *name); -int set_option_parameter(QEMUOptionParameter *list, const char *name, - const char *value); -int set_option_parameter_int(QEMUOptionParameter *list, const char *name, - uint64_t value); -QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, - QEMUOptionParameter *list); -QEMUOptionParameter *parse_option_parameters(const char *param, - QEMUOptionParameter *list, QEMUOptionParameter *dest); -void free_option_parameters(QEMUOptionParameter *list); -void print_option_parameters(QEMUOptionParameter *list); -void print_option_help(QEMUOptionParameter *list); - -/* ------------------------------------------------------------------ */ - -typedef struct QemuOpt QemuOpt; -typedef struct QemuOpts QemuOpts; -typedef struct QemuOptsList QemuOptsList; - -enum QemuOptType { - QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */ - QEMU_OPT_BOOL, /* on/off */ - QEMU_OPT_NUMBER, /* simple number */ - QEMU_OPT_SIZE, /* size, accepts (K)ilo, (M)ega, (G)iga, (T)era postfix */ -}; - -typedef struct QemuOptDesc { - const char *name; - enum QemuOptType type; - const char *help; -} QemuOptDesc; - -struct QemuOptsList { - const char *name; - const char *implied_opt_name; - bool merge_lists; /* Merge multiple uses of option into a single list? */ - QTAILQ_HEAD(, QemuOpts) head; - QemuOptDesc desc[]; -}; - -const char *qemu_opt_get(QemuOpts *opts, const char *name); -/** - * qemu_opt_has_help_opt: - * @opts: options to search for a help request - * - * Check whether the options specified by @opts include one of the - * standard strings which indicate that the user is asking for a - * list of the valid values for a command line option (as defined - * by is_help_option()). - * - * Returns: true if @opts includes 'help' or equivalent. - */ -bool qemu_opt_has_help_opt(QemuOpts *opts); -bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval); -uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval); -uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval); -int qemu_opt_set(QemuOpts *opts, const char *name, const char *value); -void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value, - Error **errp); -int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val); -int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val); -typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque); -int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque, - int abort_on_failure); - -QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id); -QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, - int fail_if_exists, Error **errp); -QemuOpts *qemu_opts_create_nofail(QemuOptsList *list); -void qemu_opts_reset(QemuOptsList *list); -void qemu_opts_loc_restore(QemuOpts *opts); -int qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value); -const char *qemu_opts_id(QemuOpts *opts); -void qemu_opts_del(QemuOpts *opts); -void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp); -int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname); -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev); -void qemu_opts_set_defaults(QemuOptsList *list, const char *params, - int permit_abbrev); -QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, - Error **errp); -QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict); -void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp); - -typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque); -int qemu_opts_print(QemuOpts *opts, void *dummy); -int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, - int abort_on_failure); - -#endif diff --git a/contrib/qemu/include/qemu/option_int.h b/contrib/qemu/include/qemu/option_int.h deleted file mode 100644 index 8212fa4a485..00000000000 --- a/contrib/qemu/include/qemu/option_int.h +++ /dev/null @@ -1,54 +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. - */ - -#ifndef QEMU_OPTIONS_INTERNAL_H -#define QEMU_OPTIONS_INTERNAL_H - -#include "qemu/option.h" -#include "qemu/error-report.h" - -struct QemuOpt { - const char *name; - const char *str; - - const QemuOptDesc *desc; - union { - bool boolean; - uint64_t uint; - } value; - - QemuOpts *opts; - QTAILQ_ENTRY(QemuOpt) next; -}; - -struct QemuOpts { - char *id; - QemuOptsList *list; - Location loc; - QTAILQ_HEAD(QemuOptHead, QemuOpt) head; - QTAILQ_ENTRY(QemuOpts) next; -}; - -#endif diff --git a/contrib/qemu/include/qemu/osdep.h b/contrib/qemu/include/qemu/osdep.h deleted file mode 100644 index 26136f16ecd..00000000000 --- a/contrib/qemu/include/qemu/osdep.h +++ /dev/null @@ -1,218 +0,0 @@ -#ifndef QEMU_OSDEP_H -#define QEMU_OSDEP_H - -#include "config-host.h" -#include <stdarg.h> -#include <stddef.h> -#include <stdbool.h> -#include <sys/types.h> -#ifdef __OpenBSD__ -#include <sys/signal.h> -#endif - -#ifndef _WIN32 -#include <sys/wait.h> -#else -#define WIFEXITED(x) 1 -#define WEXITSTATUS(x) (x) -#endif - -#include <sys/time.h> - -#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10 -/* [u]int_fast*_t not in <sys/int_types.h> */ -typedef unsigned char uint_fast8_t; -typedef unsigned int uint_fast16_t; -typedef signed int int_fast16_t; -#endif - -#ifndef glue -#define xglue(x, y) x ## y -#define glue(x, y) xglue(x, y) -#define stringify(s) tostring(s) -#define tostring(s) #s -#endif - -#ifndef likely -#if __GNUC__ < 3 -#define __builtin_expect(x, n) (x) -#endif - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#endif - -#ifndef container_of -#define container_of(ptr, type, member) ({ \ - const typeof(((type *) 0)->member) *__mptr = (ptr); \ - (type *) ((char *) __mptr - offsetof(type, member));}) -#endif - -/* Convert from a base type to a parent type, with compile time checking. */ -#ifdef __GNUC__ -#define DO_UPCAST(type, field, dev) ( __extension__ ( { \ - char __attribute__((unused)) offset_must_be_zero[ \ - -offsetof(type, field)]; \ - container_of(dev, type, field);})) -#else -#define DO_UPCAST(type, field, dev) container_of(dev, type, field) -#endif - -#define typeof_field(type, field) typeof(((type *)0)->field) -#define type_check(t1,t2) ((t1*)0 - (t2*)0) - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef ROUND_UP -#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d)) -#endif - -#ifndef DIV_ROUND_UP -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -#ifndef always_inline -#if !((__GNUC__ < 3) || defined(__APPLE__)) -#ifdef __OPTIMIZE__ -#undef inline -#define inline __attribute__ (( always_inline )) __inline__ -#endif -#endif -#else -#undef inline -#define inline always_inline -#endif - -#define qemu_printf printf - -int qemu_daemon(int nochdir, int noclose); -void *qemu_memalign(size_t alignment, size_t size); -void *qemu_anon_ram_alloc(size_t size); -void qemu_vfree(void *ptr); -void qemu_anon_ram_free(void *ptr, size_t size); - -#define QEMU_MADV_INVALID -1 - -#if defined(CONFIG_MADVISE) - -#define QEMU_MADV_WILLNEED MADV_WILLNEED -#define QEMU_MADV_DONTNEED MADV_DONTNEED -#ifdef MADV_DONTFORK -#define QEMU_MADV_DONTFORK MADV_DONTFORK -#else -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#endif -#ifdef MADV_MERGEABLE -#define QEMU_MADV_MERGEABLE MADV_MERGEABLE -#else -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#endif -#ifdef MADV_DONTDUMP -#define QEMU_MADV_DONTDUMP MADV_DONTDUMP -#else -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#endif -#ifdef MADV_HUGEPAGE -#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE -#else -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID -#endif - -#elif defined(CONFIG_POSIX_MADVISE) - -#define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED -#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID - -#else /* no-op */ - -#define QEMU_MADV_WILLNEED QEMU_MADV_INVALID -#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID -#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID -#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID -#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID -#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID - -#endif - -int qemu_madvise(void *addr, size_t len, int advice); - -int qemu_open(const char *name, int flags, ...); -int qemu_close(int fd); - -#if defined(__HAIKU__) && defined(__i386__) -#define FMT_pid "%ld" -#elif defined(WIN64) -#define FMT_pid "%" PRId64 -#else -#define FMT_pid "%d" -#endif - -int qemu_create_pidfile(const char *filename); -int qemu_get_thread_id(void); - -#ifndef CONFIG_IOVEC -struct iovec { - void *iov_base; - size_t iov_len; -}; -/* - * Use the same value as Linux for now. - */ -#define IOV_MAX 1024 - -ssize_t readv(int fd, const struct iovec *iov, int iov_cnt); -ssize_t writev(int fd, const struct iovec *iov, int iov_cnt); -#else -#include <sys/uio.h> -#endif - -#ifdef _WIN32 -static inline void qemu_timersub(const struct timeval *val1, - const struct timeval *val2, - struct timeval *res) -{ - res->tv_sec = val1->tv_sec - val2->tv_sec; - if (val1->tv_usec < val2->tv_usec) { - res->tv_sec--; - res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000; - } else { - res->tv_usec = val1->tv_usec - val2->tv_usec; - } -} -#else -#define qemu_timersub timersub -#endif - -void qemu_set_cloexec(int fd); - -void qemu_set_version(const char *); -const char *qemu_get_version(void); - -void fips_set_state(bool requested); -bool fips_get_state(void); - -/* Return a dynamically allocated pathname denoting a file or directory that is - * appropriate for storing local state. - * - * @relative_pathname need not start with a directory separator; one will be - * added automatically. - * - * The caller is responsible for releasing the value returned with g_free() - * after use. - */ -char *qemu_get_local_state_pathname(const char *relative_pathname); - -#endif diff --git a/contrib/qemu/include/qemu/queue.h b/contrib/qemu/include/qemu/queue.h deleted file mode 100644 index d433b9017ce..00000000000 --- a/contrib/qemu/include/qemu/queue.h +++ /dev/null @@ -1,414 +0,0 @@ -/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ - -/* - * QEMU version: Copy from netbsd, removed debug code, removed some of - * the implementations. Left in singly-linked lists, lists, simple - * queues, and tail queues. - */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef QEMU_SYS_QUEUE_H_ -#define QEMU_SYS_QUEUE_H_ - -/* - * This file defines four types of data structures: singly-linked lists, - * lists, simple queues, and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The - * elements are singly linked for minimum space and pointer manipulation - * overhead at the expense of O(n) removal for arbitrary elements. New - * elements can be added to the list after an existing element or at the - * head of the list. Elements being removed from the head of the list - * should use the explicit macro for this purpose for optimum - * efficiency. A singly-linked list may only be traversed in the forward - * direction. Singly-linked lists are ideal for applications with large - * datasets and few or no removals or for implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#include "qemu/atomic.h" /* for smp_wmb() */ - -/* - * List definitions. - */ -#define QLIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define QLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QLIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ -#define QLIST_INIT(head) do { \ - (head)->lh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_HEAD_RCU(head, elm, field) do { \ - (elm)->field.le_prev = &(head)->lh_first; \ - (elm)->field.le_next = (head)->lh_first; \ - smp_wmb(); /* fill elm before linking it */ \ - if ((head)->lh_first != NULL) { \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next; \ - } \ - (head)->lh_first = (elm); \ - smp_wmb(); \ -} while (/* CONSTCOND*/0) - -#define QLIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_FOREACH(var, head, field) \ - for ((var) = ((head)->lh_first); \ - (var); \ - (var) = ((var)->field.le_next)) - -#define QLIST_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->lh_first); \ - (var) && ((next_var) = ((var)->field.le_next), 1); \ - (var) = (next_var)) - -/* - * List access methods. - */ -#define QLIST_EMPTY(head) ((head)->lh_first == NULL) -#define QLIST_FIRST(head) ((head)->lh_first) -#define QLIST_NEXT(elm, field) ((elm)->field.le_next) - - -/* - * Singly-linked List definitions. - */ -#define QSLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define QSLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QSLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define QSLIST_INIT(head) do { \ - (head)->slh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_AFTER(slistelm, field) do { \ - (slistelm)->field.sle_next = \ - QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_FOREACH(var, head, field) \ - for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) - -#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = QSLIST_FIRST((head)); \ - (var) && ((tvar) = QSLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -/* - * Singly-linked List access methods. - */ -#define QSLIST_EMPTY(head) ((head)->slh_first == NULL) -#define QSLIST_FIRST(head) ((head)->slh_first) -#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next) - - -/* - * Simple queue definitions. - */ -#define QSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define QSIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define QSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue functions. - */ -#define QSIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \ - if ((head)->sqh_first == (elm)) { \ - QSIMPLEQ_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->sqh_first; \ - while (curelm->field.sqe_next != (elm)) \ - curelm = curelm->field.sqe_next; \ - if ((curelm->field.sqe_next = \ - curelm->field.sqe_next->field.sqe_next) == NULL) \ - (head)->sqh_last = &(curelm)->field.sqe_next; \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->sqh_first); \ - (var); \ - (var) = ((var)->field.sqe_next)) - -#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \ - for ((var) = ((head)->sqh_first); \ - (var) && ((next = ((var)->field.sqe_next)), 1); \ - (var) = (next)) - -#define QSIMPLEQ_CONCAT(head1, head2) do { \ - if (!QSIMPLEQ_EMPTY((head2))) { \ - *(head1)->sqh_last = (head2)->sqh_first; \ - (head1)->sqh_last = (head2)->sqh_last; \ - QSIMPLEQ_INIT((head2)); \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_LAST(head, type, field) \ - (QSIMPLEQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->sqh_last) - offsetof(struct type, field)))) - -/* - * Simple queue access methods. - */ -#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) -#define QSIMPLEQ_FIRST(head) ((head)->sqh_first) -#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - - -/* - * Tail queue definitions. - */ -#define Q_TAILQ_HEAD(name, type, qual) \ -struct name { \ - qual type *tqh_first; /* first element */ \ - qual type *qual *tqh_last; /* addr of last next element */ \ -} -#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,) - -#define QTAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define Q_TAILQ_ENTRY(type, qual) \ -struct { \ - qual type *tqe_next; /* next element */ \ - qual type *qual *tqe_prev; /* address of previous next element */\ -} -#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,) - -/* - * Tail queue functions. - */ -#define QTAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_FOREACH(var, head, field) \ - for ((var) = ((head)->tqh_first); \ - (var); \ - (var) = ((var)->field.tqe_next)) - -#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->tqh_first); \ - (var) && ((next_var) = ((var)->field.tqe_next), 1); \ - (var) = (next_var)) - -#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ - (var); \ - (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) - -/* - * Tail queue access methods. - */ -#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) -#define QTAILQ_FIRST(head) ((head)->tqh_first) -#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define QTAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -#define QTAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#endif /* !QEMU_SYS_QUEUE_H_ */ diff --git a/contrib/qemu/include/qemu/sockets.h b/contrib/qemu/include/qemu/sockets.h deleted file mode 100644 index c5174d76a70..00000000000 --- a/contrib/qemu/include/qemu/sockets.h +++ /dev/null @@ -1,83 +0,0 @@ -/* headers to use the BSD sockets */ -#ifndef QEMU_SOCKET_H -#define QEMU_SOCKET_H - -#ifdef _WIN32 -#include <windows.h> -#include <winsock2.h> -#include <ws2tcpip.h> - -#define socket_error() WSAGetLastError() - -int inet_aton(const char *cp, struct in_addr *ia); - -#else - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/un.h> - -#define socket_error() errno -#define closesocket(s) close(s) - -#endif /* !_WIN32 */ - -#include "qemu/option.h" -#include "qapi/error.h" -#include "qapi/qmp/qerror.h" - -extern QemuOptsList socket_optslist; - -/* misc helpers */ -int qemu_socket(int domain, int type, int protocol); -int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int socket_set_cork(int fd, int v); -int socket_set_nodelay(int fd); -void qemu_set_block(int fd); -void qemu_set_nonblock(int fd); -int send_all(int fd, const void *buf, int len1); -int recv_all(int fd, void *buf, int len1, bool single_read); - -/* callback function for nonblocking connect - * valid fd on success, negative error code on failure - */ -typedef void NonBlockingConnectHandler(int fd, void *opaque); - -InetSocketAddress *inet_parse(const char *str, Error **errp); -int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp); -int inet_listen(const char *str, char *ostr, int olen, - int socktype, int port_offset, Error **errp); -int inet_connect_opts(QemuOpts *opts, Error **errp, - NonBlockingConnectHandler *callback, void *opaque); -int inet_connect(const char *str, Error **errp); -int inet_nonblocking_connect(const char *str, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp); - -int inet_dgram_opts(QemuOpts *opts, Error **errp); -const char *inet_strfamily(int family); - -int unix_listen_opts(QemuOpts *opts, Error **errp); -int unix_listen(const char *path, char *ostr, int olen, Error **errp); -int unix_connect_opts(QemuOpts *opts, Error **errp, - NonBlockingConnectHandler *callback, void *opaque); -int unix_connect(const char *path, Error **errp); -int unix_nonblocking_connect(const char *str, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp); - -SocketAddress *socket_parse(const char *str, Error **errp); -int socket_connect(SocketAddress *addr, Error **errp, - NonBlockingConnectHandler *callback, void *opaque); -int socket_listen(SocketAddress *addr, Error **errp); -int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp); - -/* Old, ipv4 only bits. Don't use for new code. */ -int parse_host_port(struct sockaddr_in *saddr, const char *str); -int socket_init(void); - -#endif /* QEMU_SOCKET_H */ diff --git a/contrib/qemu/include/qemu/thread-posix.h b/contrib/qemu/include/qemu/thread-posix.h deleted file mode 100644 index 0f30dccb53c..00000000000 --- a/contrib/qemu/include/qemu/thread-posix.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __QEMU_THREAD_POSIX_H -#define __QEMU_THREAD_POSIX_H 1 -#include "pthread.h" -#include <semaphore.h> - -struct QemuMutex { - pthread_mutex_t lock; -}; - -struct QemuCond { - pthread_cond_t cond; -}; - -struct QemuSemaphore { -#if defined(__APPLE__) || defined(__NetBSD__) - pthread_mutex_t lock; - pthread_cond_t cond; - int count; -#else - sem_t sem; -#endif -}; - -struct QemuThread { - pthread_t thread; -}; - -#endif diff --git a/contrib/qemu/include/qemu/thread.h b/contrib/qemu/include/qemu/thread.h deleted file mode 100644 index c02404b9fbf..00000000000 --- a/contrib/qemu/include/qemu/thread.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __QEMU_THREAD_H -#define __QEMU_THREAD_H 1 - -#include <inttypes.h> -#include <stdbool.h> - -typedef struct QemuMutex QemuMutex; -typedef struct QemuCond QemuCond; -typedef struct QemuSemaphore QemuSemaphore; -typedef struct QemuThread QemuThread; - -#ifdef _WIN32 -#include "qemu/thread-win32.h" -#else -#include "qemu/thread-posix.h" -#endif - -#define QEMU_THREAD_JOINABLE 0 -#define QEMU_THREAD_DETACHED 1 - -void qemu_mutex_init(QemuMutex *mutex); -void qemu_mutex_destroy(QemuMutex *mutex); -void qemu_mutex_lock(QemuMutex *mutex); -int qemu_mutex_trylock(QemuMutex *mutex); -void qemu_mutex_unlock(QemuMutex *mutex); - -#define rcu_read_lock() do { } while (0) -#define rcu_read_unlock() do { } while (0) - -void qemu_cond_init(QemuCond *cond); -void qemu_cond_destroy(QemuCond *cond); - -/* - * IMPORTANT: The implementation does not guarantee that pthread_cond_signal - * and pthread_cond_broadcast can be called except while the same mutex is - * held as in the corresponding pthread_cond_wait calls! - */ -void qemu_cond_signal(QemuCond *cond); -void qemu_cond_broadcast(QemuCond *cond); -void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex); - -void qemu_sem_init(QemuSemaphore *sem, int init); -void qemu_sem_post(QemuSemaphore *sem); -void qemu_sem_wait(QemuSemaphore *sem); -int qemu_sem_timedwait(QemuSemaphore *sem, int ms); -void qemu_sem_destroy(QemuSemaphore *sem); - -void qemu_thread_create(QemuThread *thread, - void *(*start_routine)(void *), - void *arg, int mode); -void *qemu_thread_join(QemuThread *thread); -void qemu_thread_get_self(QemuThread *thread); -bool qemu_thread_is_self(QemuThread *thread); -void qemu_thread_exit(void *retval); - -#endif diff --git a/contrib/qemu/include/qemu/timer.h b/contrib/qemu/include/qemu/timer.h deleted file mode 100644 index 9dd206ce7f4..00000000000 --- a/contrib/qemu/include/qemu/timer.h +++ /dev/null @@ -1,305 +0,0 @@ -#ifndef QEMU_TIMER_H -#define QEMU_TIMER_H - -#include "qemu-common.h" -#include "qemu/main-loop.h" -#include "qemu/notify.h" - -/* timers */ - -#define SCALE_MS 1000000 -#define SCALE_US 1000 -#define SCALE_NS 1 - -typedef struct QEMUClock QEMUClock; -typedef void QEMUTimerCB(void *opaque); - -/* The real time clock should be used only for stuff which does not - change the virtual machine state, as it is run even if the virtual - machine is stopped. The real time clock has a frequency of 1000 - Hz. */ -extern QEMUClock *rt_clock; - -/* The virtual clock is only run during the emulation. It is stopped - when the virtual machine is stopped. Virtual timers use a high - precision clock, usually cpu cycles (use ticks_per_sec). */ -extern QEMUClock *vm_clock; - -/* The host clock should be use for device models that emulate accurate - real time sources. It will continue to run when the virtual machine - is suspended, and it will reflect system time changes the host may - undergo (e.g. due to NTP). The host clock has the same precision as - the virtual clock. */ -extern QEMUClock *host_clock; - -int64_t qemu_get_clock_ns(QEMUClock *clock); -int64_t qemu_clock_has_timers(QEMUClock *clock); -int64_t qemu_clock_expired(QEMUClock *clock); -int64_t qemu_clock_deadline(QEMUClock *clock); -void qemu_clock_enable(QEMUClock *clock, bool enabled); -void qemu_clock_warp(QEMUClock *clock); - -void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier); -void qemu_unregister_clock_reset_notifier(QEMUClock *clock, - Notifier *notifier); - -QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, - QEMUTimerCB *cb, void *opaque); -void qemu_free_timer(QEMUTimer *ts); -void qemu_del_timer(QEMUTimer *ts); -void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time); -void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time); -bool qemu_timer_pending(QEMUTimer *ts); -bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time); -uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts); - -void qemu_run_timers(QEMUClock *clock); -void qemu_run_all_timers(void); -void configure_alarms(char const *opt); -void init_clocks(void); -int init_timer_alarm(void); - -int64_t cpu_get_ticks(void); -void cpu_enable_ticks(void); -void cpu_disable_ticks(void); - -static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb, - void *opaque) -{ - return qemu_new_timer(clock, SCALE_NS, cb, opaque); -} - -static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb, - void *opaque) -{ - return qemu_new_timer(clock, SCALE_MS, cb, opaque); -} - -static inline int64_t qemu_get_clock_ms(QEMUClock *clock) -{ - return qemu_get_clock_ns(clock) / SCALE_MS; -} - -static inline int64_t get_ticks_per_sec(void) -{ - return 1000000000LL; -} - -/* real time host monotonic timer */ -static inline int64_t get_clock_realtime(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); -} - -/* Warning: don't insert tracepoints into these functions, they are - also used by simpletrace backend and tracepoints would cause - an infinite recursion! */ -#ifdef _WIN32 -extern int64_t clock_freq; - -static inline int64_t get_clock(void) -{ - LARGE_INTEGER ti; - QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); -} - -#else - -extern int use_rt_clock; - -static inline int64_t get_clock(void) -{ -#ifdef CLOCK_MONOTONIC - if (use_rt_clock) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000LL + ts.tv_nsec; - } else -#endif - { - /* XXX: using gettimeofday leads to problems if the date - changes, so it should be avoided. */ - return get_clock_realtime(); - } -} -#endif - -void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); -void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); - -/* icount */ -int64_t cpu_get_icount(void); -int64_t cpu_get_clock(void); - -/*******************************************/ -/* host CPU ticks (if available) */ - -#if defined(_ARCH_PPC) - -static inline int64_t cpu_get_real_ticks(void) -{ - int64_t retval; -#ifdef _ARCH_PPC64 - /* This reads timebase in one 64bit go and includes Cell workaround from: - http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html - */ - __asm__ __volatile__ ("mftb %0\n\t" - "cmpwi %0,0\n\t" - "beq- $-8" - : "=r" (retval)); -#else - /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */ - unsigned long junk; - __asm__ __volatile__ ("mfspr %1,269\n\t" /* mftbu */ - "mfspr %L0,268\n\t" /* mftb */ - "mfspr %0,269\n\t" /* mftbu */ - "cmpw %0,%1\n\t" - "bne $-16" - : "=r" (retval), "=r" (junk)); -#endif - return retval; -} - -#elif defined(__i386__) - -static inline int64_t cpu_get_real_ticks(void) -{ - int64_t val; - asm volatile ("rdtsc" : "=A" (val)); - return val; -} - -#elif defined(__x86_64__) - -static inline int64_t cpu_get_real_ticks(void) -{ - uint32_t low,high; - int64_t val; - asm volatile("rdtsc" : "=a" (low), "=d" (high)); - val = high; - val <<= 32; - val |= low; - return val; -} - -#elif defined(__hppa__) - -static inline int64_t cpu_get_real_ticks(void) -{ - int val; - asm volatile ("mfctl %%cr16, %0" : "=r"(val)); - return val; -} - -#elif defined(__ia64) - -static inline int64_t cpu_get_real_ticks(void) -{ - int64_t val; - asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory"); - return val; -} - -#elif defined(__s390__) - -static inline int64_t cpu_get_real_ticks(void) -{ - int64_t val; - asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc"); - return val; -} - -#elif defined(__sparc__) - -static inline int64_t cpu_get_real_ticks (void) -{ -#if defined(_LP64) - uint64_t rval; - asm volatile("rd %%tick,%0" : "=r"(rval)); - return rval; -#else - /* We need an %o or %g register for this. For recent enough gcc - there is an "h" constraint for that. Don't bother with that. */ - union { - uint64_t i64; - struct { - uint32_t high; - uint32_t low; - } i32; - } rval; - asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1" - : "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1"); - return rval.i64; -#endif -} - -#elif defined(__mips__) && \ - ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__)) -/* - * binutils wants to use rdhwr only on mips32r2 - * but as linux kernel emulate it, it's fine - * to use it. - * - */ -#define MIPS_RDHWR(rd, value) { \ - __asm__ __volatile__ (".set push\n\t" \ - ".set mips32r2\n\t" \ - "rdhwr %0, "rd"\n\t" \ - ".set pop" \ - : "=r" (value)); \ - } - -static inline int64_t cpu_get_real_ticks(void) -{ - /* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */ - uint32_t count; - static uint32_t cyc_per_count = 0; - - if (!cyc_per_count) { - MIPS_RDHWR("$3", cyc_per_count); - } - - MIPS_RDHWR("$2", count); - return (int64_t)(count * cyc_per_count); -} - -#elif defined(__alpha__) - -static inline int64_t cpu_get_real_ticks(void) -{ - uint64_t cc; - uint32_t cur, ofs; - - asm volatile("rpcc %0" : "=r"(cc)); - cur = cc; - ofs = cc >> 32; - return cur - ofs; -} - -#else -/* The host CPU doesn't have an easily accessible cycle counter. - Just return a monotonically increasing value. This will be - totally wrong, but hopefully better than nothing. */ -static inline int64_t cpu_get_real_ticks (void) -{ - static int64_t ticks = 0; - return ticks++; -} -#endif - -#ifdef CONFIG_PROFILER -static inline int64_t profile_getclock(void) -{ - return cpu_get_real_ticks(); -} - -extern int64_t qemu_time, qemu_time_start; -extern int64_t tlb_flush_time; -extern int64_t dev_time; -#endif - -#endif diff --git a/contrib/qemu/include/qemu/typedefs.h b/contrib/qemu/include/qemu/typedefs.h deleted file mode 100644 index ac9f8d41a35..00000000000 --- a/contrib/qemu/include/qemu/typedefs.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef QEMU_TYPEDEFS_H -#define QEMU_TYPEDEFS_H - -/* A load of opaque types so that device init declarations don't have to - pull in all the real definitions. */ -typedef struct QEMUTimer QEMUTimer; -typedef struct QEMUFile QEMUFile; -typedef struct QEMUBH QEMUBH; - -struct Monitor; -typedef struct Monitor Monitor; -typedef struct MigrationParams MigrationParams; - -typedef struct Property Property; -typedef struct PropertyInfo PropertyInfo; -typedef struct CompatProperty CompatProperty; -typedef struct DeviceState DeviceState; -typedef struct BusState BusState; -typedef struct BusClass BusClass; - -typedef struct AddressSpace AddressSpace; -typedef struct MemoryRegion MemoryRegion; -typedef struct MemoryRegionSection MemoryRegionSection; - -typedef struct MemoryMappingList MemoryMappingList; - -typedef struct NICInfo NICInfo; -typedef struct HCIInfo HCIInfo; -typedef struct AudioState AudioState; -typedef struct BlockDriverState BlockDriverState; -typedef struct DriveInfo DriveInfo; -typedef struct DisplayState DisplayState; -typedef struct DisplayChangeListener DisplayChangeListener; -typedef struct DisplaySurface DisplaySurface; -typedef struct PixelFormat PixelFormat; -typedef struct QemuConsole QemuConsole; -typedef struct CharDriverState CharDriverState; -typedef struct MACAddr MACAddr; -typedef struct NetClientState NetClientState; -typedef struct i2c_bus i2c_bus; -typedef struct ISABus ISABus; -typedef struct ISADevice ISADevice; -typedef struct SMBusDevice SMBusDevice; -typedef struct PCIHostState PCIHostState; -typedef struct PCIExpressHost PCIExpressHost; -typedef struct PCIBus PCIBus; -typedef struct PCIDevice PCIDevice; -typedef struct PCIExpressDevice PCIExpressDevice; -typedef struct PCIBridge PCIBridge; -typedef struct PCIEAERMsg PCIEAERMsg; -typedef struct PCIEAERLog PCIEAERLog; -typedef struct PCIEAERErr PCIEAERErr; -typedef struct PCIEPort PCIEPort; -typedef struct PCIESlot PCIESlot; -typedef struct MSIMessage MSIMessage; -typedef struct SerialState SerialState; -typedef struct PCMCIACardState PCMCIACardState; -typedef struct MouseTransformInfo MouseTransformInfo; -typedef struct uWireSlave uWireSlave; -typedef struct I2SCodec I2SCodec; -typedef struct SSIBus SSIBus; -typedef struct EventNotifier EventNotifier; -typedef struct VirtIODevice VirtIODevice; -typedef struct QEMUSGList QEMUSGList; -typedef struct SHPCDevice SHPCDevice; -typedef struct FWCfgState FWCfgState; -typedef struct PcGuestInfo PcGuestInfo; - -#endif /* QEMU_TYPEDEFS_H */ diff --git a/contrib/qemu/include/sysemu/os-posix.h b/contrib/qemu/include/sysemu/os-posix.h deleted file mode 100644 index ac4a80e6d8c..00000000000 --- a/contrib/qemu/include/sysemu/os-posix.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * posix specific declarations - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2010 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. - */ - -#ifndef QEMU_OS_POSIX_H -#define QEMU_OS_POSIX_H - -void os_set_line_buffering(void); -void os_set_proc_name(const char *s); -void os_setup_signal_handling(void); -void os_daemonize(void); -void os_setup_post(void); -int os_mlock(void); - -typedef struct timeval qemu_timeval; -#define qemu_gettimeofday(tp) gettimeofday(tp, NULL) - -#if !defined(CONFIG_UTIMENSAT) || defined(__FreeBSD__) || defined(__APPLE__) -#ifndef UTIME_NOW -# define UTIME_NOW ((1l << 30) - 1l) -#endif -#ifndef UTIME_OMIT -# define UTIME_OMIT ((1l << 30) - 2l) -#endif -#endif -typedef struct timespec qemu_timespec; -int qemu_utimens(const char *path, const qemu_timespec *times); - -bool is_daemonized(void); - -#endif diff --git a/contrib/qemu/include/sysemu/sysemu.h b/contrib/qemu/include/sysemu/sysemu.h deleted file mode 100644 index 3caeb66eb2f..00000000000 --- a/contrib/qemu/include/sysemu/sysemu.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef SYSEMU_H -#define SYSEMU_H -/* Misc. things related to the system emulator. */ - -#include "qemu/typedefs.h" -#include "qemu/option.h" -#include "qemu/queue.h" -#include "qemu/timer.h" -#include "qapi-types.h" -#include "qemu/notify.h" -#include "qemu/main-loop.h" - -/* vl.c */ - -extern const char *bios_name; - -extern const char *qemu_name; -extern uint8_t qemu_uuid[]; -int qemu_uuid_parse(const char *str, uint8_t *uuid); -#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" - -bool runstate_check(RunState state); -void runstate_set(RunState new_state); -int runstate_is_running(void); -bool runstate_needs_reset(void); -typedef struct vm_change_state_entry VMChangeStateEntry; -typedef void VMChangeStateHandler(void *opaque, int running, RunState state); - -VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, - void *opaque); -void qemu_del_vm_change_state_handler(VMChangeStateEntry *e); -void vm_state_notify(int running, RunState state); - -#define VMRESET_SILENT false -#define VMRESET_REPORT true - -void vm_start(void); -int vm_stop(RunState state); -int vm_stop_force_state(RunState state); - -typedef enum WakeupReason { - QEMU_WAKEUP_REASON_OTHER = 0, - QEMU_WAKEUP_REASON_RTC, - QEMU_WAKEUP_REASON_PMTIMER, -} WakeupReason; - -void qemu_system_reset_request(void); -void qemu_system_suspend_request(void); -void qemu_register_suspend_notifier(Notifier *notifier); -void qemu_system_wakeup_request(WakeupReason reason); -void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); -void qemu_register_wakeup_notifier(Notifier *notifier); -void qemu_system_shutdown_request(void); -void qemu_system_powerdown_request(void); -void qemu_register_powerdown_notifier(Notifier *notifier); -void qemu_system_debug_request(void); -void qemu_system_vmstop_request(RunState reason); -int qemu_shutdown_requested_get(void); -int qemu_reset_requested_get(void); -void qemu_system_killed(int signal, pid_t pid); -void qemu_devices_reset(void); -void qemu_system_reset(bool report); - -void qemu_add_exit_notifier(Notifier *notify); -void qemu_remove_exit_notifier(Notifier *notify); - -void qemu_add_machine_init_done_notifier(Notifier *notify); - -void do_savevm(Monitor *mon, const QDict *qdict); -int load_vmstate(const char *name); -void do_delvm(Monitor *mon, const QDict *qdict); -void do_info_snapshots(Monitor *mon, const QDict *qdict); - -void qemu_announce_self(void); - -bool qemu_savevm_state_blocked(Error **errp); -void qemu_savevm_state_begin(QEMUFile *f, - const MigrationParams *params); -int qemu_savevm_state_iterate(QEMUFile *f); -void qemu_savevm_state_complete(QEMUFile *f); -void qemu_savevm_state_cancel(void); -uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size); -int qemu_loadvm_state(QEMUFile *f); - -/* SLIRP */ -void do_info_slirp(Monitor *mon); - -typedef enum DisplayType -{ - DT_DEFAULT, - DT_CURSES, - DT_SDL, - DT_GTK, - DT_NOGRAPHIC, - DT_NONE, -} DisplayType; - -extern int autostart; - -typedef enum { - VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, -} VGAInterfaceType; - -extern int vga_interface_type; -#define xenfb_enabled (vga_interface_type == VGA_XENFB) -#define qxl_enabled (vga_interface_type == VGA_QXL) - -extern int graphic_width; -extern int graphic_height; -extern int graphic_depth; -extern DisplayType display_type; -extern const char *keyboard_layout; -extern int win2k_install_hack; -extern int alt_grab; -extern int ctrl_grab; -extern int smp_cpus; -extern int max_cpus; -extern int cursor_hide; -extern int graphic_rotate; -extern int no_quit; -extern int no_shutdown; -extern int semihosting_enabled; -extern int old_param; -extern int boot_menu; -extern uint8_t *boot_splash_filedata; -extern size_t boot_splash_filedata_size; -extern uint8_t qemu_extra_params_fw[2]; -extern QEMUClock *rtc_clock; - -#define MAX_NODES 64 -#define MAX_CPUMASK_BITS 255 -extern int nb_numa_nodes; -extern uint64_t node_mem[MAX_NODES]; -extern unsigned long *node_cpumask[MAX_NODES]; - -#define MAX_OPTION_ROMS 16 -typedef struct QEMUOptionRom { - const char *name; - int32_t bootindex; -} QEMUOptionRom; -extern QEMUOptionRom option_rom[MAX_OPTION_ROMS]; -extern int nb_option_roms; - -#define MAX_PROM_ENVS 128 -extern const char *prom_envs[MAX_PROM_ENVS]; -extern unsigned int nb_prom_envs; - -/* pci-hotplug */ -void pci_device_hot_add(Monitor *mon, const QDict *qdict); -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo); -void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); - -/* generic hotplug */ -void drive_hot_add(Monitor *mon, const QDict *qdict); - -/* CPU hotplug */ -void qemu_register_cpu_added_notifier(Notifier *notifier); - -/* pcie aer error injection */ -void pcie_aer_inject_error_print(Monitor *mon, const QObject *data); -int do_pcie_aer_inject_error(Monitor *mon, - const QDict *qdict, QObject **ret_data); - -/* serial ports */ - -#define MAX_SERIAL_PORTS 4 - -extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; - -/* parallel ports */ - -#define MAX_PARALLEL_PORTS 3 - -extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; - -void do_usb_add(Monitor *mon, const QDict *qdict); -void do_usb_del(Monitor *mon, const QDict *qdict); -void usb_info(Monitor *mon, const QDict *qdict); - -void rtc_change_mon_event(struct tm *tm); - -void add_boot_device_path(int32_t bootindex, DeviceState *dev, - const char *suffix); -char *get_boot_devices_list(size_t *size); - -DeviceState *get_boot_device(uint32_t position); - -QemuOpts *qemu_get_machine_opts(void); - -bool usb_enabled(bool default_usb); - -extern QemuOptsList qemu_drive_opts; -extern QemuOptsList qemu_chardev_opts; -extern QemuOptsList qemu_device_opts; -extern QemuOptsList qemu_netdev_opts; -extern QemuOptsList qemu_net_opts; -extern QemuOptsList qemu_global_opts; -extern QemuOptsList qemu_mon_opts; - -#endif diff --git a/contrib/qemu/include/trace.h b/contrib/qemu/include/trace.h deleted file mode 100644 index c15f4981280..00000000000 --- a/contrib/qemu/include/trace.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TRACE_H -#define TRACE_H - -#include "trace/generated-tracers.h" - -#endif /* TRACE_H */ diff --git a/contrib/qemu/nop-symbols.c b/contrib/qemu/nop-symbols.c deleted file mode 100644 index ae93a3d3bef..00000000000 --- a/contrib/qemu/nop-symbols.c +++ /dev/null @@ -1,12 +0,0 @@ -int notifier_with_return_list_init () { return 0; } -int notifier_with_return_list_notify () { return 0; } -int notifier_with_return_list_add () { return 0; } -int notifier_list_init () { return 0; } -int notifier_list_notify () { return 0; } -int notifier_list_add () { return 0; } -int monitor_protocol_event () { return 0; } -int block_job_cancel_sync () { return 0; } -int block_job_iostatus_reset () { return 0; } -int vm_stop () { return 0; } -int qemu_get_aio_context () { return 0; } - diff --git a/contrib/qemu/qapi-types.h b/contrib/qemu/qapi-types.h deleted file mode 100644 index 082b06d1c2b..00000000000 --- a/contrib/qemu/qapi-types.h +++ /dev/null @@ -1,2746 +0,0 @@ -/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ - -/* - * schema-defined QAPI types - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QAPI_TYPES_H -#define QAPI_TYPES_H - -#include <stdbool.h> -#include <stdint.h> - - -#ifndef QAPI_TYPES_BUILTIN_STRUCT_DECL_H -#define QAPI_TYPES_BUILTIN_STRUCT_DECL_H - - -typedef struct strList -{ - union { - char * value; - uint64_t padding; - }; - struct strList *next; -} strList; - -typedef struct intList -{ - union { - int64_t value; - uint64_t padding; - }; - struct intList *next; -} intList; - -typedef struct numberList -{ - union { - double value; - uint64_t padding; - }; - struct numberList *next; -} numberList; - -typedef struct boolList -{ - union { - bool value; - uint64_t padding; - }; - struct boolList *next; -} boolList; - -typedef struct int8List -{ - union { - int8_t value; - uint64_t padding; - }; - struct int8List *next; -} int8List; - -typedef struct int16List -{ - union { - int16_t value; - uint64_t padding; - }; - struct int16List *next; -} int16List; - -typedef struct int32List -{ - union { - int32_t value; - uint64_t padding; - }; - struct int32List *next; -} int32List; - -typedef struct int64List -{ - union { - int64_t value; - uint64_t padding; - }; - struct int64List *next; -} int64List; - -typedef struct uint8List -{ - union { - uint8_t value; - uint64_t padding; - }; - struct uint8List *next; -} uint8List; - -typedef struct uint16List -{ - union { - uint16_t value; - uint64_t padding; - }; - struct uint16List *next; -} uint16List; - -typedef struct uint32List -{ - union { - uint32_t value; - uint64_t padding; - }; - struct uint32List *next; -} uint32List; - -typedef struct uint64List -{ - union { - uint64_t value; - uint64_t padding; - }; - struct uint64List *next; -} uint64List; - -#endif /* QAPI_TYPES_BUILTIN_STRUCT_DECL_H */ - - -extern const char *ErrorClass_lookup[]; -typedef enum ErrorClass -{ - ERROR_CLASS_GENERIC_ERROR = 0, - ERROR_CLASS_COMMAND_NOT_FOUND = 1, - ERROR_CLASS_DEVICE_ENCRYPTED = 2, - ERROR_CLASS_DEVICE_NOT_ACTIVE = 3, - ERROR_CLASS_DEVICE_NOT_FOUND = 4, - ERROR_CLASS_K_V_M_MISSING_CAP = 5, - ERROR_CLASS_MAX = 6, -} ErrorClass; - -typedef struct ErrorClassList -{ - ErrorClass value; - struct ErrorClassList *next; -} ErrorClassList; - - -typedef struct NameInfo NameInfo; - -typedef struct NameInfoList -{ - union { - NameInfo *value; - uint64_t padding; - }; - struct NameInfoList *next; -} NameInfoList; - - -typedef struct VersionInfo VersionInfo; - -typedef struct VersionInfoList -{ - union { - VersionInfo *value; - uint64_t padding; - }; - struct VersionInfoList *next; -} VersionInfoList; - - -typedef struct KvmInfo KvmInfo; - -typedef struct KvmInfoList -{ - union { - KvmInfo *value; - uint64_t padding; - }; - struct KvmInfoList *next; -} KvmInfoList; - -extern const char *RunState_lookup[]; -typedef enum RunState -{ - RUN_STATE_DEBUG = 0, - RUN_STATE_INMIGRATE = 1, - RUN_STATE_INTERNAL_ERROR = 2, - RUN_STATE_IO_ERROR = 3, - RUN_STATE_PAUSED = 4, - RUN_STATE_POSTMIGRATE = 5, - RUN_STATE_PRELAUNCH = 6, - RUN_STATE_FINISH_MIGRATE = 7, - RUN_STATE_RESTORE_VM = 8, - RUN_STATE_RUNNING = 9, - RUN_STATE_SAVE_VM = 10, - RUN_STATE_SHUTDOWN = 11, - RUN_STATE_SUSPENDED = 12, - RUN_STATE_WATCHDOG = 13, - RUN_STATE_GUEST_PANICKED = 14, - RUN_STATE_MAX = 15, -} RunState; - -typedef struct RunStateList -{ - RunState value; - struct RunStateList *next; -} RunStateList; - - -typedef struct SnapshotInfo SnapshotInfo; - -typedef struct SnapshotInfoList -{ - union { - SnapshotInfo *value; - uint64_t padding; - }; - struct SnapshotInfoList *next; -} SnapshotInfoList; - - -typedef struct ImageInfo ImageInfo; - -typedef struct ImageInfoList -{ - union { - ImageInfo *value; - uint64_t padding; - }; - struct ImageInfoList *next; -} ImageInfoList; - - -typedef struct ImageCheck ImageCheck; - -typedef struct ImageCheckList -{ - union { - ImageCheck *value; - uint64_t padding; - }; - struct ImageCheckList *next; -} ImageCheckList; - - -typedef struct StatusInfo StatusInfo; - -typedef struct StatusInfoList -{ - union { - StatusInfo *value; - uint64_t padding; - }; - struct StatusInfoList *next; -} StatusInfoList; - - -typedef struct UuidInfo UuidInfo; - -typedef struct UuidInfoList -{ - union { - UuidInfo *value; - uint64_t padding; - }; - struct UuidInfoList *next; -} UuidInfoList; - - -typedef struct ChardevInfo ChardevInfo; - -typedef struct ChardevInfoList -{ - union { - ChardevInfo *value; - uint64_t padding; - }; - struct ChardevInfoList *next; -} ChardevInfoList; - -extern const char *DataFormat_lookup[]; -typedef enum DataFormat -{ - DATA_FORMAT_UTF8 = 0, - DATA_FORMAT_BASE64 = 1, - DATA_FORMAT_MAX = 2, -} DataFormat; - -typedef struct DataFormatList -{ - DataFormat value; - struct DataFormatList *next; -} DataFormatList; - - -typedef struct CommandInfo CommandInfo; - -typedef struct CommandInfoList -{ - union { - CommandInfo *value; - uint64_t padding; - }; - struct CommandInfoList *next; -} CommandInfoList; - - -typedef struct EventInfo EventInfo; - -typedef struct EventInfoList -{ - union { - EventInfo *value; - uint64_t padding; - }; - struct EventInfoList *next; -} EventInfoList; - - -typedef struct MigrationStats MigrationStats; - -typedef struct MigrationStatsList -{ - union { - MigrationStats *value; - uint64_t padding; - }; - struct MigrationStatsList *next; -} MigrationStatsList; - - -typedef struct XBZRLECacheStats XBZRLECacheStats; - -typedef struct XBZRLECacheStatsList -{ - union { - XBZRLECacheStats *value; - uint64_t padding; - }; - struct XBZRLECacheStatsList *next; -} XBZRLECacheStatsList; - - -typedef struct MigrationInfo MigrationInfo; - -typedef struct MigrationInfoList -{ - union { - MigrationInfo *value; - uint64_t padding; - }; - struct MigrationInfoList *next; -} MigrationInfoList; - -extern const char *MigrationCapability_lookup[]; -typedef enum MigrationCapability -{ - MIGRATION_CAPABILITY_XBZRLE = 0, - MIGRATION_CAPABILITY_X_RDMA_PIN_ALL = 1, - MIGRATION_CAPABILITY_AUTO_CONVERGE = 2, - MIGRATION_CAPABILITY_MAX = 3, -} MigrationCapability; - -typedef struct MigrationCapabilityList -{ - MigrationCapability value; - struct MigrationCapabilityList *next; -} MigrationCapabilityList; - - -typedef struct MigrationCapabilityStatus MigrationCapabilityStatus; - -typedef struct MigrationCapabilityStatusList -{ - union { - MigrationCapabilityStatus *value; - uint64_t padding; - }; - struct MigrationCapabilityStatusList *next; -} MigrationCapabilityStatusList; - - -typedef struct MouseInfo MouseInfo; - -typedef struct MouseInfoList -{ - union { - MouseInfo *value; - uint64_t padding; - }; - struct MouseInfoList *next; -} MouseInfoList; - - -typedef struct CpuInfo CpuInfo; - -typedef struct CpuInfoList -{ - union { - CpuInfo *value; - uint64_t padding; - }; - struct CpuInfoList *next; -} CpuInfoList; - - -typedef struct BlockDeviceInfo BlockDeviceInfo; - -typedef struct BlockDeviceInfoList -{ - union { - BlockDeviceInfo *value; - uint64_t padding; - }; - struct BlockDeviceInfoList *next; -} BlockDeviceInfoList; - -extern const char *BlockDeviceIoStatus_lookup[]; -typedef enum BlockDeviceIoStatus -{ - BLOCK_DEVICE_IO_STATUS_OK = 0, - BLOCK_DEVICE_IO_STATUS_FAILED = 1, - BLOCK_DEVICE_IO_STATUS_NOSPACE = 2, - BLOCK_DEVICE_IO_STATUS_MAX = 3, -} BlockDeviceIoStatus; - -typedef struct BlockDeviceIoStatusList -{ - BlockDeviceIoStatus value; - struct BlockDeviceIoStatusList *next; -} BlockDeviceIoStatusList; - - -typedef struct BlockDirtyInfo BlockDirtyInfo; - -typedef struct BlockDirtyInfoList -{ - union { - BlockDirtyInfo *value; - uint64_t padding; - }; - struct BlockDirtyInfoList *next; -} BlockDirtyInfoList; - - -typedef struct BlockInfo BlockInfo; - -typedef struct BlockInfoList -{ - union { - BlockInfo *value; - uint64_t padding; - }; - struct BlockInfoList *next; -} BlockInfoList; - - -typedef struct BlockDeviceStats BlockDeviceStats; - -typedef struct BlockDeviceStatsList -{ - union { - BlockDeviceStats *value; - uint64_t padding; - }; - struct BlockDeviceStatsList *next; -} BlockDeviceStatsList; - - -typedef struct BlockStats BlockStats; - -typedef struct BlockStatsList -{ - union { - BlockStats *value; - uint64_t padding; - }; - struct BlockStatsList *next; -} BlockStatsList; - - -typedef struct VncClientInfo VncClientInfo; - -typedef struct VncClientInfoList -{ - union { - VncClientInfo *value; - uint64_t padding; - }; - struct VncClientInfoList *next; -} VncClientInfoList; - - -typedef struct VncInfo VncInfo; - -typedef struct VncInfoList -{ - union { - VncInfo *value; - uint64_t padding; - }; - struct VncInfoList *next; -} VncInfoList; - - -typedef struct SpiceChannel SpiceChannel; - -typedef struct SpiceChannelList -{ - union { - SpiceChannel *value; - uint64_t padding; - }; - struct SpiceChannelList *next; -} SpiceChannelList; - -extern const char *SpiceQueryMouseMode_lookup[]; -typedef enum SpiceQueryMouseMode -{ - SPICE_QUERY_MOUSE_MODE_CLIENT = 0, - SPICE_QUERY_MOUSE_MODE_SERVER = 1, - SPICE_QUERY_MOUSE_MODE_UNKNOWN = 2, - SPICE_QUERY_MOUSE_MODE_MAX = 3, -} SpiceQueryMouseMode; - -typedef struct SpiceQueryMouseModeList -{ - SpiceQueryMouseMode value; - struct SpiceQueryMouseModeList *next; -} SpiceQueryMouseModeList; - - -typedef struct SpiceInfo SpiceInfo; - -typedef struct SpiceInfoList -{ - union { - SpiceInfo *value; - uint64_t padding; - }; - struct SpiceInfoList *next; -} SpiceInfoList; - - -typedef struct BalloonInfo BalloonInfo; - -typedef struct BalloonInfoList -{ - union { - BalloonInfo *value; - uint64_t padding; - }; - struct BalloonInfoList *next; -} BalloonInfoList; - - -typedef struct PciMemoryRange PciMemoryRange; - -typedef struct PciMemoryRangeList -{ - union { - PciMemoryRange *value; - uint64_t padding; - }; - struct PciMemoryRangeList *next; -} PciMemoryRangeList; - - -typedef struct PciMemoryRegion PciMemoryRegion; - -typedef struct PciMemoryRegionList -{ - union { - PciMemoryRegion *value; - uint64_t padding; - }; - struct PciMemoryRegionList *next; -} PciMemoryRegionList; - - -typedef struct PciBridgeInfo PciBridgeInfo; - -typedef struct PciBridgeInfoList -{ - union { - PciBridgeInfo *value; - uint64_t padding; - }; - struct PciBridgeInfoList *next; -} PciBridgeInfoList; - - -typedef struct PciDeviceInfo PciDeviceInfo; - -typedef struct PciDeviceInfoList -{ - union { - PciDeviceInfo *value; - uint64_t padding; - }; - struct PciDeviceInfoList *next; -} PciDeviceInfoList; - - -typedef struct PciInfo PciInfo; - -typedef struct PciInfoList -{ - union { - PciInfo *value; - uint64_t padding; - }; - struct PciInfoList *next; -} PciInfoList; - -extern const char *BlockdevOnError_lookup[]; -typedef enum BlockdevOnError -{ - BLOCKDEV_ON_ERROR_REPORT = 0, - BLOCKDEV_ON_ERROR_IGNORE = 1, - BLOCKDEV_ON_ERROR_ENOSPC = 2, - BLOCKDEV_ON_ERROR_STOP = 3, - BLOCKDEV_ON_ERROR_MAX = 4, -} BlockdevOnError; - -typedef struct BlockdevOnErrorList -{ - BlockdevOnError value; - struct BlockdevOnErrorList *next; -} BlockdevOnErrorList; - -extern const char *MirrorSyncMode_lookup[]; -typedef enum MirrorSyncMode -{ - MIRROR_SYNC_MODE_TOP = 0, - MIRROR_SYNC_MODE_FULL = 1, - MIRROR_SYNC_MODE_NONE = 2, - MIRROR_SYNC_MODE_MAX = 3, -} MirrorSyncMode; - -typedef struct MirrorSyncModeList -{ - MirrorSyncMode value; - struct MirrorSyncModeList *next; -} MirrorSyncModeList; - - -typedef struct BlockJobInfo BlockJobInfo; - -typedef struct BlockJobInfoList -{ - union { - BlockJobInfo *value; - uint64_t padding; - }; - struct BlockJobInfoList *next; -} BlockJobInfoList; - -extern const char *NewImageMode_lookup[]; -typedef enum NewImageMode -{ - NEW_IMAGE_MODE_EXISTING = 0, - NEW_IMAGE_MODE_ABSOLUTE_PATHS = 1, - NEW_IMAGE_MODE_MAX = 2, -} NewImageMode; - -typedef struct NewImageModeList -{ - NewImageMode value; - struct NewImageModeList *next; -} NewImageModeList; - - -typedef struct BlockdevSnapshot BlockdevSnapshot; - -typedef struct BlockdevSnapshotList -{ - union { - BlockdevSnapshot *value; - uint64_t padding; - }; - struct BlockdevSnapshotList *next; -} BlockdevSnapshotList; - - -typedef struct DriveBackup DriveBackup; - -typedef struct DriveBackupList -{ - union { - DriveBackup *value; - uint64_t padding; - }; - struct DriveBackupList *next; -} DriveBackupList; - - -typedef struct Abort Abort; - -typedef struct AbortList -{ - union { - Abort *value; - uint64_t padding; - }; - struct AbortList *next; -} AbortList; - - -typedef struct TransactionAction TransactionAction; - -typedef struct TransactionActionList -{ - union { - TransactionAction *value; - uint64_t padding; - }; - struct TransactionActionList *next; -} TransactionActionList; - -extern const char *TransactionActionKind_lookup[]; -typedef enum TransactionActionKind -{ - TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC = 0, - TRANSACTION_ACTION_KIND_DRIVE_BACKUP = 1, - TRANSACTION_ACTION_KIND_ABORT = 2, - TRANSACTION_ACTION_KIND_MAX = 3, -} TransactionActionKind; - - -typedef struct ObjectPropertyInfo ObjectPropertyInfo; - -typedef struct ObjectPropertyInfoList -{ - union { - ObjectPropertyInfo *value; - uint64_t padding; - }; - struct ObjectPropertyInfoList *next; -} ObjectPropertyInfoList; - - -typedef struct ObjectTypeInfo ObjectTypeInfo; - -typedef struct ObjectTypeInfoList -{ - union { - ObjectTypeInfo *value; - uint64_t padding; - }; - struct ObjectTypeInfoList *next; -} ObjectTypeInfoList; - - -typedef struct DevicePropertyInfo DevicePropertyInfo; - -typedef struct DevicePropertyInfoList -{ - union { - DevicePropertyInfo *value; - uint64_t padding; - }; - struct DevicePropertyInfoList *next; -} DevicePropertyInfoList; - - -typedef struct NetdevNoneOptions NetdevNoneOptions; - -typedef struct NetdevNoneOptionsList -{ - union { - NetdevNoneOptions *value; - uint64_t padding; - }; - struct NetdevNoneOptionsList *next; -} NetdevNoneOptionsList; - - -typedef struct NetLegacyNicOptions NetLegacyNicOptions; - -typedef struct NetLegacyNicOptionsList -{ - union { - NetLegacyNicOptions *value; - uint64_t padding; - }; - struct NetLegacyNicOptionsList *next; -} NetLegacyNicOptionsList; - - -typedef struct String String; - -typedef struct StringList -{ - union { - String *value; - uint64_t padding; - }; - struct StringList *next; -} StringList; - - -typedef struct NetdevUserOptions NetdevUserOptions; - -typedef struct NetdevUserOptionsList -{ - union { - NetdevUserOptions *value; - uint64_t padding; - }; - struct NetdevUserOptionsList *next; -} NetdevUserOptionsList; - - -typedef struct NetdevTapOptions NetdevTapOptions; - -typedef struct NetdevTapOptionsList -{ - union { - NetdevTapOptions *value; - uint64_t padding; - }; - struct NetdevTapOptionsList *next; -} NetdevTapOptionsList; - - -typedef struct NetdevSocketOptions NetdevSocketOptions; - -typedef struct NetdevSocketOptionsList -{ - union { - NetdevSocketOptions *value; - uint64_t padding; - }; - struct NetdevSocketOptionsList *next; -} NetdevSocketOptionsList; - - -typedef struct NetdevVdeOptions NetdevVdeOptions; - -typedef struct NetdevVdeOptionsList -{ - union { - NetdevVdeOptions *value; - uint64_t padding; - }; - struct NetdevVdeOptionsList *next; -} NetdevVdeOptionsList; - - -typedef struct NetdevDumpOptions NetdevDumpOptions; - -typedef struct NetdevDumpOptionsList -{ - union { - NetdevDumpOptions *value; - uint64_t padding; - }; - struct NetdevDumpOptionsList *next; -} NetdevDumpOptionsList; - - -typedef struct NetdevBridgeOptions NetdevBridgeOptions; - -typedef struct NetdevBridgeOptionsList -{ - union { - NetdevBridgeOptions *value; - uint64_t padding; - }; - struct NetdevBridgeOptionsList *next; -} NetdevBridgeOptionsList; - - -typedef struct NetdevHubPortOptions NetdevHubPortOptions; - -typedef struct NetdevHubPortOptionsList -{ - union { - NetdevHubPortOptions *value; - uint64_t padding; - }; - struct NetdevHubPortOptionsList *next; -} NetdevHubPortOptionsList; - - -typedef struct NetClientOptions NetClientOptions; - -typedef struct NetClientOptionsList -{ - union { - NetClientOptions *value; - uint64_t padding; - }; - struct NetClientOptionsList *next; -} NetClientOptionsList; - -extern const char *NetClientOptionsKind_lookup[]; -typedef enum NetClientOptionsKind -{ - NET_CLIENT_OPTIONS_KIND_NONE = 0, - NET_CLIENT_OPTIONS_KIND_NIC = 1, - NET_CLIENT_OPTIONS_KIND_USER = 2, - NET_CLIENT_OPTIONS_KIND_TAP = 3, - NET_CLIENT_OPTIONS_KIND_SOCKET = 4, - NET_CLIENT_OPTIONS_KIND_VDE = 5, - NET_CLIENT_OPTIONS_KIND_DUMP = 6, - NET_CLIENT_OPTIONS_KIND_BRIDGE = 7, - NET_CLIENT_OPTIONS_KIND_HUBPORT = 8, - NET_CLIENT_OPTIONS_KIND_MAX = 9, -} NetClientOptionsKind; - - -typedef struct NetLegacy NetLegacy; - -typedef struct NetLegacyList -{ - union { - NetLegacy *value; - uint64_t padding; - }; - struct NetLegacyList *next; -} NetLegacyList; - - -typedef struct Netdev Netdev; - -typedef struct NetdevList -{ - union { - Netdev *value; - uint64_t padding; - }; - struct NetdevList *next; -} NetdevList; - - -typedef struct InetSocketAddress InetSocketAddress; - -typedef struct InetSocketAddressList -{ - union { - InetSocketAddress *value; - uint64_t padding; - }; - struct InetSocketAddressList *next; -} InetSocketAddressList; - - -typedef struct UnixSocketAddress UnixSocketAddress; - -typedef struct UnixSocketAddressList -{ - union { - UnixSocketAddress *value; - uint64_t padding; - }; - struct UnixSocketAddressList *next; -} UnixSocketAddressList; - - -typedef struct SocketAddress SocketAddress; - -typedef struct SocketAddressList -{ - union { - SocketAddress *value; - uint64_t padding; - }; - struct SocketAddressList *next; -} SocketAddressList; - -extern const char *SocketAddressKind_lookup[]; -typedef enum SocketAddressKind -{ - SOCKET_ADDRESS_KIND_INET = 0, - SOCKET_ADDRESS_KIND_UNIX = 1, - SOCKET_ADDRESS_KIND_FD = 2, - SOCKET_ADDRESS_KIND_MAX = 3, -} SocketAddressKind; - - -typedef struct MachineInfo MachineInfo; - -typedef struct MachineInfoList -{ - union { - MachineInfo *value; - uint64_t padding; - }; - struct MachineInfoList *next; -} MachineInfoList; - - -typedef struct CpuDefinitionInfo CpuDefinitionInfo; - -typedef struct CpuDefinitionInfoList -{ - union { - CpuDefinitionInfo *value; - uint64_t padding; - }; - struct CpuDefinitionInfoList *next; -} CpuDefinitionInfoList; - - -typedef struct AddfdInfo AddfdInfo; - -typedef struct AddfdInfoList -{ - union { - AddfdInfo *value; - uint64_t padding; - }; - struct AddfdInfoList *next; -} AddfdInfoList; - - -typedef struct FdsetFdInfo FdsetFdInfo; - -typedef struct FdsetFdInfoList -{ - union { - FdsetFdInfo *value; - uint64_t padding; - }; - struct FdsetFdInfoList *next; -} FdsetFdInfoList; - - -typedef struct FdsetInfo FdsetInfo; - -typedef struct FdsetInfoList -{ - union { - FdsetInfo *value; - uint64_t padding; - }; - struct FdsetInfoList *next; -} FdsetInfoList; - - -typedef struct TargetInfo TargetInfo; - -typedef struct TargetInfoList -{ - union { - TargetInfo *value; - uint64_t padding; - }; - struct TargetInfoList *next; -} TargetInfoList; - -extern const char *QKeyCode_lookup[]; -typedef enum QKeyCode -{ - Q_KEY_CODE_SHIFT = 0, - Q_KEY_CODE_SHIFT_R = 1, - Q_KEY_CODE_ALT = 2, - Q_KEY_CODE_ALT_R = 3, - Q_KEY_CODE_ALTGR = 4, - Q_KEY_CODE_ALTGR_R = 5, - Q_KEY_CODE_CTRL = 6, - Q_KEY_CODE_CTRL_R = 7, - Q_KEY_CODE_MENU = 8, - Q_KEY_CODE_ESC = 9, - Q_KEY_CODE_1 = 10, - Q_KEY_CODE_2 = 11, - Q_KEY_CODE_3 = 12, - Q_KEY_CODE_4 = 13, - Q_KEY_CODE_5 = 14, - Q_KEY_CODE_6 = 15, - Q_KEY_CODE_7 = 16, - Q_KEY_CODE_8 = 17, - Q_KEY_CODE_9 = 18, - Q_KEY_CODE_0 = 19, - Q_KEY_CODE_MINUS = 20, - Q_KEY_CODE_EQUAL = 21, - Q_KEY_CODE_BACKSPACE = 22, - Q_KEY_CODE_TAB = 23, - Q_KEY_CODE_Q = 24, - Q_KEY_CODE_W = 25, - Q_KEY_CODE_E = 26, - Q_KEY_CODE_R = 27, - Q_KEY_CODE_T = 28, - Q_KEY_CODE_Y = 29, - Q_KEY_CODE_U = 30, - Q_KEY_CODE_I = 31, - Q_KEY_CODE_O = 32, - Q_KEY_CODE_P = 33, - Q_KEY_CODE_BRACKET_LEFT = 34, - Q_KEY_CODE_BRACKET_RIGHT = 35, - Q_KEY_CODE_RET = 36, - Q_KEY_CODE_A = 37, - Q_KEY_CODE_S = 38, - Q_KEY_CODE_D = 39, - Q_KEY_CODE_F = 40, - Q_KEY_CODE_G = 41, - Q_KEY_CODE_H = 42, - Q_KEY_CODE_J = 43, - Q_KEY_CODE_K = 44, - Q_KEY_CODE_L = 45, - Q_KEY_CODE_SEMICOLON = 46, - Q_KEY_CODE_APOSTROPHE = 47, - Q_KEY_CODE_GRAVE_ACCENT = 48, - Q_KEY_CODE_BACKSLASH = 49, - Q_KEY_CODE_Z = 50, - Q_KEY_CODE_X = 51, - Q_KEY_CODE_C = 52, - Q_KEY_CODE_V = 53, - Q_KEY_CODE_B = 54, - Q_KEY_CODE_N = 55, - Q_KEY_CODE_M = 56, - Q_KEY_CODE_COMMA = 57, - Q_KEY_CODE_DOT = 58, - Q_KEY_CODE_SLASH = 59, - Q_KEY_CODE_ASTERISK = 60, - Q_KEY_CODE_SPC = 61, - Q_KEY_CODE_CAPS_LOCK = 62, - Q_KEY_CODE_F1 = 63, - Q_KEY_CODE_F2 = 64, - Q_KEY_CODE_F3 = 65, - Q_KEY_CODE_F4 = 66, - Q_KEY_CODE_F5 = 67, - Q_KEY_CODE_F6 = 68, - Q_KEY_CODE_F7 = 69, - Q_KEY_CODE_F8 = 70, - Q_KEY_CODE_F9 = 71, - Q_KEY_CODE_F10 = 72, - Q_KEY_CODE_NUM_LOCK = 73, - Q_KEY_CODE_SCROLL_LOCK = 74, - Q_KEY_CODE_KP_DIVIDE = 75, - Q_KEY_CODE_KP_MULTIPLY = 76, - Q_KEY_CODE_KP_SUBTRACT = 77, - Q_KEY_CODE_KP_ADD = 78, - Q_KEY_CODE_KP_ENTER = 79, - Q_KEY_CODE_KP_DECIMAL = 80, - Q_KEY_CODE_SYSRQ = 81, - Q_KEY_CODE_KP_0 = 82, - Q_KEY_CODE_KP_1 = 83, - Q_KEY_CODE_KP_2 = 84, - Q_KEY_CODE_KP_3 = 85, - Q_KEY_CODE_KP_4 = 86, - Q_KEY_CODE_KP_5 = 87, - Q_KEY_CODE_KP_6 = 88, - Q_KEY_CODE_KP_7 = 89, - Q_KEY_CODE_KP_8 = 90, - Q_KEY_CODE_KP_9 = 91, - Q_KEY_CODE_LESS = 92, - Q_KEY_CODE_F11 = 93, - Q_KEY_CODE_F12 = 94, - Q_KEY_CODE_PRINT = 95, - Q_KEY_CODE_HOME = 96, - Q_KEY_CODE_PGUP = 97, - Q_KEY_CODE_PGDN = 98, - Q_KEY_CODE_END = 99, - Q_KEY_CODE_LEFT = 100, - Q_KEY_CODE_UP = 101, - Q_KEY_CODE_DOWN = 102, - Q_KEY_CODE_RIGHT = 103, - Q_KEY_CODE_INSERT = 104, - Q_KEY_CODE_DELETE = 105, - Q_KEY_CODE_STOP = 106, - Q_KEY_CODE_AGAIN = 107, - Q_KEY_CODE_PROPS = 108, - Q_KEY_CODE_UNDO = 109, - Q_KEY_CODE_FRONT = 110, - Q_KEY_CODE_COPY = 111, - Q_KEY_CODE_OPEN = 112, - Q_KEY_CODE_PASTE = 113, - Q_KEY_CODE_FIND = 114, - Q_KEY_CODE_CUT = 115, - Q_KEY_CODE_LF = 116, - Q_KEY_CODE_HELP = 117, - Q_KEY_CODE_META_L = 118, - Q_KEY_CODE_META_R = 119, - Q_KEY_CODE_COMPOSE = 120, - Q_KEY_CODE_MAX = 121, -} QKeyCode; - -typedef struct QKeyCodeList -{ - QKeyCode value; - struct QKeyCodeList *next; -} QKeyCodeList; - - -typedef struct KeyValue KeyValue; - -typedef struct KeyValueList -{ - union { - KeyValue *value; - uint64_t padding; - }; - struct KeyValueList *next; -} KeyValueList; - -extern const char *KeyValueKind_lookup[]; -typedef enum KeyValueKind -{ - KEY_VALUE_KIND_NUMBER = 0, - KEY_VALUE_KIND_QCODE = 1, - KEY_VALUE_KIND_MAX = 2, -} KeyValueKind; - - -typedef struct ChardevFile ChardevFile; - -typedef struct ChardevFileList -{ - union { - ChardevFile *value; - uint64_t padding; - }; - struct ChardevFileList *next; -} ChardevFileList; - - -typedef struct ChardevHostdev ChardevHostdev; - -typedef struct ChardevHostdevList -{ - union { - ChardevHostdev *value; - uint64_t padding; - }; - struct ChardevHostdevList *next; -} ChardevHostdevList; - - -typedef struct ChardevSocket ChardevSocket; - -typedef struct ChardevSocketList -{ - union { - ChardevSocket *value; - uint64_t padding; - }; - struct ChardevSocketList *next; -} ChardevSocketList; - - -typedef struct ChardevUdp ChardevUdp; - -typedef struct ChardevUdpList -{ - union { - ChardevUdp *value; - uint64_t padding; - }; - struct ChardevUdpList *next; -} ChardevUdpList; - - -typedef struct ChardevMux ChardevMux; - -typedef struct ChardevMuxList -{ - union { - ChardevMux *value; - uint64_t padding; - }; - struct ChardevMuxList *next; -} ChardevMuxList; - - -typedef struct ChardevStdio ChardevStdio; - -typedef struct ChardevStdioList -{ - union { - ChardevStdio *value; - uint64_t padding; - }; - struct ChardevStdioList *next; -} ChardevStdioList; - - -typedef struct ChardevSpiceChannel ChardevSpiceChannel; - -typedef struct ChardevSpiceChannelList -{ - union { - ChardevSpiceChannel *value; - uint64_t padding; - }; - struct ChardevSpiceChannelList *next; -} ChardevSpiceChannelList; - - -typedef struct ChardevSpicePort ChardevSpicePort; - -typedef struct ChardevSpicePortList -{ - union { - ChardevSpicePort *value; - uint64_t padding; - }; - struct ChardevSpicePortList *next; -} ChardevSpicePortList; - - -typedef struct ChardevVC ChardevVC; - -typedef struct ChardevVCList -{ - union { - ChardevVC *value; - uint64_t padding; - }; - struct ChardevVCList *next; -} ChardevVCList; - - -typedef struct ChardevMemory ChardevMemory; - -typedef struct ChardevMemoryList -{ - union { - ChardevMemory *value; - uint64_t padding; - }; - struct ChardevMemoryList *next; -} ChardevMemoryList; - - -typedef struct ChardevDummy ChardevDummy; - -typedef struct ChardevDummyList -{ - union { - ChardevDummy *value; - uint64_t padding; - }; - struct ChardevDummyList *next; -} ChardevDummyList; - - -typedef struct ChardevBackend ChardevBackend; - -typedef struct ChardevBackendList -{ - union { - ChardevBackend *value; - uint64_t padding; - }; - struct ChardevBackendList *next; -} ChardevBackendList; - -extern const char *ChardevBackendKind_lookup[]; -typedef enum ChardevBackendKind -{ - CHARDEV_BACKEND_KIND_FILE = 0, - CHARDEV_BACKEND_KIND_SERIAL = 1, - CHARDEV_BACKEND_KIND_PARALLEL = 2, - CHARDEV_BACKEND_KIND_PIPE = 3, - CHARDEV_BACKEND_KIND_SOCKET = 4, - CHARDEV_BACKEND_KIND_UDP = 5, - CHARDEV_BACKEND_KIND_PTY = 6, - CHARDEV_BACKEND_KIND_NULL = 7, - CHARDEV_BACKEND_KIND_MUX = 8, - CHARDEV_BACKEND_KIND_MSMOUSE = 9, - CHARDEV_BACKEND_KIND_BRAILLE = 10, - CHARDEV_BACKEND_KIND_STDIO = 11, - CHARDEV_BACKEND_KIND_CONSOLE = 12, - CHARDEV_BACKEND_KIND_SPICEVMC = 13, - CHARDEV_BACKEND_KIND_SPICEPORT = 14, - CHARDEV_BACKEND_KIND_VC = 15, - CHARDEV_BACKEND_KIND_MEMORY = 16, - CHARDEV_BACKEND_KIND_MAX = 17, -} ChardevBackendKind; - - -typedef struct ChardevReturn ChardevReturn; - -typedef struct ChardevReturnList -{ - union { - ChardevReturn *value; - uint64_t padding; - }; - struct ChardevReturnList *next; -} ChardevReturnList; - -extern const char *TpmModel_lookup[]; -typedef enum TpmModel -{ - TPM_MODEL_TPM_TIS = 0, - TPM_MODEL_MAX = 1, -} TpmModel; - -typedef struct TpmModelList -{ - TpmModel value; - struct TpmModelList *next; -} TpmModelList; - -extern const char *TpmType_lookup[]; -typedef enum TpmType -{ - TPM_TYPE_PASSTHROUGH = 0, - TPM_TYPE_MAX = 1, -} TpmType; - -typedef struct TpmTypeList -{ - TpmType value; - struct TpmTypeList *next; -} TpmTypeList; - - -typedef struct TPMPassthroughOptions TPMPassthroughOptions; - -typedef struct TPMPassthroughOptionsList -{ - union { - TPMPassthroughOptions *value; - uint64_t padding; - }; - struct TPMPassthroughOptionsList *next; -} TPMPassthroughOptionsList; - - -typedef struct TpmTypeOptions TpmTypeOptions; - -typedef struct TpmTypeOptionsList -{ - union { - TpmTypeOptions *value; - uint64_t padding; - }; - struct TpmTypeOptionsList *next; -} TpmTypeOptionsList; - -extern const char *TpmTypeOptionsKind_lookup[]; -typedef enum TpmTypeOptionsKind -{ - TPM_TYPE_OPTIONS_KIND_PASSTHROUGH = 0, - TPM_TYPE_OPTIONS_KIND_MAX = 1, -} TpmTypeOptionsKind; - - -typedef struct TPMInfo TPMInfo; - -typedef struct TPMInfoList -{ - union { - TPMInfo *value; - uint64_t padding; - }; - struct TPMInfoList *next; -} TPMInfoList; - - -typedef struct AcpiTableOptions AcpiTableOptions; - -typedef struct AcpiTableOptionsList -{ - union { - AcpiTableOptions *value; - uint64_t padding; - }; - struct AcpiTableOptionsList *next; -} AcpiTableOptionsList; - -extern const char *CommandLineParameterType_lookup[]; -typedef enum CommandLineParameterType -{ - COMMAND_LINE_PARAMETER_TYPE_STRING = 0, - COMMAND_LINE_PARAMETER_TYPE_BOOLEAN = 1, - COMMAND_LINE_PARAMETER_TYPE_NUMBER = 2, - COMMAND_LINE_PARAMETER_TYPE_SIZE = 3, - COMMAND_LINE_PARAMETER_TYPE_MAX = 4, -} CommandLineParameterType; - -typedef struct CommandLineParameterTypeList -{ - CommandLineParameterType value; - struct CommandLineParameterTypeList *next; -} CommandLineParameterTypeList; - - -typedef struct CommandLineParameterInfo CommandLineParameterInfo; - -typedef struct CommandLineParameterInfoList -{ - union { - CommandLineParameterInfo *value; - uint64_t padding; - }; - struct CommandLineParameterInfoList *next; -} CommandLineParameterInfoList; - - -typedef struct CommandLineOptionInfo CommandLineOptionInfo; - -typedef struct CommandLineOptionInfoList -{ - union { - CommandLineOptionInfo *value; - uint64_t padding; - }; - struct CommandLineOptionInfoList *next; -} CommandLineOptionInfoList; - -extern const char *X86CPURegister32_lookup[]; -typedef enum X86CPURegister32 -{ - X86_C_P_U_REGISTER32_EAX = 0, - X86_C_P_U_REGISTER32_EBX = 1, - X86_C_P_U_REGISTER32_ECX = 2, - X86_C_P_U_REGISTER32_EDX = 3, - X86_C_P_U_REGISTER32_ESP = 4, - X86_C_P_U_REGISTER32_EBP = 5, - X86_C_P_U_REGISTER32_ESI = 6, - X86_C_P_U_REGISTER32_EDI = 7, - X86_C_P_U_REGISTER32_MAX = 8, -} X86CPURegister32; - -typedef struct X86CPURegister32List -{ - X86CPURegister32 value; - struct X86CPURegister32List *next; -} X86CPURegister32List; - - -typedef struct X86CPUFeatureWordInfo X86CPUFeatureWordInfo; - -typedef struct X86CPUFeatureWordInfoList -{ - union { - X86CPUFeatureWordInfo *value; - uint64_t padding; - }; - struct X86CPUFeatureWordInfoList *next; -} X86CPUFeatureWordInfoList; - -extern const char *RxState_lookup[]; -typedef enum RxState -{ - RX_STATE_NORMAL = 0, - RX_STATE_NONE = 1, - RX_STATE_ALL = 2, - RX_STATE_MAX = 3, -} RxState; - -typedef struct RxStateList -{ - RxState value; - struct RxStateList *next; -} RxStateList; - - -typedef struct RxFilterInfo RxFilterInfo; - -typedef struct RxFilterInfoList -{ - union { - RxFilterInfo *value; - uint64_t padding; - }; - struct RxFilterInfoList *next; -} RxFilterInfoList; - -#ifndef QAPI_TYPES_BUILTIN_CLEANUP_DECL_H -#define QAPI_TYPES_BUILTIN_CLEANUP_DECL_H - -void qapi_free_strList(strList * obj); -void qapi_free_intList(intList * obj); -void qapi_free_numberList(numberList * obj); -void qapi_free_boolList(boolList * obj); -void qapi_free_int8List(int8List * obj); -void qapi_free_int16List(int16List * obj); -void qapi_free_int32List(int32List * obj); -void qapi_free_int64List(int64List * obj); -void qapi_free_uint8List(uint8List * obj); -void qapi_free_uint16List(uint16List * obj); -void qapi_free_uint32List(uint32List * obj); -void qapi_free_uint64List(uint64List * obj); - -#endif /* QAPI_TYPES_BUILTIN_CLEANUP_DECL_H */ - - -void qapi_free_ErrorClassList(ErrorClassList * obj); - -struct NameInfo -{ - bool has_name; - char * name; -}; - -void qapi_free_NameInfoList(NameInfoList * obj); -void qapi_free_NameInfo(NameInfo * obj); - -struct VersionInfo -{ - struct - { - int64_t major; - int64_t minor; - int64_t micro; - } qemu; - char * package; -}; - -void qapi_free_VersionInfoList(VersionInfoList * obj); -void qapi_free_VersionInfo(VersionInfo * obj); - -struct KvmInfo -{ - bool enabled; - bool present; -}; - -void qapi_free_KvmInfoList(KvmInfoList * obj); -void qapi_free_KvmInfo(KvmInfo * obj); - -void qapi_free_RunStateList(RunStateList * obj); - -struct SnapshotInfo -{ - char * id; - char * name; - int64_t vm_state_size; - int64_t date_sec; - int64_t date_nsec; - int64_t vm_clock_sec; - int64_t vm_clock_nsec; -}; - -void qapi_free_SnapshotInfoList(SnapshotInfoList * obj); -void qapi_free_SnapshotInfo(SnapshotInfo * obj); - -struct ImageInfo -{ - char * filename; - char * format; - bool has_dirty_flag; - bool dirty_flag; - bool has_actual_size; - int64_t actual_size; - int64_t virtual_size; - bool has_cluster_size; - int64_t cluster_size; - bool has_encrypted; - bool encrypted; - bool has_backing_filename; - char * backing_filename; - bool has_full_backing_filename; - char * full_backing_filename; - bool has_backing_filename_format; - char * backing_filename_format; - bool has_snapshots; - SnapshotInfoList * snapshots; - bool has_backing_image; - ImageInfo * backing_image; -}; - -void qapi_free_ImageInfoList(ImageInfoList * obj); -void qapi_free_ImageInfo(ImageInfo * obj); - -struct ImageCheck -{ - char * filename; - char * format; - int64_t check_errors; - bool has_image_end_offset; - int64_t image_end_offset; - bool has_corruptions; - int64_t corruptions; - bool has_leaks; - int64_t leaks; - bool has_corruptions_fixed; - int64_t corruptions_fixed; - bool has_leaks_fixed; - int64_t leaks_fixed; - bool has_total_clusters; - int64_t total_clusters; - bool has_allocated_clusters; - int64_t allocated_clusters; - bool has_fragmented_clusters; - int64_t fragmented_clusters; - bool has_compressed_clusters; - int64_t compressed_clusters; -}; - -void qapi_free_ImageCheckList(ImageCheckList * obj); -void qapi_free_ImageCheck(ImageCheck * obj); - -struct StatusInfo -{ - bool running; - bool singlestep; - RunState status; -}; - -void qapi_free_StatusInfoList(StatusInfoList * obj); -void qapi_free_StatusInfo(StatusInfo * obj); - -struct UuidInfo -{ - char * UUID; -}; - -void qapi_free_UuidInfoList(UuidInfoList * obj); -void qapi_free_UuidInfo(UuidInfo * obj); - -struct ChardevInfo -{ - char * label; - char * filename; -}; - -void qapi_free_ChardevInfoList(ChardevInfoList * obj); -void qapi_free_ChardevInfo(ChardevInfo * obj); - -void qapi_free_DataFormatList(DataFormatList * obj); - -struct CommandInfo -{ - char * name; -}; - -void qapi_free_CommandInfoList(CommandInfoList * obj); -void qapi_free_CommandInfo(CommandInfo * obj); - -struct EventInfo -{ - char * name; -}; - -void qapi_free_EventInfoList(EventInfoList * obj); -void qapi_free_EventInfo(EventInfo * obj); - -struct MigrationStats -{ - int64_t transferred; - int64_t remaining; - int64_t total; - int64_t duplicate; - int64_t skipped; - int64_t normal; - int64_t normal_bytes; - int64_t dirty_pages_rate; - double mbps; -}; - -void qapi_free_MigrationStatsList(MigrationStatsList * obj); -void qapi_free_MigrationStats(MigrationStats * obj); - -struct XBZRLECacheStats -{ - int64_t cache_size; - int64_t bytes; - int64_t pages; - int64_t cache_miss; - int64_t overflow; -}; - -void qapi_free_XBZRLECacheStatsList(XBZRLECacheStatsList * obj); -void qapi_free_XBZRLECacheStats(XBZRLECacheStats * obj); - -struct MigrationInfo -{ - bool has_status; - char * status; - bool has_ram; - MigrationStats * ram; - bool has_disk; - MigrationStats * disk; - bool has_xbzrle_cache; - XBZRLECacheStats * xbzrle_cache; - bool has_total_time; - int64_t total_time; - bool has_expected_downtime; - int64_t expected_downtime; - bool has_downtime; - int64_t downtime; -}; - -void qapi_free_MigrationInfoList(MigrationInfoList * obj); -void qapi_free_MigrationInfo(MigrationInfo * obj); - -void qapi_free_MigrationCapabilityList(MigrationCapabilityList * obj); - -struct MigrationCapabilityStatus -{ - MigrationCapability capability; - bool state; -}; - -void qapi_free_MigrationCapabilityStatusList(MigrationCapabilityStatusList * obj); -void qapi_free_MigrationCapabilityStatus(MigrationCapabilityStatus * obj); - -struct MouseInfo -{ - char * name; - int64_t index; - bool current; - bool absolute; -}; - -void qapi_free_MouseInfoList(MouseInfoList * obj); -void qapi_free_MouseInfo(MouseInfo * obj); - -struct CpuInfo -{ - int64_t CPU; - bool current; - bool halted; - bool has_pc; - int64_t pc; - bool has_nip; - int64_t nip; - bool has_npc; - int64_t npc; - bool has_PC; - int64_t PC; - int64_t thread_id; -}; - -void qapi_free_CpuInfoList(CpuInfoList * obj); -void qapi_free_CpuInfo(CpuInfo * obj); - -struct BlockDeviceInfo -{ - char * file; - bool ro; - char * drv; - bool has_backing_file; - char * backing_file; - int64_t backing_file_depth; - bool encrypted; - bool encryption_key_missing; - int64_t bps; - int64_t bps_rd; - int64_t bps_wr; - int64_t iops; - int64_t iops_rd; - int64_t iops_wr; - ImageInfo * image; -}; - -void qapi_free_BlockDeviceInfoList(BlockDeviceInfoList * obj); -void qapi_free_BlockDeviceInfo(BlockDeviceInfo * obj); - -void qapi_free_BlockDeviceIoStatusList(BlockDeviceIoStatusList * obj); - -struct BlockDirtyInfo -{ - int64_t count; - int64_t granularity; -}; - -void qapi_free_BlockDirtyInfoList(BlockDirtyInfoList * obj); -void qapi_free_BlockDirtyInfo(BlockDirtyInfo * obj); - -struct BlockInfo -{ - char * device; - char * type; - bool removable; - bool locked; - bool has_inserted; - BlockDeviceInfo * inserted; - bool has_tray_open; - bool tray_open; - bool has_io_status; - BlockDeviceIoStatus io_status; - bool has_dirty; - BlockDirtyInfo * dirty; -}; - -void qapi_free_BlockInfoList(BlockInfoList * obj); -void qapi_free_BlockInfo(BlockInfo * obj); - -struct BlockDeviceStats -{ - int64_t rd_bytes; - int64_t wr_bytes; - int64_t rd_operations; - int64_t wr_operations; - int64_t flush_operations; - int64_t flush_total_time_ns; - int64_t wr_total_time_ns; - int64_t rd_total_time_ns; - int64_t wr_highest_offset; -}; - -void qapi_free_BlockDeviceStatsList(BlockDeviceStatsList * obj); -void qapi_free_BlockDeviceStats(BlockDeviceStats * obj); - -struct BlockStats -{ - bool has_device; - char * device; - BlockDeviceStats * stats; - bool has_parent; - BlockStats * parent; -}; - -void qapi_free_BlockStatsList(BlockStatsList * obj); -void qapi_free_BlockStats(BlockStats * obj); - -struct VncClientInfo -{ - char * host; - char * family; - char * service; - bool has_x509_dname; - char * x509_dname; - bool has_sasl_username; - char * sasl_username; -}; - -void qapi_free_VncClientInfoList(VncClientInfoList * obj); -void qapi_free_VncClientInfo(VncClientInfo * obj); - -struct VncInfo -{ - bool enabled; - bool has_host; - char * host; - bool has_family; - char * family; - bool has_service; - char * service; - bool has_auth; - char * auth; - bool has_clients; - VncClientInfoList * clients; -}; - -void qapi_free_VncInfoList(VncInfoList * obj); -void qapi_free_VncInfo(VncInfo * obj); - -struct SpiceChannel -{ - char * host; - char * family; - char * port; - int64_t connection_id; - int64_t channel_type; - int64_t channel_id; - bool tls; -}; - -void qapi_free_SpiceChannelList(SpiceChannelList * obj); -void qapi_free_SpiceChannel(SpiceChannel * obj); - -void qapi_free_SpiceQueryMouseModeList(SpiceQueryMouseModeList * obj); - -struct SpiceInfo -{ - bool enabled; - bool migrated; - bool has_host; - char * host; - bool has_port; - int64_t port; - bool has_tls_port; - int64_t tls_port; - bool has_auth; - char * auth; - bool has_compiled_version; - char * compiled_version; - SpiceQueryMouseMode mouse_mode; - bool has_channels; - SpiceChannelList * channels; -}; - -void qapi_free_SpiceInfoList(SpiceInfoList * obj); -void qapi_free_SpiceInfo(SpiceInfo * obj); - -struct BalloonInfo -{ - int64_t actual; -}; - -void qapi_free_BalloonInfoList(BalloonInfoList * obj); -void qapi_free_BalloonInfo(BalloonInfo * obj); - -struct PciMemoryRange -{ - int64_t base; - int64_t limit; -}; - -void qapi_free_PciMemoryRangeList(PciMemoryRangeList * obj); -void qapi_free_PciMemoryRange(PciMemoryRange * obj); - -struct PciMemoryRegion -{ - int64_t bar; - char * type; - int64_t address; - int64_t size; - bool has_prefetch; - bool prefetch; - bool has_mem_type_64; - bool mem_type_64; -}; - -void qapi_free_PciMemoryRegionList(PciMemoryRegionList * obj); -void qapi_free_PciMemoryRegion(PciMemoryRegion * obj); - -struct PciBridgeInfo -{ - struct - { - int64_t number; - int64_t secondary; - int64_t subordinate; - PciMemoryRange * io_range; - PciMemoryRange * memory_range; - PciMemoryRange * prefetchable_range; - } bus; - bool has_devices; - PciDeviceInfoList * devices; -}; - -void qapi_free_PciBridgeInfoList(PciBridgeInfoList * obj); -void qapi_free_PciBridgeInfo(PciBridgeInfo * obj); - -struct PciDeviceInfo -{ - int64_t bus; - int64_t slot; - int64_t function; - struct - { - bool has_desc; - char * desc; - int64_t class; - } class_info; - struct - { - int64_t device; - int64_t vendor; - } id; - bool has_irq; - int64_t irq; - char * qdev_id; - bool has_pci_bridge; - PciBridgeInfo * pci_bridge; - PciMemoryRegionList * regions; -}; - -void qapi_free_PciDeviceInfoList(PciDeviceInfoList * obj); -void qapi_free_PciDeviceInfo(PciDeviceInfo * obj); - -struct PciInfo -{ - int64_t bus; - PciDeviceInfoList * devices; -}; - -void qapi_free_PciInfoList(PciInfoList * obj); -void qapi_free_PciInfo(PciInfo * obj); - -void qapi_free_BlockdevOnErrorList(BlockdevOnErrorList * obj); - -void qapi_free_MirrorSyncModeList(MirrorSyncModeList * obj); - -struct BlockJobInfo -{ - char * type; - char * device; - int64_t len; - int64_t offset; - bool busy; - bool paused; - int64_t speed; - BlockDeviceIoStatus io_status; -}; - -void qapi_free_BlockJobInfoList(BlockJobInfoList * obj); -void qapi_free_BlockJobInfo(BlockJobInfo * obj); - -void qapi_free_NewImageModeList(NewImageModeList * obj); - -struct BlockdevSnapshot -{ - char * device; - char * snapshot_file; - bool has_format; - char * format; - bool has_mode; - NewImageMode mode; -}; - -void qapi_free_BlockdevSnapshotList(BlockdevSnapshotList * obj); -void qapi_free_BlockdevSnapshot(BlockdevSnapshot * obj); - -struct DriveBackup -{ - char * device; - char * target; - bool has_format; - char * format; - MirrorSyncMode sync; - bool has_mode; - NewImageMode mode; - bool has_speed; - int64_t speed; - bool has_on_source_error; - BlockdevOnError on_source_error; - bool has_on_target_error; - BlockdevOnError on_target_error; -}; - -void qapi_free_DriveBackupList(DriveBackupList * obj); -void qapi_free_DriveBackup(DriveBackup * obj); - -struct Abort -{ -}; - -void qapi_free_AbortList(AbortList * obj); -void qapi_free_Abort(Abort * obj); - -struct TransactionAction -{ - TransactionActionKind kind; - union { - void *data; - BlockdevSnapshot * blockdev_snapshot_sync; - DriveBackup * drive_backup; - Abort * abort; - }; -}; -void qapi_free_TransactionActionList(TransactionActionList * obj); -void qapi_free_TransactionAction(TransactionAction * obj); - -struct ObjectPropertyInfo -{ - char * name; - char * type; -}; - -void qapi_free_ObjectPropertyInfoList(ObjectPropertyInfoList * obj); -void qapi_free_ObjectPropertyInfo(ObjectPropertyInfo * obj); - -struct ObjectTypeInfo -{ - char * name; -}; - -void qapi_free_ObjectTypeInfoList(ObjectTypeInfoList * obj); -void qapi_free_ObjectTypeInfo(ObjectTypeInfo * obj); - -struct DevicePropertyInfo -{ - char * name; - char * type; -}; - -void qapi_free_DevicePropertyInfoList(DevicePropertyInfoList * obj); -void qapi_free_DevicePropertyInfo(DevicePropertyInfo * obj); - -struct NetdevNoneOptions -{ -}; - -void qapi_free_NetdevNoneOptionsList(NetdevNoneOptionsList * obj); -void qapi_free_NetdevNoneOptions(NetdevNoneOptions * obj); - -struct NetLegacyNicOptions -{ - bool has_netdev; - char * netdev; - bool has_macaddr; - char * macaddr; - bool has_model; - char * model; - bool has_addr; - char * addr; - bool has_vectors; - uint32_t vectors; -}; - -void qapi_free_NetLegacyNicOptionsList(NetLegacyNicOptionsList * obj); -void qapi_free_NetLegacyNicOptions(NetLegacyNicOptions * obj); - -struct String -{ - char * str; -}; - -void qapi_free_StringList(StringList * obj); -void qapi_free_String(String * obj); - -struct NetdevUserOptions -{ - bool has_hostname; - char * hostname; - bool has_q_restrict; - bool q_restrict; - bool has_ip; - char * ip; - bool has_net; - char * net; - bool has_host; - char * host; - bool has_tftp; - char * tftp; - bool has_bootfile; - char * bootfile; - bool has_dhcpstart; - char * dhcpstart; - bool has_dns; - char * dns; - bool has_dnssearch; - StringList * dnssearch; - bool has_smb; - char * smb; - bool has_smbserver; - char * smbserver; - bool has_hostfwd; - StringList * hostfwd; - bool has_guestfwd; - StringList * guestfwd; -}; - -void qapi_free_NetdevUserOptionsList(NetdevUserOptionsList * obj); -void qapi_free_NetdevUserOptions(NetdevUserOptions * obj); - -struct NetdevTapOptions -{ - bool has_ifname; - char * ifname; - bool has_fd; - char * fd; - bool has_fds; - char * fds; - bool has_script; - char * script; - bool has_downscript; - char * downscript; - bool has_helper; - char * helper; - bool has_sndbuf; - uint64_t sndbuf; - bool has_vnet_hdr; - bool vnet_hdr; - bool has_vhost; - bool vhost; - bool has_vhostfd; - char * vhostfd; - bool has_vhostfds; - char * vhostfds; - bool has_vhostforce; - bool vhostforce; - bool has_queues; - uint32_t queues; -}; - -void qapi_free_NetdevTapOptionsList(NetdevTapOptionsList * obj); -void qapi_free_NetdevTapOptions(NetdevTapOptions * obj); - -struct NetdevSocketOptions -{ - bool has_fd; - char * fd; - bool has_listen; - char * listen; - bool has_connect; - char * connect; - bool has_mcast; - char * mcast; - bool has_localaddr; - char * localaddr; - bool has_udp; - char * udp; -}; - -void qapi_free_NetdevSocketOptionsList(NetdevSocketOptionsList * obj); -void qapi_free_NetdevSocketOptions(NetdevSocketOptions * obj); - -struct NetdevVdeOptions -{ - bool has_sock; - char * sock; - bool has_port; - uint16_t port; - bool has_group; - char * group; - bool has_mode; - uint16_t mode; -}; - -void qapi_free_NetdevVdeOptionsList(NetdevVdeOptionsList * obj); -void qapi_free_NetdevVdeOptions(NetdevVdeOptions * obj); - -struct NetdevDumpOptions -{ - bool has_len; - uint64_t len; - bool has_file; - char * file; -}; - -void qapi_free_NetdevDumpOptionsList(NetdevDumpOptionsList * obj); -void qapi_free_NetdevDumpOptions(NetdevDumpOptions * obj); - -struct NetdevBridgeOptions -{ - bool has_br; - char * br; - bool has_helper; - char * helper; -}; - -void qapi_free_NetdevBridgeOptionsList(NetdevBridgeOptionsList * obj); -void qapi_free_NetdevBridgeOptions(NetdevBridgeOptions * obj); - -struct NetdevHubPortOptions -{ - int32_t hubid; -}; - -void qapi_free_NetdevHubPortOptionsList(NetdevHubPortOptionsList * obj); -void qapi_free_NetdevHubPortOptions(NetdevHubPortOptions * obj); - -struct NetClientOptions -{ - NetClientOptionsKind kind; - union { - void *data; - NetdevNoneOptions * none; - NetLegacyNicOptions * nic; - NetdevUserOptions * user; - NetdevTapOptions * tap; - NetdevSocketOptions * socket; - NetdevVdeOptions * vde; - NetdevDumpOptions * dump; - NetdevBridgeOptions * bridge; - NetdevHubPortOptions * hubport; - }; -}; -void qapi_free_NetClientOptionsList(NetClientOptionsList * obj); -void qapi_free_NetClientOptions(NetClientOptions * obj); - -struct NetLegacy -{ - bool has_vlan; - int32_t vlan; - bool has_id; - char * id; - bool has_name; - char * name; - NetClientOptions * opts; -}; - -void qapi_free_NetLegacyList(NetLegacyList * obj); -void qapi_free_NetLegacy(NetLegacy * obj); - -struct Netdev -{ - char * id; - NetClientOptions * opts; -}; - -void qapi_free_NetdevList(NetdevList * obj); -void qapi_free_Netdev(Netdev * obj); - -struct InetSocketAddress -{ - char * host; - char * port; - bool has_to; - uint16_t to; - bool has_ipv4; - bool ipv4; - bool has_ipv6; - bool ipv6; -}; - -void qapi_free_InetSocketAddressList(InetSocketAddressList * obj); -void qapi_free_InetSocketAddress(InetSocketAddress * obj); - -struct UnixSocketAddress -{ - char * path; -}; - -void qapi_free_UnixSocketAddressList(UnixSocketAddressList * obj); -void qapi_free_UnixSocketAddress(UnixSocketAddress * obj); - -struct SocketAddress -{ - SocketAddressKind kind; - union { - void *data; - InetSocketAddress * inet; - UnixSocketAddress * q_unix; - String * fd; - }; -}; -void qapi_free_SocketAddressList(SocketAddressList * obj); -void qapi_free_SocketAddress(SocketAddress * obj); - -struct MachineInfo -{ - char * name; - bool has_alias; - char * alias; - bool has_is_default; - bool is_default; - int64_t cpu_max; -}; - -void qapi_free_MachineInfoList(MachineInfoList * obj); -void qapi_free_MachineInfo(MachineInfo * obj); - -struct CpuDefinitionInfo -{ - char * name; -}; - -void qapi_free_CpuDefinitionInfoList(CpuDefinitionInfoList * obj); -void qapi_free_CpuDefinitionInfo(CpuDefinitionInfo * obj); - -struct AddfdInfo -{ - int64_t fdset_id; - int64_t fd; -}; - -void qapi_free_AddfdInfoList(AddfdInfoList * obj); -void qapi_free_AddfdInfo(AddfdInfo * obj); - -struct FdsetFdInfo -{ - int64_t fd; - bool has_opaque; - char * opaque; -}; - -void qapi_free_FdsetFdInfoList(FdsetFdInfoList * obj); -void qapi_free_FdsetFdInfo(FdsetFdInfo * obj); - -struct FdsetInfo -{ - int64_t fdset_id; - FdsetFdInfoList * fds; -}; - -void qapi_free_FdsetInfoList(FdsetInfoList * obj); -void qapi_free_FdsetInfo(FdsetInfo * obj); - -struct TargetInfo -{ - char * arch; -}; - -void qapi_free_TargetInfoList(TargetInfoList * obj); -void qapi_free_TargetInfo(TargetInfo * obj); - -void qapi_free_QKeyCodeList(QKeyCodeList * obj); - -struct KeyValue -{ - KeyValueKind kind; - union { - void *data; - int64_t number; - QKeyCode qcode; - }; -}; -void qapi_free_KeyValueList(KeyValueList * obj); -void qapi_free_KeyValue(KeyValue * obj); - -struct ChardevFile -{ - bool has_in; - char * in; - char * out; -}; - -void qapi_free_ChardevFileList(ChardevFileList * obj); -void qapi_free_ChardevFile(ChardevFile * obj); - -struct ChardevHostdev -{ - char * device; -}; - -void qapi_free_ChardevHostdevList(ChardevHostdevList * obj); -void qapi_free_ChardevHostdev(ChardevHostdev * obj); - -struct ChardevSocket -{ - SocketAddress * addr; - bool has_server; - bool server; - bool has_wait; - bool wait; - bool has_nodelay; - bool nodelay; - bool has_telnet; - bool telnet; -}; - -void qapi_free_ChardevSocketList(ChardevSocketList * obj); -void qapi_free_ChardevSocket(ChardevSocket * obj); - -struct ChardevUdp -{ - SocketAddress * remote; - bool has_local; - SocketAddress * local; -}; - -void qapi_free_ChardevUdpList(ChardevUdpList * obj); -void qapi_free_ChardevUdp(ChardevUdp * obj); - -struct ChardevMux -{ - char * chardev; -}; - -void qapi_free_ChardevMuxList(ChardevMuxList * obj); -void qapi_free_ChardevMux(ChardevMux * obj); - -struct ChardevStdio -{ - bool has_signal; - bool signal; -}; - -void qapi_free_ChardevStdioList(ChardevStdioList * obj); -void qapi_free_ChardevStdio(ChardevStdio * obj); - -struct ChardevSpiceChannel -{ - char * type; -}; - -void qapi_free_ChardevSpiceChannelList(ChardevSpiceChannelList * obj); -void qapi_free_ChardevSpiceChannel(ChardevSpiceChannel * obj); - -struct ChardevSpicePort -{ - char * fqdn; -}; - -void qapi_free_ChardevSpicePortList(ChardevSpicePortList * obj); -void qapi_free_ChardevSpicePort(ChardevSpicePort * obj); - -struct ChardevVC -{ - bool has_width; - int64_t width; - bool has_height; - int64_t height; - bool has_cols; - int64_t cols; - bool has_rows; - int64_t rows; -}; - -void qapi_free_ChardevVCList(ChardevVCList * obj); -void qapi_free_ChardevVC(ChardevVC * obj); - -struct ChardevMemory -{ - bool has_size; - int64_t size; -}; - -void qapi_free_ChardevMemoryList(ChardevMemoryList * obj); -void qapi_free_ChardevMemory(ChardevMemory * obj); - -struct ChardevDummy -{ -}; - -void qapi_free_ChardevDummyList(ChardevDummyList * obj); -void qapi_free_ChardevDummy(ChardevDummy * obj); - -struct ChardevBackend -{ - ChardevBackendKind kind; - union { - void *data; - ChardevFile * file; - ChardevHostdev * serial; - ChardevHostdev * parallel; - ChardevHostdev * pipe; - ChardevSocket * socket; - ChardevUdp * udp; - ChardevDummy * pty; - ChardevDummy * null; - ChardevMux * mux; - ChardevDummy * msmouse; - ChardevDummy * braille; - ChardevStdio * stdio; - ChardevDummy * console; - ChardevSpiceChannel * spicevmc; - ChardevSpicePort * spiceport; - ChardevVC * vc; - ChardevMemory * memory; - }; -}; -void qapi_free_ChardevBackendList(ChardevBackendList * obj); -void qapi_free_ChardevBackend(ChardevBackend * obj); - -struct ChardevReturn -{ - bool has_pty; - char * pty; -}; - -void qapi_free_ChardevReturnList(ChardevReturnList * obj); -void qapi_free_ChardevReturn(ChardevReturn * obj); - -void qapi_free_TpmModelList(TpmModelList * obj); - -void qapi_free_TpmTypeList(TpmTypeList * obj); - -struct TPMPassthroughOptions -{ - bool has_path; - char * path; - bool has_cancel_path; - char * cancel_path; -}; - -void qapi_free_TPMPassthroughOptionsList(TPMPassthroughOptionsList * obj); -void qapi_free_TPMPassthroughOptions(TPMPassthroughOptions * obj); - -struct TpmTypeOptions -{ - TpmTypeOptionsKind kind; - union { - void *data; - TPMPassthroughOptions * passthrough; - }; -}; -void qapi_free_TpmTypeOptionsList(TpmTypeOptionsList * obj); -void qapi_free_TpmTypeOptions(TpmTypeOptions * obj); - -struct TPMInfo -{ - char * id; - TpmModel model; - TpmTypeOptions * options; -}; - -void qapi_free_TPMInfoList(TPMInfoList * obj); -void qapi_free_TPMInfo(TPMInfo * obj); - -struct AcpiTableOptions -{ - bool has_sig; - char * sig; - bool has_rev; - uint8_t rev; - bool has_oem_id; - char * oem_id; - bool has_oem_table_id; - char * oem_table_id; - bool has_oem_rev; - uint32_t oem_rev; - bool has_asl_compiler_id; - char * asl_compiler_id; - bool has_asl_compiler_rev; - uint32_t asl_compiler_rev; - bool has_file; - char * file; - bool has_data; - char * data; -}; - -void qapi_free_AcpiTableOptionsList(AcpiTableOptionsList * obj); -void qapi_free_AcpiTableOptions(AcpiTableOptions * obj); - -void qapi_free_CommandLineParameterTypeList(CommandLineParameterTypeList * obj); - -struct CommandLineParameterInfo -{ - char * name; - CommandLineParameterType type; - bool has_help; - char * help; -}; - -void qapi_free_CommandLineParameterInfoList(CommandLineParameterInfoList * obj); -void qapi_free_CommandLineParameterInfo(CommandLineParameterInfo * obj); - -struct CommandLineOptionInfo -{ - char * option; - CommandLineParameterInfoList * parameters; -}; - -void qapi_free_CommandLineOptionInfoList(CommandLineOptionInfoList * obj); -void qapi_free_CommandLineOptionInfo(CommandLineOptionInfo * obj); - -void qapi_free_X86CPURegister32List(X86CPURegister32List * obj); - -struct X86CPUFeatureWordInfo -{ - int64_t cpuid_input_eax; - bool has_cpuid_input_ecx; - int64_t cpuid_input_ecx; - X86CPURegister32 cpuid_register; - int64_t features; -}; - -void qapi_free_X86CPUFeatureWordInfoList(X86CPUFeatureWordInfoList * obj); -void qapi_free_X86CPUFeatureWordInfo(X86CPUFeatureWordInfo * obj); - -void qapi_free_RxStateList(RxStateList * obj); - -struct RxFilterInfo -{ - char * name; - bool promiscuous; - RxState multicast; - RxState unicast; - bool broadcast_allowed; - bool multicast_overflow; - bool unicast_overflow; - char * main_mac; - intList * vlan_table; - strList * unicast_table; - strList * multicast_table; -}; - -void qapi_free_RxFilterInfoList(RxFilterInfoList * obj); -void qapi_free_RxFilterInfo(RxFilterInfo * obj); - -#endif diff --git a/contrib/qemu/qemu-coroutine-lock.c b/contrib/qemu/qemu-coroutine-lock.c deleted file mode 100644 index d9fea4989d4..00000000000 --- a/contrib/qemu/qemu-coroutine-lock.c +++ /dev/null @@ -1,178 +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-common.h" -#include "block/coroutine.h" -#include "block/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()); -} - -void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue) -{ - Coroutine *self = qemu_coroutine_self(); - QTAILQ_INSERT_HEAD(&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 qemu_co_queue_next(CoQueue *queue) -{ - return qemu_co_queue_do_restart(queue, true); -} - -void qemu_co_queue_restart_all(CoQueue *queue) -{ - qemu_co_queue_do_restart(queue, false); -} - -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/contrib/qemu/qemu-coroutine-sleep.c b/contrib/qemu/qemu-coroutine-sleep.c deleted file mode 100644 index 169ce5ccc92..00000000000 --- a/contrib/qemu/qemu-coroutine-sleep.c +++ /dev/null @@ -1,39 +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 "block/coroutine.h" -#include "qemu/timer.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_sleep_ns(QEMUClock *clock, int64_t ns) -{ - CoSleepCB sleep_cb = { - .co = qemu_coroutine_self(), - }; - sleep_cb.ts = qemu_new_timer(clock, SCALE_NS, co_sleep_cb, &sleep_cb); - qemu_mod_timer(sleep_cb.ts, qemu_get_clock_ns(clock) + ns); - qemu_coroutine_yield(); - qemu_del_timer(sleep_cb.ts); - qemu_free_timer(sleep_cb.ts); -} diff --git a/contrib/qemu/qemu-coroutine.c b/contrib/qemu/qemu-coroutine.c deleted file mode 100644 index 5e19307eeda..00000000000 --- a/contrib/qemu/qemu-coroutine.c +++ /dev/null @@ -1,135 +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 "trace.h" -#include "qemu-common.h" -#include "qemu/thread.h" -#include "block/coroutine.h" -#include "block/coroutine_int.h" - -enum { - /* Maximum free pool size prevents holding too many freed coroutines */ - POOL_MAX_SIZE = 0, -}; - -/** Free list to speed up creation */ -static QemuMutex pool_lock; -static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool); -static unsigned int pool_size; - -Coroutine *qemu_coroutine_create(CoroutineEntry *entry) -{ - Coroutine *co; - - qemu_mutex_lock(&pool_lock); - co = QSLIST_FIRST(&pool); - if (co) { - QSLIST_REMOVE_HEAD(&pool, pool_next); - pool_size--; - } - qemu_mutex_unlock(&pool_lock); - - if (!co) { - co = qemu_coroutine_new(); - } - - co->entry = entry; - QTAILQ_INIT(&co->co_queue_wakeup); - return co; -} - -static void coroutine_delete(Coroutine *co) -{ - qemu_mutex_lock(&pool_lock); - if (pool_size < POOL_MAX_SIZE) { - QSLIST_INSERT_HEAD(&pool, co, pool_next); - co->caller = NULL; - pool_size++; - qemu_mutex_unlock(&pool_lock); - return; - } - qemu_mutex_unlock(&pool_lock); - - qemu_coroutine_delete(co); -} - -static void __attribute__((constructor)) coroutine_pool_init(void) -{ - qemu_mutex_init(&pool_lock); -} - -static void __attribute__((destructor)) coroutine_pool_cleanup(void) -{ - Coroutine *co; - Coroutine *tmp; - - QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) { - QSLIST_REMOVE_HEAD(&pool, pool_next); - qemu_coroutine_delete(co); - } - - qemu_mutex_destroy(&pool_lock); -} - -static void coroutine_swap(Coroutine *from, Coroutine *to) -{ - CoroutineAction ret; - - ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD); - - qemu_co_queue_run_restart(to); - - switch (ret) { - case COROUTINE_YIELD: - return; - case COROUTINE_TERMINATE: - trace_qemu_coroutine_terminate(to); - coroutine_delete(to); - return; - default: - abort(); - } -} - -void qemu_coroutine_enter(Coroutine *co, void *opaque) -{ - Coroutine *self = qemu_coroutine_self(); - - 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; - coroutine_swap(self, co); -} - -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; - coroutine_swap(self, to); -} diff --git a/contrib/qemu/qmp-commands.h b/contrib/qemu/qmp-commands.h deleted file mode 100644 index fcc0ff0f7f0..00000000000 --- a/contrib/qemu/qmp-commands.h +++ /dev/null @@ -1,204 +0,0 @@ -/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ - -/* - * schema-defined QAPI function prototypes - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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. - * - */ - -#ifndef QMP_COMMANDS_H -#define QMP_COMMANDS_H - -#include "qapi-types.h" -#include "qapi/qmp/qdict.h" -#include "qapi/error.h" - -void qmp_add_client(const char * protocol, const char * fdname, bool has_skipauth, bool skipauth, bool has_tls, bool tls, Error **errp); -int qmp_marshal_input_add_client(Monitor *mon, const QDict *qdict, QObject **ret); -NameInfo * qmp_query_name(Error **errp); -int qmp_marshal_input_query_name(Monitor *mon, const QDict *qdict, QObject **ret); -VersionInfo * qmp_query_version(Error **errp); -int qmp_marshal_input_query_version(Monitor *mon, const QDict *qdict, QObject **ret); -KvmInfo * qmp_query_kvm(Error **errp); -int qmp_marshal_input_query_kvm(Monitor *mon, const QDict *qdict, QObject **ret); -StatusInfo * qmp_query_status(Error **errp); -int qmp_marshal_input_query_status(Monitor *mon, const QDict *qdict, QObject **ret); -UuidInfo * qmp_query_uuid(Error **errp); -int qmp_marshal_input_query_uuid(Monitor *mon, const QDict *qdict, QObject **ret); -ChardevInfoList * qmp_query_chardev(Error **errp); -int qmp_marshal_input_query_chardev(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_ringbuf_write(const char * device, const char * data, bool has_format, DataFormat format, Error **errp); -int qmp_marshal_input_ringbuf_write(Monitor *mon, const QDict *qdict, QObject **ret); -char * qmp_ringbuf_read(const char * device, int64_t size, bool has_format, DataFormat format, Error **errp); -int qmp_marshal_input_ringbuf_read(Monitor *mon, const QDict *qdict, QObject **ret); -CommandInfoList * qmp_query_commands(Error **errp); -int qmp_marshal_input_query_commands(Monitor *mon, const QDict *qdict, QObject **ret); -EventInfoList * qmp_query_events(Error **errp); -int qmp_marshal_input_query_events(Monitor *mon, const QDict *qdict, QObject **ret); -MigrationInfo * qmp_query_migrate(Error **errp); -int qmp_marshal_input_query_migrate(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate_set_capabilities(MigrationCapabilityStatusList * capabilities, Error **errp); -int qmp_marshal_input_migrate_set_capabilities(Monitor *mon, const QDict *qdict, QObject **ret); -MigrationCapabilityStatusList * qmp_query_migrate_capabilities(Error **errp); -int qmp_marshal_input_query_migrate_capabilities(Monitor *mon, const QDict *qdict, QObject **ret); -MouseInfoList * qmp_query_mice(Error **errp); -int qmp_marshal_input_query_mice(Monitor *mon, const QDict *qdict, QObject **ret); -CpuInfoList * qmp_query_cpus(Error **errp); -int qmp_marshal_input_query_cpus(Monitor *mon, const QDict *qdict, QObject **ret); -BlockInfoList * qmp_query_block(Error **errp); -int qmp_marshal_input_query_block(Monitor *mon, const QDict *qdict, QObject **ret); -BlockStatsList * qmp_query_blockstats(Error **errp); -int qmp_marshal_input_query_blockstats(Monitor *mon, const QDict *qdict, QObject **ret); -VncInfo * qmp_query_vnc(Error **errp); -int qmp_marshal_input_query_vnc(Monitor *mon, const QDict *qdict, QObject **ret); -SpiceInfo * qmp_query_spice(Error **errp); -int qmp_marshal_input_query_spice(Monitor *mon, const QDict *qdict, QObject **ret); -BalloonInfo * qmp_query_balloon(Error **errp); -int qmp_marshal_input_query_balloon(Monitor *mon, const QDict *qdict, QObject **ret); -PciInfoList * qmp_query_pci(Error **errp); -int qmp_marshal_input_query_pci(Monitor *mon, const QDict *qdict, QObject **ret); -BlockJobInfoList * qmp_query_block_jobs(Error **errp); -int qmp_marshal_input_query_block_jobs(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_quit(Error **errp); -int qmp_marshal_input_quit(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_stop(Error **errp); -int qmp_marshal_input_stop(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_system_reset(Error **errp); -int qmp_marshal_input_system_reset(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_system_powerdown(Error **errp); -int qmp_marshal_input_system_powerdown(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_cpu(int64_t index, Error **errp); -int qmp_marshal_input_cpu(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_cpu_add(int64_t id, Error **errp); -int qmp_marshal_input_cpu_add(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_memsave(int64_t val, int64_t size, const char * filename, bool has_cpu_index, int64_t cpu_index, Error **errp); -int qmp_marshal_input_memsave(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_pmemsave(int64_t val, int64_t size, const char * filename, Error **errp); -int qmp_marshal_input_pmemsave(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_cont(Error **errp); -int qmp_marshal_input_cont(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_system_wakeup(Error **errp); -int qmp_marshal_input_system_wakeup(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_inject_nmi(Error **errp); -int qmp_marshal_input_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_set_link(const char * name, bool up, Error **errp); -int qmp_marshal_input_set_link(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_passwd(const char * device, const char * password, Error **errp); -int qmp_marshal_input_block_passwd(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_balloon(int64_t value, Error **errp); -int qmp_marshal_input_balloon(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_resize(const char * device, int64_t size, Error **errp); -int qmp_marshal_input_block_resize(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_transaction(TransactionActionList * actions, Error **errp); -int qmp_marshal_input_transaction(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_blockdev_snapshot_sync(const char * device, const char * snapshot_file, bool has_format, const char * format, bool has_mode, NewImageMode mode, Error **errp); -int qmp_marshal_input_blockdev_snapshot_sync(Monitor *mon, const QDict *qdict, QObject **ret); -char * qmp_human_monitor_command(const char * command_line, bool has_cpu_index, int64_t cpu_index, Error **errp); -int qmp_marshal_input_human_monitor_command(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_commit(const char * device, bool has_base, const char * base, const char * top, bool has_speed, int64_t speed, Error **errp); -int qmp_marshal_input_block_commit(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_drive_backup(const char * device, const char * target, bool has_format, const char * format, MirrorSyncMode sync, bool has_mode, NewImageMode mode, bool has_speed, int64_t speed, bool has_on_source_error, BlockdevOnError on_source_error, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp); -int qmp_marshal_input_drive_backup(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_drive_mirror(const char * device, const char * target, bool has_format, const char * format, MirrorSyncMode sync, bool has_mode, NewImageMode mode, bool has_speed, int64_t speed, bool has_granularity, uint32_t granularity, bool has_buf_size, int64_t buf_size, bool has_on_source_error, BlockdevOnError on_source_error, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp); -int qmp_marshal_input_drive_mirror(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate_cancel(Error **errp); -int qmp_marshal_input_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate_set_downtime(double value, Error **errp); -int qmp_marshal_input_migrate_set_downtime(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate_set_speed(int64_t value, Error **errp); -int qmp_marshal_input_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate_set_cache_size(int64_t value, Error **errp); -int qmp_marshal_input_migrate_set_cache_size(Monitor *mon, const QDict *qdict, QObject **ret); -int64_t qmp_query_migrate_cache_size(Error **errp); -int qmp_marshal_input_query_migrate_cache_size(Monitor *mon, const QDict *qdict, QObject **ret); -ObjectPropertyInfoList * qmp_qom_list(const char * path, Error **errp); -int qmp_marshal_input_qom_list(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_set_password(const char * protocol, const char * password, bool has_connected, const char * connected, Error **errp); -int qmp_marshal_input_set_password(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_expire_password(const char * protocol, const char * time, Error **errp); -int qmp_marshal_input_expire_password(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_eject(const char * device, bool has_force, bool force, Error **errp); -int qmp_marshal_input_eject(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_change_vnc_password(const char * password, Error **errp); -int qmp_marshal_input_change_vnc_password(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_change(const char * device, const char * target, bool has_arg, const char * arg, Error **errp); -int qmp_marshal_input_change(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_set_io_throttle(const char * device, int64_t bps, int64_t bps_rd, int64_t bps_wr, int64_t iops, int64_t iops_rd, int64_t iops_wr, Error **errp); -int qmp_marshal_input_block_set_io_throttle(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_stream(const char * device, bool has_base, const char * base, bool has_speed, int64_t speed, bool has_on_error, BlockdevOnError on_error, Error **errp); -int qmp_marshal_input_block_stream(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_job_set_speed(const char * device, int64_t speed, Error **errp); -int qmp_marshal_input_block_job_set_speed(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_job_cancel(const char * device, bool has_force, bool force, Error **errp); -int qmp_marshal_input_block_job_cancel(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_job_pause(const char * device, Error **errp); -int qmp_marshal_input_block_job_pause(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_job_resume(const char * device, Error **errp); -int qmp_marshal_input_block_job_resume(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_block_job_complete(const char * device, Error **errp); -int qmp_marshal_input_block_job_complete(Monitor *mon, const QDict *qdict, QObject **ret); -ObjectTypeInfoList * qmp_qom_list_types(bool has_implements, const char * implements, bool has_abstract, bool abstract, Error **errp); -int qmp_marshal_input_qom_list_types(Monitor *mon, const QDict *qdict, QObject **ret); -DevicePropertyInfoList * qmp_device_list_properties(const char * typename, Error **errp); -int qmp_marshal_input_device_list_properties(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_migrate(const char * uri, bool has_blk, bool blk, bool has_inc, bool inc, bool has_detach, bool detach, Error **errp); -int qmp_marshal_input_migrate(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_xen_save_devices_state(const char * filename, Error **errp); -int qmp_marshal_input_xen_save_devices_state(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_xen_set_global_dirty_log(bool enable, Error **errp); -int qmp_marshal_input_xen_set_global_dirty_log(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_device_del(const char * id, Error **errp); -int qmp_marshal_input_device_del(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_dump_guest_memory(bool paging, const char * protocol, bool has_begin, int64_t begin, bool has_length, int64_t length, Error **errp); -int qmp_marshal_input_dump_guest_memory(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_netdev_del(const char * id, Error **errp); -int qmp_marshal_input_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_getfd(const char * fdname, Error **errp); -int qmp_marshal_input_getfd(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_closefd(const char * fdname, Error **errp); -int qmp_marshal_input_closefd(Monitor *mon, const QDict *qdict, QObject **ret); -MachineInfoList * qmp_query_machines(Error **errp); -int qmp_marshal_input_query_machines(Monitor *mon, const QDict *qdict, QObject **ret); -CpuDefinitionInfoList * qmp_query_cpu_definitions(Error **errp); -int qmp_marshal_input_query_cpu_definitions(Monitor *mon, const QDict *qdict, QObject **ret); -AddfdInfo * qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, const char * opaque, Error **errp); -int qmp_marshal_input_add_fd(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp); -int qmp_marshal_input_remove_fd(Monitor *mon, const QDict *qdict, QObject **ret); -FdsetInfoList * qmp_query_fdsets(Error **errp); -int qmp_marshal_input_query_fdsets(Monitor *mon, const QDict *qdict, QObject **ret); -TargetInfo * qmp_query_target(Error **errp); -int qmp_marshal_input_query_target(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_send_key(KeyValueList * keys, bool has_hold_time, int64_t hold_time, Error **errp); -int qmp_marshal_input_send_key(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_screendump(const char * filename, Error **errp); -int qmp_marshal_input_screendump(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_nbd_server_start(SocketAddress * addr, Error **errp); -int qmp_marshal_input_nbd_server_start(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_nbd_server_add(const char * device, bool has_writable, bool writable, Error **errp); -int qmp_marshal_input_nbd_server_add(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_nbd_server_stop(Error **errp); -int qmp_marshal_input_nbd_server_stop(Monitor *mon, const QDict *qdict, QObject **ret); -ChardevReturn * qmp_chardev_add(const char * id, ChardevBackend * backend, Error **errp); -int qmp_marshal_input_chardev_add(Monitor *mon, const QDict *qdict, QObject **ret); -void qmp_chardev_remove(const char * id, Error **errp); -int qmp_marshal_input_chardev_remove(Monitor *mon, const QDict *qdict, QObject **ret); -TpmModelList * qmp_query_tpm_models(Error **errp); -int qmp_marshal_input_query_tpm_models(Monitor *mon, const QDict *qdict, QObject **ret); -TpmTypeList * qmp_query_tpm_types(Error **errp); -int qmp_marshal_input_query_tpm_types(Monitor *mon, const QDict *qdict, QObject **ret); -TPMInfoList * qmp_query_tpm(Error **errp); -int qmp_marshal_input_query_tpm(Monitor *mon, const QDict *qdict, QObject **ret); -CommandLineOptionInfoList * qmp_query_command_line_options(bool has_option, const char * option, Error **errp); -int qmp_marshal_input_query_command_line_options(Monitor *mon, const QDict *qdict, QObject **ret); -RxFilterInfoList * qmp_query_rx_filter(bool has_name, const char * name, Error **errp); -int qmp_marshal_input_query_rx_filter(Monitor *mon, const QDict *qdict, QObject **ret); - -#endif diff --git a/contrib/qemu/qobject/json-lexer.c b/contrib/qemu/qobject/json-lexer.c deleted file mode 100644 index 440df60392b..00000000000 --- a/contrib/qemu/qobject/json-lexer.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * JSON lexer - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 "qapi/qmp/qstring.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qint.h" -#include "qemu-common.h" -#include "qapi/qmp/json-lexer.h" - -#define MAX_TOKEN_SIZE (64ULL << 20) - -/* - * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\" - * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*' - * 0|([1-9][0-9]*(.[0-9]+)?([eE]([-+])?[0-9]+)) - * [{}\[\],:] - * [a-z]+ - * - */ - -enum json_lexer_state { - IN_ERROR = 0, - IN_DQ_UCODE3, - IN_DQ_UCODE2, - IN_DQ_UCODE1, - IN_DQ_UCODE0, - IN_DQ_STRING_ESCAPE, - IN_DQ_STRING, - IN_SQ_UCODE3, - IN_SQ_UCODE2, - IN_SQ_UCODE1, - IN_SQ_UCODE0, - IN_SQ_STRING_ESCAPE, - IN_SQ_STRING, - IN_ZERO, - IN_DIGITS, - IN_DIGIT, - IN_EXP_E, - IN_MANTISSA, - IN_MANTISSA_DIGITS, - IN_NONZERO_NUMBER, - IN_NEG_NONZERO_NUMBER, - IN_KEYWORD, - IN_ESCAPE, - IN_ESCAPE_L, - IN_ESCAPE_LL, - IN_ESCAPE_I, - IN_ESCAPE_I6, - IN_ESCAPE_I64, - IN_WHITESPACE, - IN_START, -}; - -#define TERMINAL(state) [0 ... 0x7F] = (state) - -/* Return whether TERMINAL is a terminal state and the transition to it - from OLD_STATE required lookahead. This happens whenever the table - below uses the TERMINAL macro. */ -#define TERMINAL_NEEDED_LOOKAHEAD(old_state, terminal) \ - (json_lexer[(old_state)][0] == (terminal)) - -static const uint8_t json_lexer[][256] = { - /* double quote string */ - [IN_DQ_UCODE3] = { - ['0' ... '9'] = IN_DQ_STRING, - ['a' ... 'f'] = IN_DQ_STRING, - ['A' ... 'F'] = IN_DQ_STRING, - }, - [IN_DQ_UCODE2] = { - ['0' ... '9'] = IN_DQ_UCODE3, - ['a' ... 'f'] = IN_DQ_UCODE3, - ['A' ... 'F'] = IN_DQ_UCODE3, - }, - [IN_DQ_UCODE1] = { - ['0' ... '9'] = IN_DQ_UCODE2, - ['a' ... 'f'] = IN_DQ_UCODE2, - ['A' ... 'F'] = IN_DQ_UCODE2, - }, - [IN_DQ_UCODE0] = { - ['0' ... '9'] = IN_DQ_UCODE1, - ['a' ... 'f'] = IN_DQ_UCODE1, - ['A' ... 'F'] = IN_DQ_UCODE1, - }, - [IN_DQ_STRING_ESCAPE] = { - ['b'] = IN_DQ_STRING, - ['f'] = IN_DQ_STRING, - ['n'] = IN_DQ_STRING, - ['r'] = IN_DQ_STRING, - ['t'] = IN_DQ_STRING, - ['/'] = IN_DQ_STRING, - ['\\'] = IN_DQ_STRING, - ['\''] = IN_DQ_STRING, - ['\"'] = IN_DQ_STRING, - ['u'] = IN_DQ_UCODE0, - }, - [IN_DQ_STRING] = { - [1 ... 0xBF] = IN_DQ_STRING, - [0xC2 ... 0xF4] = IN_DQ_STRING, - ['\\'] = IN_DQ_STRING_ESCAPE, - ['"'] = JSON_STRING, - }, - - /* single quote string */ - [IN_SQ_UCODE3] = { - ['0' ... '9'] = IN_SQ_STRING, - ['a' ... 'f'] = IN_SQ_STRING, - ['A' ... 'F'] = IN_SQ_STRING, - }, - [IN_SQ_UCODE2] = { - ['0' ... '9'] = IN_SQ_UCODE3, - ['a' ... 'f'] = IN_SQ_UCODE3, - ['A' ... 'F'] = IN_SQ_UCODE3, - }, - [IN_SQ_UCODE1] = { - ['0' ... '9'] = IN_SQ_UCODE2, - ['a' ... 'f'] = IN_SQ_UCODE2, - ['A' ... 'F'] = IN_SQ_UCODE2, - }, - [IN_SQ_UCODE0] = { - ['0' ... '9'] = IN_SQ_UCODE1, - ['a' ... 'f'] = IN_SQ_UCODE1, - ['A' ... 'F'] = IN_SQ_UCODE1, - }, - [IN_SQ_STRING_ESCAPE] = { - ['b'] = IN_SQ_STRING, - ['f'] = IN_SQ_STRING, - ['n'] = IN_SQ_STRING, - ['r'] = IN_SQ_STRING, - ['t'] = IN_SQ_STRING, - ['/'] = IN_DQ_STRING, - ['\\'] = IN_DQ_STRING, - ['\''] = IN_SQ_STRING, - ['\"'] = IN_SQ_STRING, - ['u'] = IN_SQ_UCODE0, - }, - [IN_SQ_STRING] = { - [1 ... 0xBF] = IN_SQ_STRING, - [0xC2 ... 0xF4] = IN_SQ_STRING, - ['\\'] = IN_SQ_STRING_ESCAPE, - ['\''] = JSON_STRING, - }, - - /* Zero */ - [IN_ZERO] = { - TERMINAL(JSON_INTEGER), - ['0' ... '9'] = IN_ERROR, - ['.'] = IN_MANTISSA, - }, - - /* Float */ - [IN_DIGITS] = { - TERMINAL(JSON_FLOAT), - ['0' ... '9'] = IN_DIGITS, - }, - - [IN_DIGIT] = { - ['0' ... '9'] = IN_DIGITS, - }, - - [IN_EXP_E] = { - ['-'] = IN_DIGIT, - ['+'] = IN_DIGIT, - ['0' ... '9'] = IN_DIGITS, - }, - - [IN_MANTISSA_DIGITS] = { - TERMINAL(JSON_FLOAT), - ['0' ... '9'] = IN_MANTISSA_DIGITS, - ['e'] = IN_EXP_E, - ['E'] = IN_EXP_E, - }, - - [IN_MANTISSA] = { - ['0' ... '9'] = IN_MANTISSA_DIGITS, - }, - - /* Number */ - [IN_NONZERO_NUMBER] = { - TERMINAL(JSON_INTEGER), - ['0' ... '9'] = IN_NONZERO_NUMBER, - ['e'] = IN_EXP_E, - ['E'] = IN_EXP_E, - ['.'] = IN_MANTISSA, - }, - - [IN_NEG_NONZERO_NUMBER] = { - ['0'] = IN_ZERO, - ['1' ... '9'] = IN_NONZERO_NUMBER, - }, - - /* keywords */ - [IN_KEYWORD] = { - TERMINAL(JSON_KEYWORD), - ['a' ... 'z'] = IN_KEYWORD, - }, - - /* whitespace */ - [IN_WHITESPACE] = { - TERMINAL(JSON_SKIP), - [' '] = IN_WHITESPACE, - ['\t'] = IN_WHITESPACE, - ['\r'] = IN_WHITESPACE, - ['\n'] = IN_WHITESPACE, - }, - - /* escape */ - [IN_ESCAPE_LL] = { - ['d'] = JSON_ESCAPE, - }, - - [IN_ESCAPE_L] = { - ['d'] = JSON_ESCAPE, - ['l'] = IN_ESCAPE_LL, - }, - - [IN_ESCAPE_I64] = { - ['d'] = JSON_ESCAPE, - }, - - [IN_ESCAPE_I6] = { - ['4'] = IN_ESCAPE_I64, - }, - - [IN_ESCAPE_I] = { - ['6'] = IN_ESCAPE_I6, - }, - - [IN_ESCAPE] = { - ['d'] = JSON_ESCAPE, - ['i'] = JSON_ESCAPE, - ['p'] = JSON_ESCAPE, - ['s'] = JSON_ESCAPE, - ['f'] = JSON_ESCAPE, - ['l'] = IN_ESCAPE_L, - ['I'] = IN_ESCAPE_I, - }, - - /* top level rule */ - [IN_START] = { - ['"'] = IN_DQ_STRING, - ['\''] = IN_SQ_STRING, - ['0'] = IN_ZERO, - ['1' ... '9'] = IN_NONZERO_NUMBER, - ['-'] = IN_NEG_NONZERO_NUMBER, - ['{'] = JSON_OPERATOR, - ['}'] = JSON_OPERATOR, - ['['] = JSON_OPERATOR, - [']'] = JSON_OPERATOR, - [','] = JSON_OPERATOR, - [':'] = JSON_OPERATOR, - ['a' ... 'z'] = IN_KEYWORD, - ['%'] = IN_ESCAPE, - [' '] = IN_WHITESPACE, - ['\t'] = IN_WHITESPACE, - ['\r'] = IN_WHITESPACE, - ['\n'] = IN_WHITESPACE, - }, -}; - -void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func) -{ - lexer->emit = func; - lexer->state = IN_START; - lexer->token = qstring_new(); - lexer->x = lexer->y = 0; -} - -static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) -{ - int char_consumed, new_state; - - lexer->x++; - if (ch == '\n') { - lexer->x = 0; - lexer->y++; - } - - do { - new_state = json_lexer[lexer->state][(uint8_t)ch]; - char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state); - if (char_consumed) { - qstring_append_chr(lexer->token, ch); - } - - switch (new_state) { - case JSON_OPERATOR: - case JSON_ESCAPE: - case JSON_INTEGER: - case JSON_FLOAT: - case JSON_KEYWORD: - case JSON_STRING: - lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y); - /* fall through */ - case JSON_SKIP: - QDECREF(lexer->token); - lexer->token = qstring_new(); - new_state = IN_START; - break; - case IN_ERROR: - /* XXX: To avoid having previous bad input leaving the parser in an - * unresponsive state where we consume unpredictable amounts of - * subsequent "good" input, percolate this error state up to the - * tokenizer/parser by forcing a NULL object to be emitted, then - * reset state. - * - * Also note that this handling is required for reliable channel - * negotiation between QMP and the guest agent, since chr(0xFF) - * is placed at the beginning of certain events to ensure proper - * delivery when the channel is in an unknown state. chr(0xFF) is - * never a valid ASCII/UTF-8 sequence, so this should reliably - * induce an error/flush state. - */ - lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y); - QDECREF(lexer->token); - lexer->token = qstring_new(); - new_state = IN_START; - lexer->state = new_state; - return 0; - default: - break; - } - lexer->state = new_state; - } while (!char_consumed && !flush); - - /* Do not let a single token grow to an arbitrarily large size, - * this is a security consideration. - */ - if (lexer->token->length > MAX_TOKEN_SIZE) { - lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y); - QDECREF(lexer->token); - lexer->token = qstring_new(); - lexer->state = IN_START; - } - - return 0; -} - -int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) -{ - size_t i; - - for (i = 0; i < size; i++) { - int err; - - err = json_lexer_feed_char(lexer, buffer[i], false); - if (err < 0) { - return err; - } - } - - return 0; -} - -int json_lexer_flush(JSONLexer *lexer) -{ - return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true); -} - -void json_lexer_destroy(JSONLexer *lexer) -{ - QDECREF(lexer->token); -} diff --git a/contrib/qemu/qobject/json-parser.c b/contrib/qemu/qobject/json-parser.c deleted file mode 100644 index e7947b340c1..00000000000 --- a/contrib/qemu/qobject/json-parser.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - * JSON Parser - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 <stdarg.h> - -#include "qemu-common.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qint.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qfloat.h" -#include "qapi/qmp/qbool.h" -#include "qapi/qmp/json-parser.h" -#include "qapi/qmp/json-lexer.h" -#include "qapi/qmp/qerror.h" - -typedef struct JSONParserContext -{ - Error *err; - struct { - QObject **buf; - size_t pos; - size_t count; - } tokens; -} JSONParserContext; - -#define BUG_ON(cond) assert(!(cond)) - -/** - * TODO - * - * 0) make errors meaningful again - * 1) add geometry information to tokens - * 3) should we return a parsed size? - * 4) deal with premature EOI - */ - -static QObject *parse_value(JSONParserContext *ctxt, va_list *ap); - -/** - * Token manipulators - * - * tokens are dictionaries that contain a type, a string value, and geometry information - * about a token identified by the lexer. These are routines that make working with - * these objects a bit easier. - */ -static const char *token_get_value(QObject *obj) -{ - return qdict_get_str(qobject_to_qdict(obj), "token"); -} - -static JSONTokenType token_get_type(QObject *obj) -{ - return qdict_get_int(qobject_to_qdict(obj), "type"); -} - -static int token_is_operator(QObject *obj, char op) -{ - const char *val; - - if (token_get_type(obj) != JSON_OPERATOR) { - return 0; - } - - val = token_get_value(obj); - - return (val[0] == op) && (val[1] == 0); -} - -static int token_is_keyword(QObject *obj, const char *value) -{ - if (token_get_type(obj) != JSON_KEYWORD) { - return 0; - } - - return strcmp(token_get_value(obj), value) == 0; -} - -static int token_is_escape(QObject *obj, const char *value) -{ - if (token_get_type(obj) != JSON_ESCAPE) { - return 0; - } - - return (strcmp(token_get_value(obj), value) == 0); -} - -/** - * Error handler - */ -static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt, - QObject *token, const char *msg, ...) -{ - va_list ap; - char message[1024]; - va_start(ap, msg); - vsnprintf(message, sizeof(message), msg, ap); - va_end(ap); - if (ctxt->err) { - error_free(ctxt->err); - ctxt->err = NULL; - } - error_set(&ctxt->err, QERR_JSON_PARSE_ERROR, message); -} - -/** - * String helpers - * - * These helpers are used to unescape strings. - */ -static void wchar_to_utf8(uint16_t wchar, char *buffer, size_t buffer_length) -{ - if (wchar <= 0x007F) { - BUG_ON(buffer_length < 2); - - buffer[0] = wchar & 0x7F; - buffer[1] = 0; - } else if (wchar <= 0x07FF) { - BUG_ON(buffer_length < 3); - - buffer[0] = 0xC0 | ((wchar >> 6) & 0x1F); - buffer[1] = 0x80 | (wchar & 0x3F); - buffer[2] = 0; - } else { - BUG_ON(buffer_length < 4); - - buffer[0] = 0xE0 | ((wchar >> 12) & 0x0F); - buffer[1] = 0x80 | ((wchar >> 6) & 0x3F); - buffer[2] = 0x80 | (wchar & 0x3F); - buffer[3] = 0; - } -} - -static int hex2decimal(char ch) -{ - if (ch >= '0' && ch <= '9') { - return (ch - '0'); - } else if (ch >= 'a' && ch <= 'f') { - return 10 + (ch - 'a'); - } else if (ch >= 'A' && ch <= 'F') { - return 10 + (ch - 'A'); - } - - return -1; -} - -/** - * parse_string(): Parse a json string and return a QObject - * - * string - * "" - * " chars " - * chars - * char - * char chars - * char - * any-Unicode-character- - * except-"-or-\-or- - * control-character - * \" - * \\ - * \/ - * \b - * \f - * \n - * \r - * \t - * \u four-hex-digits - */ -static QString *qstring_from_escaped_str(JSONParserContext *ctxt, QObject *token) -{ - const char *ptr = token_get_value(token); - QString *str; - int double_quote = 1; - - if (*ptr == '"') { - double_quote = 1; - } else { - double_quote = 0; - } - ptr++; - - str = qstring_new(); - while (*ptr && - ((double_quote && *ptr != '"') || (!double_quote && *ptr != '\''))) { - if (*ptr == '\\') { - ptr++; - - switch (*ptr) { - case '"': - qstring_append(str, "\""); - ptr++; - break; - case '\'': - qstring_append(str, "'"); - ptr++; - break; - case '\\': - qstring_append(str, "\\"); - ptr++; - break; - case '/': - qstring_append(str, "/"); - ptr++; - break; - case 'b': - qstring_append(str, "\b"); - ptr++; - break; - case 'f': - qstring_append(str, "\f"); - ptr++; - break; - case 'n': - qstring_append(str, "\n"); - ptr++; - break; - case 'r': - qstring_append(str, "\r"); - ptr++; - break; - case 't': - qstring_append(str, "\t"); - ptr++; - break; - case 'u': { - uint16_t unicode_char = 0; - char utf8_char[4]; - int i = 0; - - ptr++; - - for (i = 0; i < 4; i++) { - if (qemu_isxdigit(*ptr)) { - unicode_char |= hex2decimal(*ptr) << ((3 - i) * 4); - } else { - parse_error(ctxt, token, - "invalid hex escape sequence in string"); - goto out; - } - ptr++; - } - - wchar_to_utf8(unicode_char, utf8_char, sizeof(utf8_char)); - qstring_append(str, utf8_char); - } break; - default: - parse_error(ctxt, token, "invalid escape sequence in string"); - goto out; - } - } else { - char dummy[2]; - - dummy[0] = *ptr++; - dummy[1] = 0; - - qstring_append(str, dummy); - } - } - - return str; - -out: - QDECREF(str); - return NULL; -} - -static QObject *parser_context_pop_token(JSONParserContext *ctxt) -{ - QObject *token; - g_assert(ctxt->tokens.pos < ctxt->tokens.count); - token = ctxt->tokens.buf[ctxt->tokens.pos]; - ctxt->tokens.pos++; - return token; -} - -/* Note: parser_context_{peek|pop}_token do not increment the - * token object's refcount. In both cases the references will continue - * to be tracked and cleaned up in parser_context_free(), so do not - * attempt to free the token object. - */ -static QObject *parser_context_peek_token(JSONParserContext *ctxt) -{ - QObject *token; - g_assert(ctxt->tokens.pos < ctxt->tokens.count); - token = ctxt->tokens.buf[ctxt->tokens.pos]; - return token; -} - -static JSONParserContext parser_context_save(JSONParserContext *ctxt) -{ - JSONParserContext saved_ctxt = {0}; - saved_ctxt.tokens.pos = ctxt->tokens.pos; - saved_ctxt.tokens.count = ctxt->tokens.count; - saved_ctxt.tokens.buf = ctxt->tokens.buf; - return saved_ctxt; -} - -static void parser_context_restore(JSONParserContext *ctxt, - JSONParserContext saved_ctxt) -{ - ctxt->tokens.pos = saved_ctxt.tokens.pos; - ctxt->tokens.count = saved_ctxt.tokens.count; - ctxt->tokens.buf = saved_ctxt.tokens.buf; -} - -static void tokens_append_from_iter(QObject *obj, void *opaque) -{ - JSONParserContext *ctxt = opaque; - g_assert(ctxt->tokens.pos < ctxt->tokens.count); - ctxt->tokens.buf[ctxt->tokens.pos++] = obj; - qobject_incref(obj); -} - -static JSONParserContext *parser_context_new(QList *tokens) -{ - JSONParserContext *ctxt; - size_t count; - - if (!tokens) { - return NULL; - } - - count = qlist_size(tokens); - if (count == 0) { - return NULL; - } - - ctxt = g_malloc0(sizeof(JSONParserContext)); - ctxt->tokens.pos = 0; - ctxt->tokens.count = count; - ctxt->tokens.buf = g_malloc(count * sizeof(QObject *)); - qlist_iter(tokens, tokens_append_from_iter, ctxt); - ctxt->tokens.pos = 0; - - return ctxt; -} - -/* to support error propagation, ctxt->err must be freed separately */ -static void parser_context_free(JSONParserContext *ctxt) -{ - int i; - if (ctxt) { - for (i = 0; i < ctxt->tokens.count; i++) { - qobject_decref(ctxt->tokens.buf[i]); - } - g_free(ctxt->tokens.buf); - g_free(ctxt); - } -} - -/** - * Parsing rules - */ -static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap) -{ - QObject *key = NULL, *token = NULL, *value, *peek; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - peek = parser_context_peek_token(ctxt); - if (peek == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - key = parse_value(ctxt, ap); - if (!key || qobject_type(key) != QTYPE_QSTRING) { - parse_error(ctxt, peek, "key is not a string in object"); - goto out; - } - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - if (!token_is_operator(token, ':')) { - parse_error(ctxt, token, "missing : in object pair"); - goto out; - } - - value = parse_value(ctxt, ap); - if (value == NULL) { - parse_error(ctxt, token, "Missing value in dict"); - goto out; - } - - qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value); - - qobject_decref(key); - - return 0; - -out: - parser_context_restore(ctxt, saved_ctxt); - qobject_decref(key); - - return -1; -} - -static QObject *parse_object(JSONParserContext *ctxt, va_list *ap) -{ - QDict *dict = NULL; - QObject *token, *peek; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - goto out; - } - - if (!token_is_operator(token, '{')) { - goto out; - } - token = NULL; - - dict = qdict_new(); - - peek = parser_context_peek_token(ctxt); - if (peek == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - if (!token_is_operator(peek, '}')) { - if (parse_pair(ctxt, dict, ap) == -1) { - goto out; - } - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - while (!token_is_operator(token, '}')) { - if (!token_is_operator(token, ',')) { - parse_error(ctxt, token, "expected separator in dict"); - goto out; - } - token = NULL; - - if (parse_pair(ctxt, dict, ap) == -1) { - goto out; - } - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - } - token = NULL; - } else { - token = parser_context_pop_token(ctxt); - token = NULL; - } - - return QOBJECT(dict); - -out: - parser_context_restore(ctxt, saved_ctxt); - QDECREF(dict); - return NULL; -} - -static QObject *parse_array(JSONParserContext *ctxt, va_list *ap) -{ - QList *list = NULL; - QObject *token, *peek; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - goto out; - } - - if (!token_is_operator(token, '[')) { - token = NULL; - goto out; - } - token = NULL; - - list = qlist_new(); - - peek = parser_context_peek_token(ctxt); - if (peek == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - if (!token_is_operator(peek, ']')) { - QObject *obj; - - obj = parse_value(ctxt, ap); - if (obj == NULL) { - parse_error(ctxt, token, "expecting value"); - goto out; - } - - qlist_append_obj(list, obj); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - - while (!token_is_operator(token, ']')) { - if (!token_is_operator(token, ',')) { - parse_error(ctxt, token, "expected separator in list"); - goto out; - } - - token = NULL; - - obj = parse_value(ctxt, ap); - if (obj == NULL) { - parse_error(ctxt, token, "expecting value"); - goto out; - } - - qlist_append_obj(list, obj); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - parse_error(ctxt, NULL, "premature EOI"); - goto out; - } - } - - token = NULL; - } else { - token = parser_context_pop_token(ctxt); - token = NULL; - } - - return QOBJECT(list); - -out: - parser_context_restore(ctxt, saved_ctxt); - QDECREF(list); - return NULL; -} - -static QObject *parse_keyword(JSONParserContext *ctxt) -{ - QObject *token, *ret; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - goto out; - } - - if (token_get_type(token) != JSON_KEYWORD) { - goto out; - } - - if (token_is_keyword(token, "true")) { - ret = QOBJECT(qbool_from_int(true)); - } else if (token_is_keyword(token, "false")) { - ret = QOBJECT(qbool_from_int(false)); - } else { - parse_error(ctxt, token, "invalid keyword `%s'", token_get_value(token)); - goto out; - } - - return ret; - -out: - parser_context_restore(ctxt, saved_ctxt); - - return NULL; -} - -static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap) -{ - QObject *token = NULL, *obj; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - if (ap == NULL) { - goto out; - } - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - goto out; - } - - if (token_is_escape(token, "%p")) { - obj = va_arg(*ap, QObject *); - } else if (token_is_escape(token, "%i")) { - obj = QOBJECT(qbool_from_int(va_arg(*ap, int))); - } else if (token_is_escape(token, "%d")) { - obj = QOBJECT(qint_from_int(va_arg(*ap, int))); - } else if (token_is_escape(token, "%ld")) { - obj = QOBJECT(qint_from_int(va_arg(*ap, long))); - } else if (token_is_escape(token, "%lld") || - token_is_escape(token, "%I64d")) { - obj = QOBJECT(qint_from_int(va_arg(*ap, long long))); - } else if (token_is_escape(token, "%s")) { - obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *))); - } else if (token_is_escape(token, "%f")) { - obj = QOBJECT(qfloat_from_double(va_arg(*ap, double))); - } else { - goto out; - } - - return obj; - -out: - parser_context_restore(ctxt, saved_ctxt); - - return NULL; -} - -static QObject *parse_literal(JSONParserContext *ctxt) -{ - QObject *token, *obj; - JSONParserContext saved_ctxt = parser_context_save(ctxt); - - token = parser_context_pop_token(ctxt); - if (token == NULL) { - goto out; - } - - switch (token_get_type(token)) { - case JSON_STRING: - obj = QOBJECT(qstring_from_escaped_str(ctxt, token)); - break; - case JSON_INTEGER: { - /* A possibility exists that this is a whole-valued float where the - * fractional part was left out due to being 0 (.0). It's not a big - * deal to treat these as ints in the parser, so long as users of the - * resulting QObject know to expect a QInt in place of a QFloat in - * cases like these. - * - * However, in some cases these values will overflow/underflow a - * QInt/int64 container, thus we should assume these are to be handled - * as QFloats/doubles rather than silently changing their values. - * - * strtoll() indicates these instances by setting errno to ERANGE - */ - int64_t value; - - errno = 0; /* strtoll doesn't set errno on success */ - value = strtoll(token_get_value(token), NULL, 10); - if (errno != ERANGE) { - obj = QOBJECT(qint_from_int(value)); - break; - } - /* fall through to JSON_FLOAT */ - } - case JSON_FLOAT: - /* FIXME dependent on locale */ - obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL))); - break; - default: - goto out; - } - - return obj; - -out: - parser_context_restore(ctxt, saved_ctxt); - - return NULL; -} - -static QObject *parse_value(JSONParserContext *ctxt, va_list *ap) -{ - QObject *obj; - - obj = parse_object(ctxt, ap); - if (obj == NULL) { - obj = parse_array(ctxt, ap); - } - if (obj == NULL) { - obj = parse_escape(ctxt, ap); - } - if (obj == NULL) { - obj = parse_keyword(ctxt); - } - if (obj == NULL) { - obj = parse_literal(ctxt); - } - - return obj; -} - -QObject *json_parser_parse(QList *tokens, va_list *ap) -{ - return json_parser_parse_err(tokens, ap, NULL); -} - -QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp) -{ - JSONParserContext *ctxt = parser_context_new(tokens); - QObject *result; - - if (!ctxt) { - return NULL; - } - - result = parse_value(ctxt, ap); - - error_propagate(errp, ctxt->err); - - parser_context_free(ctxt); - - return result; -} diff --git a/contrib/qemu/qobject/json-streamer.c b/contrib/qemu/qobject/json-streamer.c deleted file mode 100644 index 1b2f9b1d107..00000000000 --- a/contrib/qemu/qobject/json-streamer.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * JSON streaming support - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 "qapi/qmp/qlist.h" -#include "qapi/qmp/qint.h" -#include "qapi/qmp/qdict.h" -#include "qemu-common.h" -#include "qapi/qmp/json-lexer.h" -#include "qapi/qmp/json-streamer.h" - -#define MAX_TOKEN_SIZE (64ULL << 20) -#define MAX_NESTING (1ULL << 10) - -static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y) -{ - JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer); - QDict *dict; - - if (type == JSON_OPERATOR) { - switch (qstring_get_str(token)[0]) { - case '{': - parser->brace_count++; - break; - case '}': - parser->brace_count--; - break; - case '[': - parser->bracket_count++; - break; - case ']': - parser->bracket_count--; - break; - default: - break; - } - } - - dict = qdict_new(); - qdict_put(dict, "type", qint_from_int(type)); - QINCREF(token); - qdict_put(dict, "token", token); - qdict_put(dict, "x", qint_from_int(x)); - qdict_put(dict, "y", qint_from_int(y)); - - parser->token_size += token->length; - - qlist_append(parser->tokens, dict); - - if (type == JSON_ERROR) { - goto out_emit_bad; - } else if (parser->brace_count < 0 || - parser->bracket_count < 0 || - (parser->brace_count == 0 && - parser->bracket_count == 0)) { - goto out_emit; - } else if (parser->token_size > MAX_TOKEN_SIZE || - parser->bracket_count > MAX_NESTING || - parser->brace_count > MAX_NESTING) { - /* Security consideration, we limit total memory allocated per object - * and the maximum recursion depth that a message can force. - */ - goto out_emit; - } - - return; - -out_emit_bad: - /* clear out token list and tell the parser to emit and error - * indication by passing it a NULL list - */ - QDECREF(parser->tokens); - parser->tokens = NULL; -out_emit: - /* send current list of tokens to parser and reset tokenizer */ - parser->brace_count = 0; - parser->bracket_count = 0; - parser->emit(parser, parser->tokens); - if (parser->tokens) { - QDECREF(parser->tokens); - } - parser->tokens = qlist_new(); - parser->token_size = 0; -} - -void json_message_parser_init(JSONMessageParser *parser, - void (*func)(JSONMessageParser *, QList *)) -{ - parser->emit = func; - parser->brace_count = 0; - parser->bracket_count = 0; - parser->tokens = qlist_new(); - parser->token_size = 0; - - json_lexer_init(&parser->lexer, json_message_process_token); -} - -int json_message_parser_feed(JSONMessageParser *parser, - const char *buffer, size_t size) -{ - return json_lexer_feed(&parser->lexer, buffer, size); -} - -int json_message_parser_flush(JSONMessageParser *parser) -{ - return json_lexer_flush(&parser->lexer); -} - -void json_message_parser_destroy(JSONMessageParser *parser) -{ - json_lexer_destroy(&parser->lexer); - QDECREF(parser->tokens); -} diff --git a/contrib/qemu/qobject/qbool.c b/contrib/qemu/qobject/qbool.c deleted file mode 100644 index a3d2afa827f..00000000000 --- a/contrib/qemu/qobject/qbool.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * QBool Module - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 "qapi/qmp/qbool.h" -#include "qapi/qmp/qobject.h" -#include "qemu-common.h" - -static void qbool_destroy_obj(QObject *obj); - -static const QType qbool_type = { - .code = QTYPE_QBOOL, - .destroy = qbool_destroy_obj, -}; - -/** - * qbool_from_int(): Create a new QBool from an int - * - * Return strong reference. - */ -QBool *qbool_from_int(int value) -{ - QBool *qb; - - qb = g_malloc(sizeof(*qb)); - qb->value = value; - QOBJECT_INIT(qb, &qbool_type); - - return qb; -} - -/** - * qbool_get_int(): Get the stored int - */ -int qbool_get_int(const QBool *qb) -{ - return qb->value; -} - -/** - * qobject_to_qbool(): Convert a QObject into a QBool - */ -QBool *qobject_to_qbool(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QBOOL) - return NULL; - - return container_of(obj, QBool, base); -} - -/** - * qbool_destroy_obj(): Free all memory allocated by a - * QBool object - */ -static void qbool_destroy_obj(QObject *obj) -{ - assert(obj != NULL); - g_free(qobject_to_qbool(obj)); -} diff --git a/contrib/qemu/qobject/qdict.c b/contrib/qemu/qobject/qdict.c deleted file mode 100644 index ed381f9a507..00000000000 --- a/contrib/qemu/qobject/qdict.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * QDict Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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 "qapi/qmp/qint.h" -#include "qapi/qmp/qfloat.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qbool.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qobject.h" -#include "qemu/queue.h" -#include "qemu-common.h" - -static void qdict_destroy_obj(QObject *obj); - -static const QType qdict_type = { - .code = QTYPE_QDICT, - .destroy = qdict_destroy_obj, -}; - -/** - * qdict_new(): Create a new QDict - * - * Return strong reference. - */ -QDict *qdict_new(void) -{ - QDict *qdict; - - qdict = g_malloc0(sizeof(*qdict)); - QOBJECT_INIT(qdict, &qdict_type); - - return qdict; -} - -/** - * qobject_to_qdict(): Convert a QObject into a QDict - */ -QDict *qobject_to_qdict(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QDICT) - return NULL; - - return container_of(obj, QDict, base); -} - -/** - * tdb_hash(): based on the hash agorithm from gdbm, via tdb - * (from module-init-tools) - */ -static unsigned int tdb_hash(const char *name) -{ - unsigned value; /* Used to compute the hash value. */ - unsigned i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) - value = (value + (((const unsigned char *)name)[i] << (i*5 % 24))); - - return (1103515243 * value + 12345); -} - -/** - * alloc_entry(): allocate a new QDictEntry - */ -static QDictEntry *alloc_entry(const char *key, QObject *value) -{ - QDictEntry *entry; - - entry = g_malloc0(sizeof(*entry)); - entry->key = g_strdup(key); - entry->value = value; - - return entry; -} - -/** - * qdict_entry_value(): Return qdict entry value - * - * Return weak reference. - */ -QObject *qdict_entry_value(const QDictEntry *entry) -{ - return entry->value; -} - -/** - * qdict_entry_key(): Return qdict entry key - * - * Return a *pointer* to the string, it has to be duplicated before being - * stored. - */ -const char *qdict_entry_key(const QDictEntry *entry) -{ - return entry->key; -} - -/** - * qdict_find(): List lookup function - */ -static QDictEntry *qdict_find(const QDict *qdict, - const char *key, unsigned int bucket) -{ - QDictEntry *entry; - - QLIST_FOREACH(entry, &qdict->table[bucket], next) - if (!strcmp(entry->key, key)) - return entry; - - return NULL; -} - -/** - * qdict_put_obj(): Put a new QObject into the dictionary - * - * Insert the pair 'key:value' into 'qdict', if 'key' already exists - * its 'value' will be replaced. - * - * This is done by freeing the reference to the stored QObject and - * storing the new one in the same entry. - * - * NOTE: ownership of 'value' is transferred to the QDict - */ -void qdict_put_obj(QDict *qdict, const char *key, QObject *value) -{ - unsigned int bucket; - QDictEntry *entry; - - bucket = tdb_hash(key) % QDICT_BUCKET_MAX; - entry = qdict_find(qdict, key, bucket); - if (entry) { - /* replace key's value */ - qobject_decref(entry->value); - entry->value = value; - } else { - /* allocate a new entry */ - entry = alloc_entry(key, value); - QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next); - qdict->size++; - } -} - -/** - * qdict_get(): Lookup for a given 'key' - * - * Return a weak reference to the QObject associated with 'key' if - * 'key' is present in the dictionary, NULL otherwise. - */ -QObject *qdict_get(const QDict *qdict, const char *key) -{ - QDictEntry *entry; - - entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); - return (entry == NULL ? NULL : entry->value); -} - -/** - * qdict_haskey(): Check if 'key' exists - * - * Return 1 if 'key' exists in the dict, 0 otherwise - */ -int qdict_haskey(const QDict *qdict, const char *key) -{ - unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX; - return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1); -} - -/** - * qdict_size(): Return the size of the dictionary - */ -size_t qdict_size(const QDict *qdict) -{ - return qdict->size; -} - -/** - * qdict_get_obj(): Get a QObject of a specific type - */ -static QObject *qdict_get_obj(const QDict *qdict, const char *key, - qtype_code type) -{ - QObject *obj; - - obj = qdict_get(qdict, key); - assert(obj != NULL); - assert(qobject_type(obj) == type); - - return obj; -} - -/** - * qdict_get_double(): Get an number mapped by 'key' - * - * This function assumes that 'key' exists and it stores a - * QFloat or QInt object. - * - * Return number mapped by 'key'. - */ -double qdict_get_double(const QDict *qdict, const char *key) -{ - QObject *obj = qdict_get(qdict, key); - - assert(obj); - switch (qobject_type(obj)) { - case QTYPE_QFLOAT: - return qfloat_get_double(qobject_to_qfloat(obj)); - case QTYPE_QINT: - return qint_get_int(qobject_to_qint(obj)); - default: - abort(); - } -} - -/** - * qdict_get_int(): Get an integer mapped by 'key' - * - * This function assumes that 'key' exists and it stores a - * QInt object. - * - * Return integer mapped by 'key'. - */ -int64_t qdict_get_int(const QDict *qdict, const char *key) -{ - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT); - return qint_get_int(qobject_to_qint(obj)); -} - -/** - * qdict_get_bool(): Get a bool mapped by 'key' - * - * This function assumes that 'key' exists and it stores a - * QBool object. - * - * Return bool mapped by 'key'. - */ -int qdict_get_bool(const QDict *qdict, const char *key) -{ - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL); - return qbool_get_int(qobject_to_qbool(obj)); -} - -/** - * qdict_get_qlist(): Get the QList mapped by 'key' - * - * This function assumes that 'key' exists and it stores a - * QList object. - * - * Return QList mapped by 'key'. - */ -QList *qdict_get_qlist(const QDict *qdict, const char *key) -{ - return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST)); -} - -/** - * qdict_get_qdict(): Get the QDict mapped by 'key' - * - * This function assumes that 'key' exists and it stores a - * QDict object. - * - * Return QDict mapped by 'key'. - */ -QDict *qdict_get_qdict(const QDict *qdict, const char *key) -{ - return qobject_to_qdict(qdict_get_obj(qdict, key, QTYPE_QDICT)); -} - -/** - * qdict_get_str(): Get a pointer to the stored string mapped - * by 'key' - * - * This function assumes that 'key' exists and it stores a - * QString object. - * - * Return pointer to the string mapped by 'key'. - */ -const char *qdict_get_str(const QDict *qdict, const char *key) -{ - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QSTRING); - return qstring_get_str(qobject_to_qstring(obj)); -} - -/** - * qdict_get_try_int(): Try to get integer mapped by 'key' - * - * Return integer mapped by 'key', if it is not present in - * the dictionary or if the stored object is not of QInt type - * 'def_value' will be returned. - */ -int64_t qdict_get_try_int(const QDict *qdict, const char *key, - int64_t def_value) -{ - QObject *obj; - - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QINT) - return def_value; - - return qint_get_int(qobject_to_qint(obj)); -} - -/** - * qdict_get_try_bool(): Try to get a bool mapped by 'key' - * - * Return bool mapped by 'key', if it is not present in the - * dictionary or if the stored object is not of QBool type - * 'def_value' will be returned. - */ -int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value) -{ - QObject *obj; - - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QBOOL) - return def_value; - - return qbool_get_int(qobject_to_qbool(obj)); -} - -/** - * qdict_get_try_str(): Try to get a pointer to the stored string - * mapped by 'key' - * - * Return a pointer to the string mapped by 'key', if it is not present - * in the dictionary or if the stored object is not of QString type - * NULL will be returned. - */ -const char *qdict_get_try_str(const QDict *qdict, const char *key) -{ - QObject *obj; - - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QSTRING) - return NULL; - - return qstring_get_str(qobject_to_qstring(obj)); -} - -/** - * qdict_iter(): Iterate over all the dictionary's stored values. - * - * This function allows the user to provide an iterator, which will be - * called for each stored value in the dictionary. - */ -void qdict_iter(const QDict *qdict, - void (*iter)(const char *key, QObject *obj, void *opaque), - void *opaque) -{ - int i; - QDictEntry *entry; - - for (i = 0; i < QDICT_BUCKET_MAX; i++) { - QLIST_FOREACH(entry, &qdict->table[i], next) - iter(entry->key, entry->value, opaque); - } -} - -static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket) -{ - int i; - - for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) { - if (!QLIST_EMPTY(&qdict->table[i])) { - return QLIST_FIRST(&qdict->table[i]); - } - } - - return NULL; -} - -/** - * qdict_first(): Return first qdict entry for iteration. - */ -const QDictEntry *qdict_first(const QDict *qdict) -{ - return qdict_next_entry(qdict, 0); -} - -/** - * qdict_next(): Return next qdict entry in an iteration. - */ -const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry) -{ - QDictEntry *ret; - - ret = QLIST_NEXT(entry, next); - if (!ret) { - unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX; - ret = qdict_next_entry(qdict, bucket + 1); - } - - return ret; -} - -/** - * qdict_clone_shallow(): Clones a given QDict. Its entries are not copied, but - * another reference is added. - */ -QDict *qdict_clone_shallow(const QDict *src) -{ - QDict *dest; - QDictEntry *entry; - int i; - - dest = qdict_new(); - - for (i = 0; i < QDICT_BUCKET_MAX; i++) { - QLIST_FOREACH(entry, &src->table[i], next) { - qobject_incref(entry->value); - qdict_put_obj(dest, entry->key, entry->value); - } - } - - return dest; -} - -/** - * qentry_destroy(): Free all the memory allocated by a QDictEntry - */ -static void qentry_destroy(QDictEntry *e) -{ - assert(e != NULL); - assert(e->key != NULL); - assert(e->value != NULL); - - qobject_decref(e->value); - g_free(e->key); - g_free(e); -} - -/** - * qdict_del(): Delete a 'key:value' pair from the dictionary - * - * This will destroy all data allocated by this entry. - */ -void qdict_del(QDict *qdict, const char *key) -{ - QDictEntry *entry; - - entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX); - if (entry) { - QLIST_REMOVE(entry, next); - qentry_destroy(entry); - qdict->size--; - } -} - -/** - * qdict_destroy_obj(): Free all the memory allocated by a QDict - */ -static void qdict_destroy_obj(QObject *obj) -{ - int i; - QDict *qdict; - - assert(obj != NULL); - qdict = qobject_to_qdict(obj); - - for (i = 0; i < QDICT_BUCKET_MAX; i++) { - QDictEntry *entry = QLIST_FIRST(&qdict->table[i]); - while (entry) { - QDictEntry *tmp = QLIST_NEXT(entry, next); - QLIST_REMOVE(entry, next); - qentry_destroy(entry); - entry = tmp; - } - } - - g_free(qdict); -} diff --git a/contrib/qemu/qobject/qerror.c b/contrib/qemu/qobject/qerror.c deleted file mode 100644 index 3aee1cf6a69..00000000000 --- a/contrib/qemu/qobject/qerror.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * QError Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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 "monitor/monitor.h" -#include "qapi/qmp/qjson.h" -#include "qapi/qmp/qerror.h" -#include "qemu-common.h" - -static void qerror_destroy_obj(QObject *obj); - -static const QType qerror_type = { - .code = QTYPE_QERROR, - .destroy = qerror_destroy_obj, -}; - -/** - * qerror_new(): Create a new QError - * - * Return strong reference. - */ -static QError *qerror_new(void) -{ - QError *qerr; - - qerr = g_malloc0(sizeof(*qerr)); - QOBJECT_INIT(qerr, &qerror_type); - - return qerr; -} - -/** - * qerror_from_info(): Create a new QError from error information - * - * Return strong reference. - */ -static QError *qerror_from_info(ErrorClass err_class, const char *fmt, - va_list *va) -{ - QError *qerr; - - qerr = qerror_new(); - loc_save(&qerr->loc); - - qerr->err_msg = g_strdup_vprintf(fmt, *va); - qerr->err_class = err_class; - - return qerr; -} - -/** - * qerror_human(): Format QError data into human-readable string. - */ -QString *qerror_human(const QError *qerror) -{ - return qstring_from_str(qerror->err_msg); -} - -/** - * qerror_print(): Print QError data - * - * This function will print the member 'desc' of the specified QError object, - * it uses error_report() for this, so that the output is routed to the right - * place (ie. stderr or Monitor's device). - */ -static void qerror_print(QError *qerror) -{ - QString *qstring = qerror_human(qerror); - loc_push_restore(&qerror->loc); - error_report("%s", qstring_get_str(qstring)); - loc_pop(&qerror->loc); - QDECREF(qstring); -} - -void qerror_report(ErrorClass eclass, const char *fmt, ...) -{ - va_list va; - QError *qerror; - - va_start(va, fmt); - qerror = qerror_from_info(eclass, fmt, &va); - va_end(va); - - if (monitor_cur_is_qmp()) { - monitor_set_error(cur_mon, qerror); - } else { - qerror_print(qerror); - QDECREF(qerror); - } -} - -/* Evil... */ -struct Error -{ - char *msg; - ErrorClass err_class; -}; - -void qerror_report_err(Error *err) -{ - QError *qerr; - - qerr = qerror_new(); - loc_save(&qerr->loc); - qerr->err_msg = g_strdup(err->msg); - qerr->err_class = err->err_class; - - if (monitor_cur_is_qmp()) { - monitor_set_error(cur_mon, qerr); - } else { - qerror_print(qerr); - QDECREF(qerr); - } -} - -void assert_no_error(Error *err) -{ - if (err) { - qerror_report_err(err); - abort(); - } -} - -/** - * qobject_to_qerror(): Convert a QObject into a QError - */ -static QError *qobject_to_qerror(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QERROR) { - return NULL; - } - - return container_of(obj, QError, base); -} - -/** - * qerror_destroy_obj(): Free all memory allocated by a QError - */ -static void qerror_destroy_obj(QObject *obj) -{ - QError *qerr; - - assert(obj != NULL); - qerr = qobject_to_qerror(obj); - - g_free(qerr->err_msg); - g_free(qerr); -} diff --git a/contrib/qemu/qobject/qfloat.c b/contrib/qemu/qobject/qfloat.c deleted file mode 100644 index 7de0992dba7..00000000000 --- a/contrib/qemu/qobject/qfloat.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * QFloat Module - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 "qapi/qmp/qfloat.h" -#include "qapi/qmp/qobject.h" -#include "qemu-common.h" - -static void qfloat_destroy_obj(QObject *obj); - -static const QType qfloat_type = { - .code = QTYPE_QFLOAT, - .destroy = qfloat_destroy_obj, -}; - -/** - * qfloat_from_int(): Create a new QFloat from a float - * - * Return strong reference. - */ -QFloat *qfloat_from_double(double value) -{ - QFloat *qf; - - qf = g_malloc(sizeof(*qf)); - qf->value = value; - QOBJECT_INIT(qf, &qfloat_type); - - return qf; -} - -/** - * qfloat_get_double(): Get the stored float - */ -double qfloat_get_double(const QFloat *qf) -{ - return qf->value; -} - -/** - * qobject_to_qfloat(): Convert a QObject into a QFloat - */ -QFloat *qobject_to_qfloat(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QFLOAT) - return NULL; - - return container_of(obj, QFloat, base); -} - -/** - * qfloat_destroy_obj(): Free all memory allocated by a - * QFloat object - */ -static void qfloat_destroy_obj(QObject *obj) -{ - assert(obj != NULL); - g_free(qobject_to_qfloat(obj)); -} diff --git a/contrib/qemu/qobject/qint.c b/contrib/qemu/qobject/qint.c deleted file mode 100644 index 86b9b04f0b6..00000000000 --- a/contrib/qemu/qobject/qint.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * QInt Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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 "qapi/qmp/qint.h" -#include "qapi/qmp/qobject.h" -#include "qemu-common.h" - -static void qint_destroy_obj(QObject *obj); - -static const QType qint_type = { - .code = QTYPE_QINT, - .destroy = qint_destroy_obj, -}; - -/** - * qint_from_int(): Create a new QInt from an int64_t - * - * Return strong reference. - */ -QInt *qint_from_int(int64_t value) -{ - QInt *qi; - - qi = g_malloc(sizeof(*qi)); - qi->value = value; - QOBJECT_INIT(qi, &qint_type); - - return qi; -} - -/** - * qint_get_int(): Get the stored integer - */ -int64_t qint_get_int(const QInt *qi) -{ - return qi->value; -} - -/** - * qobject_to_qint(): Convert a QObject into a QInt - */ -QInt *qobject_to_qint(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QINT) - return NULL; - - return container_of(obj, QInt, base); -} - -/** - * qint_destroy_obj(): Free all memory allocated by a - * QInt object - */ -static void qint_destroy_obj(QObject *obj) -{ - assert(obj != NULL); - g_free(qobject_to_qint(obj)); -} diff --git a/contrib/qemu/qobject/qjson.c b/contrib/qemu/qobject/qjson.c deleted file mode 100644 index 19085a1bb7f..00000000000 --- a/contrib/qemu/qobject/qjson.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * QObject JSON integration - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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 "qapi/qmp/json-lexer.h" -#include "qapi/qmp/json-parser.h" -#include "qapi/qmp/json-streamer.h" -#include "qapi/qmp/qjson.h" -#include "qapi/qmp/qint.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qbool.h" -#include "qapi/qmp/qfloat.h" -#include "qapi/qmp/qdict.h" - -typedef struct JSONParsingState -{ - JSONMessageParser parser; - va_list *ap; - QObject *result; -} JSONParsingState; - -static void parse_json(JSONMessageParser *parser, QList *tokens) -{ - JSONParsingState *s = container_of(parser, JSONParsingState, parser); - s->result = json_parser_parse(tokens, s->ap); -} - -QObject *qobject_from_jsonv(const char *string, va_list *ap) -{ - JSONParsingState state = {}; - - state.ap = ap; - - json_message_parser_init(&state.parser, parse_json); - json_message_parser_feed(&state.parser, string, strlen(string)); - json_message_parser_flush(&state.parser); - json_message_parser_destroy(&state.parser); - - return state.result; -} - -QObject *qobject_from_json(const char *string) -{ - return qobject_from_jsonv(string, NULL); -} - -/* - * IMPORTANT: This function aborts on error, thus it must not - * be used with untrusted arguments. - */ -QObject *qobject_from_jsonf(const char *string, ...) -{ - QObject *obj; - va_list ap; - - va_start(ap, string); - obj = qobject_from_jsonv(string, &ap); - va_end(ap); - - assert(obj != NULL); - return obj; -} - -typedef struct ToJsonIterState -{ - int indent; - int pretty; - int count; - QString *str; -} ToJsonIterState; - -static void to_json(const QObject *obj, QString *str, int pretty, int indent); - -static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) -{ - ToJsonIterState *s = opaque; - QString *qkey; - int j; - - if (s->count) - qstring_append(s->str, ", "); - - if (s->pretty) { - qstring_append(s->str, "\n"); - for (j = 0 ; j < s->indent ; j++) - qstring_append(s->str, " "); - } - - qkey = qstring_from_str(key); - to_json(QOBJECT(qkey), s->str, s->pretty, s->indent); - QDECREF(qkey); - - qstring_append(s->str, ": "); - to_json(obj, s->str, s->pretty, s->indent); - s->count++; -} - -static void to_json_list_iter(QObject *obj, void *opaque) -{ - ToJsonIterState *s = opaque; - int j; - - if (s->count) - qstring_append(s->str, ", "); - - if (s->pretty) { - qstring_append(s->str, "\n"); - for (j = 0 ; j < s->indent ; j++) - qstring_append(s->str, " "); - } - - to_json(obj, s->str, s->pretty, s->indent); - s->count++; -} - -static void to_json(const QObject *obj, QString *str, int pretty, int indent) -{ - switch (qobject_type(obj)) { - case QTYPE_QINT: { - QInt *val = qobject_to_qint(obj); - char buffer[1024]; - - snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val)); - qstring_append(str, buffer); - break; - } - case QTYPE_QSTRING: { - QString *val = qobject_to_qstring(obj); - const char *ptr; - int cp; - char buf[16]; - char *end; - - ptr = qstring_get_str(val); - qstring_append(str, "\""); - - for (; *ptr; ptr = end) { - cp = mod_utf8_codepoint(ptr, 6, &end); - switch (cp) { - case '\"': - qstring_append(str, "\\\""); - break; - case '\\': - qstring_append(str, "\\\\"); - break; - case '\b': - qstring_append(str, "\\b"); - break; - case '\f': - qstring_append(str, "\\f"); - break; - case '\n': - qstring_append(str, "\\n"); - break; - case '\r': - qstring_append(str, "\\r"); - break; - case '\t': - qstring_append(str, "\\t"); - break; - default: - if (cp < 0) { - cp = 0xFFFD; /* replacement character */ - } - if (cp > 0xFFFF) { - /* beyond BMP; need a surrogate pair */ - snprintf(buf, sizeof(buf), "\\u%04X\\u%04X", - 0xD800 + ((cp - 0x10000) >> 10), - 0xDC00 + ((cp - 0x10000) & 0x3FF)); - } else if (cp < 0x20 || cp >= 0x7F) { - snprintf(buf, sizeof(buf), "\\u%04X", cp); - } else { - buf[0] = cp; - buf[1] = 0; - } - qstring_append(str, buf); - } - }; - - qstring_append(str, "\""); - break; - } - case QTYPE_QDICT: { - ToJsonIterState s; - QDict *val = qobject_to_qdict(obj); - - s.count = 0; - s.str = str; - s.indent = indent + 1; - s.pretty = pretty; - qstring_append(str, "{"); - qdict_iter(val, to_json_dict_iter, &s); - if (pretty) { - int j; - qstring_append(str, "\n"); - for (j = 0 ; j < indent ; j++) - qstring_append(str, " "); - } - qstring_append(str, "}"); - break; - } - case QTYPE_QLIST: { - ToJsonIterState s; - QList *val = qobject_to_qlist(obj); - - s.count = 0; - s.str = str; - s.indent = indent + 1; - s.pretty = pretty; - qstring_append(str, "["); - qlist_iter(val, (void *)to_json_list_iter, &s); - if (pretty) { - int j; - qstring_append(str, "\n"); - for (j = 0 ; j < indent ; j++) - qstring_append(str, " "); - } - qstring_append(str, "]"); - break; - } - case QTYPE_QFLOAT: { - QFloat *val = qobject_to_qfloat(obj); - char buffer[1024]; - int len; - - len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val)); - while (len > 0 && buffer[len - 1] == '0') { - len--; - } - - if (len && buffer[len - 1] == '.') { - buffer[len - 1] = 0; - } else { - buffer[len] = 0; - } - - qstring_append(str, buffer); - break; - } - case QTYPE_QBOOL: { - QBool *val = qobject_to_qbool(obj); - - if (qbool_get_int(val)) { - qstring_append(str, "true"); - } else { - qstring_append(str, "false"); - } - break; - } - case QTYPE_QERROR: - /* XXX: should QError be emitted? */ - case QTYPE_NONE: - break; - } -} - -QString *qobject_to_json(const QObject *obj) -{ - QString *str = qstring_new(); - - to_json(obj, str, 0, 0); - - return str; -} - -QString *qobject_to_json_pretty(const QObject *obj) -{ - QString *str = qstring_new(); - - to_json(obj, str, 1, 0); - - return str; -} diff --git a/contrib/qemu/qobject/qlist.c b/contrib/qemu/qobject/qlist.c deleted file mode 100644 index 1ced0de58e2..00000000000 --- a/contrib/qemu/qobject/qlist.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * QList Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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 "qapi/qmp/qlist.h" -#include "qapi/qmp/qobject.h" -#include "qemu/queue.h" -#include "qemu-common.h" - -static void qlist_destroy_obj(QObject *obj); - -static const QType qlist_type = { - .code = QTYPE_QLIST, - .destroy = qlist_destroy_obj, -}; - -/** - * qlist_new(): Create a new QList - * - * Return strong reference. - */ -QList *qlist_new(void) -{ - QList *qlist; - - qlist = g_malloc(sizeof(*qlist)); - QTAILQ_INIT(&qlist->head); - QOBJECT_INIT(qlist, &qlist_type); - - return qlist; -} - -static void qlist_copy_elem(QObject *obj, void *opaque) -{ - QList *dst = opaque; - - qobject_incref(obj); - qlist_append_obj(dst, obj); -} - -QList *qlist_copy(QList *src) -{ - QList *dst = qlist_new(); - - qlist_iter(src, qlist_copy_elem, dst); - - return dst; -} - -/** - * qlist_append_obj(): Append an QObject into QList - * - * NOTE: ownership of 'value' is transferred to the QList - */ -void qlist_append_obj(QList *qlist, QObject *value) -{ - QListEntry *entry; - - entry = g_malloc(sizeof(*entry)); - entry->value = value; - - QTAILQ_INSERT_TAIL(&qlist->head, entry, next); -} - -/** - * qlist_iter(): Iterate over all the list's stored values. - * - * This function allows the user to provide an iterator, which will be - * called for each stored value in the list. - */ -void qlist_iter(const QList *qlist, - void (*iter)(QObject *obj, void *opaque), void *opaque) -{ - QListEntry *entry; - - QTAILQ_FOREACH(entry, &qlist->head, next) - iter(entry->value, opaque); -} - -QObject *qlist_pop(QList *qlist) -{ - QListEntry *entry; - QObject *ret; - - if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { - return NULL; - } - - entry = QTAILQ_FIRST(&qlist->head); - QTAILQ_REMOVE(&qlist->head, entry, next); - - ret = entry->value; - g_free(entry); - - return ret; -} - -QObject *qlist_peek(QList *qlist) -{ - QListEntry *entry; - QObject *ret; - - if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { - return NULL; - } - - entry = QTAILQ_FIRST(&qlist->head); - - ret = entry->value; - - return ret; -} - -int qlist_empty(const QList *qlist) -{ - return QTAILQ_EMPTY(&qlist->head); -} - -static void qlist_size_iter(QObject *obj, void *opaque) -{ - size_t *count = opaque; - (*count)++; -} - -size_t qlist_size(const QList *qlist) -{ - size_t count = 0; - qlist_iter(qlist, qlist_size_iter, &count); - return count; -} - -/** - * qobject_to_qlist(): Convert a QObject into a QList - */ -QList *qobject_to_qlist(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QLIST) { - return NULL; - } - - return container_of(obj, QList, base); -} - -/** - * qlist_destroy_obj(): Free all the memory allocated by a QList - */ -static void qlist_destroy_obj(QObject *obj) -{ - QList *qlist; - QListEntry *entry, *next_entry; - - assert(obj != NULL); - qlist = qobject_to_qlist(obj); - - QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) { - QTAILQ_REMOVE(&qlist->head, entry, next); - qobject_decref(entry->value); - g_free(entry); - } - - g_free(qlist); -} diff --git a/contrib/qemu/qobject/qstring.c b/contrib/qemu/qobject/qstring.c deleted file mode 100644 index 607b7a142c6..00000000000 --- a/contrib/qemu/qobject/qstring.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * QString Module - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino <lcapitulino@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 "qapi/qmp/qobject.h" -#include "qapi/qmp/qstring.h" -#include "qemu-common.h" - -static void qstring_destroy_obj(QObject *obj); - -static const QType qstring_type = { - .code = QTYPE_QSTRING, - .destroy = qstring_destroy_obj, -}; - -/** - * qstring_new(): Create a new empty QString - * - * Return strong reference. - */ -QString *qstring_new(void) -{ - return qstring_from_str(""); -} - -/** - * qstring_get_length(): Get the length of a QString - */ -size_t qstring_get_length(const QString *qstring) -{ - return qstring->length; -} - -/** - * qstring_from_substr(): Create a new QString from a C string substring - * - * Return string reference - */ -QString *qstring_from_substr(const char *str, int start, int end) -{ - QString *qstring; - - qstring = g_malloc(sizeof(*qstring)); - - qstring->length = end - start + 1; - qstring->capacity = qstring->length; - - qstring->string = g_malloc(qstring->capacity + 1); - memcpy(qstring->string, str + start, qstring->length); - qstring->string[qstring->length] = 0; - - QOBJECT_INIT(qstring, &qstring_type); - - return qstring; -} - -/** - * qstring_from_str(): Create a new QString from a regular C string - * - * Return strong reference. - */ -QString *qstring_from_str(const char *str) -{ - return qstring_from_substr(str, 0, strlen(str) - 1); -} - -static void capacity_increase(QString *qstring, size_t len) -{ - if (qstring->capacity < (qstring->length + len)) { - qstring->capacity += len; - qstring->capacity *= 2; /* use exponential growth */ - - qstring->string = g_realloc(qstring->string, qstring->capacity + 1); - } -} - -/* qstring_append(): Append a C string to a QString - */ -void qstring_append(QString *qstring, const char *str) -{ - size_t len = strlen(str); - - capacity_increase(qstring, len); - memcpy(qstring->string + qstring->length, str, len); - qstring->length += len; - qstring->string[qstring->length] = 0; -} - -void qstring_append_int(QString *qstring, int64_t value) -{ - char num[32]; - - snprintf(num, sizeof(num), "%" PRId64, value); - qstring_append(qstring, num); -} - -/** - * qstring_append_chr(): Append a C char to a QString - */ -void qstring_append_chr(QString *qstring, int c) -{ - capacity_increase(qstring, 1); - qstring->string[qstring->length++] = c; - qstring->string[qstring->length] = 0; -} - -/** - * qobject_to_qstring(): Convert a QObject to a QString - */ -QString *qobject_to_qstring(const QObject *obj) -{ - if (qobject_type(obj) != QTYPE_QSTRING) - return NULL; - - return container_of(obj, QString, base); -} - -/** - * qstring_get_str(): Return a pointer to the stored string - * - * NOTE: Should be used with caution, if the object is deallocated - * this pointer becomes invalid. - */ -const char *qstring_get_str(const QString *qstring) -{ - return qstring->string; -} - -/** - * qstring_destroy_obj(): Free all memory allocated by a QString - * object - */ -static void qstring_destroy_obj(QObject *obj) -{ - QString *qs; - - assert(obj != NULL); - qs = qobject_to_qstring(obj); - g_free(qs->string); - g_free(qs); -} diff --git a/contrib/qemu/trace/generated-tracers.h b/contrib/qemu/trace/generated-tracers.h deleted file mode 100644 index b512660f358..00000000000 --- a/contrib/qemu/trace/generated-tracers.h +++ /dev/null @@ -1,3759 +0,0 @@ -/* This file is autogenerated by tracetool, do not edit. */ - -#ifndef TRACE__GENERATED_TRACERS_H -#define TRACE__GENERATED_TRACERS_H - -#include "qemu-common.h" - -static inline void trace_qxl_interface_set_mm_time(int qid, uint32_t mm_time) -{ -} - -static inline void trace_qxl_io_write_vga(int qid, const char * mode, uint32_t addr, uint32_t val) -{ -} - -static inline void trace_g_malloc(size_t size, void * ptr) -{ -} - -static inline void trace_g_realloc(void * ptr, size_t size, void * newptr) -{ -} - -static inline void trace_g_free(void * ptr) -{ -} - -static inline void trace_qemu_memalign(size_t alignment, size_t size, void * ptr) -{ -} - -static inline void trace_qemu_anon_ram_alloc(size_t size, void * ptr) -{ -} - -static inline void trace_qemu_vfree(void * ptr) -{ -} - -static inline void trace_qemu_anon_ram_free(void * ptr, size_t size) -{ -} - -static inline void trace_virtqueue_fill(void * vq, const void * elem, unsigned int len, unsigned int idx) -{ -} - -static inline void trace_virtqueue_flush(void * vq, unsigned int count) -{ -} - -static inline void trace_virtqueue_pop(void * vq, void * elem, unsigned int in_num, unsigned int out_num) -{ -} - -static inline void trace_virtio_queue_notify(void * vdev, int n, void * vq) -{ -} - -static inline void trace_virtio_irq(void * vq) -{ -} - -static inline void trace_virtio_notify(void * vdev, void * vq) -{ -} - -static inline void trace_virtio_set_status(void * vdev, uint8_t val) -{ -} - -static inline void trace_virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) -{ -} - -static inline void trace_virtio_serial_throttle_port(unsigned int port, bool throttle) -{ -} - -static inline void trace_virtio_serial_handle_control_message(uint16_t event, uint16_t value) -{ -} - -static inline void trace_virtio_serial_handle_control_message_port(unsigned int port) -{ -} - -static inline void trace_virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) -{ -} - -static inline void trace_virtio_console_chr_read(unsigned int port, int size) -{ -} - -static inline void trace_virtio_console_chr_event(unsigned int port, int event) -{ -} - -static inline void trace_bdrv_open_common(void * bs, const char * filename, int flags, const char * format_name) -{ -} - -static inline void trace_multiwrite_cb(void * mcb, int ret) -{ -} - -static inline void trace_bdrv_aio_multiwrite(void * mcb, int num_callbacks, int num_reqs) -{ -} - -static inline void trace_bdrv_aio_discard(void * bs, int64_t sector_num, int nb_sectors, void * opaque) -{ -} - -static inline void trace_bdrv_aio_flush(void * bs, void * opaque) -{ -} - -static inline void trace_bdrv_aio_readv(void * bs, int64_t sector_num, int nb_sectors, void * opaque) -{ -} - -static inline void trace_bdrv_aio_writev(void * bs, int64_t sector_num, int nb_sectors, void * opaque) -{ -} - -static inline void trace_bdrv_lock_medium(void * bs, bool locked) -{ -} - -static inline void trace_bdrv_co_readv(void * bs, int64_t sector_num, int nb_sector) -{ -} - -static inline void trace_bdrv_co_copy_on_readv(void * bs, int64_t sector_num, int nb_sector) -{ -} - -static inline void trace_bdrv_co_writev(void * bs, int64_t sector_num, int nb_sector) -{ -} - -static inline void trace_bdrv_co_write_zeroes(void * bs, int64_t sector_num, int nb_sector) -{ -} - -static inline void trace_bdrv_co_io_em(void * bs, int64_t sector_num, int nb_sectors, int is_write, void * acb) -{ -} - -static inline void trace_bdrv_co_do_copy_on_readv(void * bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) -{ -} - -static inline void trace_stream_one_iteration(void * s, int64_t sector_num, int nb_sectors, int is_allocated) -{ -} - -static inline void trace_stream_start(void * bs, void * base, void * s, void * co, void * opaque) -{ -} - -static inline void trace_commit_one_iteration(void * s, int64_t sector_num, int nb_sectors, int is_allocated) -{ -} - -static inline void trace_commit_start(void * bs, void * base, void * top, void * s, void * co, void * opaque) -{ -} - -static inline void trace_mirror_start(void * bs, void * s, void * co, void * opaque) -{ -} - -static inline void trace_mirror_restart_iter(void * s, int64_t cnt) -{ -} - -static inline void trace_mirror_before_flush(void * s) -{ -} - -static inline void trace_mirror_before_drain(void * s, int64_t cnt) -{ -} - -static inline void trace_mirror_before_sleep(void * s, int64_t cnt, int synced) -{ -} - -static inline void trace_mirror_one_iteration(void * s, int64_t sector_num, int nb_sectors) -{ -} - -static inline void trace_mirror_cow(void * s, int64_t sector_num) -{ -} - -static inline void trace_mirror_iteration_done(void * s, int64_t sector_num, int nb_sectors, int ret) -{ -} - -static inline void trace_mirror_yield(void * s, int64_t cnt, int buf_free_count, int in_flight) -{ -} - -static inline void trace_mirror_yield_in_flight(void * s, int64_t sector_num, int in_flight) -{ -} - -static inline void trace_mirror_yield_buf_busy(void * s, int nb_chunks, int in_flight) -{ -} - -static inline void trace_mirror_break_buf_busy(void * s, int nb_chunks, int in_flight) -{ -} - -static inline void trace_backup_do_cow_enter(void * job, int64_t start, int64_t sector_num, int nb_sectors) -{ -} - -static inline void trace_backup_do_cow_return(void * job, int64_t sector_num, int nb_sectors, int ret) -{ -} - -static inline void trace_backup_do_cow_skip(void * job, int64_t start) -{ -} - -static inline void trace_backup_do_cow_process(void * job, int64_t start) -{ -} - -static inline void trace_backup_do_cow_read_fail(void * job, int64_t start, int ret) -{ -} - -static inline void trace_backup_do_cow_write_fail(void * job, int64_t start, int ret) -{ -} - -static inline void trace_qmp_block_job_cancel(void * job) -{ -} - -static inline void trace_qmp_block_job_pause(void * job) -{ -} - -static inline void trace_qmp_block_job_resume(void * job) -{ -} - -static inline void trace_qmp_block_job_complete(void * job) -{ -} - -static inline void trace_block_job_cb(void * bs, void * job, int ret) -{ -} - -static inline void trace_qmp_block_stream(void * bs, void * job) -{ -} - -static inline void trace_virtio_blk_req_complete(void * req, int status) -{ -} - -static inline void trace_virtio_blk_rw_complete(void * req, int ret) -{ -} - -static inline void trace_virtio_blk_handle_write(void * req, uint64_t sector, size_t nsectors) -{ -} - -static inline void trace_virtio_blk_handle_read(void * req, uint64_t sector, size_t nsectors) -{ -} - -static inline void trace_virtio_blk_data_plane_start(void * s) -{ -} - -static inline void trace_virtio_blk_data_plane_stop(void * s) -{ -} - -static inline void trace_virtio_blk_data_plane_process_request(void * s, unsigned int out_num, unsigned int in_num, unsigned int head) -{ -} - -static inline void trace_virtio_blk_data_plane_complete_request(void * s, unsigned int head, int ret) -{ -} - -static inline void trace_vring_setup(uint64_t physical, void * desc, void * avail, void * used) -{ -} - -static inline void trace_thread_pool_submit(void * pool, void * req, void * opaque) -{ -} - -static inline void trace_thread_pool_complete(void * pool, void * req, void * opaque, int ret) -{ -} - -static inline void trace_thread_pool_cancel(void * req, void * opaque) -{ -} - -static inline void trace_paio_submit(void * acb, void * opaque, int64_t sector_num, int nb_sectors, int type) -{ -} - -static inline void trace_paio_complete(void * acb, void * opaque, int ret) -{ -} - -static inline void trace_paio_cancel(void * acb, void * opaque) -{ -} - -static inline void trace_cpu_in(unsigned int addr, unsigned int val) -{ -} - -static inline void trace_cpu_out(unsigned int addr, unsigned int val) -{ -} - -static inline void trace_balloon_event(void * opaque, unsigned long addr) -{ -} - -static inline void trace_apic_local_deliver(int vector, uint32_t lvt) -{ -} - -static inline void trace_apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) -{ -} - -static inline void trace_cpu_set_apic_base(uint64_t val) -{ -} - -static inline void trace_cpu_get_apic_base(uint64_t val) -{ -} - -static inline void trace_apic_mem_readl(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_apic_mem_writel(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_apic_report_irq_delivered(int apic_irq_delivered) -{ -} - -static inline void trace_apic_reset_irq_delivered(int apic_irq_delivered) -{ -} - -static inline void trace_apic_get_irq_delivered(int apic_irq_delivered) -{ -} - -static inline void trace_cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) -{ -} - -static inline void trace_cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) -{ -} - -static inline void trace_cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) -{ -} - -static inline void trace_cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) -{ -} - -static inline void trace_nvram_read(uint32_t addr, uint32_t ret) -{ -} - -static inline void trace_nvram_write(uint32_t addr, uint32_t old, uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_mer(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_mdr(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_mfsr(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_vcr(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_dr(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_ecr0(uint32_t val) -{ -} - -static inline void trace_ecc_mem_writel_ecr1(uint32_t val) -{ -} - -static inline void trace_ecc_mem_readl_mer(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_mdr(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_mfsr(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_vcr(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_mfar0(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_mfar1(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_dr(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_ecr0(uint32_t ret) -{ -} - -static inline void trace_ecc_mem_readl_ecr1(uint32_t ret) -{ -} - -static inline void trace_ecc_diag_mem_writeb(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_ecc_diag_mem_readb(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_fw_cfg_write(void * s, uint8_t value) -{ -} - -static inline void trace_fw_cfg_select(void * s, uint16_t key, int ret) -{ -} - -static inline void trace_fw_cfg_read(void * s, uint8_t ret) -{ -} - -static inline void trace_fw_cfg_add_file_dupe(void * s, char * name) -{ -} - -static inline void trace_fw_cfg_add_file(void * s, int index, char * name, size_t len) -{ -} - -static inline void trace_hd_geometry_lchs_guess(void * bs, int cyls, int heads, int secs) -{ -} - -static inline void trace_hd_geometry_guess(void * bs, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) -{ -} - -static inline void trace_jazz_led_read(uint64_t addr, uint8_t val) -{ -} - -static inline void trace_jazz_led_write(uint64_t addr, uint8_t new) -{ -} - -static inline void trace_lance_mem_readw(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_lance_mem_writew(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) -{ -} - -static inline void trace_slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) -{ -} - -static inline void trace_slavio_intctl_mem_writel_set(uint32_t cpu, uint32_t val, uint32_t intreg_pending) -{ -} - -static inline void trace_slavio_intctlm_mem_readl(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_slavio_intctlm_mem_writel(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_slavio_intctlm_mem_writel_enable(uint32_t val, uint32_t intregm_disabled) -{ -} - -static inline void trace_slavio_intctlm_mem_writel_disable(uint32_t val, uint32_t intregm_disabled) -{ -} - -static inline void trace_slavio_intctlm_mem_writel_target(uint32_t cpu) -{ -} - -static inline void trace_slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) -{ -} - -static inline void trace_slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) -{ -} - -static inline void trace_slavio_set_timer_irq_cpu(int cpu, int level) -{ -} - -static inline void trace_slavio_misc_update_irq_raise(void) -{ -} - -static inline void trace_slavio_misc_update_irq_lower(void) -{ -} - -static inline void trace_slavio_set_power_fail(int power_failing, uint8_t config) -{ -} - -static inline void trace_slavio_cfg_mem_writeb(uint32_t val) -{ -} - -static inline void trace_slavio_cfg_mem_readb(uint32_t ret) -{ -} - -static inline void trace_slavio_diag_mem_writeb(uint32_t val) -{ -} - -static inline void trace_slavio_diag_mem_readb(uint32_t ret) -{ -} - -static inline void trace_slavio_mdm_mem_writeb(uint32_t val) -{ -} - -static inline void trace_slavio_mdm_mem_readb(uint32_t ret) -{ -} - -static inline void trace_slavio_aux1_mem_writeb(uint32_t val) -{ -} - -static inline void trace_slavio_aux1_mem_readb(uint32_t ret) -{ -} - -static inline void trace_slavio_aux2_mem_writeb(uint32_t val) -{ -} - -static inline void trace_slavio_aux2_mem_readb(uint32_t ret) -{ -} - -static inline void trace_apc_mem_writeb(uint32_t val) -{ -} - -static inline void trace_apc_mem_readb(uint32_t ret) -{ -} - -static inline void trace_slavio_sysctrl_mem_writel(uint32_t val) -{ -} - -static inline void trace_slavio_sysctrl_mem_readl(uint32_t ret) -{ -} - -static inline void trace_slavio_led_mem_writew(uint32_t val) -{ -} - -static inline void trace_slavio_led_mem_readw(uint32_t ret) -{ -} - -static inline void trace_slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) -{ -} - -static inline void trace_slavio_timer_irq(uint32_t counthigh, uint32_t count) -{ -} - -static inline void trace_slavio_timer_mem_readl_invalid(uint64_t addr) -{ -} - -static inline void trace_slavio_timer_mem_readl(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_slavio_timer_mem_writel(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_slavio_timer_mem_writel_limit(unsigned int timer_index, uint64_t count) -{ -} - -static inline void trace_slavio_timer_mem_writel_counter_invalid(void) -{ -} - -static inline void trace_slavio_timer_mem_writel_status_start(unsigned int timer_index) -{ -} - -static inline void trace_slavio_timer_mem_writel_status_stop(unsigned int timer_index) -{ -} - -static inline void trace_slavio_timer_mem_writel_mode_user(unsigned int timer_index) -{ -} - -static inline void trace_slavio_timer_mem_writel_mode_counter(unsigned int timer_index) -{ -} - -static inline void trace_slavio_timer_mem_writel_mode_invalid(void) -{ -} - -static inline void trace_slavio_timer_mem_writel_invalid(uint64_t addr) -{ -} - -static inline void trace_ledma_memory_read(uint64_t addr) -{ -} - -static inline void trace_ledma_memory_write(uint64_t addr) -{ -} - -static inline void trace_sparc32_dma_set_irq_raise(void) -{ -} - -static inline void trace_sparc32_dma_set_irq_lower(void) -{ -} - -static inline void trace_espdma_memory_read(uint32_t addr) -{ -} - -static inline void trace_espdma_memory_write(uint32_t addr) -{ -} - -static inline void trace_sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) -{ -} - -static inline void trace_sparc32_dma_enable_raise(void) -{ -} - -static inline void trace_sparc32_dma_enable_lower(void) -{ -} - -static inline void trace_sun4m_cpu_interrupt(unsigned int level) -{ -} - -static inline void trace_sun4m_cpu_reset_interrupt(unsigned int level) -{ -} - -static inline void trace_sun4m_cpu_set_irq_raise(int level) -{ -} - -static inline void trace_sun4m_cpu_set_irq_lower(int level) -{ -} - -static inline void trace_sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) -{ -} - -static inline void trace_sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_sun4m_iommu_mem_writel_ctrl(uint64_t iostart) -{ -} - -static inline void trace_sun4m_iommu_mem_writel_tlbflush(uint32_t val) -{ -} - -static inline void trace_sun4m_iommu_mem_writel_pgflush(uint32_t val) -{ -} - -static inline void trace_sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) -{ -} - -static inline void trace_sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) -{ -} - -static inline void trace_sun4m_iommu_bad_addr(uint64_t addr) -{ -} - -static inline void trace_usb_packet_state_change(int bus, const char * port, int ep, void * p, const char * o, const char * n) -{ -} - -static inline void trace_usb_packet_state_fault(int bus, const char * port, int ep, void * p, const char * o, const char * n) -{ -} - -static inline void trace_usb_port_claim(int bus, const char * port) -{ -} - -static inline void trace_usb_port_attach(int bus, const char * port, const char * devspeed, const char * portspeed) -{ -} - -static inline void trace_usb_port_detach(int bus, const char * port) -{ -} - -static inline void trace_usb_port_release(int bus, const char * port) -{ -} - -static inline void trace_usb_ehci_reset(void) -{ -} - -static inline void trace_usb_ehci_opreg_read(uint32_t addr, const char * str, uint32_t val) -{ -} - -static inline void trace_usb_ehci_opreg_write(uint32_t addr, const char * str, uint32_t val) -{ -} - -static inline void trace_usb_ehci_opreg_change(uint32_t addr, const char * str, uint32_t new, uint32_t old) -{ -} - -static inline void trace_usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) -{ -} - -static inline void trace_usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) -{ -} - -static inline void trace_usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) -{ -} - -static inline void trace_usb_ehci_usbsts(const char * sts, int state) -{ -} - -static inline void trace_usb_ehci_state(const char * schedule, const char * state) -{ -} - -static inline void trace_usb_ehci_qh_ptrs(void * q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) -{ -} - -static inline void trace_usb_ehci_qh_fields(uint32_t addr, int rl, int mplen, int eps, int ep, int devaddr) -{ -} - -static inline void trace_usb_ehci_qh_bits(uint32_t addr, int c, int h, int dtc, int i) -{ -} - -static inline void trace_usb_ehci_qtd_ptrs(void * q, uint32_t addr, uint32_t nxt, uint32_t altnext) -{ -} - -static inline void trace_usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) -{ -} - -static inline void trace_usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) -{ -} - -static inline void trace_usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) -{ -} - -static inline void trace_usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) -{ -} - -static inline void trace_usb_ehci_port_attach(uint32_t port, const char * owner, const char * device) -{ -} - -static inline void trace_usb_ehci_port_detach(uint32_t port, const char * owner) -{ -} - -static inline void trace_usb_ehci_port_reset(uint32_t port, int enable) -{ -} - -static inline void trace_usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) -{ -} - -static inline void trace_usb_ehci_queue_action(void * q, const char * action) -{ -} - -static inline void trace_usb_ehci_packet_action(void * q, void * p, const char * action) -{ -} - -static inline void trace_usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) -{ -} - -static inline void trace_usb_ehci_guest_bug(const char * reason) -{ -} - -static inline void trace_usb_ehci_doorbell_ring(void) -{ -} - -static inline void trace_usb_ehci_doorbell_ack(void) -{ -} - -static inline void trace_usb_ehci_dma_error(void) -{ -} - -static inline void trace_usb_uhci_reset(void) -{ -} - -static inline void trace_usb_uhci_schedule_start(void) -{ -} - -static inline void trace_usb_uhci_schedule_stop(void) -{ -} - -static inline void trace_usb_uhci_frame_start(uint32_t num) -{ -} - -static inline void trace_usb_uhci_frame_stop_bandwidth(void) -{ -} - -static inline void trace_usb_uhci_frame_loop_stop_idle(void) -{ -} - -static inline void trace_usb_uhci_frame_loop_continue(void) -{ -} - -static inline void trace_usb_uhci_mmio_readw(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_usb_uhci_mmio_writew(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_usb_uhci_queue_add(uint32_t token) -{ -} - -static inline void trace_usb_uhci_queue_del(uint32_t token, const char * reason) -{ -} - -static inline void trace_usb_uhci_packet_add(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_link_async(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_unlink_async(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_cancel(uint32_t token, uint32_t addr, int done) -{ -} - -static inline void trace_usb_uhci_packet_complete_success(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_complete_shortxfer(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_complete_stall(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_complete_babble(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_complete_error(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_packet_del(uint32_t token, uint32_t addr) -{ -} - -static inline void trace_usb_uhci_qh_load(uint32_t qh) -{ -} - -static inline void trace_usb_uhci_td_load(uint32_t qh, uint32_t td, uint32_t ctrl, uint32_t token) -{ -} - -static inline void trace_usb_uhci_td_queue(uint32_t td, uint32_t ctrl, uint32_t token) -{ -} - -static inline void trace_usb_uhci_td_nextqh(uint32_t qh, uint32_t td) -{ -} - -static inline void trace_usb_uhci_td_async(uint32_t qh, uint32_t td) -{ -} - -static inline void trace_usb_uhci_td_complete(uint32_t qh, uint32_t td) -{ -} - -static inline void trace_usb_xhci_reset(void) -{ -} - -static inline void trace_usb_xhci_run(void) -{ -} - -static inline void trace_usb_xhci_stop(void) -{ -} - -static inline void trace_usb_xhci_cap_read(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_oper_read(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_runtime_read(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_doorbell_read(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_oper_write(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_runtime_write(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_doorbell_write(uint32_t off, uint32_t val) -{ -} - -static inline void trace_usb_xhci_irq_intx(uint32_t level) -{ -} - -static inline void trace_usb_xhci_irq_msi(uint32_t nr) -{ -} - -static inline void trace_usb_xhci_irq_msix(uint32_t nr) -{ -} - -static inline void trace_usb_xhci_irq_msix_use(uint32_t nr) -{ -} - -static inline void trace_usb_xhci_irq_msix_unuse(uint32_t nr) -{ -} - -static inline void trace_usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char * trb, const char * evt, uint64_t param, uint32_t status, uint32_t control) -{ -} - -static inline void trace_usb_xhci_fetch_trb(uint64_t addr, const char * name, uint64_t param, uint32_t status, uint32_t control) -{ -} - -static inline void trace_usb_xhci_port_reset(uint32_t port) -{ -} - -static inline void trace_usb_xhci_port_link(uint32_t port, uint32_t pls) -{ -} - -static inline void trace_usb_xhci_port_notify(uint32_t port, uint32_t pls) -{ -} - -static inline void trace_usb_xhci_slot_enable(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_slot_disable(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_slot_address(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_slot_configure(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_slot_evaluate(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_slot_reset(uint32_t slotid) -{ -} - -static inline void trace_usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) -{ -} - -static inline void trace_usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) -{ -} - -static inline void trace_usb_xhci_ep_set_dequeue(uint32_t slotid, uint32_t epid, uint32_t streamid, uint64_t param) -{ -} - -static inline void trace_usb_xhci_ep_kick(uint32_t slotid, uint32_t epid, uint32_t streamid) -{ -} - -static inline void trace_usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) -{ -} - -static inline void trace_usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) -{ -} - -static inline void trace_usb_xhci_xfer_start(void * xfer, uint32_t slotid, uint32_t epid, uint32_t streamid) -{ -} - -static inline void trace_usb_xhci_xfer_async(void * xfer) -{ -} - -static inline void trace_usb_xhci_xfer_nak(void * xfer) -{ -} - -static inline void trace_usb_xhci_xfer_retry(void * xfer) -{ -} - -static inline void trace_usb_xhci_xfer_success(void * xfer, uint32_t bytes) -{ -} - -static inline void trace_usb_xhci_xfer_error(void * xfer, uint32_t ret) -{ -} - -static inline void trace_usb_xhci_unimplemented(const char * item, int nr) -{ -} - -static inline void trace_usb_desc_device(int addr, int len, int ret) -{ -} - -static inline void trace_usb_desc_device_qualifier(int addr, int len, int ret) -{ -} - -static inline void trace_usb_desc_config(int addr, int index, int len, int ret) -{ -} - -static inline void trace_usb_desc_other_speed_config(int addr, int index, int len, int ret) -{ -} - -static inline void trace_usb_desc_string(int addr, int index, int len, int ret) -{ -} - -static inline void trace_usb_desc_bos(int addr, int len, int ret) -{ -} - -static inline void trace_usb_set_addr(int addr) -{ -} - -static inline void trace_usb_set_config(int addr, int config, int ret) -{ -} - -static inline void trace_usb_set_interface(int addr, int iface, int alt, int ret) -{ -} - -static inline void trace_usb_clear_device_feature(int addr, int feature, int ret) -{ -} - -static inline void trace_usb_set_device_feature(int addr, int feature, int ret) -{ -} - -static inline void trace_usb_hub_reset(int addr) -{ -} - -static inline void trace_usb_hub_control(int addr, int request, int value, int index, int length) -{ -} - -static inline void trace_usb_hub_get_port_status(int addr, int nr, int status, int changed) -{ -} - -static inline void trace_usb_hub_set_port_feature(int addr, int nr, const char * f) -{ -} - -static inline void trace_usb_hub_clear_port_feature(int addr, int nr, const char * f) -{ -} - -static inline void trace_usb_hub_attach(int addr, int nr) -{ -} - -static inline void trace_usb_hub_detach(int addr, int nr) -{ -} - -static inline void trace_usb_uas_reset(int addr) -{ -} - -static inline void trace_usb_uas_command(int addr, uint16_t tag, int lun, uint32_t lun64_1, uint32_t lun64_2) -{ -} - -static inline void trace_usb_uas_response(int addr, uint16_t tag, uint8_t code) -{ -} - -static inline void trace_usb_uas_sense(int addr, uint16_t tag, uint8_t status) -{ -} - -static inline void trace_usb_uas_read_ready(int addr, uint16_t tag) -{ -} - -static inline void trace_usb_uas_write_ready(int addr, uint16_t tag) -{ -} - -static inline void trace_usb_uas_xfer_data(int addr, uint16_t tag, uint32_t copy, uint32_t uoff, uint32_t usize, uint32_t soff, uint32_t ssize) -{ -} - -static inline void trace_usb_uas_scsi_data(int addr, uint16_t tag, uint32_t bytes) -{ -} - -static inline void trace_usb_uas_scsi_complete(int addr, uint16_t tag, uint32_t status, uint32_t resid) -{ -} - -static inline void trace_usb_uas_tmf_abort_task(int addr, uint16_t tag, uint16_t task_tag) -{ -} - -static inline void trace_usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) -{ -} - -static inline void trace_usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) -{ -} - -static inline void trace_usb_host_open_started(int bus, int addr) -{ -} - -static inline void trace_usb_host_open_success(int bus, int addr) -{ -} - -static inline void trace_usb_host_open_failure(int bus, int addr) -{ -} - -static inline void trace_usb_host_disconnect(int bus, int addr) -{ -} - -static inline void trace_usb_host_close(int bus, int addr) -{ -} - -static inline void trace_usb_host_attach_kernel(int bus, int addr, int interface) -{ -} - -static inline void trace_usb_host_detach_kernel(int bus, int addr, int interface) -{ -} - -static inline void trace_usb_host_set_address(int bus, int addr, int config) -{ -} - -static inline void trace_usb_host_set_config(int bus, int addr, int config) -{ -} - -static inline void trace_usb_host_set_interface(int bus, int addr, int interface, int alt) -{ -} - -static inline void trace_usb_host_claim_interfaces(int bus, int addr, int config, int nif) -{ -} - -static inline void trace_usb_host_claim_interface(int bus, int addr, int config, int interface) -{ -} - -static inline void trace_usb_host_release_interfaces(int bus, int addr) -{ -} - -static inline void trace_usb_host_release_interface(int bus, int addr, int interface) -{ -} - -static inline void trace_usb_host_req_control(int bus, int addr, void * p, int req, int value, int index) -{ -} - -static inline void trace_usb_host_req_data(int bus, int addr, void * p, int in, int ep, int size) -{ -} - -static inline void trace_usb_host_req_complete(int bus, int addr, void * p, int status, int length) -{ -} - -static inline void trace_usb_host_req_emulated(int bus, int addr, void * p, int status) -{ -} - -static inline void trace_usb_host_req_canceled(int bus, int addr, void * p) -{ -} - -static inline void trace_usb_host_urb_submit(int bus, int addr, void * aurb, int length, int more) -{ -} - -static inline void trace_usb_host_urb_complete(int bus, int addr, void * aurb, int status, int length, int more) -{ -} - -static inline void trace_usb_host_urb_canceled(int bus, int addr, void * aurb) -{ -} - -static inline void trace_usb_host_ep_set_halt(int bus, int addr, int ep) -{ -} - -static inline void trace_usb_host_ep_clear_halt(int bus, int addr, int ep) -{ -} - -static inline void trace_usb_host_iso_start(int bus, int addr, int ep) -{ -} - -static inline void trace_usb_host_iso_stop(int bus, int addr, int ep) -{ -} - -static inline void trace_usb_host_iso_out_of_bufs(int bus, int addr, int ep) -{ -} - -static inline void trace_usb_host_iso_many_urbs(int bus, int addr, int count) -{ -} - -static inline void trace_usb_host_reset(int bus, int addr) -{ -} - -static inline void trace_usb_host_auto_scan_enabled(void) -{ -} - -static inline void trace_usb_host_auto_scan_disabled(void) -{ -} - -static inline void trace_usb_host_claim_port(int bus, int hub, int port) -{ -} - -static inline void trace_usb_host_parse_device(int bus, int addr, int vendor, int product) -{ -} - -static inline void trace_usb_host_parse_config(int bus, int addr, int value, int active) -{ -} - -static inline void trace_usb_host_parse_interface(int bus, int addr, int num, int alt, int active) -{ -} - -static inline void trace_usb_host_parse_endpoint(int bus, int addr, int ep, const char * dir, const char * type, int active) -{ -} - -static inline void trace_usb_host_parse_unknown(int bus, int addr, int len, int type) -{ -} - -static inline void trace_usb_host_parse_error(int bus, int addr, const char * errmsg) -{ -} - -static inline void trace_scsi_req_alloc(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_req_cancel(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_req_data(int target, int lun, int tag, int len) -{ -} - -static inline void trace_scsi_req_data_canceled(int target, int lun, int tag, int len) -{ -} - -static inline void trace_scsi_req_dequeue(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_req_continue(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_req_continue_canceled(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) -{ -} - -static inline void trace_scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) -{ -} - -static inline void trace_scsi_req_parse_bad(int target, int lun, int tag, int cmd) -{ -} - -static inline void trace_scsi_req_build_sense(int target, int lun, int tag, int key, int asc, int ascq) -{ -} - -static inline void trace_scsi_device_set_ua(int target, int lun, int key, int asc, int ascq) -{ -} - -static inline void trace_scsi_report_luns(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_inquiry(int target, int lun, int tag, int cdb1, int cdb2) -{ -} - -static inline void trace_scsi_test_unit_ready(int target, int lun, int tag) -{ -} - -static inline void trace_scsi_request_sense(int target, int lun, int tag) -{ -} - -static inline void trace_vm_state_notify(int running, int reason) -{ -} - -static inline void trace_load_file(const char * name, const char * path) -{ -} - -static inline void trace_runstate_set(int new_state) -{ -} - -static inline void trace_qcow2_writev_start_req(void * co, int64_t sector, int nb_sectors) -{ -} - -static inline void trace_qcow2_writev_done_req(void * co, int ret) -{ -} - -static inline void trace_qcow2_writev_start_part(void * co) -{ -} - -static inline void trace_qcow2_writev_done_part(void * co, int cur_nr_sectors) -{ -} - -static inline void trace_qcow2_writev_data(void * co, uint64_t offset) -{ -} - -static inline void trace_qcow2_alloc_clusters_offset(void * co, uint64_t offset, int n_start, int n_end) -{ -} - -static inline void trace_qcow2_handle_copied(void * co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) -{ -} - -static inline void trace_qcow2_handle_alloc(void * co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) -{ -} - -static inline void trace_qcow2_do_alloc_clusters_offset(void * co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) -{ -} - -static inline void trace_qcow2_cluster_alloc_phys(void * co) -{ -} - -static inline void trace_qcow2_cluster_link_l2(void * co, int nb_clusters) -{ -} - -static inline void trace_qcow2_l2_allocate(void * bs, int l1_index) -{ -} - -static inline void trace_qcow2_l2_allocate_get_empty(void * bs, int l1_index) -{ -} - -static inline void trace_qcow2_l2_allocate_write_l2(void * bs, int l1_index) -{ -} - -static inline void trace_qcow2_l2_allocate_write_l1(void * bs, int l1_index) -{ -} - -static inline void trace_qcow2_l2_allocate_done(void * bs, int l1_index, int ret) -{ -} - -static inline void trace_qcow2_cache_get(void * co, int c, uint64_t offset, bool read_from_disk) -{ -} - -static inline void trace_qcow2_cache_get_replace_entry(void * co, int c, int i) -{ -} - -static inline void trace_qcow2_cache_get_read(void * co, int c, int i) -{ -} - -static inline void trace_qcow2_cache_get_done(void * co, int c, int i) -{ -} - -static inline void trace_qcow2_cache_flush(void * co, int c) -{ -} - -static inline void trace_qcow2_cache_entry_flush(void * co, int c, int i) -{ -} - -static inline void trace_qed_alloc_l2_cache_entry(void * l2_cache, void * entry) -{ -} - -static inline void trace_qed_unref_l2_cache_entry(void * entry, int ref) -{ -} - -static inline void trace_qed_find_l2_cache_entry(void * l2_cache, void * entry, uint64_t offset, int ref) -{ -} - -static inline void trace_qed_read_table(void * s, uint64_t offset, void * table) -{ -} - -static inline void trace_qed_read_table_cb(void * s, void * table, int ret) -{ -} - -static inline void trace_qed_write_table(void * s, uint64_t offset, void * table, unsigned int index, unsigned int n) -{ -} - -static inline void trace_qed_write_table_cb(void * s, void * table, int flush, int ret) -{ -} - -static inline void trace_qed_need_check_timer_cb(void * s) -{ -} - -static inline void trace_qed_start_need_check_timer(void * s) -{ -} - -static inline void trace_qed_cancel_need_check_timer(void * s) -{ -} - -static inline void trace_qed_aio_complete(void * s, void * acb, int ret) -{ -} - -static inline void trace_qed_aio_setup(void * s, void * acb, int64_t sector_num, int nb_sectors, void * opaque, int flags) -{ -} - -static inline void trace_qed_aio_next_io(void * s, void * acb, int ret, uint64_t cur_pos) -{ -} - -static inline void trace_qed_aio_read_data(void * s, void * acb, int ret, uint64_t offset, size_t len) -{ -} - -static inline void trace_qed_aio_write_data(void * s, void * acb, int ret, uint64_t offset, size_t len) -{ -} - -static inline void trace_qed_aio_write_prefill(void * s, void * acb, uint64_t start, size_t len, uint64_t offset) -{ -} - -static inline void trace_qed_aio_write_postfill(void * s, void * acb, uint64_t start, size_t len, uint64_t offset) -{ -} - -static inline void trace_qed_aio_write_main(void * s, void * acb, int ret, uint64_t offset, size_t len) -{ -} - -static inline void trace_g364fb_read(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_g364fb_write(uint64_t addr, uint32_t new) -{ -} - -static inline void trace_grlib_gptimer_enable(int id, uint32_t count) -{ -} - -static inline void trace_grlib_gptimer_disabled(int id, uint32_t config) -{ -} - -static inline void trace_grlib_gptimer_restart(int id, uint32_t reload) -{ -} - -static inline void trace_grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) -{ -} - -static inline void trace_grlib_gptimer_hit(int id) -{ -} - -static inline void trace_grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) -{ -} - -static inline void trace_grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) -{ -} - -static inline void trace_grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) -{ -} - -static inline void trace_grlib_irqmp_ack(int intno) -{ -} - -static inline void trace_grlib_irqmp_set_irq(int irq) -{ -} - -static inline void trace_grlib_irqmp_readl_unknown(uint64_t addr) -{ -} - -static inline void trace_grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) -{ -} - -static inline void trace_grlib_apbuart_event(int event) -{ -} - -static inline void trace_grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) -{ -} - -static inline void trace_grlib_apbuart_readl_unknown(uint64_t addr) -{ -} - -static inline void trace_leon3_set_irq(int intno) -{ -} - -static inline void trace_leon3_reset_irq(int intno) -{ -} - -static inline void trace_spice_vmc_write(ssize_t out, int len) -{ -} - -static inline void trace_spice_vmc_read(int bytes, int len) -{ -} - -static inline void trace_spice_vmc_register_interface(void * scd) -{ -} - -static inline void trace_spice_vmc_unregister_interface(void * scd) -{ -} - -static inline void trace_spice_vmc_event(int event) -{ -} - -static inline void trace_lm32_pic_raise_irq(void) -{ -} - -static inline void trace_lm32_pic_lower_irq(void) -{ -} - -static inline void trace_lm32_pic_interrupt(int irq, int level) -{ -} - -static inline void trace_lm32_pic_set_im(uint32_t im) -{ -} - -static inline void trace_lm32_pic_set_ip(uint32_t ip) -{ -} - -static inline void trace_lm32_pic_get_im(uint32_t im) -{ -} - -static inline void trace_lm32_pic_get_ip(uint32_t ip) -{ -} - -static inline void trace_lm32_juart_get_jtx(uint32_t value) -{ -} - -static inline void trace_lm32_juart_set_jtx(uint32_t value) -{ -} - -static inline void trace_lm32_juart_get_jrx(uint32_t value) -{ -} - -static inline void trace_lm32_juart_set_jrx(uint32_t value) -{ -} - -static inline void trace_lm32_timer_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_lm32_timer_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_lm32_timer_hit(void) -{ -} - -static inline void trace_lm32_timer_irq_state(int level) -{ -} - -static inline void trace_lm32_uart_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_lm32_uart_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_lm32_uart_irq_state(int level) -{ -} - -static inline void trace_lm32_sys_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_megasas_init_firmware(uint64_t pa) -{ -} - -static inline void trace_megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) -{ -} - -static inline void trace_megasas_initq_map_failed(int frame) -{ -} - -static inline void trace_megasas_initq_mismatch(int queue_len, int fw_cmds) -{ -} - -static inline void trace_megasas_qf_found(unsigned int index, uint64_t pa) -{ -} - -static inline void trace_megasas_qf_new(unsigned int index, void * cmd) -{ -} - -static inline void trace_megasas_qf_failed(unsigned long pa) -{ -} - -static inline void trace_megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) -{ -} - -static inline void trace_megasas_qf_update(unsigned int head, unsigned int busy) -{ -} - -static inline void trace_megasas_qf_dequeue(unsigned int index) -{ -} - -static inline void trace_megasas_qf_map_failed(int cmd, unsigned long frame) -{ -} - -static inline void trace_megasas_qf_complete_noirq(uint64_t context) -{ -} - -static inline void trace_megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) -{ -} - -static inline void trace_megasas_handle_frame(const char * cmd, uint64_t addr, uint64_t context, uint32_t count) -{ -} - -static inline void trace_megasas_frame_busy(uint64_t addr) -{ -} - -static inline void trace_megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) -{ -} - -static inline void trace_megasas_handle_scsi(const char * frame, int bus, int dev, int lun, void * sdev, unsigned long size) -{ -} - -static inline void trace_megasas_scsi_target_not_present(const char * frame, int bus, int dev, int lun) -{ -} - -static inline void trace_megasas_scsi_invalid_cdb_len(const char * frame, int bus, int dev, int lun, int len) -{ -} - -static inline void trace_megasas_iov_read_overflow(int cmd, int bytes, int len) -{ -} - -static inline void trace_megasas_iov_write_overflow(int cmd, int bytes, int len) -{ -} - -static inline void trace_megasas_iov_read_underflow(int cmd, int bytes, int len) -{ -} - -static inline void trace_megasas_iov_write_underflow(int cmd, int bytes, int len) -{ -} - -static inline void trace_megasas_scsi_req_alloc_failed(const char * frame, int dev, int lun) -{ -} - -static inline void trace_megasas_scsi_read_start(int cmd, int len) -{ -} - -static inline void trace_megasas_scsi_write_start(int cmd, int len) -{ -} - -static inline void trace_megasas_scsi_nodata(int cmd) -{ -} - -static inline void trace_megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) -{ -} - -static inline void trace_megasas_command_complete(int cmd, uint32_t status, uint32_t resid) -{ -} - -static inline void trace_megasas_handle_io(int cmd, const char * frame, int dev, int lun, unsigned long lba, unsigned long count) -{ -} - -static inline void trace_megasas_io_target_not_present(int cmd, const char * frame, int dev, int lun) -{ -} - -static inline void trace_megasas_io_read_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) -{ -} - -static inline void trace_megasas_io_write_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) -{ -} - -static inline void trace_megasas_io_complete(int cmd, uint32_t len) -{ -} - -static inline void trace_megasas_io_read(int cmd, int bytes, int len, unsigned long offset) -{ -} - -static inline void trace_megasas_io_write(int cmd, int bytes, int len, unsigned long offset) -{ -} - -static inline void trace_megasas_io_continue(int cmd, int bytes) -{ -} - -static inline void trace_megasas_iovec_map_failed(int cmd, int index, unsigned long iov_size) -{ -} - -static inline void trace_megasas_iovec_sgl_overflow(int cmd, int index, int limit) -{ -} - -static inline void trace_megasas_iovec_sgl_underflow(int cmd, int index) -{ -} - -static inline void trace_megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) -{ -} - -static inline void trace_megasas_iovec_overflow(int cmd, int len, int limit) -{ -} - -static inline void trace_megasas_iovec_underflow(int cmd, int len, int limit) -{ -} - -static inline void trace_megasas_handle_dcmd(int cmd, int opcode) -{ -} - -static inline void trace_megasas_finish_dcmd(int cmd, int size) -{ -} - -static inline void trace_megasas_dcmd_req_alloc_failed(int cmd, const char * desc) -{ -} - -static inline void trace_megasas_dcmd_internal_submit(int cmd, const char * desc, int dev) -{ -} - -static inline void trace_megasas_dcmd_internal_finish(int cmd, int opcode, int lun) -{ -} - -static inline void trace_megasas_dcmd_internal_invalid(int cmd, int opcode) -{ -} - -static inline void trace_megasas_dcmd_unhandled(int cmd, int opcode, int len) -{ -} - -static inline void trace_megasas_dcmd_zero_sge(int cmd) -{ -} - -static inline void trace_megasas_dcmd_invalid_sge(int cmd, int count) -{ -} - -static inline void trace_megasas_dcmd_map_failed(int cmd) -{ -} - -static inline void trace_megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) -{ -} - -static inline void trace_megasas_dcmd_enter(int cmd, const char * dcmd, int len) -{ -} - -static inline void trace_megasas_dcmd_dummy(int cmd, unsigned long size) -{ -} - -static inline void trace_megasas_dcmd_set_fw_time(int cmd, unsigned long time) -{ -} - -static inline void trace_megasas_dcmd_pd_get_list(int cmd, int num, int max, int offset) -{ -} - -static inline void trace_megasas_dcmd_ld_get_list(int cmd, int num, int max) -{ -} - -static inline void trace_megasas_dcmd_ld_get_info(int cmd, int ld_id) -{ -} - -static inline void trace_megasas_dcmd_pd_get_info(int cmd, int pd_id) -{ -} - -static inline void trace_megasas_dcmd_pd_list_query(int cmd, int flags) -{ -} - -static inline void trace_megasas_dcmd_unsupported(int cmd, unsigned long size) -{ -} - -static inline void trace_megasas_abort_frame(int cmd, int abort_cmd) -{ -} - -static inline void trace_megasas_abort_no_cmd(int cmd, uint64_t context) -{ -} - -static inline void trace_megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) -{ -} - -static inline void trace_megasas_reset(void) -{ -} - -static inline void trace_megasas_init(int sges, int cmds, const char * intr, const char * mode) -{ -} - -static inline void trace_megasas_msix_raise(int vector) -{ -} - -static inline void trace_megasas_irq_lower(void) -{ -} - -static inline void trace_megasas_irq_raise(void) -{ -} - -static inline void trace_megasas_intr_enabled(void) -{ -} - -static inline void trace_megasas_intr_disabled(void) -{ -} - -static inline void trace_megasas_mmio_readl(unsigned long addr, uint32_t val) -{ -} - -static inline void trace_megasas_mmio_invalid_readl(unsigned long addr) -{ -} - -static inline void trace_megasas_mmio_writel(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_megasas_mmio_invalid_writel(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_milkymist_ac97_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_ac97_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_ac97_pulse_irq_crrequest(void) -{ -} - -static inline void trace_milkymist_ac97_pulse_irq_crreply(void) -{ -} - -static inline void trace_milkymist_ac97_pulse_irq_dmaw(void) -{ -} - -static inline void trace_milkymist_ac97_pulse_irq_dmar(void) -{ -} - -static inline void trace_milkymist_ac97_in_cb(int avail, uint32_t remaining) -{ -} - -static inline void trace_milkymist_ac97_in_cb_transferred(int transferred) -{ -} - -static inline void trace_milkymist_ac97_out_cb(int free, uint32_t remaining) -{ -} - -static inline void trace_milkymist_ac97_out_cb_transferred(int transferred) -{ -} - -static inline void trace_milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_memcard_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_memcard_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) -{ -} - -static inline void trace_milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) -{ -} - -static inline void trace_milkymist_minimac2_tx_frame(uint32_t length) -{ -} - -static inline void trace_milkymist_minimac2_rx_frame(const void * buf, uint32_t length) -{ -} - -static inline void trace_milkymist_minimac2_drop_rx_frame(const void * buf) -{ -} - -static inline void trace_milkymist_minimac2_rx_transfer(const void * buf, uint32_t length) -{ -} - -static inline void trace_milkymist_minimac2_raise_irq_rx(void) -{ -} - -static inline void trace_milkymist_minimac2_lower_irq_rx(void) -{ -} - -static inline void trace_milkymist_minimac2_pulse_irq_tx(void) -{ -} - -static inline void trace_milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) -{ -} - -static inline void trace_milkymist_pfpu_pulse_irq(void) -{ -} - -static inline void trace_milkymist_softusb_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_softusb_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_softusb_mevt(uint8_t m) -{ -} - -static inline void trace_milkymist_softusb_kevt(uint8_t m) -{ -} - -static inline void trace_milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) -{ -} - -static inline void trace_milkymist_softusb_pulse_irq(void) -{ -} - -static inline void trace_milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_sysctl_icap_write(uint32_t value) -{ -} - -static inline void trace_milkymist_sysctl_start_timer0(void) -{ -} - -static inline void trace_milkymist_sysctl_stop_timer0(void) -{ -} - -static inline void trace_milkymist_sysctl_start_timer1(void) -{ -} - -static inline void trace_milkymist_sysctl_stop_timer1(void) -{ -} - -static inline void trace_milkymist_sysctl_pulse_irq_timer0(void) -{ -} - -static inline void trace_milkymist_sysctl_pulse_irq_timer1(void) -{ -} - -static inline void trace_milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_tmu2_start(void) -{ -} - -static inline void trace_milkymist_tmu2_pulse_irq(void) -{ -} - -static inline void trace_milkymist_uart_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_uart_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_uart_raise_irq(void) -{ -} - -static inline void trace_milkymist_uart_lower_irq(void) -{ -} - -static inline void trace_milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) -{ -} - -static inline void trace_mipsnet_send(uint32_t size) -{ -} - -static inline void trace_mipsnet_receive(uint32_t size) -{ -} - -static inline void trace_mipsnet_read(uint64_t addr, uint32_t val) -{ -} - -static inline void trace_mipsnet_write(uint64_t addr, uint64_t val) -{ -} - -static inline void trace_mipsnet_irq(uint32_t isr, uint32_t intctl) -{ -} - -static inline void trace_pc87312_io_read(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_pc87312_io_write(uint32_t addr, uint32_t val) -{ -} - -static inline void trace_pc87312_info_floppy(uint32_t base) -{ -} - -static inline void trace_pc87312_info_ide(uint32_t base) -{ -} - -static inline void trace_pc87312_info_parallel(uint32_t base, uint32_t irq) -{ -} - -static inline void trace_pc87312_info_serial(int n, uint32_t base, uint32_t irq) -{ -} - -static inline void trace_pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) -{ -} - -static inline void trace_pvscsi_ring_init_msg(uint32_t len_log2) -{ -} - -static inline void trace_pvscsi_ring_flush_cmp(uint64_t filled_cmp_ptr) -{ -} - -static inline void trace_pvscsi_ring_flush_msg(uint64_t filled_cmp_ptr) -{ -} - -static inline void trace_pvscsi_update_irq_level(bool raise, uint64_t mask, uint64_t status) -{ -} - -static inline void trace_pvscsi_update_irq_msi(void) -{ -} - -static inline void trace_pvscsi_cmp_ring_put(unsigned long addr) -{ -} - -static inline void trace_pvscsi_msg_ring_put(unsigned long addr) -{ -} - -static inline void trace_pvscsi_complete_request(uint64_t context, uint64_t len, uint8_t sense_key) -{ -} - -static inline void trace_pvscsi_get_sg_list(int nsg, size_t size) -{ -} - -static inline void trace_pvscsi_get_next_sg_elem(uint32_t flags) -{ -} - -static inline void trace_pvscsi_command_complete_not_found(uint32_t tag) -{ -} - -static inline void trace_pvscsi_command_complete_data_run(void) -{ -} - -static inline void trace_pvscsi_command_complete_sense_len(int len) -{ -} - -static inline void trace_pvscsi_convert_sglist(uint64_t context, unsigned long addr, uint32_t resid) -{ -} - -static inline void trace_pvscsi_process_req_descr(uint8_t cmd, uint64_t ctx) -{ -} - -static inline void trace_pvscsi_process_req_descr_unknown_device(void) -{ -} - -static inline void trace_pvscsi_process_req_descr_invalid_dir(void) -{ -} - -static inline void trace_pvscsi_process_io(unsigned long addr) -{ -} - -static inline void trace_pvscsi_on_cmd_noimpl(const char* cmd) -{ -} - -static inline void trace_pvscsi_on_cmd_reset_dev(uint32_t tgt, int lun, void* dev) -{ -} - -static inline void trace_pvscsi_on_cmd_arrived(const char* cmd) -{ -} - -static inline void trace_pvscsi_on_cmd_abort(uint64_t ctx, uint32_t tgt) -{ -} - -static inline void trace_pvscsi_on_cmd_unknown(uint64_t cmd_id) -{ -} - -static inline void trace_pvscsi_on_cmd_unknown_data(uint32_t data) -{ -} - -static inline void trace_pvscsi_io_write(const char* cmd, uint64_t val) -{ -} - -static inline void trace_pvscsi_io_write_unknown(unsigned long addr, unsigned sz, uint64_t val) -{ -} - -static inline void trace_pvscsi_io_read(const char* cmd, uint64_t status) -{ -} - -static inline void trace_pvscsi_io_read_unknown(unsigned long addr, unsigned sz) -{ -} - -static inline void trace_pvscsi_init_msi_fail(int res) -{ -} - -static inline void trace_pvscsi_state(const char* state) -{ -} - -static inline void trace_pvscsi_tx_rings_ppn(const char* label, uint64_t ppn) -{ -} - -static inline void trace_pvscsi_tx_rings_num_pages(const char* label, uint32_t num) -{ -} - -static inline void trace_xen_ram_alloc(unsigned long ram_addr, unsigned long size) -{ -} - -static inline void trace_xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) -{ -} - -static inline void trace_xen_map_cache(uint64_t phys_addr) -{ -} - -static inline void trace_xen_remap_bucket(uint64_t index) -{ -} - -static inline void trace_xen_map_cache_return(void* ptr) -{ -} - -static inline void trace_xen_map_block(uint64_t phys_addr, uint64_t size) -{ -} - -static inline void trace_xen_unmap_block(void* addr, unsigned long size) -{ -} - -static inline void trace_xen_platform_log(char * s) -{ -} - -static inline void trace_qemu_coroutine_enter(void * from, void * to, void * opaque) -{ -} - -static inline void trace_qemu_coroutine_yield(void * from, void * to) -{ -} - -static inline void trace_qemu_coroutine_terminate(void * co) -{ -} - -static inline void trace_qemu_co_queue_run_restart(void * co) -{ -} - -static inline void trace_qemu_co_queue_next(void * nxt) -{ -} - -static inline void trace_qemu_co_mutex_lock_entry(void * mutex, void * self) -{ -} - -static inline void trace_qemu_co_mutex_lock_return(void * mutex, void * self) -{ -} - -static inline void trace_qemu_co_mutex_unlock_entry(void * mutex, void * self) -{ -} - -static inline void trace_qemu_co_mutex_unlock_return(void * mutex, void * self) -{ -} - -static inline void trace_escc_put_queue(char channel, int b) -{ -} - -static inline void trace_escc_get_queue(char channel, int val) -{ -} - -static inline void trace_escc_update_irq(int irq) -{ -} - -static inline void trace_escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) -{ -} - -static inline void trace_escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) -{ -} - -static inline void trace_escc_mem_writeb_data(char channel, uint32_t val) -{ -} - -static inline void trace_escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) -{ -} - -static inline void trace_escc_mem_readb_data(char channel, uint32_t ret) -{ -} - -static inline void trace_escc_serial_receive_byte(char channel, int ch) -{ -} - -static inline void trace_escc_sunkbd_event_in(int ch) -{ -} - -static inline void trace_escc_sunkbd_event_out(int ch) -{ -} - -static inline void trace_escc_kbd_command(int val) -{ -} - -static inline void trace_escc_sunmouse_event(int dx, int dy, int buttons_state) -{ -} - -static inline void trace_iscsi_aio_write16_cb(void * iscsi, int status, void * acb, int canceled) -{ -} - -static inline void trace_iscsi_aio_writev(void * iscsi, int64_t sector_num, int nb_sectors, void * opaque, void * acb) -{ -} - -static inline void trace_iscsi_aio_read16_cb(void * iscsi, int status, void * acb, int canceled) -{ -} - -static inline void trace_iscsi_aio_readv(void * iscsi, int64_t sector_num, int nb_sectors, void * opaque, void * acb) -{ -} - -static inline void trace_esp_error_fifo_overrun(void) -{ -} - -static inline void trace_esp_error_unhandled_command(uint32_t val) -{ -} - -static inline void trace_esp_error_invalid_write(uint32_t val, uint32_t addr) -{ -} - -static inline void trace_esp_raise_irq(void) -{ -} - -static inline void trace_esp_lower_irq(void) -{ -} - -static inline void trace_esp_dma_enable(void) -{ -} - -static inline void trace_esp_dma_disable(void) -{ -} - -static inline void trace_esp_get_cmd(uint32_t dmalen, int target) -{ -} - -static inline void trace_esp_do_busid_cmd(uint8_t busid) -{ -} - -static inline void trace_esp_handle_satn_stop(uint32_t cmdlen) -{ -} - -static inline void trace_esp_write_response(uint32_t status) -{ -} - -static inline void trace_esp_do_dma(uint32_t cmdlen, uint32_t len) -{ -} - -static inline void trace_esp_command_complete(void) -{ -} - -static inline void trace_esp_command_complete_unexpected(void) -{ -} - -static inline void trace_esp_command_complete_fail(void) -{ -} - -static inline void trace_esp_transfer_data(uint32_t dma_left, int32_t ti_size) -{ -} - -static inline void trace_esp_handle_ti(uint32_t minlen) -{ -} - -static inline void trace_esp_handle_ti_cmd(uint32_t cmdlen) -{ -} - -static inline void trace_esp_mem_readb(uint32_t saddr, uint8_t reg) -{ -} - -static inline void trace_esp_mem_writeb(uint32_t saddr, uint8_t reg, uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_nop(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_flush(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_reset(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_bus_reset(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_iccs(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_msgacc(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_pad(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_satn(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_rstatn(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_sel(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_selatn(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_selatns(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_ensel(uint32_t val) -{ -} - -static inline void trace_esp_mem_writeb_cmd_dissel(uint32_t val) -{ -} - -static inline void trace_esp_pci_error_invalid_dma_direction(void) -{ -} - -static inline void trace_esp_pci_error_invalid_read(uint32_t reg) -{ -} - -static inline void trace_esp_pci_error_invalid_write(uint32_t reg) -{ -} - -static inline void trace_esp_pci_error_invalid_write_dma(uint32_t val, uint32_t addr) -{ -} - -static inline void trace_esp_pci_dma_read(uint32_t saddr, uint32_t reg) -{ -} - -static inline void trace_esp_pci_dma_write(uint32_t saddr, uint32_t reg, uint32_t val) -{ -} - -static inline void trace_esp_pci_dma_idle(uint32_t val) -{ -} - -static inline void trace_esp_pci_dma_blast(uint32_t val) -{ -} - -static inline void trace_esp_pci_dma_abort(uint32_t val) -{ -} - -static inline void trace_esp_pci_dma_start(uint32_t val) -{ -} - -static inline void trace_esp_pci_sbac_read(uint32_t reg) -{ -} - -static inline void trace_esp_pci_sbac_write(uint32_t reg, uint32_t val) -{ -} - -static inline void trace_handle_qmp_command(void * mon, const char * cmd_name) -{ -} - -static inline void trace_monitor_protocol_emitter(void * mon) -{ -} - -static inline void trace_monitor_protocol_event(uint32_t event, const char * evname, void * data) -{ -} - -static inline void trace_monitor_protocol_event_handler(uint32_t event, void * data, uint64_t last, uint64_t now) -{ -} - -static inline void trace_monitor_protocol_event_emit(uint32_t event, void * data) -{ -} - -static inline void trace_monitor_protocol_event_queue(uint32_t event, void * data, uint64_t rate, uint64_t last, uint64_t now) -{ -} - -static inline void trace_monitor_protocol_event_throttle(uint32_t event, uint64_t rate) -{ -} - -static inline void trace_open_eth_mii_write(unsigned idx, uint16_t v) -{ -} - -static inline void trace_open_eth_mii_read(unsigned idx, uint16_t v) -{ -} - -static inline void trace_open_eth_update_irq(uint32_t v) -{ -} - -static inline void trace_open_eth_receive(unsigned len) -{ -} - -static inline void trace_open_eth_receive_mcast(unsigned idx, uint32_t h0, uint32_t h1) -{ -} - -static inline void trace_open_eth_receive_reject(void) -{ -} - -static inline void trace_open_eth_receive_desc(uint32_t addr, uint32_t len_flags) -{ -} - -static inline void trace_open_eth_start_xmit(uint32_t addr, unsigned len, unsigned tx_len) -{ -} - -static inline void trace_open_eth_reg_read(uint32_t addr, uint32_t v) -{ -} - -static inline void trace_open_eth_reg_write(uint32_t addr, uint32_t v) -{ -} - -static inline void trace_open_eth_desc_read(uint32_t addr, uint32_t v) -{ -} - -static inline void trace_open_eth_desc_write(uint32_t addr, uint32_t v) -{ -} - -static inline void trace_v9fs_rerror(uint16_t tag, uint8_t id, int err) -{ -} - -static inline void trace_v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) -{ -} - -static inline void trace_v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) -{ -} - -static inline void trace_v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) -{ -} - -static inline void trace_v9fs_attach_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) -{ -} - -static inline void trace_v9fs_stat(uint16_t tag, uint8_t id, int32_t fid) -{ -} - -static inline void trace_v9fs_stat_return(uint16_t tag, uint8_t id, int32_t mode, int32_t atime, int32_t mtime, int64_t length) -{ -} - -static inline void trace_v9fs_getattr(uint16_t tag, uint8_t id, int32_t fid, uint64_t request_mask) -{ -} - -static inline void trace_v9fs_getattr_return(uint16_t tag, uint8_t id, uint64_t result_mask, uint32_t mode, uint32_t uid, uint32_t gid) -{ -} - -static inline void trace_v9fs_walk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, uint16_t nwnames) -{ -} - -static inline void trace_v9fs_walk_return(uint16_t tag, uint8_t id, uint16_t nwnames, void* qids) -{ -} - -static inline void trace_v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode) -{ -} - -static inline void trace_v9fs_open_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) -{ -} - -static inline void trace_v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode, uint32_t gid) -{ -} - -static inline void trace_v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) -{ -} - -static inline void trace_v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) -{ -} - -static inline void trace_v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) -{ -} - -static inline void trace_v9fs_read(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t max_count) -{ -} - -static inline void trace_v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) -{ -} - -static inline void trace_v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, uint64_t offset, uint32_t max_count) -{ -} - -static inline void trace_v9fs_readdir_return(uint16_t tag, uint8_t id, uint32_t count, ssize_t retval) -{ -} - -static inline void trace_v9fs_write(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t count, int cnt) -{ -} - -static inline void trace_v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) -{ -} - -static inline void trace_v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) -{ -} - -static inline void trace_v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) -{ -} - -static inline void trace_v9fs_symlink(uint16_t tag, uint8_t id, int32_t fid, char* name, char* symname, uint32_t gid) -{ -} - -static inline void trace_v9fs_symlink_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) -{ -} - -static inline void trace_v9fs_flush(uint16_t tag, uint8_t id, int16_t flush_tag) -{ -} - -static inline void trace_v9fs_link(uint16_t tag, uint8_t id, int32_t dfid, int32_t oldfid, char* name) -{ -} - -static inline void trace_v9fs_remove(uint16_t tag, uint8_t id, int32_t fid) -{ -} - -static inline void trace_v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) -{ -} - -static inline void trace_v9fs_mknod(uint16_t tag, uint8_t id, int32_t fid, int mode, int major, int minor) -{ -} - -static inline void trace_v9fs_mknod_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) -{ -} - -static inline void trace_v9fs_lock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) -{ -} - -static inline void trace_v9fs_lock_return(uint16_t tag, uint8_t id, int8_t status) -{ -} - -static inline void trace_v9fs_getlock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) -{ -} - -static inline void trace_v9fs_getlock_return(uint16_t tag, uint8_t id, uint8_t type, uint64_t start, uint64_t length, uint32_t proc_id) -{ -} - -static inline void trace_v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) -{ -} - -static inline void trace_v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) -{ -} - -static inline void trace_v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) -{ -} - -static inline void trace_v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) -{ -} - -static inline void trace_v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) -{ -} - -static inline void trace_v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) -{ -} - -static inline void trace_v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) -{ -} - -static inline void trace_mmu_helper_dfault(uint64_t address, uint64_t context, int mmu_idx, uint32_t tl) -{ -} - -static inline void trace_mmu_helper_dprot(uint64_t address, uint64_t context, int mmu_idx, uint32_t tl) -{ -} - -static inline void trace_mmu_helper_dmiss(uint64_t address, uint64_t context) -{ -} - -static inline void trace_mmu_helper_tfault(uint64_t address, uint64_t context) -{ -} - -static inline void trace_mmu_helper_tmiss(uint64_t address, uint64_t context) -{ -} - -static inline void trace_mmu_helper_get_phys_addr_code(uint32_t tl, int mmu_idx, uint64_t prim_context, uint64_t sec_context, uint64_t address) -{ -} - -static inline void trace_mmu_helper_get_phys_addr_data(uint32_t tl, int mmu_idx, uint64_t prim_context, uint64_t sec_context, uint64_t address) -{ -} - -static inline void trace_mmu_helper_mmu_fault(uint64_t address, uint64_t paddr, int mmu_idx, uint32_t tl, uint64_t prim_context, uint64_t sec_context) -{ -} - -static inline void trace_int_helper_set_softint(uint32_t softint) -{ -} - -static inline void trace_int_helper_clear_softint(uint32_t softint) -{ -} - -static inline void trace_int_helper_write_softint(uint32_t softint) -{ -} - -static inline void trace_int_helper_icache_freeze(void) -{ -} - -static inline void trace_int_helper_dcache_freeze(void) -{ -} - -static inline void trace_win_helper_gregset_error(uint32_t pstate) -{ -} - -static inline void trace_win_helper_switch_pstate(uint32_t pstate_regs, uint32_t new_pstate_regs) -{ -} - -static inline void trace_win_helper_no_switch_pstate(uint32_t new_pstate_regs) -{ -} - -static inline void trace_win_helper_wrpil(uint32_t psrpil, uint32_t new_pil) -{ -} - -static inline void trace_win_helper_done(uint32_t tl) -{ -} - -static inline void trace_win_helper_retry(uint32_t tl) -{ -} - -static inline void trace_dma_bdrv_io(void * dbs, void * bs, int64_t sector_num, bool to_dev) -{ -} - -static inline void trace_dma_aio_cancel(void * dbs) -{ -} - -static inline void trace_dma_complete(void * dbs, int ret, void * cb) -{ -} - -static inline void trace_dma_bdrv_cb(void * dbs, int ret) -{ -} - -static inline void trace_dma_map_wait(void * dbs) -{ -} - -static inline void trace_console_gfx_new(void) -{ -} - -static inline void trace_console_txt_new(int w, int h) -{ -} - -static inline void trace_console_select(int nr) -{ -} - -static inline void trace_console_refresh(int interval) -{ -} - -static inline void trace_displaysurface_create(void * display_surface, int w, int h) -{ -} - -static inline void trace_displaysurface_create_from(void * display_surface, int w, int h, int bpp, int swap) -{ -} - -static inline void trace_displaysurface_free(void * display_surface) -{ -} - -static inline void trace_displaychangelistener_register(void * dcl, const char * name) -{ -} - -static inline void trace_displaychangelistener_unregister(void * dcl, const char * name) -{ -} - -static inline void trace_ppm_save(const char * filename, void * display_surface) -{ -} - -static inline void trace_vmware_value_read(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_value_write(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_palette_read(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_palette_write(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_scratch_read(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_scratch_write(uint32_t index, uint32_t value) -{ -} - -static inline void trace_vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) -{ -} - -static inline void trace_savevm_section_start(void) -{ -} - -static inline void trace_savevm_section_end(unsigned int section_id) -{ -} - -static inline void trace_migration_bitmap_sync_start(void) -{ -} - -static inline void trace_migration_bitmap_sync_end(uint64_t dirty_pages) -{ -} - -static inline void trace_migration_throttle(void) -{ -} - -static inline void trace_qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) -{ -} - -static inline void trace_qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) -{ -} - -static inline void trace_qxl_destroy_primary(int qid) -{ -} - -static inline void trace_qxl_enter_vga_mode(int qid) -{ -} - -static inline void trace_qxl_exit_vga_mode(int qid) -{ -} - -static inline void trace_qxl_hard_reset(int qid, int64_t loadvm) -{ -} - -static inline void trace_qxl_interface_async_complete_io(int qid, uint32_t current_async, void * cookie) -{ -} - -static inline void trace_qxl_interface_attach_worker(int qid) -{ -} - -static inline void trace_qxl_interface_get_init_info(int qid) -{ -} - -static inline void trace_qxl_interface_set_compression_level(int qid, int64_t level) -{ -} - -static inline void trace_qxl_interface_update_area_complete(int qid, uint32_t surface_id, uint32_t dirty_left, uint32_t dirty_right, uint32_t dirty_top, uint32_t dirty_bottom) -{ -} - -static inline void trace_qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) -{ -} - -static inline void trace_qxl_interface_update_area_complete_overflow(int qid, int max) -{ -} - -static inline void trace_qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) -{ -} - -static inline void trace_qxl_io_destroy_primary_ignored(int qid, const char * mode) -{ -} - -static inline void trace_qxl_io_log(int qid, const uint8_t * log_buf) -{ -} - -static inline void trace_qxl_io_read_unexpected(int qid) -{ -} - -static inline void trace_qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char * desc) -{ -} - -static inline void trace_qxl_io_write(int qid, const char * mode, uint64_t addr, uint64_t val, unsigned size, int async) -{ -} - -static inline void trace_qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) -{ -} - -static inline void trace_qxl_post_load(int qid, const char * mode) -{ -} - -static inline void trace_qxl_pre_load(int qid) -{ -} - -static inline void trace_qxl_pre_save(int qid) -{ -} - -static inline void trace_qxl_reset_surfaces(int qid) -{ -} - -static inline void trace_qxl_ring_command_check(int qid, const char * mode) -{ -} - -static inline void trace_qxl_ring_command_get(int qid, const char * mode) -{ -} - -static inline void trace_qxl_ring_command_req_notification(int qid) -{ -} - -static inline void trace_qxl_ring_cursor_check(int qid, const char * mode) -{ -} - -static inline void trace_qxl_ring_cursor_get(int qid, const char * mode) -{ -} - -static inline void trace_qxl_ring_cursor_req_notification(int qid) -{ -} - -static inline void trace_qxl_ring_res_push(int qid, const char * mode, uint32_t surface_count, uint32_t free_res, void * last_release, const char * notify) -{ -} - -static inline void trace_qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t prod, uint32_t cons) -{ -} - -static inline void trace_qxl_ring_res_put(int qid, uint32_t free_res) -{ -} - -static inline void trace_qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) -{ -} - -static inline void trace_qxl_soft_reset(int qid) -{ -} - -static inline void trace_qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) -{ -} - -static inline void trace_qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) -{ -} - -static inline void trace_qemu_spice_create_primary_surface(int qid, uint32_t sid, void * surface, int async) -{ -} - -static inline void trace_qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) -{ -} - -static inline void trace_qemu_spice_wakeup(uint32_t qid) -{ -} - -static inline void trace_qemu_spice_start(uint32_t qid) -{ -} - -static inline void trace_qemu_spice_stop(uint32_t qid) -{ -} - -static inline void trace_qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) -{ -} - -static inline void trace_qxl_spice_destroy_surfaces_complete(int qid) -{ -} - -static inline void trace_qxl_spice_destroy_surfaces(int qid, int async) -{ -} - -static inline void trace_qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) -{ -} - -static inline void trace_qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) -{ -} - -static inline void trace_qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) -{ -} - -static inline void trace_qxl_spice_monitors_config(int qid) -{ -} - -static inline void trace_qxl_spice_loadvm_commands(int qid, void * ext, uint32_t count) -{ -} - -static inline void trace_qxl_spice_oom(int qid) -{ -} - -static inline void trace_qxl_spice_reset_cursor(int qid) -{ -} - -static inline void trace_qxl_spice_reset_image_cache(int qid) -{ -} - -static inline void trace_qxl_spice_reset_memslots(int qid) -{ -} - -static inline void trace_qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) -{ -} - -static inline void trace_qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) -{ -} - -static inline void trace_qxl_surfaces_dirty(int qid, int surface, int offset, int size) -{ -} - -static inline void trace_qxl_send_events(int qid, uint32_t events) -{ -} - -static inline void trace_qxl_send_events_vm_stopped(int qid, uint32_t events) -{ -} - -static inline void trace_qxl_set_guest_bug(int qid) -{ -} - -static inline void trace_qxl_interrupt_client_monitors_config(int qid, int num_heads, void * heads) -{ -} - -static inline void trace_qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void * client_monitors_config) -{ -} - -static inline void trace_qxl_client_monitors_config_unsupported_by_device(int qid, int revision) -{ -} - -static inline void trace_qxl_client_monitors_config_capped(int qid, int requested, int limit) -{ -} - -static inline void trace_qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) -{ -} - -static inline void trace_qxl_set_client_capabilities_unsupported_by_revision(int qid, int revision) -{ -} - -static inline void trace_qxl_render_blit_guest_primary_initialized(void) -{ -} - -static inline void trace_qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) -{ -} - -static inline void trace_qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) -{ -} - -static inline void trace_qxl_render_update_area_done(void * cookie) -{ -} - -static inline void trace_spapr_pci_msi(const char * msg, uint32_t n, uint32_t ca) -{ -} - -static inline void trace_spapr_pci_msi_setup(const char * name, unsigned vector, uint64_t addr) -{ -} - -static inline void trace_spapr_pci_rtas_ibm_change_msi(unsigned func, unsigned req) -{ -} - -static inline void trace_spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) -{ -} - -static inline void trace_spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) -{ -} - -static inline void trace_spapr_pci_lsi_set(const char * busname, int pin, uint32_t irq) -{ -} - -static inline void trace_xics_icp_check_ipi(int server, uint8_t mfrr) -{ -} - -static inline void trace_xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) -{ -} - -static inline void trace_xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) -{ -} - -static inline void trace_xics_icp_irq(int server, int nr, uint8_t priority) -{ -} - -static inline void trace_xics_icp_raise(uint32_t xirr, uint8_t pending_priority) -{ -} - -static inline void trace_xics_set_irq_msi(int srcno, int nr) -{ -} - -static inline void trace_xics_masked_pending(void) -{ -} - -static inline void trace_xics_set_irq_lsi(int srcno, int nr) -{ -} - -static inline void trace_xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) -{ -} - -static inline void trace_xics_ics_reject(int nr, int srcno) -{ -} - -static inline void trace_xics_ics_eoi(int nr) -{ -} - -static inline void trace_hbitmap_iter_skip_words(const void * hb, void * hbi, uint64_t pos, unsigned long cur) -{ -} - -static inline void trace_hbitmap_reset(void * hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) -{ -} - -static inline void trace_hbitmap_set(void * hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) -{ -} - -static inline void trace_ioinst(const char * insn) -{ -} - -static inline void trace_ioinst_sch_id(const char * insn, int cssid, int ssid, int schid) -{ -} - -static inline void trace_ioinst_chp_id(const char * insn, int cssid, int chpid) -{ -} - -static inline void trace_ioinst_chsc_cmd(uint16_t cmd, uint16_t len) -{ -} - -static inline void trace_css_enable_facility(const char * facility) -{ -} - -static inline void trace_css_crw(uint8_t rsc, uint8_t erc, uint16_t rsid, const char * chained) -{ -} - -static inline void trace_css_chpid_add(uint8_t cssid, uint8_t chpid, uint8_t type) -{ -} - -static inline void trace_css_new_image(uint8_t cssid, const char * default_cssid) -{ -} - -static inline void trace_css_assign_subch(const char * do_assign, uint8_t cssid, uint8_t ssid, uint16_t schid, uint16_t devno) -{ -} - -static inline void trace_css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc, const char * conditional) -{ -} - -static inline void trace_virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) -{ -} - -static inline void trace_virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char * devno_mode) -{ -} - -static inline void trace_migrate_set_state(int new_state) -{ -} - -static inline void trace_kvm_ioctl(int type, void * arg) -{ -} - -static inline void trace_kvm_vm_ioctl(int type, void * arg) -{ -} - -static inline void trace_kvm_vcpu_ioctl(int cpu_index, int type, void * arg) -{ -} - -static inline void trace_kvm_run_exit(int cpu_index, uint32_t reason) -{ -} - -static inline void trace_object_dynamic_cast_assert(const char * type, const char * target, const char * file, int line, const char * func) -{ -} - -static inline void trace_object_class_dynamic_cast_assert(const char * type, const char * target, const char * file, int line, const char * func) -{ -} -#endif /* TRACE__GENERATED_TRACERS_H */ diff --git a/contrib/qemu/util/aes.c b/contrib/qemu/util/aes.c deleted file mode 100644 index 91e97fa6e7f..00000000000 --- a/contrib/qemu/util/aes.c +++ /dev/null @@ -1,1314 +0,0 @@ -/** - * - * aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project. - */ -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - * @author Paulo Barreto <paulo.barreto@terra.com.br> - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "qemu-common.h" -#include "qemu/aes.h" - -#ifndef NDEBUG -#define NDEBUG -#endif - -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -/* This controls loop-unrolling in aes_core.c */ -#undef FULL_UNROLL -# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - -/* -AES_Te0[x] = S [x].[02, 01, 01, 03]; -AES_Te1[x] = S [x].[03, 02, 01, 01]; -AES_Te2[x] = S [x].[01, 03, 02, 01]; -AES_Te3[x] = S [x].[01, 01, 03, 02]; -AES_Te4[x] = S [x].[01, 01, 01, 01]; - -AES_Td0[x] = Si[x].[0e, 09, 0d, 0b]; -AES_Td1[x] = Si[x].[0b, 0e, 09, 0d]; -AES_Td2[x] = Si[x].[0d, 0b, 0e, 09]; -AES_Td3[x] = Si[x].[09, 0d, 0b, 0e]; -AES_Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -const uint32_t AES_Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -const uint32_t AES_Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -const uint32_t AES_Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -const uint32_t AES_Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -const uint32_t AES_Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -const uint32_t AES_Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -const uint32_t AES_Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -const uint32_t AES_Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -const uint32_t AES_Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -const uint32_t AES_Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -/** - * Expand the cipher key into the encryption key schedule. - */ -int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) { - - u32 *rk; - int i = 0; - u32 temp; - - if (!userKey || !key) - return -1; - if (bits != 128 && bits != 192 && bits != 256) - return -2; - - rk = key->rd_key; - - if (bits==128) - key->rounds = 10; - else if (bits==192) - key->rounds = 12; - else - key->rounds = 14; - - rk[0] = GETU32(userKey ); - rk[1] = GETU32(userKey + 4); - rk[2] = GETU32(userKey + 8); - rk[3] = GETU32(userKey + 12); - if (bits == 128) { - while (1) { - temp = rk[3]; - rk[4] = rk[0] ^ - (AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - return 0; - } - rk += 4; - } - } - rk[4] = GETU32(userKey + 16); - rk[5] = GETU32(userKey + 20); - if (bits == 192) { - while (1) { - temp = rk[ 5]; - rk[ 6] = rk[ 0] ^ - (AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) { - return 0; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETU32(userKey + 24); - rk[7] = GETU32(userKey + 28); - if (bits == 256) { - while (1) { - temp = rk[ 7]; - rk[ 8] = rk[ 0] ^ - (AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - return 0; - } - temp = rk[11]; - rk[12] = rk[ 4] ^ - (AES_Te4[(temp >> 24) ] & 0xff000000) ^ - (AES_Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(temp ) & 0xff] & 0x000000ff); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - - rk += 8; - } - } - return 0; -} - -/** - * Expand the cipher key into the decryption key schedule. - */ -int AES_set_decrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) { - - u32 *rk; - int i, j, status; - u32 temp; - - /* first, start with an encryption schedule */ - status = AES_set_encrypt_key(userKey, bits, key); - if (status < 0) - return status; - - rk = key->rd_key; - - /* invert the order of the round keys: */ - for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - for (i = 1; i < (key->rounds); i++) { - rk += 4; - rk[0] = - AES_Td0[AES_Te4[(rk[0] >> 24) ] & 0xff] ^ - AES_Td1[AES_Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - AES_Td2[AES_Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - AES_Td3[AES_Te4[(rk[0] ) & 0xff] & 0xff]; - rk[1] = - AES_Td0[AES_Te4[(rk[1] >> 24) ] & 0xff] ^ - AES_Td1[AES_Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - AES_Td2[AES_Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - AES_Td3[AES_Te4[(rk[1] ) & 0xff] & 0xff]; - rk[2] = - AES_Td0[AES_Te4[(rk[2] >> 24) ] & 0xff] ^ - AES_Td1[AES_Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - AES_Td2[AES_Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - AES_Td3[AES_Te4[(rk[2] ) & 0xff] & 0xff]; - rk[3] = - AES_Td0[AES_Te4[(rk[3] >> 24) ] & 0xff] ^ - AES_Td1[AES_Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - AES_Td2[AES_Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - AES_Td3[AES_Te4[(rk[3] ) & 0xff] & 0xff]; - } - return 0; -} - -#ifndef AES_ASM -/* - * Encrypt a single block - * in and out can overlap - */ -void AES_encrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) { - - const u32 *rk; - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in ) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[ 4]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[ 5]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[ 6]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[ 8]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[ 9]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[10]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[12]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[13]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[14]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[16]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[17]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[18]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[20]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[21]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[22]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[24]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[25]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[26]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[28]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[29]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[30]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[32]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[33]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[34]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[36]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[37]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[38]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[39]; - if (key->rounds > 10) { - /* round 10: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[40]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[41]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[42]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[44]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[45]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[46]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[47]; - if (key->rounds > 12) { - /* round 12: */ - s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[48]; - s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[49]; - s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[50]; - s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[52]; - t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[53]; - t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[54]; - t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[55]; - } - } - rk += key->rounds << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = key->rounds >> 1; - for (;;) { - t0 = - AES_Te0[(s0 >> 24) ] ^ - AES_Te1[(s1 >> 16) & 0xff] ^ - AES_Te2[(s2 >> 8) & 0xff] ^ - AES_Te3[(s3 ) & 0xff] ^ - rk[4]; - t1 = - AES_Te0[(s1 >> 24) ] ^ - AES_Te1[(s2 >> 16) & 0xff] ^ - AES_Te2[(s3 >> 8) & 0xff] ^ - AES_Te3[(s0 ) & 0xff] ^ - rk[5]; - t2 = - AES_Te0[(s2 >> 24) ] ^ - AES_Te1[(s3 >> 16) & 0xff] ^ - AES_Te2[(s0 >> 8) & 0xff] ^ - AES_Te3[(s1 ) & 0xff] ^ - rk[6]; - t3 = - AES_Te0[(s3 >> 24) ] ^ - AES_Te1[(s0 >> 16) & 0xff] ^ - AES_Te2[(s1 >> 8) & 0xff] ^ - AES_Te3[(s2 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - AES_Te0[(t0 >> 24) ] ^ - AES_Te1[(t1 >> 16) & 0xff] ^ - AES_Te2[(t2 >> 8) & 0xff] ^ - AES_Te3[(t3 ) & 0xff] ^ - rk[0]; - s1 = - AES_Te0[(t1 >> 24) ] ^ - AES_Te1[(t2 >> 16) & 0xff] ^ - AES_Te2[(t3 >> 8) & 0xff] ^ - AES_Te3[(t0 ) & 0xff] ^ - rk[1]; - s2 = - AES_Te0[(t2 >> 24) ] ^ - AES_Te1[(t3 >> 16) & 0xff] ^ - AES_Te2[(t0 >> 8) & 0xff] ^ - AES_Te3[(t1 ) & 0xff] ^ - rk[2]; - s3 = - AES_Te0[(t3 >> 24) ] ^ - AES_Te1[(t0 >> 16) & 0xff] ^ - AES_Te2[(t1 >> 8) & 0xff] ^ - AES_Te3[(t2 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (AES_Te4[(t0 >> 24) ] & 0xff000000) ^ - (AES_Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(out , s0); - s1 = - (AES_Te4[(t1 >> 24) ] & 0xff000000) ^ - (AES_Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(out + 4, s1); - s2 = - (AES_Te4[(t2 >> 24) ] & 0xff000000) ^ - (AES_Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(out + 8, s2); - s3 = - (AES_Te4[(t3 >> 24) ] & 0xff000000) ^ - (AES_Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(out + 12, s3); -} - -/* - * Decrypt a single block - * in and out can overlap - */ -void AES_decrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) { - - const u32 *rk; - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in ) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[ 4]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[ 5]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[ 6]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[ 8]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[ 9]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[10]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[12]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[13]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[14]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[16]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[17]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[18]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[20]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[21]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[22]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[24]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[25]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[26]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[28]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[29]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[30]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[32]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[33]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[34]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[36]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[37]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[38]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[39]; - if (key->rounds > 10) { - /* round 10: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[40]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[41]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[42]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[44]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[45]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[46]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[47]; - if (key->rounds > 12) { - /* round 12: */ - s0 = AES_Td0[t0 >> 24] ^ AES_Td1[(t3 >> 16) & 0xff] ^ AES_Td2[(t2 >> 8) & 0xff] ^ AES_Td3[t1 & 0xff] ^ rk[48]; - s1 = AES_Td0[t1 >> 24] ^ AES_Td1[(t0 >> 16) & 0xff] ^ AES_Td2[(t3 >> 8) & 0xff] ^ AES_Td3[t2 & 0xff] ^ rk[49]; - s2 = AES_Td0[t2 >> 24] ^ AES_Td1[(t1 >> 16) & 0xff] ^ AES_Td2[(t0 >> 8) & 0xff] ^ AES_Td3[t3 & 0xff] ^ rk[50]; - s3 = AES_Td0[t3 >> 24] ^ AES_Td1[(t2 >> 16) & 0xff] ^ AES_Td2[(t1 >> 8) & 0xff] ^ AES_Td3[t0 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = AES_Td0[s0 >> 24] ^ AES_Td1[(s3 >> 16) & 0xff] ^ AES_Td2[(s2 >> 8) & 0xff] ^ AES_Td3[s1 & 0xff] ^ rk[52]; - t1 = AES_Td0[s1 >> 24] ^ AES_Td1[(s0 >> 16) & 0xff] ^ AES_Td2[(s3 >> 8) & 0xff] ^ AES_Td3[s2 & 0xff] ^ rk[53]; - t2 = AES_Td0[s2 >> 24] ^ AES_Td1[(s1 >> 16) & 0xff] ^ AES_Td2[(s0 >> 8) & 0xff] ^ AES_Td3[s3 & 0xff] ^ rk[54]; - t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[55]; - } - } - rk += key->rounds << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = key->rounds >> 1; - for (;;) { - t0 = - AES_Td0[(s0 >> 24) ] ^ - AES_Td1[(s3 >> 16) & 0xff] ^ - AES_Td2[(s2 >> 8) & 0xff] ^ - AES_Td3[(s1 ) & 0xff] ^ - rk[4]; - t1 = - AES_Td0[(s1 >> 24) ] ^ - AES_Td1[(s0 >> 16) & 0xff] ^ - AES_Td2[(s3 >> 8) & 0xff] ^ - AES_Td3[(s2 ) & 0xff] ^ - rk[5]; - t2 = - AES_Td0[(s2 >> 24) ] ^ - AES_Td1[(s1 >> 16) & 0xff] ^ - AES_Td2[(s0 >> 8) & 0xff] ^ - AES_Td3[(s3 ) & 0xff] ^ - rk[6]; - t3 = - AES_Td0[(s3 >> 24) ] ^ - AES_Td1[(s2 >> 16) & 0xff] ^ - AES_Td2[(s1 >> 8) & 0xff] ^ - AES_Td3[(s0 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - AES_Td0[(t0 >> 24) ] ^ - AES_Td1[(t3 >> 16) & 0xff] ^ - AES_Td2[(t2 >> 8) & 0xff] ^ - AES_Td3[(t1 ) & 0xff] ^ - rk[0]; - s1 = - AES_Td0[(t1 >> 24) ] ^ - AES_Td1[(t0 >> 16) & 0xff] ^ - AES_Td2[(t3 >> 8) & 0xff] ^ - AES_Td3[(t2 ) & 0xff] ^ - rk[1]; - s2 = - AES_Td0[(t2 >> 24) ] ^ - AES_Td1[(t1 >> 16) & 0xff] ^ - AES_Td2[(t0 >> 8) & 0xff] ^ - AES_Td3[(t3 ) & 0xff] ^ - rk[2]; - s3 = - AES_Td0[(t3 >> 24) ] ^ - AES_Td1[(t2 >> 16) & 0xff] ^ - AES_Td2[(t1 >> 8) & 0xff] ^ - AES_Td3[(t0 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (AES_Td4[(t0 >> 24) ] & 0xff000000) ^ - (AES_Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(out , s0); - s1 = - (AES_Td4[(t1 >> 24) ] & 0xff000000) ^ - (AES_Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(out + 4, s1); - s2 = - (AES_Td4[(t2 >> 24) ] & 0xff000000) ^ - (AES_Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(out + 8, s2); - s3 = - (AES_Td4[(t3 >> 24) ] & 0xff000000) ^ - (AES_Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (AES_Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (AES_Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(out + 12, s3); -} - -#endif /* AES_ASM */ - -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc) -{ - - unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - - assert(in && out && key && ivec); - - if (enc) { - while (len >= AES_BLOCK_SIZE) { - for(n=0; n < AES_BLOCK_SIZE; ++n) - tmp[n] = in[n] ^ ivec[n]; - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - for(n=0; n < len; ++n) - tmp[n] = in[n] ^ ivec[n]; - for(n=len; n < AES_BLOCK_SIZE; ++n) - tmp[n] = ivec[n]; - AES_encrypt(tmp, tmp, key); - memcpy(out, tmp, AES_BLOCK_SIZE); - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } else { - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for(n=0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(tmp, tmp, key); - for(n=0; n < len; ++n) - out[n] = tmp[n] ^ ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } -} diff --git a/contrib/qemu/util/bitmap.c b/contrib/qemu/util/bitmap.c deleted file mode 100644 index 687841dcec0..00000000000 --- a/contrib/qemu/util/bitmap.c +++ /dev/null @@ -1,256 +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/bitops.h" -#include "qemu/bitmap.h" - -/* - * bitmaps provide an array of bits, implemented using an 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, int bits) -{ - int 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, int bits) -{ - int 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, int bits) -{ - int 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, - int bits) -{ - int 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, int bits) -{ - int k; - int 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, int bits) -{ - int k; - int 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, int bits) -{ - int k; - int 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, int bits) -{ - int k; - int 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, int start, int nr) -{ - unsigned long *p = map + BIT_WORD(start); - const int 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_clear(unsigned long *map, int start, int nr) -{ - unsigned long *p = map + BIT_WORD(start); - const int 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; - } -} - -#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 int 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, int bits) -{ - int 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/contrib/qemu/util/bitops.c b/contrib/qemu/util/bitops.c deleted file mode 100644 index 227c38b883d..00000000000 --- a/contrib/qemu/util/bitops.c +++ /dev/null @@ -1,158 +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/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/contrib/qemu/util/cutils.c b/contrib/qemu/util/cutils.c deleted file mode 100644 index 6caa4b8ddc4..00000000000 --- a/contrib/qemu/util/cutils.c +++ /dev/null @@ -1,532 +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-common.h" -#include "qemu/host-utils.h" -#include <math.h> - -#include "qemu/sockets.h" -#include "qemu/iov.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; -} - -int qemu_fls(int i) -{ - return 32 - clz32(i); -} - -/* - * 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 HAVE_FDATASYNC - return fdatasync(fd); -#else - return fsync(fd); -#endif -} - -/* - * 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() 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. - */ - -size_t buffer_find_nonzero_offset(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(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 = p[i + 0] | p[i + 1]; - VECTYPE tmp1 = p[i + 2] | p[i + 3]; - VECTYPE tmp2 = p[i + 4] | p[i + 5]; - VECTYPE tmp3 = p[i + 6] | p[i + 7]; - VECTYPE tmp01 = tmp0 | tmp1; - VECTYPE tmp23 = tmp2 | tmp3; - if (!ALL_EQ(tmp01 | tmp23, zero)) { - break; - } - } - - return i * sizeof(VECTYPE); -} - -/* - * 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 STRTOSZ_DEFSUFFIX_B: - return 1; - case STRTOSZ_DEFSUFFIX_KB: - return unit; - case STRTOSZ_DEFSUFFIX_MB: - return unit * unit; - case STRTOSZ_DEFSUFFIX_GB: - return unit * unit * unit; - case STRTOSZ_DEFSUFFIX_TB: - return unit * unit * unit * unit; - case STRTOSZ_DEFSUFFIX_PB: - return unit * unit * unit * unit * unit; - case 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 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 strtosz_suffix(const char *nptr, char **end, const char default_suffix) -{ - return strtosz_suffix_unit(nptr, end, default_suffix, 1024); -} - -int64_t strtosz(const char *nptr, char **end) -{ - return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB); -} - -/** - * 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) -{ - int fd; - char *endptr = NULL; - - fd = strtol(param, &endptr, 10); - if (*endptr || (fd == 0 && param == endptr)) { - return -1; - } - return fd; -} - -/* round down to the nearest power of 2*/ -int64_t pow2floor(int64_t value) -{ - if (!is_power_of_2(value)) { - value = 0x8000000000000000ULL >> clz64(value); - } - return value; -} - -/* - * 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; - int debug; - - if (!debug_env) { - return initial; - } - debug = strtol(debug_env, &inv, 10); - if (inv == debug_env) { - return initial; - } - if (debug < 0 || debug > max) { - fprintf(stderr, "warning: %s not in [0, %d]", name, max); - return initial; - } - return debug; -} diff --git a/contrib/qemu/util/error.c b/contrib/qemu/util/error.c deleted file mode 100644 index 53b04354aef..00000000000 --- a/contrib/qemu/util/error.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * QEMU Error Objects - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.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-common.h" -#include "qapi/error.h" -#include "qapi/qmp/qjson.h" -#include "qapi/qmp/qdict.h" -#include "qapi-types.h" -#include "qapi/qmp/qerror.h" - -struct Error -{ - char *msg; - ErrorClass err_class; -}; - -void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) -{ - Error *err; - va_list ap; - - if (errp == NULL) { - return; - } - assert(*errp == NULL); - - err = g_malloc0(sizeof(*err)); - - va_start(ap, fmt); - err->msg = g_strdup_vprintf(fmt, ap); - va_end(ap); - err->err_class = err_class; - - *errp = err; -} - -void error_set_errno(Error **errp, int os_errno, ErrorClass err_class, - const char *fmt, ...) -{ - Error *err; - char *msg1; - va_list ap; - - if (errp == NULL) { - return; - } - assert(*errp == NULL); - - err = g_malloc0(sizeof(*err)); - - va_start(ap, fmt); - msg1 = g_strdup_vprintf(fmt, ap); - if (os_errno != 0) { - err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno)); - g_free(msg1); - } else { - err->msg = msg1; - } - va_end(ap); - err->err_class = err_class; - - *errp = err; -} - -void error_setg_file_open(Error **errp, int os_errno, const char *filename) -{ - error_setg_errno(errp, os_errno, "Could not open '%s'", filename); -} - -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; - - return err_new; -} - -bool error_is_set(Error **errp) -{ - return (errp && *errp); -} - -ErrorClass error_get_class(const Error *err) -{ - return err->err_class; -} - -const char *error_get_pretty(Error *err) -{ - return err->msg; -} - -void error_free(Error *err) -{ - if (err) { - g_free(err->msg); - g_free(err); - } -} - -void error_propagate(Error **dst_err, Error *local_err) -{ - if (dst_err && !*dst_err) { - *dst_err = local_err; - } else if (local_err) { - error_free(local_err); - } -} diff --git a/contrib/qemu/util/hbitmap.c b/contrib/qemu/util/hbitmap.c deleted file mode 100644 index e063e681f52..00000000000 --- a/contrib/qemu/util/hbitmap.c +++ /dev/null @@ -1,404 +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 <string.h> -#include <glib.h> -#include <assert.h> -#include "qemu/osdep.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]; -}; - -#ifndef __NetBSD__ /* we have it in <strings.h> */ -static inline int popcountl(unsigned long l) -{ - return BITS_PER_LONG == 32 ? ctpop32(l) : ctpop64(l); -} -#endif - -/* 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 += popcountl(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 += popcountl(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); -} - -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_malloc0(sizeof (struct HBitmap)); - 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->levels[i] = g_malloc0(size * sizeof(unsigned long)); - } - - /* 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; -} diff --git a/contrib/qemu/util/hexdump.c b/contrib/qemu/util/hexdump.c deleted file mode 100644 index 969b3406c07..00000000000 --- a/contrib/qemu/util/hexdump.c +++ /dev/null @@ -1,37 +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-common.h" - -void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size) -{ - unsigned int b; - - for (b = 0; b < size; b++) { - if ((b % 16) == 0) { - fprintf(fp, "%s: %04x:", prefix, b); - } - if ((b % 4) == 0) { - fprintf(fp, " "); - } - fprintf(fp, " %02x", (unsigned char)buf[b]); - if ((b % 16) == 15) { - fprintf(fp, "\n"); - } - } - if ((b % 16) != 0) { - fprintf(fp, "\n"); - } -} diff --git a/contrib/qemu/util/iov.c b/contrib/qemu/util/iov.c deleted file mode 100644 index cc6e837c836..00000000000 --- a/contrib/qemu/util/iov.c +++ /dev/null @@ -1,426 +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/iov.h" - -#ifdef _WIN32 -# include <windows.h> -# include <winsock2.h> -#else -# include <sys/types.h> -# include <sys/socket.h> -#endif - -size_t iov_from_buf(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(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, 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; - - 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 */ - if (tail) { - iov[niov-1].iov_len = orig_len; - } - if (offset) { - iov[0].iov_base -= offset; - iov[0].iov_len += offset; - } - - if (ret < 0) { - assert(errno != EINTR); - if (errno == EAGAIN && total > 0) { - return total; - } - return -1; - } - - /* Prepare for the next iteration */ - offset += ret; - total += ret; - bytes -= ret; - } - - 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_malloc(alloc_hint * sizeof(struct iovec)); - 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_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); - } - 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. - */ -void 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; - } - 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 */ -} - -/* - * 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); -} - -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); -} - -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; -} diff --git a/contrib/qemu/util/module.c b/contrib/qemu/util/module.c deleted file mode 100644 index 7acc33d076a..00000000000 --- a/contrib/qemu/util/module.c +++ /dev/null @@ -1,81 +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-common.h" -#include "qemu/queue.h" -#include "qemu/module.h" - -typedef struct ModuleEntry -{ - void (*init)(void); - QTAILQ_ENTRY(ModuleEntry) node; -} ModuleEntry; - -typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; - -static ModuleTypeList init_type_list[MODULE_INIT_MAX]; - -static void init_types(void) -{ - static int inited; - int i; - - if (inited) { - return; - } - - for (i = 0; i < MODULE_INIT_MAX; i++) { - QTAILQ_INIT(&init_type_list[i]); - } - - inited = 1; -} - - -static ModuleTypeList *find_type(module_init_type type) -{ - ModuleTypeList *l; - - init_types(); - - 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; - - l = find_type(type); - - QTAILQ_INSERT_TAIL(l, e, node); -} - -void module_call_init(module_init_type type) -{ - ModuleTypeList *l; - ModuleEntry *e; - - l = find_type(type); - - QTAILQ_FOREACH(e, l, node) { - e->init(); - } -} diff --git a/contrib/qemu/util/oslib-posix.c b/contrib/qemu/util/oslib-posix.c deleted file mode 100644 index bac4c1a158e..00000000000 --- a/contrib/qemu/util/oslib-posix.c +++ /dev/null @@ -1,248 +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. - */ - -/* The following block of code temporarily renames the daemon() function so the - compiler does not see the warning associated with it in stdlib.h on OSX */ -#ifdef __APPLE__ -#define daemon qemu_fake_daemon_function -#include <stdlib.h> -#undef daemon -extern int daemon(int, int); -#endif - -#if defined(__linux__) && (defined(__x86_64__) || defined(__arm__)) - /* 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 <glib/gprintf.h> - -#include "config-host.h" -#include "qemu-common.h" -#include "sysemu/sysemu.h" -#include "trace.h" -#include "qemu/sockets.h" -#include <sys/mman.h> - -#ifdef CONFIG_LINUX -#include <sys/syscall.h> -#endif - -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_memalign(size_t alignment, size_t size) -{ - void *ptr; -#if defined(_POSIX_C_SOURCE) && !defined(__sun__) || defined(__APPLE__) - int ret; - ret = posix_memalign(&ptr, alignment, size); - if (ret != 0) { - fprintf(stderr, "Failed to allocate %zu B: %s\n", - size, strerror(ret)); - abort(); - } -#elif defined(GF_BSD_HOST_OS) - ptr = qemu_oom_check(valloc(size)); -#else - ptr = qemu_oom_check(memalign(alignment, size)); -#endif - trace_qemu_memalign(alignment, size, ptr); - return ptr; -} - -/* alloc shared memory pages */ -void *qemu_anon_ram_alloc(size_t size) -{ - size_t align = QEMU_VMALLOC_ALIGN; - size_t total = size + align - getpagesize(); - void *ptr = mmap(0, total, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; - - if (ptr == MAP_FAILED) { - fprintf(stderr, "Failed to allocate %zu B: %s\n", - size, strerror(errno)); - abort(); - } - - ptr += offset; - total -= offset; - - if (offset > 0) { - munmap(ptr - offset, offset); - } - if (total > size) { - munmap(ptr + size, total - size); - } - - 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); - if (ptr) { - 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); -} - -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 -#ifdef pipe2 - ret = pipe2(pipefd, O_CLOEXEC); - if (ret != -1 || errno != ENOSYS) { - return ret; - } -#endif -#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; -#if defined(CONFIG_UTIMENSAT) -#ifdef utimensat - int ret; - - ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW); - if (ret != -1 || errno != ENOSYS) { - return ret; - } -#endif -#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); -} diff --git a/contrib/qemu/util/qemu-error.c b/contrib/qemu/util/qemu-error.c deleted file mode 100644 index fec02c60754..00000000000 --- a/contrib/qemu/util/qemu-error.c +++ /dev/null @@ -1,225 +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 <stdio.h> -#include "monitor/monitor.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_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. - */ -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 sprintf(). The result should not contain - * newlines. - * Prepend the current location and append a newline. - * It's wrong to call this in a QMP monitor. Use qerror_report() there. - */ -void error_report(const char *fmt, ...) -{ - va_list ap; - GTimeVal tv; - gchar *timestr; - - if (enable_timestamp_msg) { - g_get_current_time(&tv); - timestr = g_time_val_to_iso8601(&tv); - error_printf("%s ", timestr); - g_free(timestr); - } - - error_print_loc(); - va_start(ap, fmt); - error_vprintf(fmt, ap); - va_end(ap); - error_printf("\n"); -} diff --git a/contrib/qemu/util/qemu-option.c b/contrib/qemu/util/qemu-option.c deleted file mode 100644 index e0ef426daa0..00000000000 --- a/contrib/qemu/util/qemu-option.c +++ /dev/null @@ -1,1126 +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 <stdio.h> -#include <string.h> - -#include "qemu-common.h" -#include "qemu/error-report.h" -#include "qapi/qmp/types.h" -#include "qapi/error.h" -#include "qapi/qmp/qerror.h" -#include "qemu/option_int.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); -} - -/* - * Searches an option list for an option with the given name - */ -QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list, - const char *name) -{ - while (list && list->name) { - if (!strcmp(list->name, name)) { - return list; - } - list++; - } - - return NULL; -} - -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_set(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_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number"); - return; - } - *ret = number; - } else { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number"); - } -} - -static 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); - 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_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size"); -#if 0 /* conversion from qerror_report() to error_set() broke this: */ - error_printf_unless_qmp("You may use k, M, G or T suffixes for " - "kilobytes, megabytes, gigabytes and terabytes.\n"); -#endif - return; - } - } else { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size"); - } -} - -/* - * Sets the value of a parameter in a given option list. The parsing of the - * value depends on the type of option: - * - * OPT_FLAG (uses value.n): - * If no value is given, the flag is set to 1. - * Otherwise the value must be "on" (set to 1) or "off" (set to 0) - * - * OPT_STRING (uses value.s): - * value is strdup()ed and assigned as option value - * - * OPT_SIZE (uses value.n): - * The value is converted to an integer. Suffixes for kilobytes etc. are - * allowed (powers of 1024). - * - * Returns 0 on succes, -1 in error cases - */ -int set_option_parameter(QEMUOptionParameter *list, const char *name, - const char *value) -{ - bool flag; - Error *local_err = NULL; - - // Find a matching parameter - list = get_option_parameter(list, name); - if (list == NULL) { - fprintf(stderr, "Unknown option '%s'\n", name); - return -1; - } - - // Process parameter - switch (list->type) { - case OPT_FLAG: - parse_option_bool(name, value, &flag, &local_err); - if (!error_is_set(&local_err)) { - list->value.n = flag; - } - break; - - case OPT_STRING: - if (value != NULL) { - list->value.s = g_strdup(value); - } else { - fprintf(stderr, "Option '%s' needs a parameter\n", name); - return -1; - } - break; - - case OPT_SIZE: - parse_option_size(name, value, &list->value.n, &local_err); - break; - - default: - fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name); - return -1; - } - - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return -1; - } - - return 0; -} - -/* - * Sets the given parameter to an integer instead of a string. - * This function cannot be used to set string options. - * - * Returns 0 on success, -1 in error cases - */ -int set_option_parameter_int(QEMUOptionParameter *list, const char *name, - uint64_t value) -{ - // Find a matching parameter - list = get_option_parameter(list, name); - if (list == NULL) { - fprintf(stderr, "Unknown option '%s'\n", name); - return -1; - } - - // Process parameter - switch (list->type) { - case OPT_FLAG: - case OPT_NUMBER: - case OPT_SIZE: - list->value.n = value; - break; - - default: - return -1; - } - - return 0; -} - -/* - * Frees a option list. If it contains strings, the strings are freed as well. - */ -void free_option_parameters(QEMUOptionParameter *list) -{ - QEMUOptionParameter *cur = list; - - while (cur && cur->name) { - if (cur->type == OPT_STRING) { - g_free(cur->value.s); - } - cur++; - } - - g_free(list); -} - -/* - * Count valid options in list - */ -static size_t count_option_parameters(QEMUOptionParameter *list) -{ - size_t num_options = 0; - - while (list && list->name) { - num_options++; - list++; - } - - return num_options; -} - -/* - * Append an option list (list) to an option list (dest). - * - * If dest is NULL, a new copy of list is created. - * - * Returns a pointer to the first element of dest (or the newly allocated copy) - */ -QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, - QEMUOptionParameter *list) -{ - size_t num_options, num_dest_options; - - num_options = count_option_parameters(dest); - num_dest_options = num_options; - - num_options += count_option_parameters(list); - - dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter)); - dest[num_dest_options].name = NULL; - - while (list && list->name) { - if (get_option_parameter(dest, list->name) == NULL) { - dest[num_dest_options++] = *list; - dest[num_dest_options].name = NULL; - } - list++; - } - - return dest; -} - -/* - * Parses a parameter string (param) into an option list (dest). - * - * list is the template option list. If dest is NULL, a new copy of list is - * created. If list is NULL, this function fails. - * - * A parameter string consists of one or more parameters, separated by commas. - * Each parameter consists of its name and possibly of a value. In the latter - * case, the value is delimited by an = character. To specify a value which - * contains commas, double each comma so it won't be recognized as the end of - * the parameter. - * - * For more details of the parsing see above. - * - * Returns a pointer to the first element of dest (or the newly allocated copy) - * or NULL in error cases - */ -QEMUOptionParameter *parse_option_parameters(const char *param, - QEMUOptionParameter *list, QEMUOptionParameter *dest) -{ - QEMUOptionParameter *allocated = NULL; - char name[256]; - char value[256]; - char *param_delim, *value_delim; - char next_delim; - - if (list == NULL) { - return NULL; - } - - if (dest == NULL) { - dest = allocated = append_option_parameters(NULL, list); - } - - while (*param) { - - // Find parameter name and value in the string - param_delim = strchr(param, ','); - value_delim = strchr(param, '='); - - if (value_delim && (value_delim < param_delim || !param_delim)) { - next_delim = '='; - } else { - next_delim = ','; - value_delim = NULL; - } - - param = get_opt_name(name, sizeof(name), param, next_delim); - if (value_delim) { - param = get_opt_value(value, sizeof(value), param + 1); - } - if (*param != '\0') { - param++; - } - - // Set the parameter - if (set_option_parameter(dest, name, value_delim ? value : NULL)) { - goto fail; - } - } - - return dest; - -fail: - // Only free the list if it was newly allocated - free_option_parameters(allocated); - return NULL; -} - -/* - * Prints all options of a list that have a value to stdout - */ -void print_option_parameters(QEMUOptionParameter *list) -{ - while (list && list->name) { - switch (list->type) { - case OPT_STRING: - if (list->value.s != NULL) { - printf("%s='%s' ", list->name, list->value.s); - } - break; - case OPT_FLAG: - printf("%s=%s ", list->name, list->value.n ? "on" : "off"); - break; - case OPT_SIZE: - case OPT_NUMBER: - printf("%s=%" PRId64 " ", list->name, list->value.n); - break; - default: - printf("%s=(unknown type) ", list->name); - break; - } - list++; - } -} - -/* - * Prints an overview of all available options - */ -void print_option_help(QEMUOptionParameter *list) -{ - printf("Supported options:\n"); - while (list && list->name) { - printf("%-16s %s\n", list->name, - list->help ? list->help : "No description available"); - list++; - } -} - -/* ------------------------------------------------------------------ */ - -static 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; -} - -const char *qemu_opt_get(QemuOpts *opts, const char *name) -{ - QemuOpt *opt = qemu_opt_find(opts, name); - return opt ? opt->str : NULL; -} - -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; -} - -bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval) -{ - QemuOpt *opt = qemu_opt_find(opts, name); - - if (opt == NULL) - return defval; - assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL); - return opt->value.boolean; -} - -uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval) -{ - QemuOpt *opt = qemu_opt_find(opts, name); - - if (opt == NULL) - return defval; - assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER); - return opt->value.uint; -} - -uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval) -{ - QemuOpt *opt = qemu_opt_find(opts, name); - - if (opt == NULL) - return defval; - assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE); - return opt->value.uint; -} - -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 void qemu_opt_del(QemuOpt *opt) -{ - QTAILQ_REMOVE(&opt->opts->head, opt, next); - g_free((/* !const */ char*)opt->name); - g_free((/* !const */ char*)opt->str); - g_free(opt); -} - -static bool opts_accepts_any(const QemuOpts *opts) -{ - return opts->list->desc[0].name == NULL; -} - -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; -} - -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_set(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 (error_is_set(&local_err)) { - error_propagate(errp, local_err); - qemu_opt_del(opt); - } -} - -int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) -{ - Error *local_err = NULL; - - opt_set(opts, name, value, false, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return -1; - } - - return 0; -} - -void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value, - Error **errp) -{ - opt_set(opts, name, value, false, errp); -} - -int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val) -{ - 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)) { - qerror_report(QERR_INVALID_PARAMETER, name); - g_free(opt); - return -1; - } - - 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); - - return 0; -} - -int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val) -{ - 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)) { - qerror_report(QERR_INVALID_PARAMETER, name); - g_free(opt); - return -1; - } - - 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); - - return 0; -} - -int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque, - int abort_on_failure) -{ - QemuOpt *opt; - int rc = 0; - - QTAILQ_FOREACH(opt, &opts->head, next) { - rc = func(opt->name, opt->str, opaque); - if (abort_on_failure && rc != 0) - break; - } - return rc; -} - -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; -} - -static int id_wellformed(const char *id) -{ - int i; - - if (!qemu_isalpha(id[0])) { - return 0; - } - for (i = 1; id[i]; i++) { - if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { - return 0; - } - } - return 1; -} - -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_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier"); -#if 0 /* conversion from qerror_report() to error_set() broke this: */ - error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n"); -#endif - return NULL; - } - opts = qemu_opts_find(list, id); - if (opts != NULL) { - if (fail_if_exists && !list->merge_lists) { - error_set(errp, QERR_DUPLICATE_ID, 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; -} - -QemuOpts *qemu_opts_create_nofail(QemuOptsList *list) -{ - QemuOpts *opts; - Error *errp = NULL; - opts = qemu_opts_create(list, NULL, 0, &errp); - assert_no_error(errp); - 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); -} - -int qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value) -{ - QemuOpts *opts; - Error *local_err = NULL; - - opts = qemu_opts_create(list, id, 1, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return -1; - } - return qemu_opt_set(opts, name, value); -} - -const char *qemu_opts_id(QemuOpts *opts) -{ - return opts->id; -} - -void qemu_opts_del(QemuOpts *opts) -{ - QemuOpt *opt; - - 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); -} - -int qemu_opts_print(QemuOpts *opts, void *dummy) -{ - QemuOpt *opt; - - fprintf(stderr, "%s: %s:", opts->list->name, - opts->id ? opts->id : "<noid>"); - QTAILQ_FOREACH(opt, &opts->head, next) { - fprintf(stderr, " %s=\"%s\"", opt->name, opt->str); - } - fprintf(stderr, "\n"); - return 0; -} - -static int opts_do_parse(QemuOpts *opts, const char *params, - const char *firstname, bool prepend) -{ - 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 (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return -1; - } - } - if (*p != ',') { - break; - } - } - return 0; -} - -int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname) -{ - return opts_do_parse(opts, params, firstname, false); -} - -static QemuOpts *opts_parse(QemuOptsList *list, const char *params, - int permit_abbrev, bool defaults) -{ - 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; - } - opts = qemu_opts_create(list, id, !defaults, &local_err); - if (opts == NULL) { - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - } - return NULL; - } - - if (opts_do_parse(opts, params, firstname, defaults) != 0) { - qemu_opts_del(opts); - return NULL; - } - - return opts; -} - -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, - int permit_abbrev) -{ - return opts_parse(list, params, permit_abbrev, false); -} - -void qemu_opts_set_defaults(QemuOptsList *list, const char *params, - int permit_abbrev) -{ - QemuOpts *opts; - - opts = opts_parse(list, params, permit_abbrev, true); - 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") || error_is_set(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_int(qobject_to_qbool(obj)) ? "on" : "off"); - value = buf; - break; - default: - return; - } - - qemu_opt_set_err(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 (error_is_set(&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 (error_is_set(&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 (error_is_set(&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_set(errp, QERR_INVALID_PARAMETER, opt->name); - return; - } - - qemu_opt_parse(opt, &local_err); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - return; - } - } -} - -int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, - int abort_on_failure) -{ - Location loc; - QemuOpts *opts; - int rc = 0; - - loc_push_none(&loc); - QTAILQ_FOREACH(opts, &list->head, next) { - loc_restore(&opts->loc); - rc |= func(opts, opaque); - if (abort_on_failure && rc != 0) - break; - } - loc_pop(&loc); - return rc; -} diff --git a/contrib/qemu/util/qemu-thread-posix.c b/contrib/qemu/util/qemu-thread-posix.c deleted file mode 100644 index 4489abf1d85..00000000000 --- a/contrib/qemu/util/qemu-thread-posix.c +++ /dev/null @@ -1,327 +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 <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <time.h> -#include <signal.h> -#include <stdint.h> -#include <string.h> -#include <limits.h> -#include <unistd.h> -#include <sys/time.h> -#include "qemu/thread.h" - -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; - pthread_mutexattr_t mutexattr; - - pthread_mutexattr_init(&mutexattr); - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); - err = pthread_mutex_init(&mutex->lock, &mutexattr); - pthread_mutexattr_destroy(&mutexattr); - 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 == INT_MAX) { - rc = EINVAL; - } else if (sem->count++ < 0) { - rc = pthread_cond_signal(&sem->cond); - } else { - rc = 0; - } - 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__) - compute_abs_deadline(&ts, ms); - pthread_mutex_lock(&sem->lock); - --sem->count; - while (sem->count < 0) { - rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); - if (rc == ETIMEDOUT) { - ++sem->count; - break; - } - if (rc != 0) { - error_exit(rc, __func__); - } - } - 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) -{ -#if defined(__APPLE__) || defined(__NetBSD__) - pthread_mutex_lock(&sem->lock); - --sem->count; - while (sem->count < 0) { - pthread_cond_wait(&sem->cond, &sem->lock); - } - pthread_mutex_unlock(&sem->lock); -#else - int rc; - - do { - rc = sem_wait(&sem->sem); - } while (rc == -1 && errno == EINTR); - if (rc < 0) { - error_exit(errno, __func__); - } -#endif -} - -void qemu_thread_create(QemuThread *thread, - 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__); - - 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/contrib/qemu/util/unicode.c b/contrib/qemu/util/unicode.c deleted file mode 100644 index d1c86588505..00000000000 --- a/contrib/qemu/util/unicode.c +++ /dev/null @@ -1,100 +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-common.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/contrib/stdlib/gf_mkostemp.c b/contrib/stdlib/gf_mkostemp.c deleted file mode 100644 index 931249a4520..00000000000 --- a/contrib/stdlib/gf_mkostemp.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Borrowed from glibc-2.16/sysdeps/posix/tempname.c */ - -/* Copyright (C) 1991-2001, 2006, 2007, 2009 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <sys/time.h> -#include <fcntl.h> -#include <sys/types.h> -#include <time.h> -#include <inttypes.h> - -static const char letters[] = -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). -*/ - -#if !defined(TMP_MAX) -#define TMP_MAX 238328 -#endif - -int -gf_mkostemp (char *tmpl, int suffixlen, int flags) -{ - int len; - char *XXXXXX; - static uint64_t value; - uint64_t random_time_bits; - unsigned int count; - int fd = -1; - - /* A lower bound on the number of temporary files to attempt to - generate. The maximum total number of temporary file names that - can exist for a given template is 62**6. It should never be - necessary to try all these combinations. Instead if a reasonable - number of names is tried (we define reasonable as 62**3) fail to - give the system administrator the chance to remove the problems. */ - - unsigned int attempts = TMP_MAX; /* TMP_MAX == 62³ */ - - len = strlen (tmpl); - if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], - "XXXXXX", 6)) - return -1; - - /* This is where the Xs start. */ - XXXXXX = &tmpl[len - 6 - suffixlen]; - - /* Get some more or less random data. */ -# if HAVE_GETTIMEOFDAY - struct timeval tv; - gettimeofday (&tv, NULL); - random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; -# else - random_time_bits = time (NULL); -# endif - - value += random_time_bits ^ getpid (); - - for (count = 0; count < attempts; value += 7777, ++count) { - uint64_t v = value; - - /* Fill in the random bits. */ - XXXXXX[0] = letters[v % 62]; - v /= 62; - XXXXXX[1] = letters[v % 62]; - v /= 62; - XXXXXX[2] = letters[v % 62]; - v /= 62; - XXXXXX[3] = letters[v % 62]; - v /= 62; - XXXXXX[4] = letters[v % 62]; - v /= 62; - XXXXXX[5] = letters[v % 62]; - - fd = open (tmpl, (flags & ~O_ACCMODE) - | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - - if (fd >= 0) - return fd; - else if (errno != EEXIST) - return -1; - } - - /* We got out of the loop because we ran out of combinations to try. */ - return -1; -} diff --git a/contrib/sunrpc/xdr_sizeof.c b/contrib/sunrpc/xdr_sizeof.c deleted file mode 100644 index ca1f7bf0a5e..00000000000 --- a/contrib/sunrpc/xdr_sizeof.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * xdr_sizeof.c - * - * Copyright 1990 Sun Microsystems, Inc. - * - * General purpose routine to see how much space something will use - * when serialized using XDR. - */ - -#ifdef GF_DARWIN_HOST_OS - -#include <rpc/types.h> -#include <rpc/xdr.h> -#include <sys/types.h> -#include <sys/cdefs.h> - -#include <stdlib.h> - -/* ARGSUSED */ -#ifdef GF_DARWIN_HOST_OS -static bool_t -x_putlong (XDR *xdrs, const int *longp) -{ - xdrs->x_handy += BYTES_PER_XDR_UNIT; - return TRUE; -} - -#else -static bool_t -x_putlong (XDR *xdrs, const long *longp) -{ - xdrs->x_handy += BYTES_PER_XDR_UNIT; - return TRUE; -} -#endif - -/* ARGSUSED */ -static bool_t -x_putbytes (XDR *xdrs, const char *bp, u_int len) -{ - xdrs->x_handy += len; - return TRUE; -} - -#ifdef GF_DARWIN_HOST_OS -static u_int -x_getpostn (XDR *xdrs) -{ - return xdrs->x_handy; -} -#else -static u_int -x_getpostn (const XDR *xdrs) -{ - return xdrs->x_handy; -} -#endif - -/* ARGSUSED */ -static bool_t -x_setpostn (XDR *xdrs, u_int len) -{ - /* This is not allowed */ - return FALSE; -} - -static int32_t * -x_inline (XDR *xdrs, u_int len) -{ - if (len == 0) - return NULL; - if (xdrs->x_op != XDR_ENCODE) - return NULL; - if (len < (u_int) (long int) xdrs->x_base) - { - /* x_private was already allocated */ - xdrs->x_handy += len; - return (int32_t *) xdrs->x_private; - } - else - { - /* Free the earlier space and allocate new area */ - free (xdrs->x_private); - if ((xdrs->x_private = (caddr_t) malloc (len)) == NULL) - { - xdrs->x_base = 0; - return NULL; - } - xdrs->x_base = (void *) (long) len; - xdrs->x_handy += len; - return (int32_t *) xdrs->x_private; - } -} - -static int -harmless (void) -{ - /* Always return FALSE/NULL, as the case may be */ - return 0; -} - -static void -x_destroy (XDR *xdrs) -{ - xdrs->x_handy = 0; - xdrs->x_base = 0; - if (xdrs->x_private) - { - free (xdrs->x_private); - xdrs->x_private = NULL; - } - return; -} - -unsigned long -xdr_sizeof (xdrproc_t func, void *data) -{ - XDR x; - struct xdr_ops ops; - bool_t stat; - -#ifdef GF_DARWIN_HOST_OS - typedef bool_t (*dummyfunc1) (XDR *, int *); -#else - typedef bool_t (*dummyfunc1) (XDR *, long *); -#endif - typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int); - - ops.x_putlong = x_putlong; - ops.x_putbytes = x_putbytes; - ops.x_inline = x_inline; - ops.x_getpostn = x_getpostn; - ops.x_setpostn = x_setpostn; - ops.x_destroy = x_destroy; - - /* the other harmless ones */ - ops.x_getlong = (dummyfunc1) harmless; - ops.x_getbytes = (dummyfunc2) harmless; - - x.x_op = XDR_ENCODE; - x.x_ops = &ops; - x.x_handy = 0; - x.x_private = (caddr_t) NULL; - x.x_base = (caddr_t) 0; - - stat = func (&x, data, 0); - if (x.x_private) - free (x.x_private); - return (stat == TRUE ? (unsigned) x.x_handy : 0); -} -#endif /* GF_DARWIN_HOST_OS */ diff --git a/contrib/timer-wheel/find_last_bit.c b/contrib/timer-wheel/find_last_bit.c new file mode 100644 index 00000000000..192fee802a8 --- /dev/null +++ b/contrib/timer-wheel/find_last_bit.c @@ -0,0 +1,61 @@ +/* bit search implementation + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * Copyright (C) 2008 IBM Corporation + * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au> + * (Inspired by David Howell's find_next_bit implementation) + * + * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease + * size and improve performance, 2015. + * + * 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. + */ + +/** + * @find_last_bit + * optimized implementation of find last bit in + */ + +#ifndef BITS_PER_LONG +#ifdef __LP64__ +#define BITS_PER_LONG 64 +#else +#define BITS_PER_LONG 32 +#endif +#endif + +unsigned long gw_tw_fls (unsigned long word) +{ + int num = BITS_PER_LONG; + +#if BITS_PER_LONG == 64 + if (!(word & (~0ul << 32))) { + num -= 32; + word <<= 32; + } +#endif + if (!(word & (~0ul << (BITS_PER_LONG-16)))) { + num -= 16; + word <<= 16; + } + if (!(word & (~0ul << (BITS_PER_LONG-8)))) { + num -= 8; + word <<= 8; + } + if (!(word & (~0ul << (BITS_PER_LONG-4)))) { + num -= 4; + word <<= 4; + } + if (!(word & (~0ul << (BITS_PER_LONG-2)))) { + num -= 2; + word <<= 2; + } + if (!(word & (~0ul << (BITS_PER_LONG-1)))) + num -= 1; + return num; +} diff --git a/contrib/timer-wheel/timer-wheel.c b/contrib/timer-wheel/timer-wheel.c new file mode 100644 index 00000000000..58e0607bf0c --- /dev/null +++ b/contrib/timer-wheel/timer-wheel.c @@ -0,0 +1,374 @@ +/* + * linux/kernel/timer.c + * + * Kernel internal timers + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + */ +/* + 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. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/select.h> + +#include "timer-wheel.h" + +static inline void +__gf_tw_add_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) +{ + int i; + unsigned long idx; + unsigned long expires; + struct list_head *vec; + + expires = timer->expires; + + idx = expires - base->timer_sec; + + if (idx < TVR_SIZE) { + i = expires & TVR_MASK; + vec = base->tv1.vec + i; + } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { + i = (expires >> TVR_BITS) & TVN_MASK; + vec = base->tv2.vec + i; + } else if (idx < 1 << (TVR_BITS + 2*TVN_BITS)) { + i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; + vec = base->tv3.vec + i; + } else if (idx < 1 << (TVR_BITS + 3*TVN_BITS)) { + i = (expires >> (TVR_BITS + 2*TVN_BITS)) & TVN_MASK; + vec = base->tv4.vec + i; + } else if (idx < 0) { + vec = base->tv1.vec + (base->timer_sec & TVR_MASK); + } else { + i = (expires >> (TVR_BITS + 3*TVN_BITS)) & TVN_MASK; + vec = base->tv5.vec + i; + } + + list_add_tail (&timer->entry, vec); +} + +unsigned long gf_tw_find_last_bit(const unsigned long *, unsigned long); + +#if defined(__GNUC__) || defined(__clang__) +static inline unsigned long gf_tw_fls (unsigned long word) +{ + return BITS_PER_LONG - __builtin_clzl(word); +} +#else +extern unsigned long gf_tw_fls (unsigned long); +#endif + +static inline unsigned long +apply_slack(struct tvec_base *base, struct gf_tw_timer_list *timer) +{ + long delta; + unsigned long mask, expires, expires_limit; + + expires = timer->expires; + + delta = expires - base->timer_sec; + if (delta < 256) + return expires; + + expires_limit = expires + delta / 256; + mask = expires ^ expires_limit; + if (mask == 0) + return expires; + + int bit = gf_tw_fls (mask); + mask = (1UL << bit) - 1; + + expires_limit = expires_limit & ~(mask); + return expires_limit; +} + +static inline void +__gf_tw_detach_timer (struct gf_tw_timer_list *timer) +{ + struct list_head *entry = &timer->entry; + + list_del (entry); + entry->next = NULL; +} + +static inline int +cascade (struct tvec_base *base, struct tvec *tv, int index) +{ + struct gf_tw_timer_list *timer, *tmp; + struct list_head tv_list; + + list_replace_init (tv->vec + index, &tv_list); + + list_for_each_entry_safe (timer, tmp, &tv_list, entry) { + __gf_tw_add_timer (base, timer); + } + + return index; +} + +#define INDEX(N) ((base->timer_sec >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK) + +/** + * run expired timers + */ +static inline void +run_timers (struct tvec_base *base) +{ + unsigned long index, call_time; + struct gf_tw_timer_list *timer; + + struct list_head work_list; + struct list_head *head = &work_list; + + pthread_spin_lock (&base->lock); + { + index = base->timer_sec & TVR_MASK; + + if (!index && + (!cascade (base, &base->tv2, INDEX(0))) && + (!cascade (base, &base->tv3, INDEX(1))) && + (!cascade (base, &base->tv4, INDEX(2)))) + cascade (base, &base->tv5, INDEX(3)); + + call_time = base->timer_sec++; + list_replace_init (base->tv1.vec + index, head); + while (!list_empty(head)) { + void (*fn)(struct gf_tw_timer_list *, void *, unsigned long); + void *data; + + timer = list_first_entry (head, struct gf_tw_timer_list, entry); + fn = timer->function; + data = timer->data; + + __gf_tw_detach_timer (timer); + pthread_spin_unlock(&base->lock); + { + /* It is required to run the actual function outside + of the locked zone, so we don't bother about + locked operations inside that function */ + fn(timer, data, call_time); + } + pthread_spin_lock(&base->lock); + } + } + pthread_spin_unlock (&base->lock); + +} + +void *runner (void *arg) +{ + struct timeval tv = {0,}; + struct tvec_base *base = arg; + + while (1) { + run_timers (base); + + tv.tv_sec = 1; + tv.tv_usec = 0; + (void) select (0, NULL, NULL, NULL, &tv); + } + + return NULL; + +} + +static inline int timer_pending (struct gf_tw_timer_list *timer) +{ + struct list_head *entry = &timer->entry; + + return (entry->next != NULL); +} + +static inline int __detach_if_pending (struct gf_tw_timer_list *timer) +{ + if (!timer_pending (timer)) + return 0; + + __gf_tw_detach_timer (timer); + return 1; +} + +static inline int __mod_timer (struct tvec_base *base, + struct gf_tw_timer_list *timer, int pending_only) +{ + int ret = 0; + + ret = __detach_if_pending (timer); + if (!ret && pending_only) + goto done; + + ret = 1; + __gf_tw_add_timer (base, timer); + + done: + return ret; +} + +/* interface */ + +/** + * Add a timer in the timer wheel + */ +void gf_tw_add_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) +{ + pthread_spin_lock (&base->lock); + { + timer->expires += base->timer_sec; + timer->expires = apply_slack (base, timer); + __gf_tw_add_timer (base, timer); + } + pthread_spin_unlock (&base->lock); +} + +/** + * Remove a timer from the timer wheel + */ +int gf_tw_del_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) +{ + int ret = 0; + + pthread_spin_lock (&base->lock); + { + if (timer_pending (timer)) { + ret = 1; + __gf_tw_detach_timer (timer); + } + } + pthread_spin_unlock (&base->lock); + + return ret; +} + +int gf_tw_mod_timer_pending (struct tvec_base *base, + struct gf_tw_timer_list *timer, + unsigned long expires) +{ + int ret = 1; + + pthread_spin_lock (&base->lock); + { + timer->expires = expires + base->timer_sec; + timer->expires = apply_slack (base, timer); + + ret = __mod_timer (base, timer, 1); + } + pthread_spin_unlock (&base->lock); + + return ret; +} + +int gf_tw_mod_timer (struct tvec_base *base, + struct gf_tw_timer_list *timer, unsigned long expires) +{ + int ret = 1; + + pthread_spin_lock (&base->lock); + { + /* fast path optimization */ + if (timer_pending (timer) && timer->expires == expires) + goto unblock; + + timer->expires = expires + base->timer_sec; + timer->expires = apply_slack (base, timer); + + ret = __mod_timer (base, timer, 0); + } + unblock: + pthread_spin_unlock (&base->lock); + + return ret; +} + +int gf_tw_cleanup_timers (struct tvec_base *base) +{ + int ret = 0; + void *res = NULL; + + /* terminate runner */ + ret = pthread_cancel (base->runner); + if (ret != 0) + goto error_return; + ret = pthread_join (base->runner, &res); + if (ret != 0) + goto error_return; + if (res != PTHREAD_CANCELED) + goto error_return; + + /* destroy lock */ + ret = pthread_spin_destroy (&base->lock); + if (ret != 0) + goto error_return; + + /* deallocated timer base */ + free (base); + return 0; + + error_return: + return -1; +} + +/** + * Initialize various timer wheel lists and spawn a thread that + * invokes run_timers() + */ +struct tvec_base *gf_tw_init_timers () +{ + int j = 0; + int ret = 0; + struct timeval tv = {0,}; + struct tvec_base *base = NULL; + + base = malloc (sizeof (*base)); + if (!base) + goto error_return; + + ret = pthread_spin_init (&base->lock, 0); + if (ret != 0) + goto error_dealloc; + + for (j = 0; j < TVN_SIZE; j++) { + INIT_LIST_HEAD (base->tv5.vec + j); + INIT_LIST_HEAD (base->tv4.vec + j); + INIT_LIST_HEAD (base->tv3.vec + j); + INIT_LIST_HEAD (base->tv2.vec + j); + } + + for (j = 0; j < TVR_SIZE; j++) { + INIT_LIST_HEAD (base->tv1.vec + j); + } + + ret = gettimeofday (&tv, 0); + if (ret < 0) + goto destroy_lock; + base->timer_sec = tv.tv_sec; + + ret = pthread_create (&base->runner, NULL, runner, base); + if (ret != 0) + goto destroy_lock; + return base; + + destroy_lock: + (void) pthread_spin_destroy (&base->lock); + error_dealloc: + free (base); + error_return: + return NULL; +} diff --git a/contrib/timer-wheel/timer-wheel.h b/contrib/timer-wheel/timer-wheel.h new file mode 100644 index 00000000000..5637735ec22 --- /dev/null +++ b/contrib/timer-wheel/timer-wheel.h @@ -0,0 +1,77 @@ +/* + 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. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __TIMER_WHEEL_H +#define __TIMER_WHEEL_H + +#include "glusterfs/locking.h" + +#include "glusterfs/list.h" + +#define TVR_BITS 8 +#define TVN_BITS 6 +#define TVR_SIZE (1 << TVR_BITS) +#define TVN_SIZE (1 << TVN_BITS) +#define TVR_MASK (TVR_SIZE - 1) +#define TVN_MASK (TVN_SIZE - 1) + +#define BITS_PER_LONG 64 + +struct tvec { + struct list_head vec[TVN_SIZE]; +}; + +struct tvec_root { + struct list_head vec[TVR_SIZE]; +}; + +struct tvec_base { + pthread_spinlock_t lock; /* base lock */ + + pthread_t runner; /* run_timer() */ + + unsigned long timer_sec; /* time counter */ + + struct tvec_root tv1; + struct tvec tv2; + struct tvec tv3; + struct tvec tv4; + struct tvec tv5; +}; + +struct gf_tw_timer_list { + void *data; + unsigned long expires; + + /** callback routine */ + void (*function)(struct gf_tw_timer_list *, void *, unsigned long); + + struct list_head entry; +}; + +/** The API! */ +struct tvec_base *gf_tw_init_timers (); +int gf_tw_cleanup_timers (struct tvec_base *); +void gf_tw_add_timer (struct tvec_base *, struct gf_tw_timer_list *); +int gf_tw_del_timer (struct tvec_base *, struct gf_tw_timer_list *); + +int gf_tw_mod_timer_pending (struct tvec_base *, + struct gf_tw_timer_list *, unsigned long); + +int gf_tw_mod_timer (struct tvec_base *, + struct gf_tw_timer_list *, unsigned long); + +#endif diff --git a/contrib/umountd/Makefile.am b/contrib/umountd/Makefile.am index c03b0cbcae6..b39e000f5aa 100644 --- a/contrib/umountd/Makefile.am +++ b/contrib/umountd/Makefile.am @@ -4,7 +4,8 @@ umountd_CFLAGS = $(GF_CFLAGS) -DDATADIR=\"$(localstatedir)\" umountd_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la ${GF_LDADD} umountd_LDFLAGS = $(GF_LDFLAGS) -AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src +AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ + -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src AM_CFLAGS = -Wall $(GF_CFLAGS) CLEANFILES = diff --git a/contrib/umountd/umountd.c b/contrib/umountd/umountd.c index 0d2c6f20b60..3f933ecb554 100644 --- a/contrib/umountd/umountd.c +++ b/contrib/umountd/umountd.c @@ -23,11 +23,11 @@ #include <sys/stat.h> #include <sys/mount.h> -#include "glusterfs.h" -#include "globals.h" -#include "logging.h" -#include "syscall.h" -#include "mem-types.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/globals.h" +#include "glusterfs/logging.h" +#include "glusterfs/syscall.h" +#include "glusterfs/mem-types.h" static void usage (void) @@ -56,7 +56,8 @@ sanity_check (char *path, dev_t *devp) break; default: gf_log ("umountd", GF_LOG_ERROR, - "Cannot access %s\n", path, strerror (errno)); + "Cannot access %s: %s\n", + path, strerror (errno)); goto out; } } @@ -65,12 +66,13 @@ sanity_check (char *path, dev_t *devp) if (*devp == -1 && ret == 0) *devp = st.st_dev; - strncpy (pathtmp, path, PATH_MAX); + snprintf (pathtmp, PATH_MAX, "%s", path); parent = dirname (pathtmp); if (stat (parent, &parent_st) != 0) { gf_log ("umountd", GF_LOG_ERROR, - "Cannot access %s\n", parent, strerror (errno)); + "Cannot access %s: %s\n", + parent, strerror (errno)); goto out; } diff --git a/contrib/userspace-rcu/static-wfcqueue.h b/contrib/userspace-rcu/static-wfcqueue.h new file mode 100644 index 00000000000..37d14ad674b --- /dev/null +++ b/contrib/userspace-rcu/static-wfcqueue.h @@ -0,0 +1,685 @@ +#ifndef _URCU_WFCQUEUE_STATIC_H +#define _URCU_WFCQUEUE_STATIC_H + +/* + * urcu/static/wfcqueue.h + * + * Userspace RCU library - Concurrent Queue with Wait-Free Enqueue/Blocking Dequeue + * + * TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See urcu/wfcqueue.h for + * linking dynamically with the userspace rcu library. + * + * Copyright 2010-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> + * Copyright 2011-2012 - Lai Jiangshan <laijs@cn.fujitsu.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 + */ + +/* Copied from userspace-rcu 0.10 because version 0.7 doesn't contain it. */ + +#include <pthread.h> +#include <assert.h> +#include <poll.h> +#include <stdbool.h> +#include <urcu/compiler.h> +#include <urcu/uatomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Concurrent queue with wait-free enqueue/blocking dequeue. + * + * This queue has been designed and implemented collaboratively by + * Mathieu Desnoyers and Lai Jiangshan. Inspired from + * half-wait-free/half-blocking queue implementation done by Paul E. + * McKenney. + * + * Mutual exclusion of cds_wfcq_* / __cds_wfcq_* API + * + * Synchronization table: + * + * External synchronization techniques described in the API below is + * required between pairs marked with "X". No external synchronization + * required between pairs marked with "-". + * + * Legend: + * [1] cds_wfcq_enqueue + * [2] __cds_wfcq_splice (destination queue) + * [3] __cds_wfcq_dequeue + * [4] __cds_wfcq_splice (source queue) + * [5] __cds_wfcq_first + * [6] __cds_wfcq_next + * + * [1] [2] [3] [4] [5] [6] + * [1] - - - - - - + * [2] - - - - - - + * [3] - - X X X X + * [4] - - X - X X + * [5] - - X X - - + * [6] - - X X - - + * + * Mutual exclusion can be ensured by holding cds_wfcq_dequeue_lock(). + * + * For convenience, cds_wfcq_dequeue_blocking() and + * cds_wfcq_splice_blocking() hold the dequeue lock. + * + * Besides locking, mutual exclusion of dequeue, splice and iteration + * can be ensured by performing all of those operations from a single + * thread, without requiring any lock. + */ + +#define WFCQ_ADAPT_ATTEMPTS 10 /* Retry if being set */ +#define WFCQ_WAIT 10 /* Wait 10 ms if being set */ + +/* + * cds_wfcq_node_init: initialize wait-free queue node. + */ +static inline void _cds_wfcq_node_init(struct cds_wfcq_node *node) +{ + node->next = NULL; +} + +/* + * cds_wfcq_init: initialize wait-free queue (with lock). Pair with + * cds_wfcq_destroy(). + */ +static inline void _cds_wfcq_init(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + int ret; + + /* Set queue head and tail */ + _cds_wfcq_node_init(&head->node); + tail->p = &head->node; + ret = pthread_mutex_init(&head->lock, NULL); + assert(!ret); +} + +/* + * cds_wfcq_destroy: destroy wait-free queue (with lock). Pair with + * cds_wfcq_init(). + */ +static inline void _cds_wfcq_destroy(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + int ret = pthread_mutex_destroy(&head->lock); + assert(!ret); +} + +/* + * __cds_wfcq_init: initialize wait-free queue (without lock). Don't + * pair with any destroy function. + */ +static inline void ___cds_wfcq_init(struct __cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + /* Set queue head and tail */ + _cds_wfcq_node_init(&head->node); + tail->p = &head->node; +} + +/* + * cds_wfcq_empty: return whether wait-free queue is empty. + * + * No memory barrier is issued. No mutual exclusion is required. + * + * We perform the test on head->node.next to check if the queue is + * possibly empty, but we confirm this by checking if the tail pointer + * points to the head node because the tail pointer is the linearisation + * point of the enqueuers. Just checking the head next pointer could + * make a queue appear empty if an enqueuer is preempted for a long time + * between xchg() and setting the previous node's next pointer. + */ +static inline bool _cds_wfcq_empty(cds_wfcq_head_ptr_t u_head, + struct cds_wfcq_tail *tail) +{ + struct __cds_wfcq_head *head = u_head._h; + /* + * Queue is empty if no node is pointed by head->node.next nor + * tail->p. Even though the tail->p check is sufficient to find + * out of the queue is empty, we first check head->node.next as a + * common case to ensure that dequeuers do not frequently access + * enqueuer's tail->p cache line. + */ + return CMM_LOAD_SHARED(head->node.next) == NULL + && CMM_LOAD_SHARED(tail->p) == &head->node; +} + +static inline void _cds_wfcq_dequeue_lock(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + int ret; + + ret = pthread_mutex_lock(&head->lock); + assert(!ret); +} + +static inline void _cds_wfcq_dequeue_unlock(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + int ret; + + ret = pthread_mutex_unlock(&head->lock); + assert(!ret); +} + +static inline bool ___cds_wfcq_append(cds_wfcq_head_ptr_t u_head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *new_head, + struct cds_wfcq_node *new_tail) +{ + struct __cds_wfcq_head *head = u_head._h; + struct cds_wfcq_node *old_tail; + + /* + * Implicit memory barrier before uatomic_xchg() orders earlier + * stores to data structure containing node and setting + * node->next to NULL before publication. + */ + old_tail = uatomic_xchg(&tail->p, new_tail); + + /* + * Implicit memory barrier after uatomic_xchg() orders store to + * q->tail before store to old_tail->next. + * + * At this point, dequeuers see a NULL tail->p->next, which + * indicates that the queue is being appended to. The following + * store will append "node" to the queue from a dequeuer + * perspective. + */ + CMM_STORE_SHARED(old_tail->next, new_head); + /* + * Return false if queue was empty prior to adding the node, + * else return true. + */ + return old_tail != &head->node; +} + +/* + * cds_wfcq_enqueue: enqueue a node into a wait-free queue. + * + * Issues a full memory barrier before enqueue. No mutual exclusion is + * required. + * + * Returns false if the queue was empty prior to adding the node. + * Returns true otherwise. + */ +static inline bool _cds_wfcq_enqueue(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *new_tail) +{ + return ___cds_wfcq_append(head, tail, new_tail, new_tail); +} + +/* + * CDS_WFCQ_WAIT_SLEEP: + * + * By default, this sleeps for the given @msec milliseconds. + * This is a macro which LGPL users may #define themselves before + * including wfcqueue.h to override the default behavior (e.g. + * to log a warning or perform other background work). + */ +#ifndef CDS_WFCQ_WAIT_SLEEP +#define CDS_WFCQ_WAIT_SLEEP(msec) ___cds_wfcq_wait_sleep(msec) +#endif + +static inline void ___cds_wfcq_wait_sleep(int msec) +{ + (void) poll(NULL, 0, msec); +} + +/* + * ___cds_wfcq_busy_wait: adaptative busy-wait. + * + * Returns 1 if nonblocking and needs to block, 0 otherwise. + */ +static inline bool +___cds_wfcq_busy_wait(int *attempt, int blocking) +{ + if (!blocking) + return 1; + if (++(*attempt) >= WFCQ_ADAPT_ATTEMPTS) { + CDS_WFCQ_WAIT_SLEEP(WFCQ_WAIT); /* Wait for 10ms */ + *attempt = 0; + } else { + caa_cpu_relax(); + } + return 0; +} + +/* + * Waiting for enqueuer to complete enqueue and return the next node. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_node_sync_next(struct cds_wfcq_node *node, int blocking) +{ + struct cds_wfcq_node *next; + int attempt = 0; + + /* + * Adaptative busy-looping waiting for enqueuer to complete enqueue. + */ + while ((next = CMM_LOAD_SHARED(node->next)) == NULL) { + if (___cds_wfcq_busy_wait(&attempt, blocking)) + return CDS_WFCQ_WOULDBLOCK; + } + + return next; +} + +static inline struct cds_wfcq_node * +___cds_wfcq_first(cds_wfcq_head_ptr_t u_head, + struct cds_wfcq_tail *tail, + int blocking) +{ + struct __cds_wfcq_head *head = u_head._h; + struct cds_wfcq_node *node; + + if (_cds_wfcq_empty(__cds_wfcq_head_cast(head), tail)) + return NULL; + node = ___cds_wfcq_node_sync_next(&head->node, blocking); + /* Load head->node.next before loading node's content */ + cmm_smp_read_barrier_depends(); + return node; +} + +/* + * __cds_wfcq_first_blocking: get first node of a queue, without dequeuing. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. + * + * Used by for-like iteration macros in urcu/wfqueue.h: + * __cds_wfcq_for_each_blocking() + * __cds_wfcq_for_each_blocking_safe() + * + * Returns NULL if queue is empty, first node otherwise. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_first_blocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail) +{ + return ___cds_wfcq_first(head, tail, 1); +} + + +/* + * __cds_wfcq_first_nonblocking: get first node of a queue, without dequeuing. + * + * Same as __cds_wfcq_first_blocking, but returns CDS_WFCQ_WOULDBLOCK if + * it needs to block. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_first_nonblocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail) +{ + return ___cds_wfcq_first(head, tail, 0); +} + +static inline struct cds_wfcq_node * +___cds_wfcq_next(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *node, + int blocking) +{ + struct cds_wfcq_node *next; + + /* + * Even though the following tail->p check is sufficient to find + * out if we reached the end of the queue, we first check + * node->next as a common case to ensure that iteration on nodes + * do not frequently access enqueuer's tail->p cache line. + */ + if ((next = CMM_LOAD_SHARED(node->next)) == NULL) { + /* Load node->next before tail->p */ + cmm_smp_rmb(); + if (CMM_LOAD_SHARED(tail->p) == node) + return NULL; + next = ___cds_wfcq_node_sync_next(node, blocking); + } + /* Load node->next before loading next's content */ + cmm_smp_read_barrier_depends(); + return next; +} + +/* + * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. + * + * Used by for-like iteration macros in urcu/wfqueue.h: + * __cds_wfcq_for_each_blocking() + * __cds_wfcq_for_each_blocking_safe() + * + * Returns NULL if reached end of queue, non-NULL next queue node + * otherwise. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_next_blocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *node) +{ + return ___cds_wfcq_next(head, tail, node, 1); +} + +/* + * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing. + * + * Same as __cds_wfcq_next_blocking, but returns CDS_WFCQ_WOULDBLOCK if + * it needs to block. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_next_nonblocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *node) +{ + return ___cds_wfcq_next(head, tail, node, 0); +} + +static inline struct cds_wfcq_node * +___cds_wfcq_dequeue_with_state(cds_wfcq_head_ptr_t u_head, + struct cds_wfcq_tail *tail, + int *state, + int blocking) +{ + struct __cds_wfcq_head *head = u_head._h; + struct cds_wfcq_node *node, *next; + + if (state) + *state = 0; + + if (_cds_wfcq_empty(__cds_wfcq_head_cast(head), tail)) { + return NULL; + } + + node = ___cds_wfcq_node_sync_next(&head->node, blocking); + if (!blocking && node == CDS_WFCQ_WOULDBLOCK) { + return CDS_WFCQ_WOULDBLOCK; + } + + if ((next = CMM_LOAD_SHARED(node->next)) == NULL) { + /* + * @node is probably the only node in the queue. + * Try to move the tail to &q->head. + * q->head.next is set to NULL here, and stays + * NULL if the cmpxchg succeeds. Should the + * cmpxchg fail due to a concurrent enqueue, the + * q->head.next will be set to the next node. + * The implicit memory barrier before + * uatomic_cmpxchg() orders load node->next + * before loading q->tail. + * The implicit memory barrier before uatomic_cmpxchg + * orders load q->head.next before loading node's + * content. + */ + _cds_wfcq_node_init(&head->node); + if (uatomic_cmpxchg(&tail->p, node, &head->node) == node) { + if (state) + *state |= CDS_WFCQ_STATE_LAST; + return node; + } + next = ___cds_wfcq_node_sync_next(node, blocking); + /* + * In nonblocking mode, if we would need to block to + * get node's next, set the head next node pointer + * (currently NULL) back to its original value. + */ + if (!blocking && next == CDS_WFCQ_WOULDBLOCK) { + head->node.next = node; + return CDS_WFCQ_WOULDBLOCK; + } + } + + /* + * Move queue head forward. + */ + head->node.next = next; + + /* Load q->head.next before loading node's content */ + cmm_smp_read_barrier_depends(); + return node; +} + +/* + * __cds_wfcq_dequeue_with_state_blocking: dequeue node from queue, with state. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * It is valid to reuse and free a dequeued node immediately. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_dequeue_with_state_blocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, int *state) +{ + return ___cds_wfcq_dequeue_with_state(head, tail, state, 1); +} + +/* + * ___cds_wfcq_dequeue_blocking: dequeue node from queue. + * + * Same as __cds_wfcq_dequeue_with_state_blocking, but without saving + * state. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_dequeue_blocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail) +{ + return ___cds_wfcq_dequeue_with_state_blocking(head, tail, NULL); +} + +/* + * __cds_wfcq_dequeue_with_state_nonblocking: dequeue node, with state. + * + * Same as __cds_wfcq_dequeue_blocking, but returns CDS_WFCQ_WOULDBLOCK + * if it needs to block. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_dequeue_with_state_nonblocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail, int *state) +{ + return ___cds_wfcq_dequeue_with_state(head, tail, state, 0); +} + +/* + * ___cds_wfcq_dequeue_nonblocking: dequeue node from queue. + * + * Same as __cds_wfcq_dequeue_with_state_nonblocking, but without saving + * state. + */ +static inline struct cds_wfcq_node * +___cds_wfcq_dequeue_nonblocking(cds_wfcq_head_ptr_t head, + struct cds_wfcq_tail *tail) +{ + return ___cds_wfcq_dequeue_with_state_nonblocking(head, tail, NULL); +} + +/* + * __cds_wfcq_splice: enqueue all src_q nodes at the end of dest_q. + * + * Dequeue all nodes from src_q. + * dest_q must be already initialized. + * Mutual exclusion for src_q should be ensured by the caller as + * specified in the "Synchronisation table". + * Returns enum cds_wfcq_ret which indicates the state of the src or + * dest queue. + */ +static inline enum cds_wfcq_ret +___cds_wfcq_splice( + cds_wfcq_head_ptr_t u_dest_q_head, + struct cds_wfcq_tail *dest_q_tail, + cds_wfcq_head_ptr_t u_src_q_head, + struct cds_wfcq_tail *src_q_tail, + int blocking) +{ + struct __cds_wfcq_head *dest_q_head = u_dest_q_head._h; + struct __cds_wfcq_head *src_q_head = u_src_q_head._h; + struct cds_wfcq_node *head, *tail; + int attempt = 0; + + /* + * Initial emptiness check to speed up cases where queue is + * empty: only require loads to check if queue is empty. + */ + if (_cds_wfcq_empty(__cds_wfcq_head_cast(src_q_head), src_q_tail)) + return CDS_WFCQ_RET_SRC_EMPTY; + + for (;;) { + /* + * Open-coded _cds_wfcq_empty() by testing result of + * uatomic_xchg, as well as tail pointer vs head node + * address. + */ + head = uatomic_xchg(&src_q_head->node.next, NULL); + if (head) + break; /* non-empty */ + if (CMM_LOAD_SHARED(src_q_tail->p) == &src_q_head->node) + return CDS_WFCQ_RET_SRC_EMPTY; + if (___cds_wfcq_busy_wait(&attempt, blocking)) + return CDS_WFCQ_RET_WOULDBLOCK; + } + + /* + * Memory barrier implied before uatomic_xchg() orders store to + * src_q->head before store to src_q->tail. This is required by + * concurrent enqueue on src_q, which exchanges the tail before + * updating the previous tail's next pointer. + */ + tail = uatomic_xchg(&src_q_tail->p, &src_q_head->node); + + /* + * Append the spliced content of src_q into dest_q. Does not + * require mutual exclusion on dest_q (wait-free). + */ + if (___cds_wfcq_append(__cds_wfcq_head_cast(dest_q_head), dest_q_tail, + head, tail)) + return CDS_WFCQ_RET_DEST_NON_EMPTY; + else + return CDS_WFCQ_RET_DEST_EMPTY; +} + +/* + * __cds_wfcq_splice_blocking: enqueue all src_q nodes at the end of dest_q. + * + * Dequeue all nodes from src_q. + * dest_q must be already initialized. + * Mutual exclusion for src_q should be ensured by the caller as + * specified in the "Synchronisation table". + * Returns enum cds_wfcq_ret which indicates the state of the src or + * dest queue. Never returns CDS_WFCQ_RET_WOULDBLOCK. + */ +static inline enum cds_wfcq_ret +___cds_wfcq_splice_blocking( + cds_wfcq_head_ptr_t dest_q_head, + struct cds_wfcq_tail *dest_q_tail, + cds_wfcq_head_ptr_t src_q_head, + struct cds_wfcq_tail *src_q_tail) +{ + return ___cds_wfcq_splice(dest_q_head, dest_q_tail, + src_q_head, src_q_tail, 1); +} + +/* + * __cds_wfcq_splice_nonblocking: enqueue all src_q nodes at the end of dest_q. + * + * Same as __cds_wfcq_splice_blocking, but returns + * CDS_WFCQ_RET_WOULDBLOCK if it needs to block. + */ +static inline enum cds_wfcq_ret +___cds_wfcq_splice_nonblocking( + cds_wfcq_head_ptr_t dest_q_head, + struct cds_wfcq_tail *dest_q_tail, + cds_wfcq_head_ptr_t src_q_head, + struct cds_wfcq_tail *src_q_tail) +{ + return ___cds_wfcq_splice(dest_q_head, dest_q_tail, + src_q_head, src_q_tail, 0); +} + +/* + * cds_wfcq_dequeue_with_state_blocking: dequeue a node from a wait-free queue. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Mutual exclusion with cds_wfcq_splice_blocking and dequeue lock is + * ensured. + * It is valid to reuse and free a dequeued node immediately. + */ +static inline struct cds_wfcq_node * +_cds_wfcq_dequeue_with_state_blocking(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail, int *state) +{ + struct cds_wfcq_node *retval; + + _cds_wfcq_dequeue_lock(head, tail); + retval = ___cds_wfcq_dequeue_with_state_blocking(cds_wfcq_head_cast(head), + tail, state); + _cds_wfcq_dequeue_unlock(head, tail); + return retval; +} + +/* + * cds_wfcq_dequeue_blocking: dequeue node from queue. + * + * Same as cds_wfcq_dequeue_blocking, but without saving state. + */ +static inline struct cds_wfcq_node * +_cds_wfcq_dequeue_blocking(struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail) +{ + return _cds_wfcq_dequeue_with_state_blocking(head, tail, NULL); +} + +/* + * cds_wfcq_splice_blocking: enqueue all src_q nodes at the end of dest_q. + * + * Dequeue all nodes from src_q. + * dest_q must be already initialized. + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Mutual exclusion with cds_wfcq_dequeue_blocking and dequeue lock is + * ensured. + * Returns enum cds_wfcq_ret which indicates the state of the src or + * dest queue. Never returns CDS_WFCQ_RET_WOULDBLOCK. + */ +static inline enum cds_wfcq_ret +_cds_wfcq_splice_blocking( + struct cds_wfcq_head *dest_q_head, + struct cds_wfcq_tail *dest_q_tail, + struct cds_wfcq_head *src_q_head, + struct cds_wfcq_tail *src_q_tail) +{ + enum cds_wfcq_ret ret; + + _cds_wfcq_dequeue_lock(src_q_head, src_q_tail); + ret = ___cds_wfcq_splice_blocking(cds_wfcq_head_cast(dest_q_head), dest_q_tail, + cds_wfcq_head_cast(src_q_head), src_q_tail); + _cds_wfcq_dequeue_unlock(src_q_head, src_q_tail); + return ret; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _URCU_WFCQUEUE_STATIC_H */ diff --git a/contrib/userspace-rcu/static-wfstack.h b/contrib/userspace-rcu/static-wfstack.h new file mode 100644 index 00000000000..29b81c3aac3 --- /dev/null +++ b/contrib/userspace-rcu/static-wfstack.h @@ -0,0 +1,455 @@ +#ifndef _URCU_STATIC_WFSTACK_H +#define _URCU_STATIC_WFSTACK_H + +/* + * urcu/static/wfstack.h + * + * Userspace RCU library - Stack with with wait-free push, blocking traversal. + * + * TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See urcu/wfstack.h for + * linking dynamically with the userspace rcu library. + * + * Copyright 2010-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.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 + */ + +/* Adapted from userspace-rcu 0.10 because version 0.7 doesn't support a stack + * without mutex. */ + +#include <pthread.h> +#include <assert.h> +#include <poll.h> +#include <stdbool.h> +#include <urcu/compiler.h> +#include <urcu/uatomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define CDS_WFS_END ((void *) 0x1UL) +#define CDS_WFS_ADAPT_ATTEMPTS 10 /* Retry if being set */ +#define CDS_WFS_WAIT 10 /* Wait 10 ms if being set */ + +/* + * Stack with wait-free push, blocking traversal. + * + * Stack implementing push, pop, pop_all operations, as well as iterator + * on the stack head returned by pop_all. + * + * Wait-free operations: cds_wfs_push, __cds_wfs_pop_all, cds_wfs_empty, + * cds_wfs_first. + * Blocking operations: cds_wfs_pop, cds_wfs_pop_all, cds_wfs_next, + * iteration on stack head returned by pop_all. + * + * Synchronization table: + * + * External synchronization techniques described in the API below is + * required between pairs marked with "X". No external synchronization + * required between pairs marked with "-". + * + * cds_wfs_push __cds_wfs_pop __cds_wfs_pop_all + * cds_wfs_push - - - + * __cds_wfs_pop - X X + * __cds_wfs_pop_all - X - + * + * cds_wfs_pop and cds_wfs_pop_all use an internal mutex to provide + * synchronization. + */ + +/* + * cds_wfs_node_init: initialize wait-free stack node. + */ +static inline +void _cds_wfs_node_init(struct cds_wfs_node *node) +{ + node->next = NULL; +} + +/* + * __cds_wfs_init: initialize wait-free stack. Don't pair with + * any destroy function. + */ +static inline void ___cds_wfs_init(struct __cds_wfs_stack *s) +{ + s->head = CDS_WFS_END; +} + +/* + * cds_wfs_init: initialize wait-free stack. Pair with + * cds_wfs_destroy(). + */ +static inline +void _cds_wfs_init(struct cds_wfs_stack *s) +{ + int ret; + + s->head = CDS_WFS_END; + ret = pthread_mutex_init(&s->lock, NULL); + assert(!ret); +} + +/* + * cds_wfs_destroy: destroy wait-free stack. Pair with + * cds_wfs_init(). + */ +static inline +void _cds_wfs_destroy(struct cds_wfs_stack *s) +{ + int ret = pthread_mutex_destroy(&s->lock); + assert(!ret); +} + +static inline bool ___cds_wfs_end(void *node) +{ + return node == CDS_WFS_END; +} + +/* + * cds_wfs_empty: return whether wait-free stack is empty. + * + * No memory barrier is issued. No mutual exclusion is required. + */ +static inline bool _cds_wfs_empty(cds_wfs_stack_ptr_t u_stack) +{ + struct __cds_wfs_stack *s = u_stack._s; + + return ___cds_wfs_end(CMM_LOAD_SHARED(s->head)); +} + +/* + * cds_wfs_push: push a node into the stack. + * + * Issues a full memory barrier before push. No mutual exclusion is + * required. + * + * Returns 0 if the stack was empty prior to adding the node. + * Returns non-zero otherwise. + */ +static inline +int _cds_wfs_push(cds_wfs_stack_ptr_t u_stack, struct cds_wfs_node *node) +{ + struct __cds_wfs_stack *s = u_stack._s; + struct cds_wfs_head *old_head, *new_head; + + assert(node->next == NULL); + new_head = caa_container_of(node, struct cds_wfs_head, node); + /* + * uatomic_xchg() implicit memory barrier orders earlier stores + * to node (setting it to NULL) before publication. + */ + old_head = uatomic_xchg(&s->head, new_head); + /* + * At this point, dequeuers see a NULL node->next, they should + * busy-wait until node->next is set to old_head. + */ + CMM_STORE_SHARED(node->next, &old_head->node); + return !___cds_wfs_end(old_head); +} + +/* + * Waiting for push to complete enqueue and return the next node. + */ +static inline struct cds_wfs_node * +___cds_wfs_node_sync_next(struct cds_wfs_node *node, int blocking) +{ + struct cds_wfs_node *next; + int attempt = 0; + + /* + * Adaptative busy-looping waiting for push to complete. + */ + while ((next = CMM_LOAD_SHARED(node->next)) == NULL) { + if (!blocking) + return CDS_WFS_WOULDBLOCK; + if (++attempt >= CDS_WFS_ADAPT_ATTEMPTS) { + (void) poll(NULL, 0, CDS_WFS_WAIT); /* Wait for 10ms */ + attempt = 0; + } else { + caa_cpu_relax(); + } + } + + return next; +} + +static inline +struct cds_wfs_node * +___cds_wfs_pop(cds_wfs_stack_ptr_t u_stack, int *state, int blocking) +{ + struct cds_wfs_head *head, *new_head; + struct cds_wfs_node *next; + struct __cds_wfs_stack *s = u_stack._s; + + if (state) + *state = 0; + for (;;) { + head = CMM_LOAD_SHARED(s->head); + if (___cds_wfs_end(head)) { + return NULL; + } + next = ___cds_wfs_node_sync_next(&head->node, blocking); + if (!blocking && next == CDS_WFS_WOULDBLOCK) { + return CDS_WFS_WOULDBLOCK; + } + new_head = caa_container_of(next, struct cds_wfs_head, node); + if (uatomic_cmpxchg(&s->head, head, new_head) == head) { + if (state && ___cds_wfs_end(new_head)) + *state |= CDS_WFS_STATE_LAST; + return &head->node; + } + if (!blocking) { + return CDS_WFS_WOULDBLOCK; + } + /* busy-loop if head changed under us */ + } +} + +/* + * __cds_wfs_pop_with_state_blocking: pop a node from the stack, with state. + * + * Returns NULL if stack is empty. + * + * __cds_wfs_pop_blocking needs to be synchronized using one of the + * following techniques: + * + * 1) Calling __cds_wfs_pop_blocking under rcu read lock critical + * section. The caller must wait for a grace period to pass before + * freeing the returned node or modifying the cds_wfs_node structure. + * 2) Using mutual exclusion (e.g. mutexes) to protect + * __cds_wfs_pop_blocking and __cds_wfs_pop_all callers. + * 3) Ensuring that only ONE thread can call __cds_wfs_pop_blocking() + * and __cds_wfs_pop_all(). (multi-provider/single-consumer scheme). + * + * "state" saves state flags atomically sampled with pop operation. + */ +static inline +struct cds_wfs_node * +___cds_wfs_pop_with_state_blocking(cds_wfs_stack_ptr_t u_stack, int *state) +{ + return ___cds_wfs_pop(u_stack, state, 1); +} + +static inline +struct cds_wfs_node * +___cds_wfs_pop_blocking(cds_wfs_stack_ptr_t u_stack) +{ + return ___cds_wfs_pop_with_state_blocking(u_stack, NULL); +} + +/* + * __cds_wfs_pop_with_state_nonblocking: pop a node from the stack. + * + * Same as __cds_wfs_pop_with_state_blocking, but returns + * CDS_WFS_WOULDBLOCK if it needs to block. + * + * "state" saves state flags atomically sampled with pop operation. + */ +static inline +struct cds_wfs_node * +___cds_wfs_pop_with_state_nonblocking(cds_wfs_stack_ptr_t u_stack, int *state) +{ + return ___cds_wfs_pop(u_stack, state, 0); +} + +/* + * __cds_wfs_pop_nonblocking: pop a node from the stack. + * + * Same as __cds_wfs_pop_blocking, but returns CDS_WFS_WOULDBLOCK if + * it needs to block. + */ +static inline +struct cds_wfs_node * +___cds_wfs_pop_nonblocking(cds_wfs_stack_ptr_t u_stack) +{ + return ___cds_wfs_pop_with_state_nonblocking(u_stack, NULL); +} + +/* + * __cds_wfs_pop_all: pop all nodes from a stack. + * + * __cds_wfs_pop_all does not require any synchronization with other + * push, nor with other __cds_wfs_pop_all, but requires synchronization + * matching the technique used to synchronize __cds_wfs_pop_blocking: + * + * 1) If __cds_wfs_pop_blocking is called under rcu read lock critical + * section, both __cds_wfs_pop_blocking and cds_wfs_pop_all callers + * must wait for a grace period to pass before freeing the returned + * node or modifying the cds_wfs_node structure. However, no RCU + * read-side critical section is needed around __cds_wfs_pop_all. + * 2) Using mutual exclusion (e.g. mutexes) to protect + * __cds_wfs_pop_blocking and __cds_wfs_pop_all callers. + * 3) Ensuring that only ONE thread can call __cds_wfs_pop_blocking() + * and __cds_wfs_pop_all(). (multi-provider/single-consumer scheme). + */ +static inline +struct cds_wfs_head * +___cds_wfs_pop_all(cds_wfs_stack_ptr_t u_stack) +{ + struct __cds_wfs_stack *s = u_stack._s; + struct cds_wfs_head *head; + + /* + * Implicit memory barrier after uatomic_xchg() matches implicit + * memory barrier before uatomic_xchg() in cds_wfs_push. It + * ensures that all nodes of the returned list are consistent. + * There is no need to issue memory barriers when iterating on + * the returned list, because the full memory barrier issued + * prior to each uatomic_cmpxchg, which each write to head, are + * taking care to order writes to each node prior to the full + * memory barrier after this uatomic_xchg(). + */ + head = uatomic_xchg(&s->head, CDS_WFS_END); + if (___cds_wfs_end(head)) + return NULL; + return head; +} + +/* + * cds_wfs_pop_lock: lock stack pop-protection mutex. + */ +static inline void _cds_wfs_pop_lock(struct cds_wfs_stack *s) +{ + int ret; + + ret = pthread_mutex_lock(&s->lock); + assert(!ret); +} + +/* + * cds_wfs_pop_unlock: unlock stack pop-protection mutex. + */ +static inline void _cds_wfs_pop_unlock(struct cds_wfs_stack *s) +{ + int ret; + + ret = pthread_mutex_unlock(&s->lock); + assert(!ret); +} + +/* + * Call __cds_wfs_pop_with_state_blocking with an internal pop mutex held. + */ +static inline +struct cds_wfs_node * +_cds_wfs_pop_with_state_blocking(struct cds_wfs_stack *s, int *state) +{ + struct cds_wfs_node *retnode; + + _cds_wfs_pop_lock(s); + retnode = ___cds_wfs_pop_with_state_blocking(s, state); + _cds_wfs_pop_unlock(s); + return retnode; +} + +/* + * Call _cds_wfs_pop_with_state_blocking without saving any state. + */ +static inline +struct cds_wfs_node * +_cds_wfs_pop_blocking(struct cds_wfs_stack *s) +{ + return _cds_wfs_pop_with_state_blocking(s, NULL); +} + +/* + * Call __cds_wfs_pop_all with an internal pop mutex held. + */ +static inline +struct cds_wfs_head * +_cds_wfs_pop_all_blocking(struct cds_wfs_stack *s) +{ + struct cds_wfs_head *rethead; + + _cds_wfs_pop_lock(s); + rethead = ___cds_wfs_pop_all(s); + _cds_wfs_pop_unlock(s); + return rethead; +} + +/* + * cds_wfs_first: get first node of a popped stack. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * + * Used by for-like iteration macros in urcu/wfstack.h: + * cds_wfs_for_each_blocking() + * cds_wfs_for_each_blocking_safe() + * + * Returns NULL if popped stack is empty, top stack node otherwise. + */ +static inline struct cds_wfs_node * +_cds_wfs_first(struct cds_wfs_head *head) +{ + if (___cds_wfs_end(head)) + return NULL; + return &head->node; +} + +static inline struct cds_wfs_node * +___cds_wfs_next(struct cds_wfs_node *node, int blocking) +{ + struct cds_wfs_node *next; + + next = ___cds_wfs_node_sync_next(node, blocking); + /* + * CDS_WFS_WOULDBLOCK != CSD_WFS_END, so we can check for end + * even if ___cds_wfs_node_sync_next returns CDS_WFS_WOULDBLOCK, + * and still return CDS_WFS_WOULDBLOCK. + */ + if (___cds_wfs_end(next)) + return NULL; + return next; +} + +/* + * cds_wfs_next_blocking: get next node of a popped stack. + * + * Content written into the node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * + * Used by for-like iteration macros in urcu/wfstack.h: + * cds_wfs_for_each_blocking() + * cds_wfs_for_each_blocking_safe() + * + * Returns NULL if reached end of popped stack, non-NULL next stack + * node otherwise. + */ +static inline struct cds_wfs_node * +_cds_wfs_next_blocking(struct cds_wfs_node *node) +{ + return ___cds_wfs_next(node, 1); +} + + +/* + * cds_wfs_next_nonblocking: get next node of a popped stack. + * + * Same as cds_wfs_next_blocking, but returns CDS_WFS_WOULDBLOCK if it + * needs to block. + */ +static inline struct cds_wfs_node * +_cds_wfs_next_nonblocking(struct cds_wfs_node *node) +{ + return ___cds_wfs_next(node, 0); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _URCU_STATIC_WFSTACK_H */ diff --git a/contrib/userspace-rcu/wfcqueue.h b/contrib/userspace-rcu/wfcqueue.h new file mode 100644 index 00000000000..0292585ac79 --- /dev/null +++ b/contrib/userspace-rcu/wfcqueue.h @@ -0,0 +1,216 @@ +#ifndef _URCU_WFCQUEUE_H +#define _URCU_WFCQUEUE_H + +/* + * urcu/wfcqueue.h + * + * Userspace RCU library - Concurrent Queue with Wait-Free Enqueue/Blocking Dequeue + * + * Copyright 2010-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> + * Copyright 2011-2012 - Lai Jiangshan <laijs@cn.fujitsu.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 + */ + +/* Adapted from userspace-rcu 0.10 because version 0.7 doesn't contain it. + * The non-LGPL section has been removed. */ + +#include <pthread.h> +#include <assert.h> +#include <stdbool.h> +#include <urcu/compiler.h> +#include <urcu/arch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Concurrent queue with wait-free enqueue/blocking dequeue. + * + * This queue has been designed and implemented collaboratively by + * Mathieu Desnoyers and Lai Jiangshan. Inspired from + * half-wait-free/half-blocking queue implementation done by Paul E. + * McKenney. + */ + +#define CDS_WFCQ_WOULDBLOCK ((struct cds_wfcq_node *) -1UL) + +enum cds_wfcq_ret { + CDS_WFCQ_RET_WOULDBLOCK = -1, + CDS_WFCQ_RET_DEST_EMPTY = 0, + CDS_WFCQ_RET_DEST_NON_EMPTY = 1, + CDS_WFCQ_RET_SRC_EMPTY = 2, +}; + +enum cds_wfcq_state { + CDS_WFCQ_STATE_LAST = (1U << 0), +}; + +struct cds_wfcq_node { + struct cds_wfcq_node *next; +}; + +/* + * Do not put head and tail on the same cache-line if concurrent + * enqueue/dequeue are expected from many CPUs. This eliminates + * false-sharing between enqueue and dequeue. + */ +struct __cds_wfcq_head { + struct cds_wfcq_node node; +}; + +struct cds_wfcq_head { + struct cds_wfcq_node node; + pthread_mutex_t lock; +}; + +#ifndef __cplusplus +/* + * The transparent union allows calling functions that work on both + * struct cds_wfcq_head and struct __cds_wfcq_head on any of those two + * types. + */ +typedef union { + struct __cds_wfcq_head *_h; + struct cds_wfcq_head *h; +} __attribute__((__transparent_union__)) cds_wfcq_head_ptr_t; + +/* + * This static inline is only present for compatibility with C++. It is + * effect-less in C. + */ +static inline struct __cds_wfcq_head *__cds_wfcq_head_cast(struct __cds_wfcq_head *head) +{ + return head; +} + +/* + * This static inline is only present for compatibility with C++. It is + * effect-less in C. + */ +static inline struct cds_wfcq_head *cds_wfcq_head_cast(struct cds_wfcq_head *head) +{ + return head; +} +#else /* #ifndef __cplusplus */ + +/* C++ ignores transparent union. */ +typedef union { + struct __cds_wfcq_head *_h; + struct cds_wfcq_head *h; +} cds_wfcq_head_ptr_t; + +/* C++ ignores transparent union. Requires an explicit conversion. */ +static inline cds_wfcq_head_ptr_t __cds_wfcq_head_cast(struct __cds_wfcq_head *head) +{ + cds_wfcq_head_ptr_t ret = { ._h = head }; + return ret; +} +/* C++ ignores transparent union. Requires an explicit conversion. */ +static inline cds_wfcq_head_ptr_t cds_wfcq_head_cast(struct cds_wfcq_head *head) +{ + cds_wfcq_head_ptr_t ret = { .h = head }; + return ret; +} +#endif /* #else #ifndef __cplusplus */ + +struct cds_wfcq_tail { + struct cds_wfcq_node *p; +}; + +#include "static-wfcqueue.h" + +#define cds_wfcq_node_init _cds_wfcq_node_init +#define cds_wfcq_init _cds_wfcq_init +#define __cds_wfcq_init ___cds_wfcq_init +#define cds_wfcq_destroy _cds_wfcq_destroy +#define cds_wfcq_empty _cds_wfcq_empty +#define cds_wfcq_enqueue _cds_wfcq_enqueue + +/* Dequeue locking */ +#define cds_wfcq_dequeue_lock _cds_wfcq_dequeue_lock +#define cds_wfcq_dequeue_unlock _cds_wfcq_dequeue_unlock + +/* Locking performed within cds_wfcq calls. */ +#define cds_wfcq_dequeue_blocking _cds_wfcq_dequeue_blocking +#define cds_wfcq_dequeue_with_state_blocking \ + _cds_wfcq_dequeue_with_state_blocking +#define cds_wfcq_splice_blocking _cds_wfcq_splice_blocking +#define cds_wfcq_first_blocking _cds_wfcq_first_blocking +#define cds_wfcq_next_blocking _cds_wfcq_next_blocking + +/* Locking ensured by caller by holding cds_wfcq_dequeue_lock() */ +#define __cds_wfcq_dequeue_blocking ___cds_wfcq_dequeue_blocking +#define __cds_wfcq_dequeue_with_state_blocking \ + ___cds_wfcq_dequeue_with_state_blocking +#define __cds_wfcq_splice_blocking ___cds_wfcq_splice_blocking +#define __cds_wfcq_first_blocking ___cds_wfcq_first_blocking +#define __cds_wfcq_next_blocking ___cds_wfcq_next_blocking + +/* + * Locking ensured by caller by holding cds_wfcq_dequeue_lock(). + * Non-blocking: deque, first, next return CDS_WFCQ_WOULDBLOCK if they + * need to block. splice returns nonzero if it needs to block. + */ +#define __cds_wfcq_dequeue_nonblocking ___cds_wfcq_dequeue_nonblocking +#define __cds_wfcq_dequeue_with_state_nonblocking \ + ___cds_wfcq_dequeue_with_state_nonblocking +#define __cds_wfcq_splice_nonblocking ___cds_wfcq_splice_nonblocking +#define __cds_wfcq_first_nonblocking ___cds_wfcq_first_nonblocking +#define __cds_wfcq_next_nonblocking ___cds_wfcq_next_nonblocking + +/* + * __cds_wfcq_for_each_blocking: Iterate over all nodes in a queue, + * without dequeuing them. + * @head: head of the queue (struct cds_wfcq_head or __cds_wfcq_head pointer). + * @tail: tail of the queue (struct cds_wfcq_tail pointer). + * @node: iterator on the queue (struct cds_wfcq_node pointer). + * + * Content written into each node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. + */ +#define __cds_wfcq_for_each_blocking(head, tail, node) \ + for (node = __cds_wfcq_first_blocking(head, tail); \ + node != NULL; \ + node = __cds_wfcq_next_blocking(head, tail, node)) + +/* + * __cds_wfcq_for_each_blocking_safe: Iterate over all nodes in a queue, + * without dequeuing them. Safe against deletion. + * @head: head of the queue (struct cds_wfcq_head or __cds_wfcq_head pointer). + * @tail: tail of the queue (struct cds_wfcq_tail pointer). + * @node: iterator on the queue (struct cds_wfcq_node pointer). + * @n: struct cds_wfcq_node pointer holding the next pointer (used + * internally). + * + * Content written into each node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. + */ +#define __cds_wfcq_for_each_blocking_safe(head, tail, node, n) \ + for (node = __cds_wfcq_first_blocking(head, tail), \ + n = (node ? __cds_wfcq_next_blocking(head, tail, node) : NULL); \ + node != NULL; \ + node = n, n = (node ? __cds_wfcq_next_blocking(head, tail, node) : NULL)) + +#ifdef __cplusplus +} +#endif + +#endif /* _URCU_WFCQUEUE_H */ diff --git a/contrib/userspace-rcu/wfstack.h b/contrib/userspace-rcu/wfstack.h new file mode 100644 index 00000000000..738fd1cfd33 --- /dev/null +++ b/contrib/userspace-rcu/wfstack.h @@ -0,0 +1,178 @@ +#ifndef _URCU_WFSTACK_H +#define _URCU_WFSTACK_H + +/* + * urcu/wfstack.h + * + * Userspace RCU library - Stack with wait-free push, blocking traversal. + * + * Copyright 2010-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.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 + */ + +/* Adapted from userspace-rcu 0.10 because version 0.7 doesn't support a stack + * without mutex. The non-LGPL section has been removed. */ + +#include <pthread.h> +#include <assert.h> +#include <stdbool.h> +#include <urcu/compiler.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Stack with wait-free push, blocking traversal. + * + * Stack implementing push, pop, pop_all operations, as well as iterator + * on the stack head returned by pop_all. + * + * Wait-free operations: cds_wfs_push, __cds_wfs_pop_all, cds_wfs_empty, + * cds_wfs_first. + * Blocking operations: cds_wfs_pop, cds_wfs_pop_all, cds_wfs_next, + * iteration on stack head returned by pop_all. + * + * Synchronization table: + * + * External synchronization techniques described in the API below is + * required between pairs marked with "X". No external synchronization + * required between pairs marked with "-". + * + * cds_wfs_push __cds_wfs_pop __cds_wfs_pop_all + * cds_wfs_push - - - + * __cds_wfs_pop - X X + * __cds_wfs_pop_all - X - + * + * cds_wfs_pop and cds_wfs_pop_all use an internal mutex to provide + * synchronization. + */ + +#define CDS_WFS_WOULDBLOCK ((void *) -1UL) + +enum cds_wfs_state { + CDS_WFS_STATE_LAST = (1U << 0), +}; + +/* + * struct cds_wfs_node is returned by __cds_wfs_pop, and also used as + * iterator on stack. It is not safe to dereference the node next + * pointer when returned by __cds_wfs_pop_blocking. + */ +struct cds_wfs_node { + struct cds_wfs_node *next; +}; + +/* + * struct cds_wfs_head is returned by __cds_wfs_pop_all, and can be used + * to begin iteration on the stack. "node" needs to be the first field of + * cds_wfs_head, so the end-of-stack pointer value can be used for both + * types. + */ +struct cds_wfs_head { + struct cds_wfs_node node; +}; + +struct __cds_wfs_stack { + struct cds_wfs_head *head; +}; + +struct cds_wfs_stack { + struct cds_wfs_head *head; + pthread_mutex_t lock; +}; + +/* + * The transparent union allows calling functions that work on both + * struct cds_wfs_stack and struct __cds_wfs_stack on any of those two + * types. + */ +typedef union { + struct __cds_wfs_stack *_s; + struct cds_wfs_stack *s; +} __attribute__((__transparent_union__)) cds_wfs_stack_ptr_t; + +#include "static-wfstack.h" + +#define cds_wfs_node_init _cds_wfs_node_init +#define cds_wfs_init _cds_wfs_init +#define cds_wfs_destroy _cds_wfs_destroy +#define __cds_wfs_init ___cds_wfs_init +#define cds_wfs_empty _cds_wfs_empty +#define cds_wfs_push _cds_wfs_push + +/* Locking performed internally */ +#define cds_wfs_pop_blocking _cds_wfs_pop_blocking +#define cds_wfs_pop_with_state_blocking _cds_wfs_pop_with_state_blocking +#define cds_wfs_pop_all_blocking _cds_wfs_pop_all_blocking + +/* + * For iteration on cds_wfs_head returned by __cds_wfs_pop_all or + * cds_wfs_pop_all_blocking. + */ +#define cds_wfs_first _cds_wfs_first +#define cds_wfs_next_blocking _cds_wfs_next_blocking +#define cds_wfs_next_nonblocking _cds_wfs_next_nonblocking + +/* Pop locking with internal mutex */ +#define cds_wfs_pop_lock _cds_wfs_pop_lock +#define cds_wfs_pop_unlock _cds_wfs_pop_unlock + +/* Synchronization ensured by the caller. See synchronization table. */ +#define __cds_wfs_pop_blocking ___cds_wfs_pop_blocking +#define __cds_wfs_pop_with_state_blocking \ + ___cds_wfs_pop_with_state_blocking +#define __cds_wfs_pop_nonblocking ___cds_wfs_pop_nonblocking +#define __cds_wfs_pop_with_state_nonblocking \ + ___cds_wfs_pop_with_state_nonblocking +#define __cds_wfs_pop_all ___cds_wfs_pop_all + +#ifdef __cplusplus +} +#endif + +/* + * cds_wfs_for_each_blocking: Iterate over all nodes returned by + * __cds_wfs_pop_all(). + * @head: head of the queue (struct cds_wfs_head pointer). + * @node: iterator (struct cds_wfs_node pointer). + * + * Content written into each node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + */ +#define cds_wfs_for_each_blocking(head, node) \ + for (node = cds_wfs_first(head); \ + node != NULL; \ + node = cds_wfs_next_blocking(node)) + +/* + * cds_wfs_for_each_blocking_safe: Iterate over all nodes returned by + * __cds_wfs_pop_all(). Safe against deletion. + * @head: head of the queue (struct cds_wfs_head pointer). + * @node: iterator (struct cds_wfs_node pointer). + * @n: struct cds_wfs_node pointer holding the next pointer (used + * internally). + * + * Content written into each node before enqueue is guaranteed to be + * consistent, but no other memory ordering is ensured. + */ +#define cds_wfs_for_each_blocking_safe(head, node, n) \ + for (node = cds_wfs_first(head), \ + n = (node ? cds_wfs_next_blocking(node) : NULL); \ + node != NULL; \ + node = n, n = (node ? cds_wfs_next_blocking(node) : NULL)) + +#endif /* _URCU_WFSTACK_H */ diff --git a/contrib/uuid/clear.c b/contrib/uuid/clear.c deleted file mode 100644 index 2d91fee9399..00000000000 --- a/contrib/uuid/clear.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * clear.c -- Clear a UUID - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "string.h" - -#include "uuidP.h" - -void uuid_clear(uuid_t uu) -{ - memset(uu, 0, 16); -} - diff --git a/contrib/uuid/compare.c b/contrib/uuid/compare.c deleted file mode 100644 index f28a72678cf..00000000000 --- a/contrib/uuid/compare.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * compare.c --- compare whether or not two UUID's are the same - * - * Returns 0 if the two UUID's are different, and 1 if they are the same. - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "uuidP.h" -#include <string.h> - -#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1); - -int uuid_compare(const uuid_t uu1, const uuid_t uu2) -{ - struct uuid uuid1, uuid2; - - uuid_unpack(uu1, &uuid1); - uuid_unpack(uu2, &uuid2); - - UUCMP(uuid1.time_low, uuid2.time_low); - UUCMP(uuid1.time_mid, uuid2.time_mid); - UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); - UUCMP(uuid1.clock_seq, uuid2.clock_seq); - return memcmp(uuid1.node, uuid2.node, 6); -} - diff --git a/contrib/uuid/copy.c b/contrib/uuid/copy.c deleted file mode 100644 index ead33aa26e8..00000000000 --- a/contrib/uuid/copy.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * copy.c --- copy UUIDs - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "uuidP.h" - -void uuid_copy(uuid_t dst, const uuid_t src) -{ - unsigned char *cp1; - const unsigned char *cp2; - int i; - - for (i=0, cp1 = dst, cp2 = src; i < 16; i++) - *cp1++ = *cp2++; -} diff --git a/contrib/uuid/gen_uuid.c b/contrib/uuid/gen_uuid.c deleted file mode 100644 index 4da0dc69b84..00000000000 --- a/contrib/uuid/gen_uuid.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * gen_uuid.c --- generate a DCE-compatible uuid - * - * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -/* - * Force inclusion of SVID stuff since we need it if we're compiling in - * gcc-wall wall mode - */ -#define _SVID_SOURCE - -#include "config.h" -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif -#include <stdio.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/wait.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_FILE_H -#include <sys/file.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -#include <sys/ioctl.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_SYS_UN_H -#include <sys/un.h> -#endif -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> -#endif -#ifdef HAVE_NET_IF_H -#include <net/if.h> -#endif -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_NET_IF_DL_H -#include <net/if_dl.h> -#endif -#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) -#include <sys/syscall.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif -#include <limits.h> - -#include "uuidP.h" -#include "uuidd.h" - -#ifdef HAVE_SRANDOM -#define srand(x) srandom(x) -#define rand() random() -#endif - -#ifdef TLS -#define THREAD_LOCAL static TLS -#else -#define THREAD_LOCAL static -#endif - -#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48) -#define DO_JRAND_MIX -THREAD_LOCAL unsigned short jrand_seed[3]; -#endif - -#ifndef OPEN_MAX -#define OPEN_MAX 1024 -#endif - -#ifdef _WIN32 -static void gettimeofday (struct timeval *tv, void *dummy) -{ - FILETIME ftime; - uint64_t n; - - GetSystemTimeAsFileTime (&ftime); - n = (((uint64_t) ftime.dwHighDateTime << 32) - + (uint64_t) ftime.dwLowDateTime); - if (n) { - n /= 10; - n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; - } - - tv->tv_sec = n / 1000000; - tv->tv_usec = n % 1000000; -} - -static int getuid (void) -{ - return 1; -} -#endif - -static int get_random_fd(void) -{ - struct timeval tv; - static int fd = -2; - int i; - - if (fd == -2) { - gettimeofday(&tv, 0); -#ifndef _WIN32 - fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (fd >= 0) { - i = fcntl(fd, F_GETFD); - if (i >= 0) - fcntl(fd, F_SETFD, i | FD_CLOEXEC); - } -#endif - srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); -#ifdef DO_JRAND_MIX - jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); - jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); - jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; -#endif - } - /* Crank the random number generator a few times */ - gettimeofday(&tv, 0); - for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) - rand(); - return fd; -} - - -/* - * Generate a series of random bytes. Use /dev/urandom if possible, - * and if not, use srandom/random. - */ -static void get_random_bytes(void *buf, int nbytes) -{ - int i, n = nbytes, fd = get_random_fd(); - int lose_counter = 0; - unsigned char *cp = (unsigned char *) buf; -#ifdef DO_JRAND_MIX - unsigned short tmp_seed[3]; -#endif - if (fd >= 0) { - while (n > 0) { - i = read(fd, cp, n); - if (i <= 0) { - if (lose_counter++ > 16) - break; - continue; - } - n -= i; - cp += i; - lose_counter = 0; - } - } - - /* - * We do this all the time, but this is the only source of - * randomness if /dev/random/urandom is out to lunch. - */ - for (cp = buf, i = 0; i < nbytes; i++) - *cp++ ^= (rand() >> 7) & 0xFF; -#ifdef DO_JRAND_MIX - memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed)); - jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid); - for (cp = buf, i = 0; i < nbytes; i++) - *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF; - memcpy(jrand_seed, tmp_seed, - sizeof(jrand_seed)-sizeof(unsigned short)); -#endif - - return; -} - -/* - * Get the ethernet hardware address, if we can find it... - * - * XXX for a windows version, probably should use GetAdaptersInfo: - * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 - * commenting out get_node_id just to get gen_uuid to compile under windows - * is not the right way to go! - */ -static int get_node_id(unsigned char *node_id) -{ -#ifdef HAVE_NET_IF_H - int sd; - struct ifreq ifr, *ifrp; - struct ifconf ifc; - char buf[1024]; - int n, i; - unsigned char *a; -#ifdef HAVE_NET_IF_DL_H - struct sockaddr_dl *sdlp; -#endif - -/* - * BSD 4.4 defines the size of an ifreq to be - * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len - * However, under earlier systems, sa_len isn't present, so the size is - * just sizeof(struct ifreq) - */ -#ifdef HAVE_SA_LEN -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif -#define ifreq_size(i) max(sizeof(struct ifreq),\ - sizeof((i).ifr_name)+(i).ifr_addr.sa_len) -#else -#define ifreq_size(i) sizeof(struct ifreq) -#endif /* HAVE_SA_LEN*/ - - sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (sd < 0) { - return -1; - } - memset(buf, 0, sizeof(buf)); - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { - close(sd); - return -1; - } - n = ifc.ifc_len; - for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { - ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); - strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); -#ifdef SIOCGIFHWADDR - if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) - continue; - a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; -#else -#ifdef SIOCGENADDR - if (ioctl(sd, SIOCGENADDR, &ifr) < 0) - continue; - a = (unsigned char *) ifr.ifr_enaddr; -#else -#ifdef HAVE_NET_IF_DL_H - sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; - if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) - continue; - a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; -#else - /* - * XXX we don't have a way of getting the hardware - * address - */ - close(sd); - return 0; -#endif /* HAVE_NET_IF_DL_H */ -#endif /* SIOCGENADDR */ -#endif /* SIOCGIFHWADDR */ - if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) - continue; - if (node_id) { - memcpy(node_id, a, 6); - close(sd); - return 1; - } - } - close(sd); -#endif - return 0; -} - -/* Assume that the gettimeofday() has microsecond granularity */ -#define MAX_ADJUSTMENT 10 - -static int get_clock(uint32_t *clock_high, uint32_t *clock_low, - uint16_t *ret_clock_seq, int *num) -{ - THREAD_LOCAL int adjustment = 0; - THREAD_LOCAL struct timeval last = {0, 0}; - THREAD_LOCAL int state_fd = -2; - THREAD_LOCAL FILE *state_f; - THREAD_LOCAL uint16_t clock_seq; - struct timeval tv; - struct flock fl; - uint64_t clock_reg; - mode_t save_umask; - int len; - - if (state_fd == -2) { - save_umask = umask(0); - state_fd = open("/var/lib/libuuid/clock.txt", - O_RDWR|O_CREAT, 0660); - (void) umask(save_umask); - state_f = fdopen(state_fd, "r+"); - if (!state_f) { - close(state_fd); - state_fd = -1; - } - } - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = 0; - if (state_fd >= 0) { - rewind(state_f); - while (fcntl(state_fd, F_SETLKW, &fl) < 0) { - if ((errno == EAGAIN) || (errno == EINTR)) - continue; - fclose(state_f); - close(state_fd); - state_fd = -1; - break; - } - } - if (state_fd >= 0) { - unsigned int cl; - unsigned long tv1, tv2; - int a; - - if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", - &cl, &tv1, &tv2, &a) == 4) { - clock_seq = cl & 0x3FFF; - last.tv_sec = tv1; - last.tv_usec = tv2; - adjustment = a; - } - } - - if ((last.tv_sec == 0) && (last.tv_usec == 0)) { - get_random_bytes(&clock_seq, sizeof(clock_seq)); - clock_seq &= 0x3FFF; - gettimeofday(&last, 0); - last.tv_sec--; - } - -try_again: - gettimeofday(&tv, 0); - if ((tv.tv_sec < last.tv_sec) || - ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec < last.tv_usec))) { - clock_seq = (clock_seq+1) & 0x3FFF; - adjustment = 0; - last = tv; - } else if ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec == last.tv_usec)) { - if (adjustment >= MAX_ADJUSTMENT) - goto try_again; - adjustment++; - } else { - adjustment = 0; - last = tv; - } - - clock_reg = tv.tv_usec*10 + adjustment; - clock_reg += ((uint64_t) tv.tv_sec)*10000000; - clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; - - if (num && (*num > 1)) { - adjustment += *num - 1; - last.tv_usec += adjustment / 10; - adjustment = adjustment % 10; - last.tv_sec += last.tv_usec / 1000000; - last.tv_usec = last.tv_usec % 1000000; - } - - if (state_fd > 0) { - rewind(state_f); - len = fprintf(state_f, - "clock: %04x tv: %016lu %08lu adj: %08d\n", - clock_seq, last.tv_sec, last.tv_usec, adjustment); - fflush(state_f); - if (ftruncate(state_fd, len) < 0) { - fprintf(state_f, " \n"); - fflush(state_f); - } - rewind(state_f); - fl.l_type = F_UNLCK; - fcntl(state_fd, F_SETLK, &fl); - } - - *clock_high = clock_reg >> 32; - *clock_low = clock_reg; - *ret_clock_seq = clock_seq; - return 0; -} - -#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) -static ssize_t read_all(int fd, char *buf, size_t count) -{ - ssize_t ret; - ssize_t c = 0; - int tries = 0; - - memset(buf, 0, count); - while (count > 0) { - ret = read(fd, buf, count); - if (ret <= 0) { - if ((errno == EAGAIN || errno == EINTR || ret == 0) && - (tries++ < 5)) - continue; - return c ? c : -1; - } - if (ret > 0) - tries = 0; - count -= ret; - buf += ret; - c += ret; - } - return c; -} -#endif - -/* - * Close all file descriptors - */ -#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) -static void close_all_fds(void) -{ -#ifdef F_CLOSEM - (void)fcntl(0, F_CLOSEM); - (void)open("/dev/null", O_RDWR); /* stdin */ - (void)open("/dev/null", O_RDWR); /* stdout */ - (void)open("/dev/null", O_RDWR); /* stderr */ -#else /* F_CLOSEM */ - int i, max; - -#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) - max = sysconf(_SC_OPEN_MAX); -#elif defined(HAVE_GETDTABLESIZE) - max = getdtablesize(); -#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) - struct rlimit rl; - - getrlimit(RLIMIT_NOFILE, &rl); - max = rl.rlim_cur; -#else - max = OPEN_MAX; -#endif - - for (i=0; i < max; i++) { - close(i); - if (i <= 2) - open("/dev/null", O_RDWR); - } -#endif /* F_CLOSEM */ -} -#endif - - -/* - * Try using the uuidd daemon to generate the UUID - * - * Returns 0 on success, non-zero on failure. - */ -static int get_uuid_via_daemon(int op, uuid_t out, int *num) -{ -#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) - char op_buf[64]; - int op_len; - int s; - ssize_t ret; - int32_t reply_len = 0, expected = 16; - struct sockaddr_un srv_addr; - struct stat st; - pid_t pid; - static const char *uuidd_path = UUIDD_PATH; - static int access_ret = -2; - static int start_attempts = 0; - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return -1; - - srv_addr.sun_family = AF_UNIX; - strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH); - - if (connect(s, (const struct sockaddr *) &srv_addr, - sizeof(struct sockaddr_un)) < 0) { - if (access_ret == -2) - access_ret = access(uuidd_path, X_OK); - if (access_ret == 0) - access_ret = stat(uuidd_path, &st); - if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0) - access_ret = access(UUIDD_DIR, W_OK); - if (access_ret == 0 && start_attempts++ < 5) { - if ((pid = fork()) == 0) { - close_all_fds(); - execl(uuidd_path, "uuidd", "-qT", "300", - (char *) NULL); - exit(1); - } - (void) waitpid(pid, 0, 0); - if (connect(s, (const struct sockaddr *) &srv_addr, - sizeof(struct sockaddr_un)) < 0) - goto fail; - } else - goto fail; - } - op_buf[0] = op; - op_len = 1; - if (op == UUIDD_OP_BULK_TIME_UUID) { - memcpy(op_buf+1, num, sizeof(*num)); - op_len += sizeof(*num); - expected += sizeof(*num); - } - - ret = write(s, op_buf, op_len); - if (ret < 1) - goto fail; - - ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); - if (ret < 0) - goto fail; - - if (reply_len != expected) - goto fail; - - ret = read_all(s, op_buf, reply_len); - - if (op == UUIDD_OP_BULK_TIME_UUID) - memcpy(op_buf+16, num, sizeof(int)); - - memcpy(out, op_buf, 16); - - close(s); - return ((ret == expected) ? 0 : -1); - -fail: - close(s); -#endif - return -1; -} - -void uuid__generate_time(uuid_t out, int *num) -{ - static unsigned char node_id[6]; - static int has_init = 0; - struct uuid uu; - uint32_t clock_mid; - - if (!has_init) { - if (get_node_id(node_id) <= 0) { - get_random_bytes(node_id, 6); - /* - * Set multicast bit, to prevent conflicts - * with IEEE 802 addresses obtained from - * network cards - */ - node_id[0] |= 0x01; - } - has_init = 1; - } - get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); - uu.clock_seq |= 0x8000; - uu.time_mid = (uint16_t) clock_mid; - uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; - memcpy(uu.node, node_id, 6); - uuid_pack(&uu, out); -} - -void uuid_generate_time(uuid_t out) -{ -#ifdef TLS - THREAD_LOCAL int num = 0; - THREAD_LOCAL struct uuid uu; - THREAD_LOCAL time_t last_time = 0; - time_t now; - - if (num > 0) { - now = time(0); - if (now > last_time+1) - num = 0; - } - if (num <= 0) { - num = 1000; - if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, - out, &num) == 0) { - last_time = time(0); - uuid_unpack(out, &uu); - num--; - return; - } - num = 0; - } - if (num > 0) { - uu.time_low++; - if (uu.time_low == 0) { - uu.time_mid++; - if (uu.time_mid == 0) - uu.time_hi_and_version++; - } - num--; - uuid_pack(&uu, out); - return; - } -#else - if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) - return; -#endif - - uuid__generate_time(out, 0); -} - - -void uuid__generate_random(uuid_t out, int *num) -{ - uuid_t buf; - struct uuid uu; - int i, n; - - if (!num || !*num) - n = 1; - else - n = *num; - - for (i = 0; i < n; i++) { - get_random_bytes(buf, sizeof(buf)); - uuid_unpack(buf, &uu); - - uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; - uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) - | 0x4000; - uuid_pack(&uu, out); - out += sizeof(uuid_t); - } -} - -void uuid_generate_random(uuid_t out) -{ - int num = 1; - /* No real reason to use the daemon for random uuid's -- yet */ - - uuid__generate_random(out, &num); -} - - -/* - * This is the generic front-end to uuid_generate_random and - * uuid_generate_time. It uses uuid_generate_random only if - * /dev/urandom is available, since otherwise we won't have - * high-quality randomness. - */ -void uuid_generate(uuid_t out) -{ - if (get_random_fd() >= 0) - uuid_generate_random(out); - else - uuid_generate_time(out); -} diff --git a/contrib/uuid/gen_uuid_nt.c b/contrib/uuid/gen_uuid_nt.c deleted file mode 100644 index aa44bfd3d7d..00000000000 --- a/contrib/uuid/gen_uuid_nt.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * gen_uuid_nt.c -- Use NT api to generate uuid - * - * Written by Andrey Shedel (andreys@ns.cr.cyco.com) - */ - - -#include "uuidP.h" - -#pragma warning(push,4) - -#pragma comment(lib, "ntdll.lib") - -// -// Here is a nice example why it's not a good idea -// to use native API in ordinary applications. -// Number of parameters in function below was changed from 3 to 4 -// for NT5. -// -// -// NTSYSAPI -// NTSTATUS -// NTAPI -// NtAllocateUuids( -// OUT PULONG p1, -// OUT PULONG p2, -// OUT PULONG p3, -// OUT PUCHAR Seed // 6 bytes -// ); -// -// - -unsigned long -__stdcall -NtAllocateUuids( - void* p1, // 8 bytes - void* p2, // 4 bytes - void* p3 // 4 bytes - ); - -typedef -unsigned long -(__stdcall* -NtAllocateUuids_2000)( - void* p1, // 8 bytes - void* p2, // 4 bytes - void* p3, // 4 bytes - void* seed // 6 bytes - ); - - - -// -// Nice, but instead of including ntddk.h ot winnt.h -// I should define it here because they MISSED __stdcall in those headers. -// - -__declspec(dllimport) -struct _TEB* -__stdcall -NtCurrentTeb(void); - - -// -// The only way to get version information from the system is to examine -// one stored in PEB. But it's pretty dangerouse because this value could -// be altered in image header. -// - -static -int -Nt5(void) -{ - //return NtCuttentTeb()->Peb->OSMajorVersion >= 5; - return (int)*(int*)((char*)(int)(*(int*)((char*)NtCurrentTeb() + 0x30)) + 0xA4) >= 5; -} - - - - -void uuid_generate(uuid_t out) -{ - if(Nt5()) - { - unsigned char seed[6]; - ((NtAllocateUuids_2000)NtAllocateUuids)(out, ((char*)out)+8, ((char*)out)+12, &seed[0] ); - } - else - { - NtAllocateUuids(out, ((char*)out)+8, ((char*)out)+12); - } -} diff --git a/contrib/uuid/isnull.c b/contrib/uuid/isnull.c deleted file mode 100644 index 931e7e7dba2..00000000000 --- a/contrib/uuid/isnull.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * isnull.c --- Check whether or not the UUID is null - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "uuidP.h" - -/* Returns 1 if the uuid is the NULL uuid */ -int uuid_is_null(const uuid_t uu) -{ - const unsigned char *cp; - int i; - - for (i=0, cp = uu; i < 16; i++) - if (*cp++) - return 0; - return 1; -} - diff --git a/contrib/uuid/pack.c b/contrib/uuid/pack.c deleted file mode 100644 index 097516d2e2f..00000000000 --- a/contrib/uuid/pack.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Internal routine for packing UUID's - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include <string.h> -#include "uuidP.h" - -void uuid_pack(const struct uuid *uu, uuid_t ptr) -{ - uint32_t tmp; - unsigned char *out = ptr; - - tmp = uu->time_low; - out[3] = (unsigned char) tmp; - tmp >>= 8; - out[2] = (unsigned char) tmp; - tmp >>= 8; - out[1] = (unsigned char) tmp; - tmp >>= 8; - out[0] = (unsigned char) tmp; - - tmp = uu->time_mid; - out[5] = (unsigned char) tmp; - tmp >>= 8; - out[4] = (unsigned char) tmp; - - tmp = uu->time_hi_and_version; - out[7] = (unsigned char) tmp; - tmp >>= 8; - out[6] = (unsigned char) tmp; - - tmp = uu->clock_seq; - out[9] = (unsigned char) tmp; - tmp >>= 8; - out[8] = (unsigned char) tmp; - - memcpy(out+10, uu->node, 6); -} - diff --git a/contrib/uuid/parse.c b/contrib/uuid/parse.c deleted file mode 100644 index 074383efae7..00000000000 --- a/contrib/uuid/parse.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * parse.c --- UUID parsing - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <string.h> - -#include "uuidP.h" - -int uuid_parse(const char *in, uuid_t uu) -{ - struct uuid uuid; - int i; - const char *cp; - char buf[3]; - - if (strlen(in) != 36) - return -1; - for (i=0, cp = in; i <= 36; i++,cp++) { - if ((i == 8) || (i == 13) || (i == 18) || - (i == 23)) { - if (*cp == '-') - continue; - else - return -1; - } - if (i== 36) - if (*cp == 0) - continue; - if (!isxdigit(*cp)) - return -1; - } - uuid.time_low = strtoul(in, NULL, 16); - uuid.time_mid = strtoul(in+9, NULL, 16); - uuid.time_hi_and_version = strtoul(in+14, NULL, 16); - uuid.clock_seq = strtoul(in+19, NULL, 16); - cp = in+24; - buf[2] = 0; - for (i=0; i < 6; i++) { - buf[0] = *cp++; - buf[1] = *cp++; - uuid.node[i] = strtoul(buf, NULL, 16); - } - - uuid_pack(&uuid, uu); - return 0; -} diff --git a/contrib/uuid/tst_uuid.c b/contrib/uuid/tst_uuid.c deleted file mode 100644 index e03138f7d18..00000000000 --- a/contrib/uuid/tst_uuid.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * tst_uuid.c --- test program from the UUID library - * - * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif - -#include <stdio.h> -#include <stdlib.h> - -#include "uuid.h" - -static int test_uuid(const char * uuid, int isValid) -{ - static const char * validStr[2] = {"invalid", "valid"}; - uuid_t uuidBits; - int parsedOk; - - parsedOk = uuid_parse(uuid, uuidBits) == 0; - - printf("%s is %s", uuid, validStr[isValid]); - if (parsedOk != isValid) { - printf(" but uuid_parse says %s\n", validStr[parsedOk]); - return 1; - } - printf(", OK\n"); - return 0; -} - -#ifdef __GNUC__ -#define ATTR(x) __attribute__(x) -#else -#define ATTR(x) -#endif - -int -main(int argc ATTR((unused)) , char **argv ATTR((unused))) -{ - uuid_t buf, tst; - char str[100]; - struct timeval tv; - time_t time_reg; - unsigned char *cp; - int i; - int failed = 0; - int type, variant; - - uuid_generate(buf); - uuid_unparse(buf, str); - printf("UUID generate = %s\n", str); - printf("UUID: "); - for (i=0, cp = (unsigned char *) &buf; i < 16; i++) { - printf("%02x", *cp++); - } - printf("\n"); - type = uuid_type(buf); variant = uuid_variant(buf); - printf("UUID type = %d, UUID variant = %d\n", type, variant); - if (variant != UUID_VARIANT_DCE) { - printf("Incorrect UUID Variant; was expecting DCE!\n"); - failed++; - } - printf("\n"); - - uuid_generate_random(buf); - uuid_unparse(buf, str); - printf("UUID random string = %s\n", str); - printf("UUID: "); - for (i=0, cp = (unsigned char *) &buf; i < 16; i++) { - printf("%02x", *cp++); - } - printf("\n"); - type = uuid_type(buf); variant = uuid_variant(buf); - printf("UUID type = %d, UUID variant = %d\n", type, variant); - if (variant != UUID_VARIANT_DCE) { - printf("Incorrect UUID Variant; was expecting DCE!\n"); - failed++; - } - if (type != 4) { - printf("Incorrect UUID type; was expecting " - "4 (random type)!\n"); - failed++; - } - printf("\n"); - - uuid_generate_time(buf); - uuid_unparse(buf, str); - printf("UUID string = %s\n", str); - printf("UUID time: "); - for (i=0, cp = (unsigned char *) &buf; i < 16; i++) { - printf("%02x", *cp++); - } - printf("\n"); - type = uuid_type(buf); variant = uuid_variant(buf); - printf("UUID type = %d, UUID variant = %d\n", type, variant); - if (variant != UUID_VARIANT_DCE) { - printf("Incorrect UUID Variant; was expecting DCE!\n"); - failed++; - } - if (type != 1) { - printf("Incorrect UUID type; was expecting " - "1 (time-based type)!\\n"); - failed++; - } - tv.tv_sec = 0; - tv.tv_usec = 0; - time_reg = uuid_time(buf, &tv); - printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, - ctime(&time_reg)); - uuid_parse(str, tst); - if (!uuid_compare(buf, tst)) - printf("UUID parse and compare succeeded.\n"); - else { - printf("UUID parse and compare failed!\n"); - failed++; - } - uuid_clear(tst); - if (uuid_is_null(tst)) - printf("UUID clear and is null succeeded.\n"); - else { - printf("UUID clear and is null failed!\n"); - failed++; - } - uuid_copy(buf, tst); - if (!uuid_compare(buf, tst)) - printf("UUID copy and compare succeeded.\n"); - else { - printf("UUID copy and compare failed!\n"); - failed++; - } - failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981b", 1); - failed += test_uuid("84949CC5-4701-4A84-895B-354C584A981B", 1); - failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981bc", 0); - failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981", 0); - failed += test_uuid("84949cc5x4701-4a84-895b-354c584a981b", 0); - failed += test_uuid("84949cc504701-4a84-895b-354c584a981b", 0); - failed += test_uuid("84949cc5-470104a84-895b-354c584a981b", 0); - failed += test_uuid("84949cc5-4701-4a840895b-354c584a981b", 0); - failed += test_uuid("84949cc5-4701-4a84-895b0354c584a981b", 0); - failed += test_uuid("g4949cc5-4701-4a84-895b-354c584a981b", 0); - failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981g", 0); - - if (failed) { - printf("%d failures.\n", failed); - exit(1); - } - return 0; -} diff --git a/contrib/uuid/unpack.c b/contrib/uuid/unpack.c deleted file mode 100644 index beaaff3ca8a..00000000000 --- a/contrib/uuid/unpack.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Internal routine for unpacking UUID - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include <string.h> -#include "uuidP.h" - -void uuid_unpack(const uuid_t in, struct uuid *uu) -{ - const uint8_t *ptr = in; - uint32_t tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_low = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_mid = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_hi_and_version = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->clock_seq = tmp; - - memcpy(uu->node, ptr, 6); -} - diff --git a/contrib/uuid/unparse.c b/contrib/uuid/unparse.c deleted file mode 100644 index a95bbb04258..00000000000 --- a/contrib/uuid/unparse.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * unparse.c -- convert a UUID to string - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include <stdio.h> - -#include "uuidP.h" - -static const char *fmt_lower = - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; - -static const char *fmt_upper = - "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; - -#ifdef UUID_UNPARSE_DEFAULT_UPPER -#define FMT_DEFAULT fmt_upper -#else -#define FMT_DEFAULT fmt_lower -#endif - -static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) -{ - struct uuid uuid; - - uuid_unpack(uu, &uuid); - sprintf(out, fmt, - uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, - uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, - uuid.node[0], uuid.node[1], uuid.node[2], - uuid.node[3], uuid.node[4], uuid.node[5]); -} - -void uuid_unparse_lower(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, fmt_lower); -} - -void uuid_unparse_upper(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, fmt_upper); -} - -void uuid_unparse(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, FMT_DEFAULT); -} diff --git a/contrib/uuid/uuid.h b/contrib/uuid/uuid.h deleted file mode 100644 index ab006652fc0..00000000000 --- a/contrib/uuid/uuid.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Public include file for the UUID library - * - * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#ifndef _UUID_UUID_H -#define _UUID_UUID_H - -#include "config.h" -#include <sys/types.h> -#ifndef _WIN32 -#include <sys/time.h> -#endif -#include <time.h> - -typedef unsigned char uuid_t[16]; - -/* UUID Variant definitions */ -#define UUID_VARIANT_NCS 0 -#define UUID_VARIANT_DCE 1 -#define UUID_VARIANT_MICROSOFT 2 -#define UUID_VARIANT_OTHER 3 - -/* UUID Type definitions */ -#define UUID_TYPE_DCE_TIME 1 -#define UUID_TYPE_DCE_RANDOM 4 - -/* Allow UUID constants to be defined */ -#ifdef __GNUC__ -#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} -#else -#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* clear.c */ -void uuid_clear(uuid_t uu); - -/* compare.c */ -int uuid_compare(const uuid_t uu1, const uuid_t uu2); - -/* copy.c */ -void uuid_copy(uuid_t dst, const uuid_t src); - -/* gen_uuid.c */ -void uuid_generate(uuid_t out); -void uuid_generate_random(uuid_t out); -void uuid_generate_time(uuid_t out); - -/* isnull.c */ -int uuid_is_null(const uuid_t uu); - -/* parse.c */ -int uuid_parse(const char *in, uuid_t uu); - -/* unparse.c */ -void uuid_unparse(const uuid_t uu, char *out); -void uuid_unparse_lower(const uuid_t uu, char *out); -void uuid_unparse_upper(const uuid_t uu, char *out); - -/* uuid_time.c */ -time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); -int uuid_type(const uuid_t uu); -int uuid_variant(const uuid_t uu); - -#ifdef __cplusplus -} -#endif - -#endif /* _UUID_UUID_H */ diff --git a/contrib/uuid/uuidP.h b/contrib/uuid/uuidP.h deleted file mode 100644 index 9a2de6132fe..00000000000 --- a/contrib/uuid/uuidP.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * uuid.h -- private header file for uuids - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "uuid.h" -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#else -#include "uuid_types.h" -#endif -#include <sys/types.h> - - -/* - * Offset between 15-Oct-1582 and 1-Jan-70 - */ -#define TIME_OFFSET_HIGH 0x01B21DD2 -#define TIME_OFFSET_LOW 0x13814000 - -struct uuid { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint16_t clock_seq; - uint8_t node[6]; -}; - - -/* - * prototypes - */ -void uuid_pack(const struct uuid *uu, uuid_t ptr); -void uuid_unpack(const uuid_t in, struct uuid *uu); diff --git a/contrib/uuid/uuid_time.c b/contrib/uuid/uuid_time.c deleted file mode 100644 index ccaa542fed0..00000000000 --- a/contrib/uuid/uuid_time.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * uuid_time.c --- Interpret the time field from a uuid. This program - * violates the UUID abstraction barrier by reaching into the guts - * of a UUID and interpreting it. - * - * Copyright (C) 1998, 1999 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif - -#include <stdio.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <stdlib.h> -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <time.h> - -#include "uuidP.h" -#include "logging.h" - -time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) -{ - struct timeval tv; - struct uuid uuid; - uint32_t high; - uint64_t clock_reg; - - uuid_unpack(uu, &uuid); - - high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); - clock_reg = uuid.time_low | ((uint64_t) high << 32); - - clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; - tv.tv_sec = clock_reg / 10000000; - tv.tv_usec = (clock_reg % 10000000) / 10; - - if (ret_tv) - *ret_tv = tv; - - return tv.tv_sec; -} - -int uuid_type(const uuid_t uu) -{ - struct uuid uuid; - - uuid_unpack(uu, &uuid); - return ((uuid.time_hi_and_version >> 12) & 0xF); -} - -int uuid_variant(const uuid_t uu) -{ - struct uuid uuid; - int var; - - uuid_unpack(uu, &uuid); - var = uuid.clock_seq; - - if ((var & 0x8000) == 0) - return UUID_VARIANT_NCS; - if ((var & 0x4000) == 0) - return UUID_VARIANT_DCE; - if ((var & 0x2000) == 0) - return UUID_VARIANT_MICROSOFT; - return UUID_VARIANT_OTHER; -} - -#ifdef DEBUG -static const char *variant_string(int variant) -{ - switch (variant) { - case UUID_VARIANT_NCS: - return "NCS"; - case UUID_VARIANT_DCE: - return "DCE"; - case UUID_VARIANT_MICROSOFT: - return "Microsoft"; - default: - return "Other"; - } -} - - -int -main(int argc, char **argv) -{ - uuid_t buf; - time_t time_reg; - struct timeval tv; - int type, variant; - - if (argc != 2) { - fprintf(stderr, "Usage: %s uuid\n", argv[0]); - exit(1); - } - if (uuid_parse(argv[1], buf)) { - fprintf(stderr, "Invalid UUID: %s\n", argv[1]); - exit(1); - } - variant = uuid_variant(buf); - type = uuid_type(buf); - time_reg = uuid_time(buf, &tv); - - printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); - if (variant != UUID_VARIANT_DCE) { - printf("Warning: This program only knows how to interpret " - "DCE UUIDs.\n\tThe rest of the output is likely " - "to be incorrect!!\n"); - } - printf("UUID type is %d", type); - switch (type) { - case 1: - printf(" (time based)\n"); - break; - case 2: - printf(" (DCE)\n"); - break; - case 3: - printf(" (name-based)\n"); - break; - case 4: - printf(" (random)\n"); - break; - default: - printf("\n"); - } - if (type != 1) { - printf("Warning: not a time-based UUID, so UUID time " - "decoding will likely not work!\n"); - } - printf("UUID time is: (%" GF_PRI_SECOND ", %" GF_PRI_USEC "): %s\n", tv.tv_sec, tv.tv_usec, ctime(&time_reg)); - - return 0; -} -#endif diff --git a/contrib/uuid/uuid_types.h.in b/contrib/uuid/uuid_types.h.in deleted file mode 100644 index f21ff4ee183..00000000000 --- a/contrib/uuid/uuid_types.h.in +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If linux/types.h is already been included, assume it has defined - * everything we need. (cross fingers) Other header files may have - * also defined the types that we need. - */ -#if (!defined(_STDINT_H) && !defined(_UUID_STDINT_H)) -#define _UUID_STDINT_H - -typedef unsigned char uint8_t; -typedef signed char int8_t; - -#if (@SIZEOF_INT@ == 8) -typedef int int64_t; -typedef unsigned int uint64_t; -#elif (@SIZEOF_LONG@ == 8) -typedef long int64_t; -typedef unsigned long uint64_t; -#elif (@SIZEOF_LONG_LONG@ == 8) -#if defined(__GNUC__) -typedef __signed__ long long int64_t; -#else -typedef signed long long int64_t; -#endif -typedef unsigned long long uint64_t; -#endif - -#if (@SIZEOF_INT@ == 2) -typedef int int16_t; -typedef unsigned int uint16_t; -#elif (@SIZEOF_SHORT@ == 2) -typedef short int16_t; -typedef unsigned short uint16_t; -#else - ?==error: undefined 16 bit type -#endif - -#if (@SIZEOF_INT@ == 4) -typedef int int32_t; -typedef unsigned int uint32_t; -#elif (@SIZEOF_LONG@ == 4) -typedef long int32_t; -typedef unsigned long uint32_t; -#elif (@SIZEOF_SHORT@ == 4) -typedef short int32_t; -typedef unsigned short uint32_t; -#else - ?== error: undefined 32 bit type -#endif - -#endif diff --git a/contrib/uuid/uuidd.h b/contrib/uuid/uuidd.h deleted file mode 100644 index c71f4b78835..00000000000 --- a/contrib/uuid/uuidd.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Definitions used by the uuidd daemon - * - * Copyright (C) 2007 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#ifndef _UUID_UUIDD_H -#define _UUID_UUIDD_H - -#define UUIDD_DIR "/var/lib/libuuid" -#define UUIDD_SOCKET_PATH UUIDD_DIR "/request" -#define UUIDD_PIDFILE_PATH UUIDD_DIR "/uuidd.pid" -#define UUIDD_PATH "/usr/sbin/uuidd" - -#define UUIDD_OP_GETPID 0 -#define UUIDD_OP_GET_MAXOP 1 -#define UUIDD_OP_TIME_UUID 2 -#define UUIDD_OP_RANDOM_UUID 3 -#define UUIDD_OP_BULK_TIME_UUID 4 -#define UUIDD_OP_BULK_RANDOM_UUID 5 -#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID - -extern void uuid__generate_time(uuid_t out, int *num); -extern void uuid__generate_random(uuid_t out, int *num); - -#endif /* _UUID_UUID_H */ diff --git a/contrib/xxhash/xxhash.c b/contrib/xxhash/xxhash.c new file mode 100644 index 00000000000..56f80f8811d --- /dev/null +++ b/contrib/xxhash/xxhash.c @@ -0,0 +1,1029 @@ +/* +* xxHash - Fast Hash algorithm +* Copyright (C) 2012-2016, Yann Collet +* +* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* You can contact the author at : +* - xxHash homepage: http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + + +/* ************************************* +* Tuning parameters +***************************************/ +/*!XXH_FORCE_MEMORY_ACCESS : + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. + * It can generate buggy code on targets which do not support unaligned memory accesses. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See http://stackoverflow.com/a/32095106/646947 for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define XXH_FORCE_MEMORY_ACCESS 2 +# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7S__) )) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/*!XXH_ACCEPT_NULL_INPUT_POINTER : + * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. + * When this macro is enabled, xxHash actively checks input for null pointer. + * It it is, result for null input pointers is the same as a null-length input. + */ +#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ +# define XXH_ACCEPT_NULL_INPUT_POINTER 0 +#endif + +/*!XXH_FORCE_NATIVE_FORMAT : + * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. + * Results are therefore identical for little-endian and big-endian CPU. + * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. + * Should endian-independence be of no importance for your application, you may set the #define below to 1, + * to improve speed for Big-endian CPU. + * This option has no impact on Little_Endian CPU. + */ +#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ +# define XXH_FORCE_NATIVE_FORMAT 0 +#endif + +/*!XXH_FORCE_ALIGN_CHECK : + * This is a minor performance trick, only useful with lots of very small keys. + * It means : check for aligned/unaligned input. + * The check costs one initial branch per hash; + * set it to 0 when the input is guaranteed to be aligned, + * or when alignment doesn't matter for performance. + */ +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ +# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +/*! Modify the local functions below should you wish to use some other memory routines +* for malloc(), free() */ +#include <stdlib.h> +static void* XXH_malloc(size_t s) { return malloc(s); } +static void XXH_free (void* p) { free(p); } +/*! and for memcpy() */ +#include <string.h> +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } + +#include <assert.h> /* assert */ + +#define XXH_STATIC_LINKING_ONLY +#include "xxhash.h" + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# define FORCE_INLINE static __forceinline +#else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif + + +/* ************************************* +* Basic Types +***************************************/ +#ifndef MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include <stdint.h> + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; +# else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; +# endif +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; } __attribute__((packed)) unalign; +static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ +static U32 XXH_read32(const void* memPtr) +{ + U32 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) +#endif + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static U32 XXH_swap32 (U32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* ************************************* +* Architecture Macros +***************************************/ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; + +/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ +#ifndef XXH_CPU_LITTLE_ENDIAN +static int XXH_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} +# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() +#endif + + +/* *************************** +* Memory reads +*****************************/ +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); + else + return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); +} + +FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE32_align(ptr, endian, XXH_unaligned); +} + +static U32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} + + +/* ************************************* +* Macros +***************************************/ +#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +static const U32 PRIME32_1 = 2654435761U; +static const U32 PRIME32_2 = 2246822519U; +static const U32 PRIME32_3 = 3266489917U; +static const U32 PRIME32_4 = 668265263U; +static const U32 PRIME32_5 = 374761393U; + +static U32 XXH32_round(U32 seed, U32 input) +{ + seed += input * PRIME32_2; + seed = XXH_rotl32(seed, 13); + seed *= PRIME32_1; + return seed; +} + +/* mix all bits */ +static U32 XXH32_avalanche(U32 h32) +{ + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + return(h32); +} + +#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) + +static U32 +XXH32_finalize(U32 h32, const void* ptr, size_t len, + XXH_endianess endian, XXH_alignment align) + +{ + const BYTE* p = (const BYTE*)ptr; +#define PROCESS1 \ + h32 += (*p) * PRIME32_5; \ + p++; \ + h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; + +#define PROCESS4 \ + h32 += XXH_get32bits(p) * PRIME32_3; \ + p+=4; \ + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + + switch(len&15) /* or switch(bEnd - p) */ + { + case 12: PROCESS4; + /* fallthrough */ + case 8: PROCESS4; + /* fallthrough */ + case 4: PROCESS4; + return XXH32_avalanche(h32); + + case 13: PROCESS4; + /* fallthrough */ + case 9: PROCESS4; + /* fallthrough */ + case 5: PROCESS4; + PROCESS1; + return XXH32_avalanche(h32); + + case 14: PROCESS4; + /* fallthrough */ + case 10: PROCESS4; + /* fallthrough */ + case 6: PROCESS4; + PROCESS1; + PROCESS1; + return XXH32_avalanche(h32); + + case 15: PROCESS4; + /* fallthrough */ + case 11: PROCESS4; + /* fallthrough */ + case 7: PROCESS4; + /* fallthrough */ + case 3: PROCESS1; + /* fallthrough */ + case 2: PROCESS1; + /* fallthrough */ + case 1: PROCESS1; + /* fallthrough */ + case 0: return XXH32_avalanche(h32); + } + assert(0); + return h32; /* reaching this point is deemed impossible */ +} + + +FORCE_INLINE U32 +XXH32_endian_align(const void* input, size_t len, U32 seed, + XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U32 h32; + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)16; + } +#endif + + if (len>=16) { + const BYTE* const limit = bEnd - 15; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; + v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; + v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; + v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; + } while (p < limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + PRIME32_5; + } + + h32 += (U32)len; + + return XXH32_finalize(h32, p, len&15, endian, align); +} + + +XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, input, len); + return XXH32_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + + +/*====== Hash streaming ======*/ + +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) +{ + XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME32_1 + PRIME32_2; + state.v2 = seed + PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME32_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + + +FORCE_INLINE +XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len_32 += (unsigned)len; + state->large_len |= (len>=16) | (state->total_len_32>=16); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); + state->memsize += (unsigned)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const U32* p32 = state->mem32; + state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; + state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; + state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; + state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do { + v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; + v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; + v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; + v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + + +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + +FORCE_INLINE U32 +XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) +{ + U32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v1, 1) + + XXH_rotl32(state->v2, 7) + + XXH_rotl32(state->v3, 12) + + XXH_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + PRIME32_5; + } + + h32 += state->total_len_32; + + return XXH32_finalize(h32, state->mem32, state->memsize, endian, XXH_aligned); +} + + +XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_digest_endian(state_in, XXH_littleEndian); + else + return XXH32_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +/*! Default XXH result types are basic unsigned 32 and 64 bits. +* The canonical representation follows human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file or buffer, remaining comparable across different systems. +*/ + +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ + +/*====== Memory access ======*/ + +#ifndef MEM_MODULE +# define MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include <stdint.h> + typedef uint64_t U64; +# else + /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ + typedef unsigned long long U64; +# endif +#endif + + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; +static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ + +static U64 XXH_read64(const void* memPtr) +{ + U64 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static U64 XXH_swap64 (U64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + +FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); + else + return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); +} + +FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE64_align(ptr, endian, XXH_unaligned); +} + +static U64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} + + +/*====== xxh64 ======*/ + +static const U64 PRIME64_1 = 11400714785074694791ULL; +static const U64 PRIME64_2 = 14029467366897019727ULL; +static const U64 PRIME64_3 = 1609587929392839161ULL; +static const U64 PRIME64_4 = 9650029242287828579ULL; +static const U64 PRIME64_5 = 2870177450012600261ULL; + +static U64 XXH64_round(U64 acc, U64 input) +{ + acc += input * PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= PRIME64_1; + return acc; +} + +static U64 XXH64_mergeRound(U64 acc, U64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * PRIME64_1 + PRIME64_4; + return acc; +} + +static U64 XXH64_avalanche(U64 h64) +{ + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + return h64; +} + + +#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) + +static U64 +XXH64_finalize(U64 h64, const void* ptr, size_t len, + XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)ptr; + +#define PROCESS1_64 \ + h64 ^= (*p) * PRIME64_5; \ + p++; \ + h64 = XXH_rotl64(h64, 11) * PRIME64_1; + +#define PROCESS4_64 \ + h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; \ + p+=4; \ + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + +#define PROCESS8_64 { \ + U64 const k1 = XXH64_round(0, XXH_get64bits(p)); \ + p+=8; \ + h64 ^= k1; \ + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \ +} + + switch(len&31) { + case 24: PROCESS8_64; + /* fallthrough */ + case 16: PROCESS8_64; + /* fallthrough */ + case 8: PROCESS8_64; + return XXH64_avalanche(h64); + + case 28: PROCESS8_64; + /* fallthrough */ + case 20: PROCESS8_64; + /* fallthrough */ + case 12: PROCESS8_64; + /* fallthrough */ + case 4: PROCESS4_64; + return XXH64_avalanche(h64); + + case 25: PROCESS8_64; + /* fallthrough */ + case 17: PROCESS8_64; + /* fallthrough */ + case 9: PROCESS8_64; + PROCESS1_64; + return XXH64_avalanche(h64); + + case 29: PROCESS8_64; + /* fallthrough */ + case 21: PROCESS8_64; + /* fallthrough */ + case 13: PROCESS8_64; + /* fallthrough */ + case 5: PROCESS4_64; + PROCESS1_64; + return XXH64_avalanche(h64); + + case 26: PROCESS8_64; + /* fallthrough */ + case 18: PROCESS8_64; + /* fallthrough */ + case 10: PROCESS8_64; + PROCESS1_64; + PROCESS1_64; + return XXH64_avalanche(h64); + + case 30: PROCESS8_64; + /* fallthrough */ + case 22: PROCESS8_64; + /* fallthrough */ + case 14: PROCESS8_64; + /* fallthrough */ + case 6: PROCESS4_64; + PROCESS1_64; + PROCESS1_64; + return XXH64_avalanche(h64); + + case 27: PROCESS8_64; + /* fallthrough */ + case 19: PROCESS8_64; + /* fallthrough */ + case 11: PROCESS8_64; + PROCESS1_64; + PROCESS1_64; + PROCESS1_64; + return XXH64_avalanche(h64); + + case 31: PROCESS8_64; + /* fallthrough */ + case 23: PROCESS8_64; + /* fallthrough */ + case 15: PROCESS8_64; + /* fallthrough */ + case 7: PROCESS4_64; + /* fallthrough */ + case 3: PROCESS1_64; + /* fallthrough */ + case 2: PROCESS1_64; + /* fallthrough */ + case 1: PROCESS1_64; + /* fallthrough */ + case 0: return XXH64_avalanche(h64); + } + + /* impossible to reach */ + assert(0); + return 0; /* unreachable, but some compilers complain without it */ +} + +FORCE_INLINE U64 +XXH64_endian_align(const void* input, size_t len, U64 seed, + XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U64 h64; + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)32; + } +#endif + + if (len>=32) { + const BYTE* const limit = bEnd - 32; + U64 v1 = seed + PRIME64_1 + PRIME64_2; + U64 v2 = seed + PRIME64_2; + U64 v3 = seed + 0; + U64 v4 = seed - PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; + v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; + v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; + v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; + } while (p<=limit); + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + + } else { + h64 = seed + PRIME64_5; + } + + h64 += (U64) len; + + return XXH64_finalize(h64, p, len, endian, align); +} + + +XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, input, len); + return XXH64_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + +/*====== Hash Streaming ======*/ + +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) +{ + XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME64_1 + PRIME64_2; + state.v2 = seed + PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME64_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + +FORCE_INLINE +XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + state->memsize += (U32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); + state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); + state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); + state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); + p += 32-state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const BYTE* const limit = bEnd - 32; + U64 v1 = state->v1; + U64 v2 = state->v2; + U64 v3 = state->v3; + U64 v4 = state->v4; + + do { + v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; + v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; + v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; + v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH64_update_endian(state_in, input, len, XXH_bigEndian); +} + +FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) +{ + U64 h64; + + if (state->total_len >= 32) { + U64 const v1 = state->v1; + U64 const v2 = state->v2; + U64 const v3 = state->v3; + U64 const v4 = state->v4; + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + } else { + h64 = state->v3 /*seed*/ + PRIME64_5; + } + + h64 += (U64) state->total_len; + + return XXH64_finalize(h64, state->mem64, (size_t)state->total_len, endian, XXH_aligned); +} + +XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_digest_endian(state_in, XXH_littleEndian); + else + return XXH64_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#endif /* XXH_NO_LONG_LONG */ diff --git a/contrib/xxhash/xxhash.h b/contrib/xxhash/xxhash.h new file mode 100644 index 00000000000..d6bad943358 --- /dev/null +++ b/contrib/xxhash/xxhash.h @@ -0,0 +1,328 @@ +/* + xxHash - Extremely Fast Hash algorithm + Header File + Copyright (C) 2012-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* Notice extracted from xxHash homepage : + +xxHash is an extremely fast Hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MumurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. + +A 64-bit version, named XXH64, is available since r35. +It offers much better speed, but for 64-bit applications only. +Name Speed on 64 bits Speed on 32 bits +XXH64 13.8 GB/s 1.9 GB/s +XXH32 6.8 GB/s 6.0 GB/s +*/ + +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* **************************** +* Definitions +******************************/ +#include <stddef.h> /* size_t */ +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + +/* **************************** + * API modifier + ******************************/ +/** XXH_INLINE_ALL (and XXH_PRIVATE_API) + * This is useful to include xxhash functions in `static` mode + * in order to inline them, and remove their symbol from the public list. + * Inlining can offer dramatic performance improvement on small keys. + * Methodology : + * #define XXH_INLINE_ALL + * #include "xxhash.h" + * `xxhash.c` is automatically included. + * It's not useful to compile and link it as a separate module. + */ +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +# endif +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif +#else +# define XXH_PUBLIC_API /* do nothing */ +#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ + +/*! XXH_NAMESPACE, aka Namespace Emulation : + * + * If you want to include _and expose_ xxHash functions from within your own library, + * but also want to avoid symbol collisions with other libraries which may also include xxHash, + * + * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library + * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). + * + * Note that no change is required within the calling program as long as it includes `xxhash.h` : + * regular symbol name will be automatically translated by this header. + */ +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +#endif + + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 6 +#define XXH_VERSION_RELEASE 5 +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) +XXH_PUBLIC_API unsigned XXH_versionNumber (void); + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +typedef unsigned int XXH32_hash_t; + +/*! XXH32() : + Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". + The memory between input & input+length must be valid (allocated and read-accessible). + "seed" can be used to alter the result predictably. + Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); + +/*====== Streaming ======*/ +typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); + +/* + * Streaming functions generate the xxHash of an input provided in multiple segments. + * Note that, for small input, they are slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * XXH state must first be allocated, using XXH*_createState() . + * + * Start a new hash by initializing state with a seed, using XXH*_reset(). + * + * Then, feed the hash state by calling XXH*_update() as many times as necessary. + * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using XXH*_digest(). + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a digest, + * and generate some new hashes later on, by calling again XXH*_digest(). + * + * When done, free XXH state space if it was allocated dynamically. + */ + +/*====== Canonical representation ======*/ + +typedef struct { unsigned char digest[4]; } XXH32_canonical_t; +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + +/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. + * The canonical representation uses human-readable write convention, aka big-endian (large digits first). + * These functions allow transformation of hash result into and from its canonical format. + * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. + */ + + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +typedef unsigned long long XXH64_hash_t; + +/*! XXH64() : + Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". + "seed" can be used to alter the result predictably. + This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). +*/ +XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); + +/*====== Streaming ======*/ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); + +/*====== Canonical representation ======*/ +typedef struct { unsigned char digest[8]; } XXH64_canonical_t; +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); +#endif /* XXH_NO_LONG_LONG */ + + + +#ifdef XXH_STATIC_LINKING_ONLY + +/* ================================================================================================ + This section contains declarations which are not guaranteed to remain stable. + They may change in future versions, becoming incompatible with a different version of the library. + These declarations should only be used with static linking. + Never use them in association with dynamic linking ! +=================================================================================================== */ + +/* These definitions are only present to allow + * static allocation of XXH state, on stack or in a struct for example. + * Never **ever** use members directly. */ + +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include <stdint.h> + +struct XXH32_state_s { + uint32_t total_len_32; + uint32_t large_len; + uint32_t v1; + uint32_t v2; + uint32_t v3; + uint32_t v4; + uint32_t mem32[4]; + uint32_t memsize; + uint32_t reserved; /* never read nor write, might be removed in a future version */ +}; /* typedef'd to XXH32_state_t */ + +struct XXH64_state_s { + uint64_t total_len; + uint64_t v1; + uint64_t v2; + uint64_t v3; + uint64_t v4; + uint64_t mem64[4]; + uint32_t memsize; + uint32_t reserved[2]; /* never read nor write, might be removed in a future version */ +}; /* typedef'd to XXH64_state_t */ + +# else + +struct XXH32_state_s { + unsigned total_len_32; + unsigned large_len; + unsigned v1; + unsigned v2; + unsigned v3; + unsigned v4; + unsigned mem32[4]; + unsigned memsize; + unsigned reserved; /* never read nor write, might be removed in a future version */ +}; /* typedef'd to XXH32_state_t */ + +# ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ +struct XXH64_state_s { + unsigned long long total_len; + unsigned long long v1; + unsigned long long v2; + unsigned long long v3; + unsigned long long v4; + unsigned long long mem64[4]; + unsigned memsize; + unsigned reserved[2]; /* never read nor write, might be removed in a future version */ +}; /* typedef'd to XXH64_state_t */ +# endif + +# endif + + +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ +#endif + +#endif /* XXH_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* XXHASH_H_5627135585666179 */ diff --git a/contrib/xxhash/xxhsum.c b/contrib/xxhash/xxhsum.c new file mode 100644 index 00000000000..69931f727f0 --- /dev/null +++ b/contrib/xxhash/xxhsum.c @@ -0,0 +1,1301 @@ +/* +* xxhsum - Command line interface for xxhash algorithms +* Copyright (C) Yann Collet 2012-2016 +* +* GPL v2 License +* +* 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. +* +* 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, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* You can contact the author at : +* - xxHash homepage : http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* xxhsum : + * Provides hash value of a file content, or a list of files, or stdin + * Display convention is Big Endian, for both 32 and 64 bits algorithms + */ + +#ifndef XXHASH_C_2097394837 +#define XXHASH_C_2097394837 + +/* ************************************ + * Compiler Options + **************************************/ +/* MS Visual */ +#if defined(_MSC_VER) || defined(_WIN32) +# define _CRT_SECURE_NO_WARNINGS /* removes visual warnings */ +#endif + +/* Under Linux at least, pull in the *64 commands */ +#ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +#endif + + +/* ************************************ + * Includes + **************************************/ +#include <stdlib.h> /* malloc, calloc, free, exit */ +#include <stdio.h> /* fprintf, fopen, ftello64, fread, stdin, stdout, _fileno (when present) */ +#include <string.h> /* strcmp */ +#include <sys/types.h> /* stat, stat64, _stat64 */ +#include <sys/stat.h> /* stat, stat64, _stat64 */ +#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */ +#include <assert.h> /* assert */ + +#define XXH_STATIC_LINKING_ONLY /* *_state_t */ +#include "xxhash.h" + + +/* ************************************ + * OS-Specific Includes + **************************************/ +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) +# include <fcntl.h> /* _O_BINARY */ +# include <io.h> /* _setmode, _isatty */ +# define SET_BINARY_MODE(file) _setmode(_fileno(file), _O_BINARY) +# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream)) +#else +# include <unistd.h> /* isatty, STDIN_FILENO */ +# define SET_BINARY_MODE(file) +# define IS_CONSOLE(stdStream) isatty(STDIN_FILENO) +#endif + +#if !defined(S_ISREG) +# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) +#endif + + +/* ************************************ +* Basic Types +**************************************/ +#ifndef MEM_MODULE +# define MEM_MODULE +# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# include <stdint.h> + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +# else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; +# endif +#endif + +static unsigned BMK_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + + +/* ************************************* + * Constants + ***************************************/ +#define LIB_VERSION XXH_VERSION_MAJOR.XXH_VERSION_MINOR.XXH_VERSION_RELEASE +#define QUOTE(str) #str +#define EXPAND_AND_QUOTE(str) QUOTE(str) +#define PROGRAM_VERSION EXPAND_AND_QUOTE(LIB_VERSION) +static const int g_nbBits = (int)(sizeof(void*)*8); +static const char g_lename[] = "little endian"; +static const char g_bename[] = "big endian"; +#define ENDIAN_NAME (BMK_isLittleEndian() ? g_lename : g_bename) +static const char author[] = "Yann Collet"; +#define WELCOME_MESSAGE(exename) "%s %s (%i-bits %s), by %s \n", \ + exename, PROGRAM_VERSION, g_nbBits, ENDIAN_NAME, author + +#define KB *( 1<<10) +#define MB *( 1<<20) +#define GB *(1U<<30) + +static size_t XXH_DEFAULT_SAMPLE_SIZE = 100 KB; +#define NBLOOPS 3 /* Default number of benchmark iterations */ +#define TIMELOOP_S 1 +#define TIMELOOP (TIMELOOP_S * CLOCKS_PER_SEC) /* Minimum timing per iteration */ +#define XXHSUM32_DEFAULT_SEED 0 /* Default seed for algo_xxh32 */ +#define XXHSUM64_DEFAULT_SEED 0 /* Default seed for algo_xxh64 */ + +#define MAX_MEM (2 GB - 64 MB) + +static const char stdinName[] = "-"; +typedef enum { algo_xxh32, algo_xxh64 } algoType; +static const algoType g_defaultAlgo = algo_xxh64; /* required within main() & usage() */ + +/* <16 hex char> <SPC> <SPC> <filename> <'\0'> + * '4096' is typical Linux PATH_MAX configuration. */ +#define DEFAULT_LINE_LENGTH (sizeof(XXH64_hash_t) * 2 + 2 + 4096 + 1) + +/* Maximum acceptable line length. */ +#define MAX_LINE_LENGTH (32 KB) + + +/* ************************************ + * Display macros + **************************************/ +#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) +#define DISPLAYRESULT(...) fprintf(stdout, __VA_ARGS__) +#define DISPLAYLEVEL(l, ...) do { if (g_displayLevel>=l) DISPLAY(__VA_ARGS__); } while (0) +static int g_displayLevel = 2; + + +/* ************************************ + * Local variables + **************************************/ +static U32 g_nbIterations = NBLOOPS; + + +/* ************************************ + * Benchmark Functions + **************************************/ +static clock_t BMK_clockSpan( clock_t start ) +{ + return clock() - start; /* works even if overflow; Typical max span ~ 30 mn */ +} + + +static size_t BMK_findMaxMem(U64 requiredMem) +{ + size_t const step = 64 MB; + void* testmem = NULL; + + requiredMem = (((requiredMem >> 26) + 1) << 26); + requiredMem += 2*step; + if (requiredMem > MAX_MEM) requiredMem = MAX_MEM; + + while (!testmem) { + if (requiredMem > step) requiredMem -= step; + else requiredMem >>= 1; + testmem = malloc ((size_t)requiredMem); + } + free (testmem); + + /* keep some space available */ + if (requiredMem > step) requiredMem -= step; + else requiredMem >>= 1; + + return (size_t)requiredMem; +} + + +static U64 BMK_GetFileSize(const char* infilename) +{ + int r; +#if defined(_MSC_VER) + struct _stat64 statbuf; + r = _stat64(infilename, &statbuf); +#else + struct stat statbuf; + r = stat(infilename, &statbuf); +#endif + if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */ + return (U64)statbuf.st_size; +} + +typedef U32 (*hashFunction)(const void* buffer, size_t bufferSize, U32 seed); + +static U32 localXXH32(const void* buffer, size_t bufferSize, U32 seed) { return XXH32(buffer, bufferSize, seed); } + +static U32 localXXH64(const void* buffer, size_t bufferSize, U32 seed) { return (U32)XXH64(buffer, bufferSize, seed); } + +static void BMK_benchHash(hashFunction h, const char* hName, const void* buffer, size_t bufferSize) +{ + U32 nbh_perIteration = ((300 MB) / (bufferSize+1)) + 1; /* first loop conservatively aims for 300 MB/s */ + U32 iterationNb; + double fastestH = 100000000.; + + DISPLAYLEVEL(2, "\r%70s\r", ""); /* Clean display line */ + if (g_nbIterations<1) g_nbIterations=1; + for (iterationNb = 1; iterationNb <= g_nbIterations; iterationNb++) { + U32 r=0; + clock_t cStart; + + DISPLAYLEVEL(2, "%1i-%-17.17s : %10u ->\r", iterationNb, hName, (U32)bufferSize); + cStart = clock(); + while (clock() == cStart); /* starts clock() at its exact beginning */ + cStart = clock(); + + { U32 i; + for (i=0; i<nbh_perIteration; i++) + r += h(buffer, bufferSize, i); + } + if (r==0) DISPLAYLEVEL(3,".\r"); /* do something with r to avoid compiler "optimizing" away hash function */ + { double const timeS = ((double)BMK_clockSpan(cStart) / CLOCKS_PER_SEC) / nbh_perIteration; + if (timeS < fastestH) fastestH = timeS; + DISPLAYLEVEL(2, "%1i-%-17.17s : %10u -> %8.0f it/s (%7.1f MB/s) \r", + iterationNb, hName, (U32)bufferSize, + (double)1 / fastestH, + ((double)bufferSize / (1<<20)) / fastestH ); + } + assert(fastestH > 1./2000000000); /* avoid U32 overflow */ + nbh_perIteration = (U32)(1 / fastestH) + 1; /* adjust nbh_perIteration to last roughtly one second */ + } + DISPLAYLEVEL(1, "%-19.19s : %10u -> %8.0f it/s (%7.1f MB/s) \n", hName, (U32)bufferSize, + (double)1 / fastestH, + ((double)bufferSize / (1<<20)) / fastestH); + if (g_displayLevel<1) + DISPLAYLEVEL(0, "%u, ", (U32)((double)1 / fastestH)); +} + + +/* BMK_benchMem(): + * specificTest : 0 == run all tests, 1+ run only specific test + * buffer : is supposed 8-bytes aligned (if malloc'ed, it should be) + * the real allocated size of buffer is supposed to be >= (bufferSize+3). + * @return : 0 on success, 1 if error (invalid mode selected) */ +static int BMK_benchMem(const void* buffer, size_t bufferSize, U32 specificTest) +{ + assert((((size_t)buffer) & 8) == 0); /* ensure alignment */ + + /* XXH32 bench */ + if ((specificTest==0) | (specificTest==1)) + BMK_benchHash(localXXH32, "XXH32", buffer, bufferSize); + + /* Bench XXH32 on Unaligned input */ + if ((specificTest==0) | (specificTest==2)) + BMK_benchHash(localXXH32, "XXH32 unaligned", ((const char*)buffer)+1, bufferSize); + + /* Bench XXH64 */ + if ((specificTest==0) | (specificTest==3)) + BMK_benchHash(localXXH64, "XXH64", buffer, bufferSize); + + /* Bench XXH64 on Unaligned input */ + if ((specificTest==0) | (specificTest==4)) + BMK_benchHash(localXXH64, "XXH64 unaligned", ((const char*)buffer)+3, bufferSize); + + if (specificTest > 4) { + DISPLAY("benchmark mode invalid \n"); + return 1; + } + return 0; +} + + +static size_t BMK_selectBenchedSize(const char* fileName) +{ U64 const inFileSize = BMK_GetFileSize(fileName); + size_t benchedSize = (size_t) BMK_findMaxMem(inFileSize); + if ((U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize; + if (benchedSize < inFileSize) { + DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", fileName, (int)(benchedSize>>20)); + } + return benchedSize; +} + + +static int BMK_benchFiles(const char** fileNamesTable, int nbFiles, U32 specificTest) +{ + int result = 0; + int fileIdx; + + for (fileIdx=0; fileIdx<nbFiles; fileIdx++) { + const char* const inFileName = fileNamesTable[fileIdx]; + FILE* const inFile = fopen( inFileName, "rb" ); + size_t const benchedSize = BMK_selectBenchedSize(inFileName); + char* const buffer = (char*)calloc(benchedSize+16+3, 1); + void* const alignedBuffer = (buffer+15) - (((size_t)(buffer+15)) & 0xF); /* align on next 16 bytes */ + + /* Checks */ + if ((inFile==NULL) || (inFileName==NULL)) { + DISPLAY("Pb opening %s\n", inFileName); + free(buffer); + return 11; + } + if(!buffer) { + DISPLAY("\nError: not enough memory!\n"); + fclose(inFile); + return 12; + } + + /* Fill input buffer */ + DISPLAYLEVEL(1, "\rLoading %s... \n", inFileName); + { size_t const readSize = fread(alignedBuffer, 1, benchedSize, inFile); + fclose(inFile); + if(readSize != benchedSize) { + DISPLAY("\nError: problem reading file '%s' !! \n", inFileName); + free(buffer); + return 13; + } } + + /* bench */ + result |= BMK_benchMem(alignedBuffer, benchedSize, specificTest); + + free(buffer); + } + + return result; +} + + + +static int BMK_benchInternal(size_t keySize, int specificTest) +{ + void* const buffer = calloc(keySize+16+3, 1); + void* const alignedBuffer = ((char*)buffer+15) - (((size_t)((char*)buffer+15)) & 0xF); /* align on next 16 bytes */ + if(!buffer) { + DISPLAY("\nError: not enough memory!\n"); + return 12; + } + + /* bench */ + DISPLAYLEVEL(1, "Sample of "); + if (keySize > 10 KB) { + DISPLAYLEVEL(1, "%u KB", (U32)(keySize >> 10)); + } else { + DISPLAYLEVEL(1, "%u bytes", (U32)keySize); + } + DISPLAYLEVEL(1, "... \n"); + + { int const result = BMK_benchMem(alignedBuffer, keySize, specificTest); + free(buffer); + return result; + } +} + + +static void BMK_checkResult(U32 r1, U32 r2) +{ + static int nbTests = 1; + if (r1==r2) { + DISPLAYLEVEL(3, "\rTest%3i : %08X == %08X ok ", nbTests, r1, r2); + } else { + DISPLAY("\rERROR : Test%3i : %08X <> %08X !!!!! \n", nbTests, r1, r2); + exit(1); + } + nbTests++; +} + + +static void BMK_checkResult64(U64 r1, U64 r2) +{ + static int nbTests = 1; + if (r1!=r2) { + DISPLAY("\rERROR : Test%3i : 64-bit values non equals !!!!! \n", nbTests); + DISPLAY("\r %08X%08X != %08X%08X \n", (U32)(r1>>32), (U32)r1, (U32)(r2>>32), (U32)r2); + exit(1); + } + nbTests++; +} + + +static void BMK_testSequence64(void* sentence, size_t len, U64 seed, U64 Nresult) +{ + XXH64_state_t state; + U64 Dresult; + size_t pos; + + Dresult = XXH64(sentence, len, seed); + BMK_checkResult64(Dresult, Nresult); + + XXH64_reset(&state, seed); + XXH64_update(&state, sentence, len); + Dresult = XXH64_digest(&state); + BMK_checkResult64(Dresult, Nresult); + + XXH64_reset(&state, seed); + for (pos=0; pos<len; pos++) + XXH64_update(&state, ((char*)sentence)+pos, 1); + Dresult = XXH64_digest(&state); + BMK_checkResult64(Dresult, Nresult); +} + + +static void BMK_testSequence(const void* sequence, size_t len, U32 seed, U32 Nresult) +{ + XXH32_state_t state; + U32 Dresult; + size_t pos; + + Dresult = XXH32(sequence, len, seed); + BMK_checkResult(Dresult, Nresult); + + XXH32_reset(&state, seed); + XXH32_update(&state, sequence, len); + Dresult = XXH32_digest(&state); + BMK_checkResult(Dresult, Nresult); + + XXH32_reset(&state, seed); + for (pos=0; pos<len; pos++) + XXH32_update(&state, ((const char*)sequence)+pos, 1); + Dresult = XXH32_digest(&state); + BMK_checkResult(Dresult, Nresult); +} + + +#define SANITY_BUFFER_SIZE 101 +static void BMK_sanityCheck(void) +{ + static const U32 prime = 2654435761U; + BYTE sanityBuffer[SANITY_BUFFER_SIZE]; + U32 byteGen = prime; + + int i; + for (i=0; i<SANITY_BUFFER_SIZE; i++) { + sanityBuffer[i] = (BYTE)(byteGen>>24); + byteGen *= byteGen; + } + + BMK_testSequence(NULL, 0, 0, 0x02CC5D05); + BMK_testSequence(NULL, 0, prime, 0x36B78AE7); + BMK_testSequence(sanityBuffer, 1, 0, 0xB85CBEE5); + BMK_testSequence(sanityBuffer, 1, prime, 0xD5845D64); + BMK_testSequence(sanityBuffer, 14, 0, 0xE5AA0AB4); + BMK_testSequence(sanityBuffer, 14, prime, 0x4481951D); + BMK_testSequence(sanityBuffer, SANITY_BUFFER_SIZE, 0, 0x1F1AA412); + BMK_testSequence(sanityBuffer, SANITY_BUFFER_SIZE, prime, 0x498EC8E2); + + BMK_testSequence64(NULL , 0, 0, 0xEF46DB3751D8E999ULL); + BMK_testSequence64(NULL , 0, prime, 0xAC75FDA2929B17EFULL); + BMK_testSequence64(sanityBuffer, 1, 0, 0x4FCE394CC88952D8ULL); + BMK_testSequence64(sanityBuffer, 1, prime, 0x739840CB819FA723ULL); + BMK_testSequence64(sanityBuffer, 14, 0, 0xCFFA8DB881BC3A3DULL); + BMK_testSequence64(sanityBuffer, 14, prime, 0x5B9611585EFCC9CBULL); + BMK_testSequence64(sanityBuffer, SANITY_BUFFER_SIZE, 0, 0x0EAB543384F878ADULL); + BMK_testSequence64(sanityBuffer, SANITY_BUFFER_SIZE, prime, 0xCAA65939306F1E21ULL); + + DISPLAYLEVEL(3, "\r%70s\r", ""); /* Clean display line */ + DISPLAYLEVEL(3, "Sanity check -- all tests ok\n"); +} + + +/* ******************************************************** +* File Hashing +**********************************************************/ + +static void BMK_display_LittleEndian(const void* ptr, size_t length) +{ + const BYTE* p = (const BYTE*)ptr; + size_t idx; + for (idx=length-1; idx<length; idx--) /* intentional underflow to negative to detect end */ + DISPLAYRESULT("%02x", p[idx]); +} + +static void BMK_display_BigEndian(const void* ptr, size_t length) +{ + const BYTE* p = (const BYTE*)ptr; + size_t idx; + for (idx=0; idx<length; idx++) + DISPLAYRESULT("%02x", p[idx]); +} + +static void BMK_hashStream(void* xxhHashValue, const algoType hashType, FILE* inFile, void* buffer, size_t blockSize) +{ + XXH64_state_t state64; + XXH32_state_t state32; + size_t readSize; + + /* Init */ + XXH32_reset(&state32, XXHSUM32_DEFAULT_SEED); + XXH64_reset(&state64, XXHSUM64_DEFAULT_SEED); + + /* Load file & update hash */ + readSize = 1; + while (readSize) { + readSize = fread(buffer, 1, blockSize, inFile); + switch(hashType) + { + case algo_xxh32: + XXH32_update(&state32, buffer, readSize); + break; + case algo_xxh64: + XXH64_update(&state64, buffer, readSize); + break; + default: + break; + } + } + + switch(hashType) + { + case algo_xxh32: + { U32 const h32 = XXH32_digest(&state32); + memcpy(xxhHashValue, &h32, sizeof(h32)); + break; + } + case algo_xxh64: + { U64 const h64 = XXH64_digest(&state64); + memcpy(xxhHashValue, &h64, sizeof(h64)); + break; + } + default: + break; + } +} + + +typedef enum { big_endian, little_endian} endianess; + +static int BMK_hash(const char* fileName, + const algoType hashType, + const endianess displayEndianess) +{ + FILE* inFile; + size_t const blockSize = 64 KB; + void* buffer; + U32 h32 = 0; + U64 h64 = 0; + + /* Check file existence */ + if (fileName == stdinName) { + inFile = stdin; + SET_BINARY_MODE(stdin); + } + else + inFile = fopen( fileName, "rb" ); + if (inFile==NULL) { + DISPLAY( "Pb opening %s\n", fileName); + return 1; + } + + /* Memory allocation & restrictions */ + buffer = malloc(blockSize); + if(!buffer) { + DISPLAY("\nError: not enough memory!\n"); + fclose(inFile); + return 1; + } + + /* loading notification */ + { const size_t fileNameSize = strlen(fileName); + const char* const fileNameEnd = fileName + fileNameSize; + const int maxInfoFilenameSize = (int)(fileNameSize > 30 ? 30 : fileNameSize); + int infoFilenameSize = 1; + while ((infoFilenameSize < maxInfoFilenameSize) + && (fileNameEnd[-1-infoFilenameSize] != '/') + && (fileNameEnd[-1-infoFilenameSize] != '\\') ) + infoFilenameSize++; + DISPLAY("\rLoading %s... \r", fileNameEnd - infoFilenameSize); + + /* Load file & update hash */ + switch(hashType) + { + case algo_xxh32: + BMK_hashStream(&h32, algo_xxh32, inFile, buffer, blockSize); + break; + case algo_xxh64: + BMK_hashStream(&h64, algo_xxh64, inFile, buffer, blockSize); + break; + default: + break; + } + + fclose(inFile); + free(buffer); + DISPLAY("%s \r", fileNameEnd - infoFilenameSize); /* erase line */ + } + + /* display Hash */ + switch(hashType) + { + case algo_xxh32: + { XXH32_canonical_t hcbe32; + XXH32_canonicalFromHash(&hcbe32, h32); + displayEndianess==big_endian ? + BMK_display_BigEndian(&hcbe32, sizeof(hcbe32)) : BMK_display_LittleEndian(&hcbe32, sizeof(hcbe32)); + DISPLAYRESULT(" %s\n", fileName); + break; + } + case algo_xxh64: + { XXH64_canonical_t hcbe64; + XXH64_canonicalFromHash(&hcbe64, h64); + displayEndianess==big_endian ? + BMK_display_BigEndian(&hcbe64, sizeof(hcbe64)) : BMK_display_LittleEndian(&hcbe64, sizeof(hcbe64)); + DISPLAYRESULT(" %s\n", fileName); + break; + } + default: + break; + } + + return 0; +} + + +static int BMK_hashFiles(const char** fnList, int fnTotal, + algoType hashType, endianess displayEndianess) +{ + int fnNb; + int result = 0; + + if (fnTotal==0) + return BMK_hash(stdinName, hashType, displayEndianess); + + for (fnNb=0; fnNb<fnTotal; fnNb++) + result += BMK_hash(fnList[fnNb], hashType, displayEndianess); + DISPLAY("\r%70s\r", ""); + return result; +} + + +typedef enum { + GetLine_ok, + GetLine_eof, + GetLine_exceedMaxLineLength, + GetLine_outOfMemory, +} GetLineResult; + +typedef enum { + CanonicalFromString_ok, + CanonicalFromString_invalidFormat, +} CanonicalFromStringResult; + +typedef enum { + ParseLine_ok, + ParseLine_invalidFormat, +} ParseLineResult; + +typedef enum { + LineStatus_hashOk, + LineStatus_hashFailed, + LineStatus_failedToOpen, +} LineStatus; + +typedef union { + XXH32_canonical_t xxh32; + XXH64_canonical_t xxh64; +} Canonical; + +typedef struct { + Canonical canonical; + const char* filename; + int xxhBits; /* canonical type : 32:xxh32, 64:xxh64 */ +} ParsedLine; + +typedef struct { + unsigned long nProperlyFormattedLines; + unsigned long nImproperlyFormattedLines; + unsigned long nMismatchedChecksums; + unsigned long nOpenOrReadFailures; + unsigned long nMixedFormatLines; + int xxhBits; + int quit; +} ParseFileReport; + +typedef struct { + const char* inFileName; + FILE* inFile; + int lineMax; + char* lineBuf; + size_t blockSize; + char* blockBuf; + int strictMode; + int statusOnly; + int warn; + int quiet; + ParseFileReport report; +} ParseFileArg; + + +/* Read line from stream. + Returns GetLine_ok, if it reads line successfully. + Returns GetLine_eof, if stream reaches EOF. + Returns GetLine_exceedMaxLineLength, if line length is longer than MAX_LINE_LENGTH. + Returns GetLine_outOfMemory, if line buffer memory allocation failed. + */ +static GetLineResult getLine(char** lineBuf, int* lineMax, FILE* inFile) +{ + GetLineResult result = GetLine_ok; + int len = 0; + + if ((*lineBuf == NULL) || (*lineMax<1)) { + free(*lineBuf); /* in case it's != NULL */ + *lineMax = 0; + *lineBuf = (char*)malloc(DEFAULT_LINE_LENGTH); + if(*lineBuf == NULL) return GetLine_outOfMemory; + *lineMax = DEFAULT_LINE_LENGTH; + } + + for (;;) { + const int c = fgetc(inFile); + if (c == EOF) { + /* If we meet EOF before first character, returns GetLine_eof, + * otherwise GetLine_ok. + */ + if (len == 0) result = GetLine_eof; + break; + } + + /* Make enough space for len+1 (for final NUL) bytes. */ + if (len+1 >= *lineMax) { + char* newLineBuf = NULL; + int newBufSize = *lineMax; + + newBufSize += (newBufSize/2) + 1; /* x 1.5 */ + if (newBufSize > MAX_LINE_LENGTH) newBufSize = MAX_LINE_LENGTH; + if (len+1 >= newBufSize) return GetLine_exceedMaxLineLength; + + newLineBuf = (char*) realloc(*lineBuf, newBufSize); + if (newLineBuf == NULL) return GetLine_outOfMemory; + + *lineBuf = newLineBuf; + *lineMax = newBufSize; + } + + if (c == '\n') break; + (*lineBuf)[len++] = (char) c; + } + + (*lineBuf)[len] = '\0'; + return result; +} + + +/* Converts one hexadecimal character to integer. + * Returns -1, if given character is not hexadecimal. + */ +static int charToHex(char c) +{ + int result = -1; + if (c >= '0' && c <= '9') { + result = (int) (c - '0'); + } else if (c >= 'A' && c <= 'F') { + result = (int) (c - 'A') + 0x0a; + } else if (c >= 'a' && c <= 'f') { + result = (int) (c - 'a') + 0x0a; + } + return result; +} + + +/* Converts XXH32 canonical hexadecimal string hashStr to big endian unsigned char array dst. + * Returns CANONICAL_FROM_STRING_INVALID_FORMAT, if hashStr is not well formatted. + * Returns CANONICAL_FROM_STRING_OK, if hashStr is parsed successfully. + */ +static CanonicalFromStringResult canonicalFromString(unsigned char* dst, + size_t dstSize, + const char* hashStr) +{ + size_t i; + for (i = 0; i < dstSize; ++i) { + int h0, h1; + + h0 = charToHex(hashStr[i*2 + 0]); + if (h0 < 0) return CanonicalFromString_invalidFormat; + + h1 = charToHex(hashStr[i*2 + 1]); + if (h1 < 0) return CanonicalFromString_invalidFormat; + + dst[i] = (unsigned char) ((h0 << 4) | h1); + } + return CanonicalFromString_ok; +} + + +/* Parse single line of xxHash checksum file. + * Returns PARSE_LINE_ERROR_INVALID_FORMAT, if line is not well formatted. + * Returns PARSE_LINE_OK if line is parsed successfully. + * And members of parseLine will be filled by parsed values. + * + * - line must be ended with '\0'. + * - Since parsedLine.filename will point within given argument `line`, + * users must keep `line`s content during they are using parsedLine. + * + * Given xxHash checksum line should have the following format: + * + * <8 or 16 hexadecimal char> <space> <space> <filename...> <'\0'> + */ +static ParseLineResult parseLine(ParsedLine* parsedLine, const char* line) +{ + const char* const firstSpace = strchr(line, ' '); + const char* const secondSpace = firstSpace + 1; + + parsedLine->filename = NULL; + parsedLine->xxhBits = 0; + + if (firstSpace == NULL || *secondSpace != ' ') return ParseLine_invalidFormat; + + switch (firstSpace - line) + { + case 8: + { XXH32_canonical_t* xxh32c = &parsedLine->canonical.xxh32; + if (canonicalFromString(xxh32c->digest, sizeof(xxh32c->digest), line) + != CanonicalFromString_ok) { + return ParseLine_invalidFormat; + } + parsedLine->xxhBits = 32; + break; + } + + case 16: + { XXH64_canonical_t* xxh64c = &parsedLine->canonical.xxh64; + if (canonicalFromString(xxh64c->digest, sizeof(xxh64c->digest), line) + != CanonicalFromString_ok) { + return ParseLine_invalidFormat; + } + parsedLine->xxhBits = 64; + break; + } + + default: + return ParseLine_invalidFormat; + break; + } + + parsedLine->filename = secondSpace + 1; + return ParseLine_ok; +} + + +/*! Parse xxHash checksum file. + */ +static void parseFile1(ParseFileArg* parseFileArg) +{ + const char* const inFileName = parseFileArg->inFileName; + ParseFileReport* const report = &parseFileArg->report; + + unsigned long lineNumber = 0; + memset(report, 0, sizeof(*report)); + + while (!report->quit) { + FILE* fp = NULL; + LineStatus lineStatus = LineStatus_hashFailed; + GetLineResult getLineResult; + ParsedLine parsedLine; + memset(&parsedLine, 0, sizeof(parsedLine)); + + lineNumber++; + if (lineNumber == 0) { + /* This is unlikely happen, but md5sum.c has this + * error check. */ + DISPLAY("%s : too many checksum lines\n", inFileName); + report->quit = 1; + break; + } + + getLineResult = getLine(&parseFileArg->lineBuf, &parseFileArg->lineMax, + parseFileArg->inFile); + if (getLineResult != GetLine_ok) { + if (getLineResult == GetLine_eof) break; + + switch (getLineResult) + { + case GetLine_ok: + case GetLine_eof: + /* These cases never happen. See above getLineResult related "if"s. + They exist just for make gcc's -Wswitch-enum happy. */ + break; + + default: + DISPLAY("%s : %lu: unknown error\n", inFileName, lineNumber); + break; + + case GetLine_exceedMaxLineLength: + DISPLAY("%s : %lu: too long line\n", inFileName, lineNumber); + break; + + case GetLine_outOfMemory: + DISPLAY("%s : %lu: out of memory\n", inFileName, lineNumber); + break; + } + report->quit = 1; + break; + } + + if (parseLine(&parsedLine, parseFileArg->lineBuf) != ParseLine_ok) { + report->nImproperlyFormattedLines++; + if (parseFileArg->warn) { + DISPLAY("%s : %lu: improperly formatted XXHASH checksum line\n" + , inFileName, lineNumber); + } + continue; + } + + if (report->xxhBits != 0 && report->xxhBits != parsedLine.xxhBits) { + /* Don't accept xxh32/xxh64 mixed file */ + report->nImproperlyFormattedLines++; + report->nMixedFormatLines++; + if (parseFileArg->warn) { + DISPLAY("%s : %lu: improperly formatted XXHASH checksum line (XXH32/64)\n" + , inFileName, lineNumber); + } + continue; + } + + report->nProperlyFormattedLines++; + if (report->xxhBits == 0) { + report->xxhBits = parsedLine.xxhBits; + } + + fp = fopen(parsedLine.filename, "rb"); + if (fp == NULL) { + lineStatus = LineStatus_failedToOpen; + } else { + lineStatus = LineStatus_hashFailed; + switch (parsedLine.xxhBits) + { + case 32: + { XXH32_hash_t xxh; + BMK_hashStream(&xxh, algo_xxh32, fp, parseFileArg->blockBuf, parseFileArg->blockSize); + if (xxh == XXH32_hashFromCanonical(&parsedLine.canonical.xxh32)) { + lineStatus = LineStatus_hashOk; + } } + break; + + case 64: + { XXH64_hash_t xxh; + BMK_hashStream(&xxh, algo_xxh64, fp, parseFileArg->blockBuf, parseFileArg->blockSize); + if (xxh == XXH64_hashFromCanonical(&parsedLine.canonical.xxh64)) { + lineStatus = LineStatus_hashOk; + } } + break; + + default: + break; + } + fclose(fp); + } + + switch (lineStatus) + { + default: + DISPLAY("%s : unknown error\n", inFileName); + report->quit = 1; + break; + + case LineStatus_failedToOpen: + report->nOpenOrReadFailures++; + if (!parseFileArg->statusOnly) { + DISPLAYRESULT("%s : %lu: FAILED open or read %s\n" + , inFileName, lineNumber, parsedLine.filename); + } + break; + + case LineStatus_hashOk: + case LineStatus_hashFailed: + { int b = 1; + if (lineStatus == LineStatus_hashOk) { + /* If --quiet is specified, don't display "OK" */ + if (parseFileArg->quiet) b = 0; + } else { + report->nMismatchedChecksums++; + } + + if (b && !parseFileArg->statusOnly) { + DISPLAYRESULT("%s: %s\n", parsedLine.filename + , lineStatus == LineStatus_hashOk ? "OK" : "FAILED"); + } } + break; + } + } /* while (!report->quit) */ +} + + +/* Parse xxHash checksum file. + * Returns 1, if all procedures were succeeded. + * Returns 0, if any procedures was failed. + * + * If strictMode != 0, return error code if any line is invalid. + * If statusOnly != 0, don't generate any output. + * If warn != 0, print a warning message to stderr. + * If quiet != 0, suppress "OK" line. + * + * "All procedures are succeeded" means: + * - Checksum file contains at least one line and less than SIZE_T_MAX lines. + * - All files are properly opened and read. + * - All hash values match with its content. + * - (strict mode) All lines in checksum file are consistent and well formatted. + * + */ +static int checkFile(const char* inFileName, + const endianess displayEndianess, + U32 strictMode, + U32 statusOnly, + U32 warn, + U32 quiet) +{ + int result = 0; + FILE* inFile = NULL; + ParseFileArg parseFileArgBody; + ParseFileArg* const parseFileArg = &parseFileArgBody; + ParseFileReport* const report = &parseFileArg->report; + + if (displayEndianess != big_endian) { + /* Don't accept little endian */ + DISPLAY( "Check file mode doesn't support little endian\n" ); + return 0; + } + + /* note : stdinName is special constant pointer. It is not a string. */ + if (inFileName == stdinName) { + /* note : Since we expect text input for xxhash -c mode, + * Don't set binary mode for stdin */ + inFile = stdin; + } else { + inFile = fopen( inFileName, "rt" ); + } + + if (inFile == NULL) { + DISPLAY( "Pb opening %s\n", inFileName); + return 0; + } + + parseFileArg->inFileName = inFileName; + parseFileArg->inFile = inFile; + parseFileArg->lineMax = DEFAULT_LINE_LENGTH; + parseFileArg->lineBuf = (char*) malloc((size_t) parseFileArg->lineMax); + parseFileArg->blockSize = 64 * 1024; + parseFileArg->blockBuf = (char*) malloc(parseFileArg->blockSize); + parseFileArg->strictMode = strictMode; + parseFileArg->statusOnly = statusOnly; + parseFileArg->warn = warn; + parseFileArg->quiet = quiet; + + parseFile1(parseFileArg); + + free(parseFileArg->blockBuf); + free(parseFileArg->lineBuf); + + if (inFile != stdin) fclose(inFile); + + /* Show error/warning messages. All messages are copied from md5sum.c + */ + if (report->nProperlyFormattedLines == 0) { + DISPLAY("%s: no properly formatted XXHASH checksum lines found\n", inFileName); + } else if (!statusOnly) { + if (report->nImproperlyFormattedLines) { + DISPLAYRESULT("%lu lines are improperly formatted\n" + , report->nImproperlyFormattedLines); + } + if (report->nOpenOrReadFailures) { + DISPLAYRESULT("%lu listed files could not be read\n" + , report->nOpenOrReadFailures); + } + if (report->nMismatchedChecksums) { + DISPLAYRESULT("%lu computed checksums did NOT match\n" + , report->nMismatchedChecksums); + } } + + /* Result (exit) code logic is copied from + * gnu coreutils/src/md5sum.c digest_check() */ + result = report->nProperlyFormattedLines != 0 + && report->nMismatchedChecksums == 0 + && report->nOpenOrReadFailures == 0 + && (!strictMode || report->nImproperlyFormattedLines == 0) + && report->quit == 0; + return result; +} + + +static int checkFiles(const char** fnList, int fnTotal, + const endianess displayEndianess, + U32 strictMode, + U32 statusOnly, + U32 warn, + U32 quiet) +{ + int ok = 1; + + /* Special case for stdinName "-", + * note: stdinName is not a string. It's special pointer. */ + if (fnTotal==0) { + ok &= checkFile(stdinName, displayEndianess, strictMode, statusOnly, warn, quiet); + } else { + int fnNb; + for (fnNb=0; fnNb<fnTotal; fnNb++) + ok &= checkFile(fnList[fnNb], displayEndianess, strictMode, statusOnly, warn, quiet); + } + return ok ? 0 : 1; +} + + +/* ******************************************************** +* Main +**********************************************************/ + +static int usage(const char* exename) +{ + DISPLAY( WELCOME_MESSAGE(exename) ); + DISPLAY( "Usage :\n"); + DISPLAY( " %s [arg] [filenames]\n", exename); + DISPLAY( "When no filename provided, or - provided : use stdin as input\n"); + DISPLAY( "Arguments :\n"); + DISPLAY( " -H# : hash selection : 0=32bits, 1=64bits (default: %i)\n", (int)g_defaultAlgo); + DISPLAY( " -c : read xxHash sums from the [filenames] and check them\n"); + DISPLAY( " -h : help \n"); + return 0; +} + + +static int usage_advanced(const char* exename) +{ + usage(exename); + DISPLAY( "Advanced :\n"); + DISPLAY( " --little-endian : hash printed using little endian convention (default: big endian)\n"); + DISPLAY( " -V, --version : display version\n"); + DISPLAY( " -h, --help : display long help and exit\n"); + DISPLAY( " -b : benchmark mode \n"); + DISPLAY( " -i# : number of iterations (benchmark mode; default %i)\n", g_nbIterations); + DISPLAY( "\n"); + DISPLAY( "The following four options are useful only when verifying checksums (-c):\n"); + DISPLAY( "--strict : don't print OK for each successfully verified file\n"); + DISPLAY( "--status : don't output anything, status code shows success\n"); + DISPLAY( "--quiet : exit non-zero for improperly formatted checksum lines\n"); + DISPLAY( "--warn : warn about improperly formatted checksum lines\n"); + return 0; +} + +static int badusage(const char* exename) +{ + DISPLAY("Wrong parameters\n"); + usage(exename); + return 1; +} + +/*! readU32FromChar() : + @return : unsigned integer value read from input in `char` format, + 0 is no figure at *stringPtr position. + Interprets K, KB, KiB, M, MB and MiB suffix. + Modifies `*stringPtr`, advancing it to position where reading stopped. + Note : function result can overflow if digit string > MAX_UINT */ +static unsigned readU32FromChar(const char** stringPtr) +{ + unsigned result = 0; + while ((**stringPtr >='0') && (**stringPtr <='9')) + result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; + if ((**stringPtr=='K') || (**stringPtr=='M')) { + result <<= 10; + if (**stringPtr=='M') result <<= 10; + (*stringPtr)++ ; + if (**stringPtr=='i') (*stringPtr)++; + if (**stringPtr=='B') (*stringPtr)++; + } + return result; +} + +int main(int argc, const char** argv) +{ + int i, filenamesStart = 0; + const char* const exename = argv[0]; + U32 benchmarkMode = 0; + U32 fileCheckMode = 0; + U32 strictMode = 0; + U32 statusOnly = 0; + U32 warn = 0; + U32 quiet = 0; + U32 specificTest = 0; + size_t keySize = XXH_DEFAULT_SAMPLE_SIZE; + algoType algo = g_defaultAlgo; + endianess displayEndianess = big_endian; + + /* special case : xxh32sum default to 32 bits checksum */ + if (strstr(exename, "xxh32sum") != NULL) algo = algo_xxh32; + + for(i=1; i<argc; i++) { + const char* argument = argv[i]; + + if(!argument) continue; /* Protection, if argument empty */ + + if (!strcmp(argument, "--little-endian")) { displayEndianess = little_endian; continue; } + if (!strcmp(argument, "--check")) { fileCheckMode = 1; continue; } + if (!strcmp(argument, "--strict")) { strictMode = 1; continue; } + if (!strcmp(argument, "--status")) { statusOnly = 1; continue; } + if (!strcmp(argument, "--quiet")) { quiet = 1; continue; } + if (!strcmp(argument, "--warn")) { warn = 1; continue; } + if (!strcmp(argument, "--help")) { return usage_advanced(exename); } + if (!strcmp(argument, "--version")) { DISPLAY(WELCOME_MESSAGE(exename)); return 0; } + + if (*argument!='-') { + if (filenamesStart==0) filenamesStart=i; /* only supports a continuous list of filenames */ + continue; + } + + /* command selection */ + argument++; /* note : *argument=='-' */ + + while (*argument!=0) { + switch(*argument) + { + /* Display version */ + case 'V': + DISPLAY(WELCOME_MESSAGE(exename)); return 0; + + /* Display help on usage */ + case 'h': + return usage_advanced(exename); + + /* select hash algorithm */ + case 'H': + algo = (algoType)(argument[1] - '0'); + argument+=2; + break; + + /* File check mode */ + case 'c': + fileCheckMode=1; + argument++; + break; + + /* Warning mode (file check mode only, alias of "--warning") */ + case 'w': + warn=1; + argument++; + break; + + /* Trigger benchmark mode */ + case 'b': + argument++; + benchmarkMode = 1; + specificTest = readU32FromChar(&argument); /* select one specific test (hidden option) */ + break; + + /* Modify Nb Iterations (benchmark only) */ + case 'i': + argument++; + g_nbIterations = readU32FromChar(&argument); + break; + + /* Modify Block size (benchmark only) */ + case 'B': + argument++; + keySize = readU32FromChar(&argument); + break; + + /* Modify verbosity of benchmark output (hidden option) */ + case 'q': + argument++; + g_displayLevel--; + break; + + default: + return badusage(exename); + } + } + } /* for(i=1; i<argc; i++) */ + + /* Check benchmark mode */ + if (benchmarkMode) { + DISPLAYLEVEL(2, WELCOME_MESSAGE(exename) ); + BMK_sanityCheck(); + if (filenamesStart==0) return BMK_benchInternal(keySize, specificTest); + return BMK_benchFiles(argv+filenamesStart, argc-filenamesStart, specificTest); + } + + /* Check if input is defined as console; trigger an error in this case */ + if ( (filenamesStart==0) && IS_CONSOLE(stdin) ) return badusage(exename); + + if (filenamesStart==0) filenamesStart = argc; + if (fileCheckMode) { + return checkFiles(argv+filenamesStart, argc-filenamesStart, + displayEndianess, strictMode, statusOnly, warn, quiet); + } else { + return BMK_hashFiles(argv+filenamesStart, argc-filenamesStart, algo, displayEndianess); + } +} + +#endif /* XXHASH_C_2097394837 */ |
